Fix mouse intersect underground, fix anim blend, icon click sound

This commit is contained in:
Retera 2020-11-01 13:05:38 -05:00
parent 238015f21d
commit bec43bcb3e
38 changed files with 2950 additions and 1949 deletions

View File

@ -157,6 +157,7 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
final Scene portraitScene = this.viewer.addSimpleScene();
this.uiScene = this.viewer.addSimpleScene();
this.uiScene.alpha = true;
this.uiScene.enableAudio();
// this.mainModel = (MdxModel) this.viewer.load("UI\\Glues\\MainMenu\\MainMenu3D_exp\\MainMenu3D_exp.mdx",
@ -385,6 +386,11 @@ public class WarsmashGdxMapGame extends ApplicationAdapter implements CanvasProv
@Override
public boolean touchUp(final int screenX, final int screenY, final int pointer, final int button) {
final float worldScreenY = getHeight() - screenY;
if (this.meleeUI.touchUp(screenX, screenY, worldScreenY, button)) {
return false;
}
return false;
}

View File

@ -346,6 +346,11 @@ public abstract class AbstractRenderableFrame implements UIFrame {
return null;
}
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
return null;
}
@Override
public String getName() {
return this.name;

View File

@ -46,4 +46,15 @@ public abstract class AbstractUIFrame extends AbstractRenderableFrame implements
}
return super.touchDown(screenX, screenY, button);
}
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
for (final UIFrame childFrame : this.childFrames) {
final UIFrame clickedChild = childFrame.touchUp(screenX, screenY, button);
if (clickedChild != null) {
return clickedChild;
}
}
return super.touchUp(screenX, screenY, button);
}
}

View File

@ -63,9 +63,4 @@ public class TextureFrame extends AbstractRenderableFrame {
public void setTexture(final TextureRegion texture) {
this.texture = texture;
}
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
return super.touchDown(screenX, screenY, button);
}
}

View File

@ -34,5 +34,7 @@ public interface UIFrame {
UIFrame touchDown(float screenX, float screenY, int button);
UIFrame touchUp(float screenX, float screenY, int button);
String getName();
}

View File

@ -13,6 +13,9 @@ public abstract class SkeletalNode extends GenericNode {
protected static final Quaternion rotationHeap = new Quaternion();
protected static final Quaternion rotationHeap2 = new Quaternion();
protected static final Vector3 scalingHeap = new Vector3();
protected static final Vector3 blendLocationHeap = new Vector3();
protected static final Vector3 blendHeap = new Vector3();
protected static final Vector3 blendScaleHeap = new Vector3();
public UpdatableObject object;
@ -21,7 +24,9 @@ public abstract class SkeletalNode extends GenericNode {
public boolean billboardedY;
public boolean billboardedZ;
public Matrix4 localBlendMatrix;
public Vector3 localBlendLocation;
public Quaternion localBlendRotation;
public Vector3 localBlendScale;
public SkeletalNode() {
this.pivot = new Vector3();
@ -35,7 +40,9 @@ public abstract class SkeletalNode extends GenericNode {
this.inverseWorldRotation = new Quaternion();
this.inverseWorldScale = new Vector3();
this.localMatrix = new Matrix4();
this.localBlendMatrix = new Matrix4();
this.localBlendLocation = new Vector3();
this.localBlendRotation = new Quaternion(0, 0, 0, 1);
this.localBlendScale = new Vector3(1, 1, 1);
this.worldMatrix = new Matrix4();
this.dontInheritTranslation = false;
this.dontInheritRotation = false;
@ -70,8 +77,10 @@ public abstract class SkeletalNode extends GenericNode {
}
public void recalculateTransformation(final Scene scene, final float blendTimeRatio) {
final float inverseBlendRatio = 1 - blendTimeRatio;
final Quaternion computedRotation;
Vector3 computedScaling;
Vector3 computedLocation;
if (this.dontInheritScaling) {
computedScaling = scalingHeap;
@ -86,7 +95,14 @@ public abstract class SkeletalNode extends GenericNode {
this.worldScale.z = this.localScale.z;
}
else {
computedScaling = this.localScale;
if (!Float.isNaN(blendTimeRatio) && (blendTimeRatio > 0)) {
blendScaleHeap.set(this.localScale).scl(inverseBlendRatio)
.add(blendHeap.set(this.localBlendScale).scl(blendTimeRatio));
computedScaling = blendScaleHeap;
}
else {
computedScaling = this.localScale;
}
final Vector3 parentScale = this.parent.worldScale;
this.worldScale.x = parentScale.x * this.localScale.x;
@ -133,18 +149,25 @@ public abstract class SkeletalNode extends GenericNode {
computedRotation.setFromAxisRad(billboardAxisHeap, angle);
}
else {
computedRotation = this.localRotation;
}
RenderMathUtils.fromRotationTranslationScaleOrigin(computedRotation, this.localLocation, computedScaling,
this.localMatrix, this.pivot);
if (!Float.isNaN(blendTimeRatio) && (blendTimeRatio > 0)) {
for (int i = 0; i < this.localMatrix.val.length; i++) {
this.localMatrix.val[i] = (this.localBlendMatrix.val[i] * blendTimeRatio)
+ (this.localMatrix.val[i] * (1 - blendTimeRatio));
if (!Float.isNaN(blendTimeRatio) && (blendTimeRatio > 0)) {
rotationHeap.set(this.localRotation).slerp(this.localBlendRotation, blendTimeRatio);
computedRotation = rotationHeap;
}
else {
computedRotation = this.localRotation;
}
}
if (!Float.isNaN(blendTimeRatio) && (blendTimeRatio > 0)) {
computedLocation = blendLocationHeap.set(this.localLocation).scl(inverseBlendRatio)
.add(blendHeap.set(this.localBlendLocation).scl(blendTimeRatio));
}
else {
computedLocation = this.localLocation;
}
RenderMathUtils.fromRotationTranslationScaleOrigin(computedRotation, computedLocation, computedScaling,
this.localMatrix, this.pivot);
RenderMathUtils.mul(this.worldMatrix, this.parent.worldMatrix, this.localMatrix);
RenderMathUtils.mul(this.worldRotation, this.parent.worldRotation, computedRotation);
@ -178,7 +201,9 @@ public abstract class SkeletalNode extends GenericNode {
}
public void beginBlending() {
this.localBlendMatrix.set(this.localMatrix);
this.localBlendLocation.set(this.localLocation);
this.localBlendRotation.set(this.localRotation);
this.localBlendScale.set(this.localScale);
}
public void updateChildren(final float dt, final Scene scene) {

View File

@ -12,244 +12,255 @@ import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
public class SequenceUtils {
public static final EnumSet<SecondaryTag> EMPTY = EnumSet.noneOf(SecondaryTag.class);
public static final EnumSet<SecondaryTag> READY = EnumSet.of(SecondaryTag.READY);
public static final EnumSet<SecondaryTag> FLESH = EnumSet.of(SecondaryTag.FLESH);
public static final EnumSet<SecondaryTag> BONE = EnumSet.of(SecondaryTag.BONE);
public static final EnumSet<SecondaryTag> EMPTY = EnumSet.noneOf(SecondaryTag.class);
public static final EnumSet<SecondaryTag> READY = EnumSet.of(SecondaryTag.READY);
public static final EnumSet<SecondaryTag> FLESH = EnumSet.of(SecondaryTag.FLESH);
public static final EnumSet<SecondaryTag> TALK = EnumSet.of(SecondaryTag.TALK);
public static final EnumSet<SecondaryTag> BONE = EnumSet.of(SecondaryTag.BONE);
private static final StandSequenceComparator STAND_SEQUENCE_COMPARATOR = new StandSequenceComparator();
private static final SecondaryTagSequenceComparator SECONDARY_TAG_SEQUENCE_COMPARATOR = new SecondaryTagSequenceComparator(STAND_SEQUENCE_COMPARATOR);
private static final StandSequenceComparator STAND_SEQUENCE_COMPARATOR = new StandSequenceComparator();
private static final SecondaryTagSequenceComparator SECONDARY_TAG_SEQUENCE_COMPARATOR = new SecondaryTagSequenceComparator(
STAND_SEQUENCE_COMPARATOR);
public static List<IndexedSequence> filterSequences(final String type, final List<Sequence> sequences) {
final List<IndexedSequence> filtered = new ArrayList<>();
public static List<IndexedSequence> filterSequences(final String type, final List<Sequence> sequences) {
final List<IndexedSequence> filtered = new ArrayList<>();
for (int i = 0, l = sequences.size(); i < l; i++) {
final Sequence sequence = sequences.get(i);
final String name = sequence.getName().split("-")[0].trim().toLowerCase();
for (int i = 0, l = sequences.size(); i < l; i++) {
final Sequence sequence = sequences.get(i);
final String name = sequence.getName().split("-")[0].trim().toLowerCase();
if (name.equals(type)) {
filtered.add(new IndexedSequence(sequence, i));
}
}
if (name.equals(type)) {
filtered.add(new IndexedSequence(sequence, i));
}
}
return filtered;
}
return filtered;
}
private static List<IndexedSequence> filterSequences(final PrimaryTag type, final EnumSet<SecondaryTag> tags,
final List<Sequence> sequences) {
final List<IndexedSequence> filtered = new ArrayList<>();
private static List<IndexedSequence> filterSequences(final PrimaryTag type, final EnumSet<SecondaryTag> tags,
final List<Sequence> sequences) {
final List<IndexedSequence> filtered = new ArrayList<>();
for (int i = 0, l = sequences.size(); i < l; i++) {
final Sequence sequence = sequences.get(i);
if (sequence.getPrimaryTags().contains(type) && (sequence.getSecondaryTags().containsAll(tags)
&& tags.containsAll(sequence.getSecondaryTags()))) {
filtered.add(new IndexedSequence(sequence, i));
}
}
for (int i = 0, l = sequences.size(); i < l; i++) {
final Sequence sequence = sequences.get(i);
if (sequence.getPrimaryTags().contains(type) && (sequence.getSecondaryTags().containsAll(tags)
&& tags.containsAll(sequence.getSecondaryTags()))) {
filtered.add(new IndexedSequence(sequence, i));
}
}
return filtered;
}
return filtered;
}
public static IndexedSequence selectSequence(final String type, final List<Sequence> sequences) {
final List<IndexedSequence> filtered = filterSequences(type, sequences);
public static IndexedSequence selectSequence(final String type, final List<Sequence> sequences) {
final List<IndexedSequence> filtered = filterSequences(type, sequences);
filtered.sort(STAND_SEQUENCE_COMPARATOR);
filtered.sort(STAND_SEQUENCE_COMPARATOR);
int i = 0;
final double randomRoll = Math.random() * 100;
for (final int l = filtered.size(); i < l; i++) {
final Sequence sequence = filtered.get(i).sequence;
final float rarity = sequence.getRarity();
int i = 0;
final double randomRoll = Math.random() * 100;
for (final int l = filtered.size(); i < l; i++) {
final Sequence sequence = filtered.get(i).sequence;
final float rarity = sequence.getRarity();
if (rarity == 0) {
break;
}
if (rarity == 0) {
break;
}
if (randomRoll < (10 - rarity)) {
return filtered.get(i);
}
}
if (randomRoll < (10 - rarity)) {
return filtered.get(i);
}
}
final int sequencesLeft = filtered.size() - i;
final int random = (int) (i + Math.floor(Math.random() * sequencesLeft));
if (sequencesLeft <= 0) {
return null; // new IndexedSequence(null, 0);
}
final IndexedSequence sequence = filtered.get(random);
final int sequencesLeft = filtered.size() - i;
final int random = (int) (i + Math.floor(Math.random() * sequencesLeft));
if (sequencesLeft <= 0) {
return null; // new IndexedSequence(null, 0);
}
final IndexedSequence sequence = filtered.get(random);
return sequence;
}
return sequence;
}
public static IndexedSequence selectSequence(final AnimationTokens.PrimaryTag type,
final EnumSet<AnimationTokens.SecondaryTag> tags, final List<Sequence> sequences,
final boolean allowRarityVariations) {
List<IndexedSequence> filtered = filterSequences(type, tags, sequences);
Comparator<IndexedSequence> sequenceComparator = STAND_SEQUENCE_COMPARATOR;
public static IndexedSequence selectSequence(final AnimationTokens.PrimaryTag type,
final EnumSet<AnimationTokens.SecondaryTag> tags, final List<Sequence> sequences,
final boolean allowRarityVariations) {
List<IndexedSequence> filtered = filterSequences(type, tags, sequences);
final Comparator<IndexedSequence> sequenceComparator = STAND_SEQUENCE_COMPARATOR;
if (filtered.isEmpty() && !tags.isEmpty()) {
filtered = filterSequences(type, EMPTY, sequences);
}
if (filtered.isEmpty()) {
// find tags
EnumSet<SecondaryTag> fallbackTags = null;
for (int i = 0, l = sequences.size(); i < l; i++) {
final Sequence sequence = sequences.get(i);
if (sequence.getPrimaryTags().contains(type)) {
if (fallbackTags == null || sequence.getSecondaryTags().size() < fallbackTags.size()
|| (sequence.getSecondaryTags().size() == fallbackTags.size() && SecondaryTagSequenceComparator.getTagsOrdinal(sequence.getSecondaryTags(), tags)
> SecondaryTagSequenceComparator.getTagsOrdinal(fallbackTags, tags))
) {
fallbackTags = sequence.getSecondaryTags();
}
}
}
if (fallbackTags != null) {
filtered = filterSequences(type, fallbackTags, sequences);
}
}
if (filtered.isEmpty() && !tags.isEmpty()) {
filtered = filterSequences(type, EMPTY, sequences);
}
if (filtered.isEmpty()) {
// find tags
EnumSet<SecondaryTag> fallbackTags = null;
for (int i = 0, l = sequences.size(); i < l; i++) {
final Sequence sequence = sequences.get(i);
if (sequence.getPrimaryTags().contains(type)) {
if ((fallbackTags == null) || (sequence.getSecondaryTags().size() < fallbackTags.size())
|| ((sequence.getSecondaryTags().size() == fallbackTags.size())
&& (SecondaryTagSequenceComparator.getTagsOrdinal(sequence.getSecondaryTags(),
tags) > SecondaryTagSequenceComparator.getTagsOrdinal(fallbackTags,
tags)))) {
fallbackTags = sequence.getSecondaryTags();
}
}
}
if (fallbackTags != null) {
filtered = filterSequences(type, fallbackTags, sequences);
}
}
filtered.sort(sequenceComparator);
filtered.sort(sequenceComparator);
int i = 0;
final double randomRoll = Math.random() * 100;
for (final int l = filtered.size(); i < l; i++) {
final Sequence sequence = filtered.get(i).sequence;
final float rarity = sequence.getRarity();
int i = 0;
final double randomRoll = Math.random() * 100;
for (final int l = filtered.size(); i < l; i++) {
final Sequence sequence = filtered.get(i).sequence;
final float rarity = sequence.getRarity();
if (rarity == 0) {
break;
}
if (rarity == 0) {
break;
}
if ((randomRoll < (10 - rarity)) && allowRarityVariations) {
return filtered.get(i);
}
}
if ((randomRoll < (10 - rarity)) && allowRarityVariations) {
return filtered.get(i);
}
}
final int sequencesLeft = filtered.size() - i;
final int random = (int) (i + Math.floor(Math.random() * sequencesLeft));
if (sequencesLeft <= 0) {
return null; // new IndexedSequence(null, 0);
}
final IndexedSequence sequence = filtered.get(random);
final int sequencesLeft = filtered.size() - i;
final int random = (int) (i + Math.floor(Math.random() * sequencesLeft));
if (sequencesLeft <= 0) {
return null; // new IndexedSequence(null, 0);
}
final IndexedSequence sequence = filtered.get(random);
return sequence;
}
return sequence;
}
public static void randomStandSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("stand", sequences);
public static void randomStandSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("stand", sequences);
if (sequence != null) {
target.setSequence(sequence.index);
} else {
target.setSequence(0);
}
}
if (sequence != null) {
target.setSequence(sequence.index);
}
else {
target.setSequence(0);
}
}
public static void randomDeathSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("death", sequences);
public static void randomDeathSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("death", sequences);
if (sequence != null) {
target.setSequence(sequence.index);
} else {
target.setSequence(0);
}
}
if (sequence != null) {
target.setSequence(sequence.index);
}
else {
target.setSequence(0);
}
}
public static void randomWalkSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("walk", sequences);
public static void randomWalkSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("walk", sequences);
if (sequence != null) {
target.setSequence(sequence.index);
} else {
randomStandSequence(target);
}
}
if (sequence != null) {
target.setSequence(sequence.index);
}
else {
randomStandSequence(target);
}
}
public static void randomBirthSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("birth", sequences);
public static void randomBirthSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("birth", sequences);
if (sequence != null) {
target.setSequence(sequence.index);
} else {
randomStandSequence(target);
}
}
if (sequence != null) {
target.setSequence(sequence.index);
}
else {
randomStandSequence(target);
}
}
public static void randomPortraitSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("portrait", sequences);
public static void randomPortraitSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("portrait", sequences);
if (sequence != null) {
target.setSequence(sequence.index);
} else {
randomStandSequence(target);
}
}
if (sequence != null) {
target.setSequence(sequence.index);
}
else {
randomStandSequence(target);
}
}
public static void randomPortraitTalkSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("portrait talk", sequences);
public static void randomPortraitTalkSequence(final MdxComplexInstance target) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence("portrait talk", sequences);
if (sequence != null) {
target.setSequence(sequence.index);
} else {
randomPortraitSequence(target);
}
}
if (sequence != null) {
target.setSequence(sequence.index);
}
else {
randomPortraitSequence(target);
}
}
public static void randomSequence(final MdxComplexInstance target, final String sequenceName) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence(sequenceName, sequences);
public static void randomSequence(final MdxComplexInstance target, final String sequenceName) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence(sequenceName, sequences);
if (sequence != null) {
target.setSequence(sequence.index);
} else {
randomStandSequence(target);
}
}
if (sequence != null) {
target.setSequence(sequence.index);
}
else {
randomStandSequence(target);
}
}
public static Sequence randomSequence(final MdxComplexInstance target, final PrimaryTag animationName,
final boolean allowRarityVariations) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence(animationName, null, sequences,
allowRarityVariations);
public static Sequence randomSequence(final MdxComplexInstance target, final PrimaryTag animationName,
final boolean allowRarityVariations) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence(animationName, null, sequences, allowRarityVariations);
if (sequence != null) {
target.setSequence(sequence.index);
return sequence.sequence;
} else {
return null;
}
}
if (sequence != null) {
target.setSequence(sequence.index);
return sequence.sequence;
}
else {
return null;
}
}
public static Sequence randomSequence(final MdxComplexInstance target, final PrimaryTag animationName,
final EnumSet<SecondaryTag> secondaryAnimationTags, final boolean allowRarityVariations) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence(animationName, secondaryAnimationTags, sequences,
allowRarityVariations);
public static Sequence randomSequence(final MdxComplexInstance target, final PrimaryTag animationName,
final EnumSet<SecondaryTag> secondaryAnimationTags, final boolean allowRarityVariations) {
final MdxModel model = (MdxModel) target.model;
final List<Sequence> sequences = model.getSequences();
final IndexedSequence sequence = selectSequence(animationName, secondaryAnimationTags, sequences,
allowRarityVariations);
if (sequence != null) {
target.setSequence(sequence.index);
return sequence.sequence;
} else {
return null;
}
}
if (sequence != null) {
target.setSequence(sequence.index);
return sequence.sequence;
}
else {
return null;
}
}
public static Sequence randomSequence(final MdxComplexInstance target, final PrimaryTag animationName) {
return randomSequence(target, animationName, EMPTY, false);
}
public static Sequence randomSequence(final MdxComplexInstance target, final PrimaryTag animationName) {
return randomSequence(target, animationName, EMPTY, false);
}
}

View File

@ -60,7 +60,7 @@ public class Terrain {
private static final Vector3 normalHeap2 = new Vector3();
private static final float[] fourComponentHeap = new float[4];
private static final Matrix4 tempMatrix = new Matrix4();
private static final boolean WIREFRAME_TERRAIN = false;
private static final boolean WIREFRAME_TERRAIN = true;
public ShaderProgram groundShader;
public ShaderProgram waterShader;
@ -411,7 +411,8 @@ public class Terrain {
this.shaderMapBoundsRectangle = new Rectangle(this.shaderMapBounds[0], this.shaderMapBounds[1],
this.shaderMapBounds[2] - this.shaderMapBounds[0], this.shaderMapBounds[3] - this.shaderMapBounds[1]);
this.mapSize = w3eFile.getMapSize();
this.entireMapRectangle = new Rectangle(centerOffset[0], centerOffset[1], (mapSize[0] * 128f) - 128, (mapSize[1] * 128f) - 128);
this.entireMapRectangle = new Rectangle(this.centerOffset[0], this.centerOffset[1],
(this.mapSize[0] * 128f) - 128, (this.mapSize[1] * 128f) - 128);
this.softwareGroundMesh = new SoftwareGroundMesh(this.groundHeights, this.groundCornerHeights,
this.centerOffset, width, height);
@ -1402,6 +1403,6 @@ public class Terrain {
}
public Rectangle getEntireMap() {
return entireMapRectangle;
return this.entireMapRectangle;
}
}

View File

@ -137,10 +137,10 @@ public class RenderUnit {
}
public void populateCommandCard(final CSimulation game, final CommandButtonListener commandButtonListener,
final AbilityDataUI abilityDataUI) {
final AbilityDataUI abilityDataUI, final int subMenuOrderId) {
for (final CAbility ability : this.simulationUnit.getAbilities()) {
ability.visit(CommandCardPopulatingAbilityVisitor.INSTANCE.reset(game, this.simulationUnit,
commandButtonListener, abilityDataUI));
commandButtonListener, abilityDataUI, subMenuOrderId));
}
}
@ -405,15 +405,17 @@ public class RenderUnit {
final boolean allowRarityVariations) {
this.animationQueue.clear();
if (force || (animationName != this.currentAnimation)) {
this.currentAnimation = animationName;
this.currentAnimationSecondaryTags = secondaryAnimationTags;
this.currentSpeedRatio = speedRatio;
this.currentlyAllowingRarityVariations = allowRarityVariations;
this.recycleSet.clear();
this.recycleSet.addAll(this.secondaryAnimationTags);
this.recycleSet.addAll(secondaryAnimationTags);
this.instance.setAnimationSpeed(speedRatio);
SequenceUtils.randomSequence(this.instance, animationName, this.recycleSet, allowRarityVariations);
if (SequenceUtils.randomSequence(this.instance, animationName, this.recycleSet,
allowRarityVariations) != null) {
this.currentAnimation = animationName;
this.currentAnimationSecondaryTags = secondaryAnimationTags;
this.currentlyAllowingRarityVariations = allowRarityVariations;
}
}
}
@ -422,15 +424,15 @@ public class RenderUnit {
final boolean allowRarityVariations) {
this.animationQueue.clear();
if (force || (animationName != this.currentAnimation)) {
this.currentAnimation = animationName;
this.currentAnimationSecondaryTags = secondaryAnimationTags;
this.currentlyAllowingRarityVariations = allowRarityVariations;
this.recycleSet.clear();
this.recycleSet.addAll(this.secondaryAnimationTags);
this.recycleSet.addAll(secondaryAnimationTags);
final Sequence sequence = SequenceUtils.randomSequence(this.instance, animationName, this.recycleSet,
allowRarityVariations);
if (sequence != null) {
this.currentAnimation = animationName;
this.currentAnimationSecondaryTags = secondaryAnimationTags;
this.currentlyAllowingRarityVariations = allowRarityVariations;
this.currentSpeedRatio = ((sequence.getInterval()[1] - sequence.getInterval()[0]) / 1000.0f)
/ duration;
this.instance.setAnimationSpeed(this.currentSpeedRatio);

View File

@ -22,15 +22,27 @@ public class AbilityDataUI {
private static final War3ID ICON_RESEARCH_X = War3ID.fromString("arpx");
private static final War3ID ICON_RESEARCH_Y = War3ID.fromString("arpy");
private static final War3ID UNIT_ICON_NORMAL_X = War3ID.fromString("ubpx");
private static final War3ID UNIT_ICON_NORMAL_Y = War3ID.fromString("ubpy");
private static final War3ID UNIT_ICON_NORMAL = War3ID.fromString("uico");
private final Map<War3ID, AbilityIconUI> rawcodeToUI = new HashMap<>();
private final Map<War3ID, IconUI> rawcodeToUnitUI = new HashMap<>();
private final IconUI moveUI;
private final IconUI stopUI;
private final IconUI holdPosUI;
private final IconUI patrolUI;
private final IconUI attackUI;
private final IconUI attackGroundUI;
private final IconUI buildHumanUI;
private final IconUI buildOrcUI;
private final IconUI buildNightElfUI;
private final IconUI buildUndeadUI;
private final IconUI buildNeutralUI;
private final IconUI buildNagaUI;
private final IconUI cancelUI;
public AbilityDataUI(final MutableObjectData abilityData, final GameUI gameUI) {
public AbilityDataUI(final MutableObjectData abilityData, final MutableObjectData unitData, final GameUI gameUI) {
final String disabledPrefix = gameUI.getSkinField("CommandButtonDisabledArtPath");
for (final War3ID alias : abilityData.keySet()) {
final MutableGameObject abilityTypeData = abilityData.get(alias);
@ -54,12 +66,28 @@ public class AbilityDataUI {
new IconUI(iconNormal, iconNormalDisabled, iconNormalX, iconNormalY),
new IconUI(iconTurnOff, iconTurnOffDisabled, iconTurnOffX, iconTurnOffY)));
}
for (final War3ID alias : unitData.keySet()) {
final MutableGameObject abilityTypeData = unitData.get(alias);
final String iconNormalPath = gameUI.trySkinField(abilityTypeData.getFieldAsString(UNIT_ICON_NORMAL, 0));
final int iconNormalX = abilityTypeData.getFieldAsInteger(UNIT_ICON_NORMAL_X, 0);
final int iconNormalY = abilityTypeData.getFieldAsInteger(UNIT_ICON_NORMAL_Y, 0);
final Texture iconNormal = gameUI.loadTexture(iconNormalPath);
final Texture iconNormalDisabled = gameUI.loadTexture(disable(iconNormalPath, disabledPrefix));
this.rawcodeToUnitUI.put(alias, new IconUI(iconNormal, iconNormalDisabled, iconNormalX, iconNormalY));
}
this.moveUI = createBuiltInIconUI(gameUI, "CmdMove", disabledPrefix);
this.stopUI = createBuiltInIconUI(gameUI, "CmdStop", disabledPrefix);
this.holdPosUI = createBuiltInIconUI(gameUI, "CmdHoldPos", disabledPrefix);
this.patrolUI = createBuiltInIconUI(gameUI, "CmdPatrol", disabledPrefix);
this.attackUI = createBuiltInIconUI(gameUI, "CmdAttack", disabledPrefix);
this.buildHumanUI = createBuiltInIconUI(gameUI, "CmdBuildHuman", disabledPrefix);
this.buildOrcUI = createBuiltInIconUI(gameUI, "CmdBuildOrc", disabledPrefix);
this.buildNightElfUI = createBuiltInIconUI(gameUI, "CmdBuildNightElf", disabledPrefix);
this.buildUndeadUI = createBuiltInIconUI(gameUI, "CmdBuildUndead", disabledPrefix);
this.buildNagaUI = createBuiltInIconUI(gameUI, "CmdBuildNaga", disabledPrefix);
this.buildNeutralUI = createBuiltInIconUI(gameUI, "CmdBuild", disabledPrefix);
this.attackGroundUI = createBuiltInIconUI(gameUI, "CmdAttackGround", disabledPrefix);
this.cancelUI = createBuiltInIconUI(gameUI, "CmdCancel", disabledPrefix);
}
private IconUI createBuiltInIconUI(final GameUI gameUI, final String key, final String disabledPrefix) {
@ -76,6 +104,10 @@ public class AbilityDataUI {
return this.rawcodeToUI.get(rawcode);
}
public IconUI getUnitUI(final War3ID rawcode) {
return this.rawcodeToUnitUI.get(rawcode);
}
private static String disable(final String path, final String disabledPrefix) {
final int slashIndex = path.lastIndexOf('\\');
String name = path;
@ -109,4 +141,32 @@ public class AbilityDataUI {
return this.attackGroundUI;
}
public IconUI getBuildHumanUI() {
return this.buildHumanUI;
}
public IconUI getBuildNightElfUI() {
return this.buildNightElfUI;
}
public IconUI getBuildOrcUI() {
return this.buildOrcUI;
}
public IconUI getBuildUndeadUI() {
return this.buildUndeadUI;
}
public IconUI getBuildNagaUI() {
return this.buildNagaUI;
}
public IconUI getBuildNeutralUI() {
return this.buildNeutralUI;
}
public IconUI getCancelUI() {
return this.cancelUI;
}
}

View File

@ -35,5 +35,5 @@ public interface CommandButtonListener {
//
// int getOrderId();
void commandButton(int buttonPositionX, int buttonPositionY, Texture icon, int abilityHandleId, int orderId,
int autoCastOrderId, boolean active, boolean autoCastActive);
int autoCastOrderId, boolean active, boolean autoCastActive, boolean menuButton);
}

View File

@ -1,85 +1,158 @@
package com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityGeneric;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.AbstractCAbilityBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityHumanBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNagaBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNeutralBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNightElfBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityOrcBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityUndeadBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CommandCardPopulatingAbilityVisitor implements CAbilityVisitor<Void> {
public static final CommandCardPopulatingAbilityVisitor INSTANCE = new CommandCardPopulatingAbilityVisitor();
public static final CommandCardPopulatingAbilityVisitor INSTANCE = new CommandCardPopulatingAbilityVisitor();
private CSimulation game;
private CUnit unit;
private CSimulation game;
private CUnit unit;
private CommandButtonListener commandButtonListener;
private AbilityDataUI abilityDataUI;
private int menuBaseOrderId;
private boolean hasStop;
private CommandButtonListener commandButtonListener;
private AbilityDataUI abilityDataUI;
private boolean hasStop;
public CommandCardPopulatingAbilityVisitor reset(final CSimulation game, final CUnit unit,
final CommandButtonListener commandButtonListener, final AbilityDataUI abilityDataUI,
final int menuBaseOrderId) {
this.game = game;
this.unit = unit;
this.commandButtonListener = commandButtonListener;
this.abilityDataUI = abilityDataUI;
this.menuBaseOrderId = menuBaseOrderId;
this.hasStop = false;
return this;
}
public CommandCardPopulatingAbilityVisitor reset(final CSimulation game, final CUnit unit,
final CommandButtonListener commandButtonListener, final AbilityDataUI abilityDataUI) {
this.game = game;
this.unit = unit;
this.commandButtonListener = commandButtonListener;
this.abilityDataUI = abilityDataUI;
this.hasStop = false;
return this;
}
@Override
public Void accept(final CAbilityAttack ability) {
if (this.menuBaseOrderId == 0) {
addCommandButton(ability, this.abilityDataUI.getAttackUI(), ability.getHandleId(), OrderIds.attack, 0,
false, false);
if (!this.hasStop) {
this.hasStop = true;
addCommandButton(null, this.abilityDataUI.getStopUI(), 0, OrderIds.stop, 0, false, false);
}
}
return null;
}
@Override
public Void accept(final CAbilityAttack ability) {
addCommandButton(ability, this.abilityDataUI.getAttackUI(), ability.getHandleId(), OrderIds.attack, 0, false);
if (!this.hasStop) {
this.hasStop = true;
addCommandButton(null, this.abilityDataUI.getStopUI(), 0, OrderIds.stop, 0, false);
}
return null;
}
@Override
public Void accept(final CAbilityMove ability) {
if (this.menuBaseOrderId == 0) {
addCommandButton(ability, this.abilityDataUI.getMoveUI(), ability.getHandleId(), OrderIds.move, 0, false,
false);
addCommandButton(ability, this.abilityDataUI.getHoldPosUI(), ability.getHandleId(), OrderIds.holdposition,
0, false, false);
addCommandButton(ability, this.abilityDataUI.getPatrolUI(), ability.getHandleId(), OrderIds.patrol, 0,
false, false);
if (!this.hasStop) {
this.hasStop = true;
addCommandButton(null, this.abilityDataUI.getStopUI(), 0, OrderIds.stop, 0, false, false);
}
}
return null;
}
@Override
public Void accept(final CAbilityMove ability) {
addCommandButton(ability, this.abilityDataUI.getMoveUI(), ability.getHandleId(), OrderIds.move, 0, false);
addCommandButton(ability, this.abilityDataUI.getHoldPosUI(), ability.getHandleId(), OrderIds.holdposition, 0,
false);
addCommandButton(ability, this.abilityDataUI.getPatrolUI(), ability.getHandleId(), OrderIds.patrol, 0, false);
if (!this.hasStop) {
this.hasStop = true;
addCommandButton(null, this.abilityDataUI.getStopUI(), 0, OrderIds.stop, 0, false);
}
return null;
}
@Override
public Void accept(final CAbilityGeneric ability) {
if (this.menuBaseOrderId == 0) {
addCommandButton(ability, this.abilityDataUI.getUI(ability.getRawcode()).getOnIconUI(),
ability.getHandleId(), 0, 0, false, false);
}
return null;
}
@Override
public Void accept(final CAbilityGeneric ability) {
addCommandButton(ability, this.abilityDataUI.getUI(ability.getRawcode()).getOnIconUI(), ability.getHandleId(),
OrderIds.channel, 0, false);
return null;
}
@Override
public Void accept(final CAbilityColdArrows ability) {
if (this.menuBaseOrderId == 0) {
final boolean autoCastActive = ability.isAutoCastActive();
int autoCastId;
if (autoCastActive) {
autoCastId = OrderIds.coldarrows;
}
else {
autoCastId = OrderIds.uncoldarrows;
}
addCommandButton(ability, this.abilityDataUI.getUI(ability.getRawcode()).getOnIconUI(),
ability.getHandleId(), OrderIds.coldarrowstarg, autoCastId, autoCastActive, false);
}
return null;
}
@Override
public Void accept(final CAbilityColdArrows ability) {
final boolean autoCastActive = ability.isAutoCastActive();
int autoCastId;
if (autoCastActive) {
autoCastId = OrderIds.coldarrows;
} else {
autoCastId = OrderIds.uncoldarrows;
}
addCommandButton(ability, this.abilityDataUI.getUI(ability.getRawcode()).getOnIconUI(), ability.getHandleId(),
OrderIds.coldarrowstarg, autoCastId, autoCastActive);
return null;
}
@Override
public Void accept(final CAbilityOrcBuild ability) {
handleBuildMenu(ability, this.abilityDataUI.getBuildOrcUI());
return null;
}
private void addCommandButton(final CAbility ability, final IconUI iconUI, final int handleId, final int orderId,
final int autoCastOrderId, final boolean autoCastActive) {
final boolean active = (this.unit.getCurrentBehavior() != null && orderId == this.unit.getCurrentBehavior().getHighlightOrderId());
this.commandButtonListener.commandButton(iconUI.getButtonPositionX(), iconUI.getButtonPositionY(),
iconUI.getIcon(), handleId, orderId, autoCastOrderId, active, autoCastActive);
}
@Override
public Void accept(final CAbilityHumanBuild ability) {
handleBuildMenu(ability, this.abilityDataUI.getBuildHumanUI());
return null;
}
@Override
public Void accept(final CAbilityNightElfBuild ability) {
handleBuildMenu(ability, this.abilityDataUI.getBuildNightElfUI());
return null;
}
@Override
public Void accept(final CAbilityUndeadBuild ability) {
handleBuildMenu(ability, this.abilityDataUI.getBuildUndeadUI());
return null;
}
@Override
public Void accept(final CAbilityNagaBuild ability) {
handleBuildMenu(ability, this.abilityDataUI.getBuildNagaUI());
return null;
}
@Override
public Void accept(final CAbilityNeutralBuild ability) {
handleBuildMenu(ability, this.abilityDataUI.getBuildNeutralUI());
return null;
}
private void handleBuildMenu(final AbstractCAbilityBuild ability, final IconUI buildUI) {
if (this.menuBaseOrderId == ability.getBaseOrderId()) {
for (final War3ID unitType : ability.getStructuresBuilt()) {
final IconUI unitUI = this.abilityDataUI.getUnitUI(unitType);
if (unitUI != null) {
addCommandButton(ability, unitUI, ability.getHandleId(), unitType.getValue(), 0, false, false);
}
}
}
else {
addCommandButton(ability, buildUI, ability.getHandleId(), ability.getBaseOrderId(), 0, false, true);
}
}
private void addCommandButton(final CAbility ability, final IconUI iconUI, final int handleId, final int orderId,
final int autoCastOrderId, final boolean autoCastActive, final boolean menuButton) {
final boolean active = ((this.unit.getCurrentBehavior() != null)
&& (orderId == this.unit.getCurrentBehavior().getHighlightOrderId()));
this.commandButtonListener.commandButton(iconUI.getButtonPositionX(), iconUI.getButtonPositionY(),
iconUI.getIcon(), handleId, orderId, autoCastOrderId, active, autoCastActive, menuButton);
}
}

View File

@ -4,11 +4,13 @@ import java.awt.image.BufferedImage;
import java.util.EnumSet;
import java.util.List;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.MovementType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CDefenseType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.data.CUnitRace;
/**
* The quick (symbol table instead of map) lookup for unit type values that we
@ -35,13 +37,19 @@ public class CUnitType {
private final EnumSet<CTargetType> targetedAs;
private final float defaultAcquisitionRange;
private final float minimumAttackRange;
private final List<War3ID> structuresBuilt;
private final CUnitRace unitRace;
private final int goldCost;
private final int lumberCost;
private final int buildTime;
public CUnitType(final String name, final boolean isBldg, final MovementType movementType,
final float defaultFlyingHeight, final float collisionSize,
final EnumSet<CUnitClassification> classifications, final List<CUnitAttack> attacks, final String armorType,
final boolean raise, final boolean decay, final CDefenseType defenseType, final float impactZ,
final BufferedImage buildingPathingPixelMap, final float deathTime, final EnumSet<CTargetType> targetedAs,
final float defaultAcquisitionRange, final float minimumAttackRange) {
final float defaultAcquisitionRange, final float minimumAttackRange, final List<War3ID> structuresBuilt,
final CUnitRace unitRace, final int goldCost, final int lumberCost, final int buildTime) {
this.name = name;
this.building = isBldg;
this.movementType = movementType;
@ -59,6 +67,11 @@ public class CUnitType {
this.targetedAs = targetedAs;
this.defaultAcquisitionRange = defaultAcquisitionRange;
this.minimumAttackRange = minimumAttackRange;
this.structuresBuilt = structuresBuilt;
this.unitRace = unitRace;
this.goldCost = goldCost;
this.lumberCost = lumberCost;
this.buildTime = buildTime;
}
public String getName() {
@ -128,4 +141,24 @@ public class CUnitType {
public float getMinimumAttackRange() {
return this.minimumAttackRange;
}
public List<War3ID> getStructuresBuilt() {
return this.structuresBuilt;
}
public CUnitRace getRace() {
return this.unitRace;
}
public int getGoldCost() {
return this.goldCost;
}
public int getLumberCost() {
return this.lumberCost;
}
public int getBuildTime() {
return this.buildTime;
}
}

View File

@ -0,0 +1,14 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities;
public abstract class AbstractCAbility implements CAbility {
private final int handleId;
public AbstractCAbility(final int handleId) {
this.handleId = handleId;
}
@Override
public final int getHandleId() {
return this.handleId;
}
}

View File

@ -1,5 +1,13 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityHumanBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNagaBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNeutralBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNightElfBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityOrcBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityUndeadBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
/**
* A visitor for the lowest level inherent types of an ability. It's a bit of a
* design clash to have the notion of an ability visitor pattern while also
@ -13,7 +21,19 @@ public interface CAbilityVisitor<T> {
T accept(CAbilityMove ability);
T accept(CAbilityOrcBuild ability);
T accept(CAbilityHumanBuild ability);
T accept(CAbilityUndeadBuild ability);
T accept(CAbilityNightElfBuild ability);
T accept(CAbilityGeneric ability);
T accept(CAbilityColdArrows ability);
T accept(CAbilityNagaBuild ability);
T accept(CAbilityNeutralBuild ability);
}

View File

@ -0,0 +1,78 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.AbstractCAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.menu.CAbilityMenu;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
public abstract class AbstractCAbilityBuild extends AbstractCAbility implements CAbilityMenu {
private final Set<War3ID> structuresBuilt;
public AbstractCAbilityBuild(final int handleId, final List<War3ID> structuresBuilt) {
super(handleId);
this.structuresBuilt = new LinkedHashSet<>(structuresBuilt);
}
public Collection<War3ID> getStructuresBuilt() {
return this.structuresBuilt;
}
@Override
public void checkCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
final CUnitType unitType = game.getUnitData().getUnitType(new War3ID(orderId));
if (unitType != null) {
final CPlayer player = game.getPlayer(unit.getPlayerIndex());
if (player.getGold() >= unitType.getGoldCost()) {
if (player.getLumber() >= unitType.getLumberCost()) {
receiver.useOk();
}
else {
receiver.notEnoughResources(ResourceType.LUMBER);
}
}
else {
receiver.notEnoughResources(ResourceType.GOLD);
}
}
else {
receiver.useOk();
}
}
@Override
public final void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
final AbilityTargetCheckReceiver<CWidget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public final void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final Vector2 target,
final AbilityTargetCheckReceiver<Vector2> receiver) {
if (this.structuresBuilt.contains(new War3ID(orderId))) {
receiver.targetOk(target);
}
else {
receiver.orderIdNotAccepted();
}
}
@Override
public final void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
receiver.orderIdNotAccepted();
}
}

View File

@ -0,0 +1,61 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.util.List;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CAbilityHumanBuild extends AbstractCAbilityBuild {
public CAbilityHumanBuild(final int handleId, final List<War3ID> structuresBuilt) {
super(handleId, structuresBuilt);
// TODO Auto-generated constructor stub
}
@Override
public int getBaseOrderId() {
return OrderIds.humanbuild;
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
// TODO Auto-generated method stub
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
// TODO Auto-generated method stub
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final Vector2 point) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> T visit(final CAbilityVisitor<T> visitor) {
return visitor.accept(this);
}
}

View File

@ -0,0 +1,53 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.util.List;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CAbilityNagaBuild extends AbstractCAbilityBuild {
public CAbilityNagaBuild(final int handleId, final List<War3ID> structuresBuilt) {
super(handleId, structuresBuilt);
}
@Override
public <T> T visit(final CAbilityVisitor<T> visitor) {
return visitor.accept(this);
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return caster.pollNextOrderBehavior(game);
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final Vector2 point) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return caster.pollNextOrderBehavior(game);
}
@Override
public int getBaseOrderId() {
return OrderIds.nagabuild;
}
}

View File

@ -0,0 +1,53 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.util.List;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CAbilityNeutralBuild extends AbstractCAbilityBuild {
public CAbilityNeutralBuild(final int handleId, final List<War3ID> structuresBuilt) {
super(handleId, structuresBuilt);
}
@Override
public <T> T visit(final CAbilityVisitor<T> visitor) {
return visitor.accept(this);
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return caster.pollNextOrderBehavior(game);
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final Vector2 point) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return caster.pollNextOrderBehavior(game);
}
@Override
public int getBaseOrderId() {
return OrderIds.buildmenu;
}
}

View File

@ -0,0 +1,61 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.util.List;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CAbilityNightElfBuild extends AbstractCAbilityBuild {
public CAbilityNightElfBuild(final int handleId, final List<War3ID> structuresBuilt) {
super(handleId, structuresBuilt);
// TODO Auto-generated constructor stub
}
@Override
public int getBaseOrderId() {
return OrderIds.nightelfbuild;
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
// TODO Auto-generated method stub
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
// TODO Auto-generated method stub
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final Vector2 point) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> T visit(final CAbilityVisitor<T> visitor) {
return visitor.accept(this);
}
}

View File

@ -0,0 +1,53 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.util.List;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CAbilityOrcBuild extends AbstractCAbilityBuild {
public CAbilityOrcBuild(final int handleId, final List<War3ID> structuresBuilt) {
super(handleId, structuresBuilt);
}
@Override
public <T> T visit(final CAbilityVisitor<T> visitor) {
return visitor.accept(this);
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return caster.pollNextOrderBehavior(game);
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final Vector2 point) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return caster.pollNextOrderBehavior(game);
}
@Override
public int getBaseOrderId() {
return OrderIds.orcbuild;
}
}

View File

@ -0,0 +1,61 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build;
import java.util.List;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
public class CAbilityUndeadBuild extends AbstractCAbilityBuild {
public CAbilityUndeadBuild(final int handleId, final List<War3ID> structuresBuilt) {
super(handleId, structuresBuilt);
// TODO Auto-generated constructor stub
}
@Override
public int getBaseOrderId() {
return OrderIds.undeadbuild;
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
// TODO Auto-generated method stub
}
@Override
public void onRemove(final CSimulation game, final CUnit unit) {
// TODO Auto-generated method stub
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final Vector2 point) {
// TODO Auto-generated method stub
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> T visit(final CAbilityVisitor<T> visitor) {
return visitor.accept(this);
}
}

View File

@ -1,10 +1,12 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities;
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat;
import com.badlogic.gdx.math.Vector2;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;

View File

@ -0,0 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.menu;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
public interface CAbilityMenu extends CAbility {
// the base order ID of the menu
int getBaseOrderId();
}

View File

@ -32,18 +32,18 @@ public class CBehaviorMove implements CBehavior {
private CUnit followUnit;
private CRangedBehavior rangedBehavior;
public CBehaviorMove reset(int highlightOrderId, final float targetX, final float targetY) {
public CBehaviorMove reset(final int highlightOrderId, final float targetX, final float targetY) {
internalResetMove(highlightOrderId, targetX, targetY);
this.rangedBehavior = null;
return this;
}
private void internalResetMove(int highlightOrderId, final float targetX, final float targetY) {
private void internalResetMove(final int highlightOrderId, final float targetX, final float targetY) {
this.highlightOrderId = highlightOrderId;
this.wasWithinPropWindow = false;
this.gridMapping = CPathfindingProcessor.isCollisionSizeBetterSuitedForCorners(
this.unit.getUnitType().getCollisionSize()) ? CPathfindingProcessor.GridMapping.CORNERS
: CPathfindingProcessor.GridMapping.CELLS;
: CPathfindingProcessor.GridMapping.CELLS;
this.target = new Point2D.Float(targetX, targetY);
this.path = null;
this.searchCycles = 0;
@ -56,26 +56,19 @@ public class CBehaviorMove implements CBehavior {
return this;
}
public CBehaviorMove reset(int highlightOrderId, final CUnit followUnit) {
public CBehaviorMove reset(final int highlightOrderId, final CUnit followUnit) {
internalResetMove(highlightOrderId, followUnit);
this.rangedBehavior = null;
return this;
}
public CBehaviorMove reset(final CUnit followUnit, final CRangedBehavior rangedBehavior) {
this.wasWithinPropWindow = false;
this.gridMapping = CPathfindingProcessor.isCollisionSizeBetterSuitedForCorners(
this.unit.getUnitType().getCollisionSize()) ? CPathfindingProcessor.GridMapping.CORNERS
: CPathfindingProcessor.GridMapping.CELLS;
this.target = new Point2D.Float(followUnit.getX(), followUnit.getY());
this.path = null;
this.searchCycles = 0;
this.followUnit = followUnit;
internalResetMove(rangedBehavior.getHighlightOrderId(), followUnit);
this.rangedBehavior = rangedBehavior;
return this;
}
private void internalResetMove(int highlightOrderId, CUnit followUnit) {
private void internalResetMove(final int highlightOrderId, final CUnit followUnit) {
this.highlightOrderId = highlightOrderId;
this.wasWithinPropWindow = false;
this.gridMapping = CPathfindingProcessor.isCollisionSizeBetterSuitedForCorners(
@ -89,7 +82,7 @@ public class CBehaviorMove implements CBehavior {
@Override
public int getHighlightOrderId() {
return highlightOrderId;
return this.highlightOrderId;
}
@Override

View File

@ -3,8 +3,8 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.data;
import com.etheller.warsmash.units.manager.MutableObjectData;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityGeneric;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
public class CAbilityData {
private static final War3ID COLD_ARROWS = War3ID.fromString("ACcw");

View File

@ -18,6 +18,12 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.HandleIdAllocator;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityAttack;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityMove;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityHumanBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNagaBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNeutralBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNightElfBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityOrcBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityUndeadBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CDefenseType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
@ -32,410 +38,479 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUni
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.SimulationRenderController;
public class CUnitData {
private static final War3ID MANA_INITIAL_AMOUNT = War3ID.fromString("umpi");
private static final War3ID MANA_MAXIMUM = War3ID.fromString("umpm");
private static final War3ID HIT_POINT_MAXIMUM = War3ID.fromString("uhpm");
private static final War3ID MOVEMENT_SPEED_BASE = War3ID.fromString("umvs");
private static final War3ID PROPULSION_WINDOW = War3ID.fromString("uprw");
private static final War3ID TURN_RATE = War3ID.fromString("umvr");
private static final War3ID IS_BLDG = War3ID.fromString("ubdg");
private static final War3ID NAME = War3ID.fromString("unam");
private static final War3ID PROJECTILE_LAUNCH_X = War3ID.fromString("ulpx");
private static final War3ID PROJECTILE_LAUNCH_Y = War3ID.fromString("ulpy");
private static final War3ID PROJECTILE_LAUNCH_Z = War3ID.fromString("ulpz");
private static final War3ID ATTACKS_ENABLED = War3ID.fromString("uaen");
private static final War3ID ATTACK1_BACKSWING_POINT = War3ID.fromString("ubs1");
private static final War3ID ATTACK1_DAMAGE_POINT = War3ID.fromString("udp1");
private static final War3ID ATTACK1_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua1f");
private static final War3ID ATTACK1_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua1h");
private static final War3ID ATTACK1_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua1q");
private static final War3ID ATTACK1_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua1p");
private static final War3ID ATTACK1_ATTACK_TYPE = War3ID.fromString("ua1t");
private static final War3ID ATTACK1_COOLDOWN = War3ID.fromString("ua1c");
private static final War3ID ATTACK1_DMG_BASE = War3ID.fromString("ua1b");
private static final War3ID ATTACK1_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd1");
private static final War3ID ATTACK1_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd1");
private static final War3ID ATTACK1_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl1");
private static final War3ID ATTACK1_DMG_DICE = War3ID.fromString("ua1d");
private static final War3ID ATTACK1_DMG_SIDES_PER_DIE = War3ID.fromString("ua1s");
private static final War3ID ATTACK1_DMG_SPILL_DIST = War3ID.fromString("usd1");
private static final War3ID ATTACK1_DMG_SPILL_RADIUS = War3ID.fromString("usr1");
private static final War3ID ATTACK1_DMG_UPGRADE_AMT = War3ID.fromString("udu1");
private static final War3ID ATTACK1_TARGET_COUNT = War3ID.fromString("utc1");
private static final War3ID ATTACK1_PROJECTILE_ARC = War3ID.fromString("uma1");
private static final War3ID ATTACK1_MISSILE_ART = War3ID.fromString("ua1m");
private static final War3ID ATTACK1_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh1");
private static final War3ID ATTACK1_PROJECTILE_SPEED = War3ID.fromString("ua1z");
private static final War3ID ATTACK1_RANGE = War3ID.fromString("ua1r");
private static final War3ID ATTACK1_RANGE_MOTION_BUFFER = War3ID.fromString("urb1");
private static final War3ID ATTACK1_SHOW_UI = War3ID.fromString("uwu1");
private static final War3ID ATTACK1_TARGETS_ALLOWED = War3ID.fromString("ua1g");
private static final War3ID ATTACK1_WEAPON_SOUND = War3ID.fromString("ucs1");
private static final War3ID ATTACK1_WEAPON_TYPE = War3ID.fromString("ua1w");
private static final War3ID MANA_INITIAL_AMOUNT = War3ID.fromString("umpi");
private static final War3ID MANA_MAXIMUM = War3ID.fromString("umpm");
private static final War3ID HIT_POINT_MAXIMUM = War3ID.fromString("uhpm");
private static final War3ID MOVEMENT_SPEED_BASE = War3ID.fromString("umvs");
private static final War3ID PROPULSION_WINDOW = War3ID.fromString("uprw");
private static final War3ID TURN_RATE = War3ID.fromString("umvr");
private static final War3ID IS_BLDG = War3ID.fromString("ubdg");
private static final War3ID NAME = War3ID.fromString("unam");
private static final War3ID PROJECTILE_LAUNCH_X = War3ID.fromString("ulpx");
private static final War3ID PROJECTILE_LAUNCH_Y = War3ID.fromString("ulpy");
private static final War3ID PROJECTILE_LAUNCH_Z = War3ID.fromString("ulpz");
private static final War3ID ATTACKS_ENABLED = War3ID.fromString("uaen");
private static final War3ID ATTACK1_BACKSWING_POINT = War3ID.fromString("ubs1");
private static final War3ID ATTACK1_DAMAGE_POINT = War3ID.fromString("udp1");
private static final War3ID ATTACK1_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua1f");
private static final War3ID ATTACK1_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua1h");
private static final War3ID ATTACK1_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua1q");
private static final War3ID ATTACK1_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua1p");
private static final War3ID ATTACK1_ATTACK_TYPE = War3ID.fromString("ua1t");
private static final War3ID ATTACK1_COOLDOWN = War3ID.fromString("ua1c");
private static final War3ID ATTACK1_DMG_BASE = War3ID.fromString("ua1b");
private static final War3ID ATTACK1_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd1");
private static final War3ID ATTACK1_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd1");
private static final War3ID ATTACK1_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl1");
private static final War3ID ATTACK1_DMG_DICE = War3ID.fromString("ua1d");
private static final War3ID ATTACK1_DMG_SIDES_PER_DIE = War3ID.fromString("ua1s");
private static final War3ID ATTACK1_DMG_SPILL_DIST = War3ID.fromString("usd1");
private static final War3ID ATTACK1_DMG_SPILL_RADIUS = War3ID.fromString("usr1");
private static final War3ID ATTACK1_DMG_UPGRADE_AMT = War3ID.fromString("udu1");
private static final War3ID ATTACK1_TARGET_COUNT = War3ID.fromString("utc1");
private static final War3ID ATTACK1_PROJECTILE_ARC = War3ID.fromString("uma1");
private static final War3ID ATTACK1_MISSILE_ART = War3ID.fromString("ua1m");
private static final War3ID ATTACK1_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh1");
private static final War3ID ATTACK1_PROJECTILE_SPEED = War3ID.fromString("ua1z");
private static final War3ID ATTACK1_RANGE = War3ID.fromString("ua1r");
private static final War3ID ATTACK1_RANGE_MOTION_BUFFER = War3ID.fromString("urb1");
private static final War3ID ATTACK1_SHOW_UI = War3ID.fromString("uwu1");
private static final War3ID ATTACK1_TARGETS_ALLOWED = War3ID.fromString("ua1g");
private static final War3ID ATTACK1_WEAPON_SOUND = War3ID.fromString("ucs1");
private static final War3ID ATTACK1_WEAPON_TYPE = War3ID.fromString("ua1w");
private static final War3ID ATTACK2_BACKSWING_POINT = War3ID.fromString("ubs2");
private static final War3ID ATTACK2_DAMAGE_POINT = War3ID.fromString("udp2");
private static final War3ID ATTACK2_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua2f");
private static final War3ID ATTACK2_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua2h");
private static final War3ID ATTACK2_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua2q");
private static final War3ID ATTACK2_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua2p");
private static final War3ID ATTACK2_ATTACK_TYPE = War3ID.fromString("ua2t");
private static final War3ID ATTACK2_COOLDOWN = War3ID.fromString("ua2c");
private static final War3ID ATTACK2_DMG_BASE = War3ID.fromString("ua2b");
private static final War3ID ATTACK2_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd2");
private static final War3ID ATTACK2_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd2");
private static final War3ID ATTACK2_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl2");
private static final War3ID ATTACK2_DMG_DICE = War3ID.fromString("ua2d");
private static final War3ID ATTACK2_DMG_SIDES_PER_DIE = War3ID.fromString("ua2s");
private static final War3ID ATTACK2_DMG_SPILL_DIST = War3ID.fromString("usd2");
private static final War3ID ATTACK2_DMG_SPILL_RADIUS = War3ID.fromString("usr2");
private static final War3ID ATTACK2_DMG_UPGRADE_AMT = War3ID.fromString("udu2");
private static final War3ID ATTACK2_TARGET_COUNT = War3ID.fromString("utc2");
private static final War3ID ATTACK2_PROJECTILE_ARC = War3ID.fromString("uma2");
private static final War3ID ATTACK2_MISSILE_ART = War3ID.fromString("ua2m");
private static final War3ID ATTACK2_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh2");
private static final War3ID ATTACK2_PROJECTILE_SPEED = War3ID.fromString("ua2z");
private static final War3ID ATTACK2_RANGE = War3ID.fromString("ua2r");
private static final War3ID ATTACK2_RANGE_MOTION_BUFFER = War3ID.fromString("urb2");
private static final War3ID ATTACK2_SHOW_UI = War3ID.fromString("uwu2");
private static final War3ID ATTACK2_TARGETS_ALLOWED = War3ID.fromString("ua2g");
private static final War3ID ATTACK2_WEAPON_SOUND = War3ID.fromString("ucs2");
private static final War3ID ATTACK2_WEAPON_TYPE = War3ID.fromString("ua2w");
private static final War3ID ATTACK2_BACKSWING_POINT = War3ID.fromString("ubs2");
private static final War3ID ATTACK2_DAMAGE_POINT = War3ID.fromString("udp2");
private static final War3ID ATTACK2_AREA_OF_EFFECT_FULL_DMG = War3ID.fromString("ua2f");
private static final War3ID ATTACK2_AREA_OF_EFFECT_HALF_DMG = War3ID.fromString("ua2h");
private static final War3ID ATTACK2_AREA_OF_EFFECT_QUARTER_DMG = War3ID.fromString("ua2q");
private static final War3ID ATTACK2_AREA_OF_EFFECT_TARGETS = War3ID.fromString("ua2p");
private static final War3ID ATTACK2_ATTACK_TYPE = War3ID.fromString("ua2t");
private static final War3ID ATTACK2_COOLDOWN = War3ID.fromString("ua2c");
private static final War3ID ATTACK2_DMG_BASE = War3ID.fromString("ua2b");
private static final War3ID ATTACK2_DAMAGE_FACTOR_HALF = War3ID.fromString("uhd2");
private static final War3ID ATTACK2_DAMAGE_FACTOR_QUARTER = War3ID.fromString("uqd2");
private static final War3ID ATTACK2_DAMAGE_LOSS_FACTOR = War3ID.fromString("udl2");
private static final War3ID ATTACK2_DMG_DICE = War3ID.fromString("ua2d");
private static final War3ID ATTACK2_DMG_SIDES_PER_DIE = War3ID.fromString("ua2s");
private static final War3ID ATTACK2_DMG_SPILL_DIST = War3ID.fromString("usd2");
private static final War3ID ATTACK2_DMG_SPILL_RADIUS = War3ID.fromString("usr2");
private static final War3ID ATTACK2_DMG_UPGRADE_AMT = War3ID.fromString("udu2");
private static final War3ID ATTACK2_TARGET_COUNT = War3ID.fromString("utc2");
private static final War3ID ATTACK2_PROJECTILE_ARC = War3ID.fromString("uma2");
private static final War3ID ATTACK2_MISSILE_ART = War3ID.fromString("ua2m");
private static final War3ID ATTACK2_PROJECTILE_HOMING_ENABLED = War3ID.fromString("umh2");
private static final War3ID ATTACK2_PROJECTILE_SPEED = War3ID.fromString("ua2z");
private static final War3ID ATTACK2_RANGE = War3ID.fromString("ua2r");
private static final War3ID ATTACK2_RANGE_MOTION_BUFFER = War3ID.fromString("urb2");
private static final War3ID ATTACK2_SHOW_UI = War3ID.fromString("uwu2");
private static final War3ID ATTACK2_TARGETS_ALLOWED = War3ID.fromString("ua2g");
private static final War3ID ATTACK2_WEAPON_SOUND = War3ID.fromString("ucs2");
private static final War3ID ATTACK2_WEAPON_TYPE = War3ID.fromString("ua2w");
private static final War3ID ACQUISITION_RANGE = War3ID.fromString("uacq");
private static final War3ID MINIMUM_ATTACK_RANGE = War3ID.fromString("uamn");
private static final War3ID ACQUISITION_RANGE = War3ID.fromString("uacq");
private static final War3ID MINIMUM_ATTACK_RANGE = War3ID.fromString("uamn");
private static final War3ID PROJECTILE_IMPACT_Z = War3ID.fromString("uimz");
private static final War3ID PROJECTILE_IMPACT_Z = War3ID.fromString("uimz");
private static final War3ID DEATH_TYPE = War3ID.fromString("udea");
private static final War3ID ARMOR_TYPE = War3ID.fromString("uarm");
private static final War3ID DEATH_TYPE = War3ID.fromString("udea");
private static final War3ID ARMOR_TYPE = War3ID.fromString("uarm");
private static final War3ID DEFENSE = War3ID.fromString("udef");
private static final War3ID DEFENSE_TYPE = War3ID.fromString("udty");
private static final War3ID MOVE_HEIGHT = War3ID.fromString("umvh");
private static final War3ID MOVE_TYPE = War3ID.fromString("umvt");
private static final War3ID COLLISION_SIZE = War3ID.fromString("ucol");
private static final War3ID CLASSIFICATION = War3ID.fromString("utyp");
private static final War3ID DEATH_TIME = War3ID.fromString("udtm");
private static final War3ID TARGETED_AS = War3ID.fromString("utar");
private static final War3ID DEFENSE = War3ID.fromString("udef");
private static final War3ID DEFENSE_TYPE = War3ID.fromString("udty");
private static final War3ID MOVE_HEIGHT = War3ID.fromString("umvh");
private static final War3ID MOVE_TYPE = War3ID.fromString("umvt");
private static final War3ID COLLISION_SIZE = War3ID.fromString("ucol");
private static final War3ID CLASSIFICATION = War3ID.fromString("utyp");
private static final War3ID DEATH_TIME = War3ID.fromString("udtm");
private static final War3ID TARGETED_AS = War3ID.fromString("utar");
private static final War3ID ABILITIES_NORMAL = War3ID.fromString("uabi");
private final MutableObjectData unitData;
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
private final CAbilityData abilityData;
private static final War3ID ABILITIES_NORMAL = War3ID.fromString("uabi");
public CUnitData(final MutableObjectData unitData, final CAbilityData abilityData) {
this.unitData = unitData;
this.abilityData = abilityData;
}
private static final War3ID STRUCTURES_BUILT = War3ID.fromString("ubui");
private static final War3ID UNIT_RACE = War3ID.fromString("urac");
public CUnit create(final CSimulation simulation, final int playerIndex, final War3ID typeId, final float x,
final float y, final float facing, final BufferedImage buildingPathingPixelMap,
final SimulationRenderController simulationRenderController, final HandleIdAllocator handleIdAllocator) {
final MutableGameObject unitType = this.unitData.get(typeId);
final int handleId = handleIdAllocator.createId();
final int life = unitType.getFieldAsInteger(HIT_POINT_MAXIMUM, 0);
final int manaInitial = unitType.getFieldAsInteger(MANA_INITIAL_AMOUNT, 0);
final int manaMaximum = unitType.getFieldAsInteger(MANA_MAXIMUM, 0);
final int speed = unitType.getFieldAsInteger(MOVEMENT_SPEED_BASE, 0);
final int defense = unitType.getFieldAsInteger(DEFENSE, 0);
final String abilityList = unitType.getFieldAsString(ABILITIES_NORMAL, 0);
private static final War3ID GOLD_COST = War3ID.fromString("ugol");
private static final War3ID LUMBER_COST = War3ID.fromString("ulum");
private static final War3ID BUILD_TIME = War3ID.fromString("ubld");
final CUnitType unitTypeInstance = getUnitTypeInstance(typeId, buildingPathingPixelMap, unitType);
private final MutableObjectData unitData;
private final Map<War3ID, CUnitType> unitIdToUnitType = new HashMap<>();
private final CAbilityData abilityData;
private SimulationRenderController simulationRenderController;
final CUnit unit = new CUnit(handleId, playerIndex, x, y, life, typeId, facing, manaInitial, life, manaMaximum,
speed, defense, unitTypeInstance);
if (speed > 0) {
unit.add(simulation, new CAbilityMove(handleIdAllocator.createId()));
}
if (!unitTypeInstance.getAttacks().isEmpty()) {
unit.add(simulation, new CAbilityAttack(handleIdAllocator.createId()));
}
for (final String ability : abilityList.split(",")) {
if (ability.length() > 0 && !"_".equals(ability)) {
unit.add(simulation, this.abilityData.createAbility(ability, handleIdAllocator.createId()));
}
}
return unit;
}
public CUnitData(final MutableObjectData unitData, final CAbilityData abilityData) {
this.unitData = unitData;
this.abilityData = abilityData;
}
private CUnitType getUnitTypeInstance(final War3ID typeId, final BufferedImage buildingPathingPixelMap,
final MutableGameObject unitType) {
CUnitType unitTypeInstance = this.unitIdToUnitType.get(typeId);
if (unitTypeInstance == null) {
final float moveHeight = unitType.getFieldAsFloat(MOVE_HEIGHT, 0);
final String movetp = unitType.getFieldAsString(MOVE_TYPE, 0);
final float collisionSize = unitType.getFieldAsFloat(COLLISION_SIZE, 0);
final boolean isBldg = unitType.getFieldAsBoolean(IS_BLDG, 0);
final PathingGrid.MovementType movementType = PathingGrid.getMovementType(movetp);
final String unitName = unitType.getFieldAsString(NAME, 0);
final float acquisitionRange = unitType.getFieldAsFloat(ACQUISITION_RANGE, 0);
final float minimumAttackRange = unitType.getFieldAsFloat(MINIMUM_ATTACK_RANGE, 0);
final EnumSet<CTargetType> targetedAs = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(TARGETED_AS, 0));
final String classificationString = unitType.getFieldAsString(CLASSIFICATION, 0);
final EnumSet<CUnitClassification> classifications = EnumSet.noneOf(CUnitClassification.class);
if (classificationString != null) {
final String[] classificationValues = classificationString.split(",");
for (final String unitEditorKey : classificationValues) {
final CUnitClassification unitClassification = CUnitClassification
.parseUnitClassification(unitEditorKey);
if (unitClassification != null) {
classifications.add(unitClassification);
}
}
}
final List<CUnitAttack> attacks = new ArrayList<>();
final int attacksEnabled = unitType.getFieldAsInteger(ATTACKS_ENABLED, 0);
if ((attacksEnabled & 0x1) != 0) {
try {
// attack one
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK1_BACKSWING_POINT, 0);
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK1_DAMAGE_POINT, 0);
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_FULL_DMG, 0);
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_HALF_DMG, 0);
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_QUARTER_DMG,
0);
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_AREA_OF_EFFECT_TARGETS, 0));
final CAttackType attackType = CAttackType
.parseAttackType(unitType.getFieldAsString(ATTACK1_ATTACK_TYPE, 0));
final float cooldownTime = unitType.getFieldAsFloat(ATTACK1_COOLDOWN, 0);
final int damageBase = unitType.getFieldAsInteger(ATTACK1_DMG_BASE, 0);
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_HALF, 0);
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_QUARTER, 0);
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK1_DAMAGE_LOSS_FACTOR, 0);
final int damageDice = unitType.getFieldAsInteger(ATTACK1_DMG_DICE, 0);
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0);
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_DIST, 0);
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_RADIUS, 0);
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK1_DMG_UPGRADE_AMT, 0);
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK1_TARGET_COUNT, 0);
final float projectileArc = unitType.getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
final String projectileArt = unitType.getFieldAsString(ATTACK1_MISSILE_ART, 0);
final boolean projectileHomingEnabled = unitType
.getFieldAsBoolean(ATTACK1_PROJECTILE_HOMING_ENABLED, 0);
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
final int range = unitType.getFieldAsInteger(ATTACK1_RANGE, 0);
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK1_RANGE_MOTION_BUFFER, 0);
final boolean showUI = unitType.getFieldAsBoolean(ATTACK1_SHOW_UI, 0);
final EnumSet<CTargetType> targetsAllowed = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_TARGETS_ALLOWED, 0));
final String weaponSound = unitType.getFieldAsString(ATTACK1_WEAPON_SOUND, 0);
final CWeaponType weaponType = CWeaponType
.parseWeaponType(unitType.getFieldAsString(ATTACK1_WEAPON_TYPE, 0));
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor,
damageDice, damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound,
weaponType));
} catch (final Exception exc) {
System.err.println("Attack 1 failed to parse with: " + exc.getClass() + ":" + exc.getMessage());
}
}
if ((attacksEnabled & 0x2) != 0) {
try {
// attack two
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK2_BACKSWING_POINT, 0);
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK2_DAMAGE_POINT, 0);
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_FULL_DMG, 0);
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_HALF_DMG, 0);
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_QUARTER_DMG,
0);
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_AREA_OF_EFFECT_TARGETS, 0));
final CAttackType attackType = CAttackType
.parseAttackType(unitType.getFieldAsString(ATTACK2_ATTACK_TYPE, 0));
final float cooldownTime = unitType.getFieldAsFloat(ATTACK2_COOLDOWN, 0);
final int damageBase = unitType.getFieldAsInteger(ATTACK2_DMG_BASE, 0);
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_HALF, 0);
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_QUARTER, 0);
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK2_DAMAGE_LOSS_FACTOR, 0);
final int damageDice = unitType.getFieldAsInteger(ATTACK2_DMG_DICE, 0);
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0);
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_DIST, 0);
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_RADIUS, 0);
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK2_DMG_UPGRADE_AMT, 0);
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK2_TARGET_COUNT, 0);
final float projectileArc = unitType.getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
final String projectileArt = unitType.getFieldAsString(ATTACK2_MISSILE_ART, 0);
final boolean projectileHomingEnabled = unitType
.getFieldAsBoolean(ATTACK2_PROJECTILE_HOMING_ENABLED, 0);
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
final int range = unitType.getFieldAsInteger(ATTACK2_RANGE, 0);
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK2_RANGE_MOTION_BUFFER, 0);
final boolean showUI = unitType.getFieldAsBoolean(ATTACK2_SHOW_UI, 0);
final EnumSet<CTargetType> targetsAllowed = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_TARGETS_ALLOWED, 0));
final String weaponSound = unitType.getFieldAsString(ATTACK2_WEAPON_SOUND, 0);
final CWeaponType weaponType = CWeaponType
.parseWeaponType(unitType.getFieldAsString(ATTACK2_WEAPON_TYPE, 0));
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor,
damageDice, damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound,
weaponType));
} catch (final Exception exc) {
System.err.println("Attack 2 failed to parse with: " + exc.getClass() + ":" + exc.getMessage());
}
}
final int deathType = unitType.getFieldAsInteger(DEATH_TYPE, 0);
final boolean raise = (deathType & 0x1) != 0;
final boolean decay = (deathType & 0x2) != 0;
final String armorType = unitType.getFieldAsString(ARMOR_TYPE, 0);
final float impactZ = unitType.getFieldAsFloat(PROJECTILE_IMPACT_Z, 0);
final CDefenseType defenseType = CDefenseType.parseDefenseType(unitType.getFieldAsString(DEFENSE_TYPE, 0));
final float deathTime = unitType.getFieldAsFloat(DEATH_TIME, 0);
unitTypeInstance = new CUnitType(unitName, isBldg, movementType, moveHeight, collisionSize, classifications,
attacks, armorType, raise, decay, defenseType, impactZ, buildingPathingPixelMap, deathTime,
targetedAs, acquisitionRange, minimumAttackRange);
this.unitIdToUnitType.put(typeId, unitTypeInstance);
}
return unitTypeInstance;
}
public CUnit create(final CSimulation simulation, final int playerIndex, final War3ID typeId, final float x,
final float y, final float facing, final BufferedImage buildingPathingPixelMap,
final SimulationRenderController simulationRenderController, final HandleIdAllocator handleIdAllocator) {
this.simulationRenderController = simulationRenderController;
final MutableGameObject unitType = this.unitData.get(typeId);
final int handleId = handleIdAllocator.createId();
final int life = unitType.getFieldAsInteger(HIT_POINT_MAXIMUM, 0);
final int manaInitial = unitType.getFieldAsInteger(MANA_INITIAL_AMOUNT, 0);
final int manaMaximum = unitType.getFieldAsInteger(MANA_MAXIMUM, 0);
final int speed = unitType.getFieldAsInteger(MOVEMENT_SPEED_BASE, 0);
final int defense = unitType.getFieldAsInteger(DEFENSE, 0);
final String abilityList = unitType.getFieldAsString(ABILITIES_NORMAL, 0);
private CUnitAttack createAttack(final float animationBackswingPoint, final float animationDamagePoint,
final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage,
final EnumSet<CTargetType> areaOfEffectTargets, final CAttackType attackType, final float cooldownTime,
final int damageBase, final float damageFactorMedium, final float damageFactorSmall,
final float damageLossFactor, final int damageDice, final int damageSidesPerDie,
final float damageSpillDistance, final float damageSpillRadius, final int damageUpgradeAmount,
final int maximumNumberOfTargets, final float projectileArc, final String projectileArt,
final boolean projectileHomingEnabled, final int projectileSpeed, final int range,
final float rangeMotionBuffer, final boolean showUI, final EnumSet<CTargetType> targetsAllowed,
final String weaponSound, final CWeaponType weaponType) {
final CUnitAttack attack;
switch (weaponType) {
case MISSILE:
attack = new CUnitAttackMissile(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed);
break;
case MBOUNCE:
attack = new CUnitAttackMissileBounce(animationBackswingPoint, animationDamagePoint, attackType,
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
projectileHomingEnabled, projectileSpeed, damageLossFactor, maximumNumberOfTargets,
areaOfEffectFullDamage, areaOfEffectTargets);
break;
case MSPLASH:
case ARTILLERY:
attack = new CUnitAttackMissileSplash(animationBackswingPoint, animationDamagePoint, attackType,
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
projectileHomingEnabled, projectileSpeed, areaOfEffectFullDamage, areaOfEffectMediumDamage,
areaOfEffectSmallDamage, areaOfEffectTargets, damageFactorMedium, damageFactorSmall);
break;
case MLINE:
case ALINE:
attack = new CUnitAttackMissileLine(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed, damageSpillDistance, damageSpillRadius);
break;
case INSTANT:
attack = new CUnitAttackInstant(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType, projectileArt);
break;
default:
case NORMAL:
attack = new CUnitAttackNormal(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType);
break;
}
return attack;
}
final CUnitType unitTypeInstance = getUnitTypeInstance(typeId, buildingPathingPixelMap, unitType);
public float getPropulsionWindow(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROPULSION_WINDOW, 0);
}
final CUnit unit = new CUnit(handleId, playerIndex, x, y, life, typeId, facing, manaInitial, life, manaMaximum,
speed, defense, unitTypeInstance);
if (speed > 0) {
unit.add(simulation, new CAbilityMove(handleIdAllocator.createId()));
}
if (!unitTypeInstance.getAttacks().isEmpty()) {
unit.add(simulation, new CAbilityAttack(handleIdAllocator.createId()));
}
final List<War3ID> structuresBuilt = unitTypeInstance.getStructuresBuilt();
if (!structuresBuilt.isEmpty()) {
switch (unitTypeInstance.getRace()) {
case ORC:
unit.add(simulation, new CAbilityOrcBuild(handleIdAllocator.createId(), structuresBuilt));
break;
case HUMAN:
unit.add(simulation, new CAbilityHumanBuild(handleIdAllocator.createId(), structuresBuilt));
break;
case UNDEAD:
unit.add(simulation, new CAbilityUndeadBuild(handleIdAllocator.createId(), structuresBuilt));
break;
case NIGHTELF:
unit.add(simulation, new CAbilityNightElfBuild(handleIdAllocator.createId(), structuresBuilt));
break;
case NAGA:
unit.add(simulation, new CAbilityNagaBuild(handleIdAllocator.createId(), structuresBuilt));
break;
case CREEPS:
case CRITTERS:
case DEMON:
case OTHER:
unit.add(simulation, new CAbilityNeutralBuild(handleIdAllocator.createId(), structuresBuilt));
break;
}
}
for (final String ability : abilityList.split(",")) {
if ((ability.length() > 0) && !"_".equals(ability)) {
unit.add(simulation, this.abilityData.createAbility(ability, handleIdAllocator.createId()));
}
}
return unit;
}
public float getTurnRate(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(TURN_RATE, 0);
}
private CUnitType getUnitTypeInstance(final War3ID typeId, final BufferedImage buildingPathingPixelMap,
final MutableGameObject unitType) {
CUnitType unitTypeInstance = this.unitIdToUnitType.get(typeId);
if (unitTypeInstance == null) {
final float moveHeight = unitType.getFieldAsFloat(MOVE_HEIGHT, 0);
final String movetp = unitType.getFieldAsString(MOVE_TYPE, 0);
final float collisionSize = unitType.getFieldAsFloat(COLLISION_SIZE, 0);
final boolean isBldg = unitType.getFieldAsBoolean(IS_BLDG, 0);
final PathingGrid.MovementType movementType = PathingGrid.getMovementType(movetp);
final String unitName = unitType.getFieldAsString(NAME, 0);
final float acquisitionRange = unitType.getFieldAsFloat(ACQUISITION_RANGE, 0);
final float minimumAttackRange = unitType.getFieldAsFloat(MINIMUM_ATTACK_RANGE, 0);
final EnumSet<CTargetType> targetedAs = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(TARGETED_AS, 0));
final String classificationString = unitType.getFieldAsString(CLASSIFICATION, 0);
final EnumSet<CUnitClassification> classifications = EnumSet.noneOf(CUnitClassification.class);
if (classificationString != null) {
final String[] classificationValues = classificationString.split(",");
for (final String unitEditorKey : classificationValues) {
final CUnitClassification unitClassification = CUnitClassification
.parseUnitClassification(unitEditorKey);
if (unitClassification != null) {
classifications.add(unitClassification);
}
}
}
final List<CUnitAttack> attacks = new ArrayList<>();
final int attacksEnabled = unitType.getFieldAsInteger(ATTACKS_ENABLED, 0);
if ((attacksEnabled & 0x1) != 0) {
try {
// attack one
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK1_BACKSWING_POINT, 0);
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK1_DAMAGE_POINT, 0);
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_FULL_DMG, 0);
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_HALF_DMG, 0);
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK1_AREA_OF_EFFECT_QUARTER_DMG,
0);
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_AREA_OF_EFFECT_TARGETS, 0));
final CAttackType attackType = CAttackType
.parseAttackType(unitType.getFieldAsString(ATTACK1_ATTACK_TYPE, 0));
final float cooldownTime = unitType.getFieldAsFloat(ATTACK1_COOLDOWN, 0);
final int damageBase = unitType.getFieldAsInteger(ATTACK1_DMG_BASE, 0);
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_HALF, 0);
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK1_DAMAGE_FACTOR_QUARTER, 0);
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK1_DAMAGE_LOSS_FACTOR, 0);
final int damageDice = unitType.getFieldAsInteger(ATTACK1_DMG_DICE, 0);
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0);
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_DIST, 0);
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK1_DMG_SPILL_RADIUS, 0);
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK1_DMG_UPGRADE_AMT, 0);
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK1_TARGET_COUNT, 0);
final float projectileArc = unitType.getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
final String projectileArt = unitType.getFieldAsString(ATTACK1_MISSILE_ART, 0);
final boolean projectileHomingEnabled = unitType
.getFieldAsBoolean(ATTACK1_PROJECTILE_HOMING_ENABLED, 0);
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
final int range = unitType.getFieldAsInteger(ATTACK1_RANGE, 0);
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK1_RANGE_MOTION_BUFFER, 0);
final boolean showUI = unitType.getFieldAsBoolean(ATTACK1_SHOW_UI, 0);
final EnumSet<CTargetType> targetsAllowed = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK1_TARGETS_ALLOWED, 0));
final String weaponSound = unitType.getFieldAsString(ATTACK1_WEAPON_SOUND, 0);
final CWeaponType weaponType = CWeaponType
.parseWeaponType(unitType.getFieldAsString(ATTACK1_WEAPON_TYPE, 0));
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor,
damageDice, damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound,
weaponType));
}
catch (final Exception exc) {
System.err.println("Attack 1 failed to parse with: " + exc.getClass() + ":" + exc.getMessage());
}
}
if ((attacksEnabled & 0x2) != 0) {
try {
// attack two
final float animationBackswingPoint = unitType.getFieldAsFloat(ATTACK2_BACKSWING_POINT, 0);
final float animationDamagePoint = unitType.getFieldAsFloat(ATTACK2_DAMAGE_POINT, 0);
final int areaOfEffectFullDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_FULL_DMG, 0);
final int areaOfEffectMediumDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_HALF_DMG, 0);
final int areaOfEffectSmallDamage = unitType.getFieldAsInteger(ATTACK2_AREA_OF_EFFECT_QUARTER_DMG,
0);
final EnumSet<CTargetType> areaOfEffectTargets = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_AREA_OF_EFFECT_TARGETS, 0));
final CAttackType attackType = CAttackType
.parseAttackType(unitType.getFieldAsString(ATTACK2_ATTACK_TYPE, 0));
final float cooldownTime = unitType.getFieldAsFloat(ATTACK2_COOLDOWN, 0);
final int damageBase = unitType.getFieldAsInteger(ATTACK2_DMG_BASE, 0);
final float damageFactorMedium = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_HALF, 0);
final float damageFactorSmall = unitType.getFieldAsFloat(ATTACK2_DAMAGE_FACTOR_QUARTER, 0);
final float damageLossFactor = unitType.getFieldAsFloat(ATTACK2_DAMAGE_LOSS_FACTOR, 0);
final int damageDice = unitType.getFieldAsInteger(ATTACK2_DMG_DICE, 0);
final int damageSidesPerDie = unitType.getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0);
final float damageSpillDistance = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_DIST, 0);
final float damageSpillRadius = unitType.getFieldAsFloat(ATTACK2_DMG_SPILL_RADIUS, 0);
final int damageUpgradeAmount = unitType.getFieldAsInteger(ATTACK2_DMG_UPGRADE_AMT, 0);
final int maximumNumberOfTargets = unitType.getFieldAsInteger(ATTACK2_TARGET_COUNT, 0);
final float projectileArc = unitType.getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
final String projectileArt = unitType.getFieldAsString(ATTACK2_MISSILE_ART, 0);
final boolean projectileHomingEnabled = unitType
.getFieldAsBoolean(ATTACK2_PROJECTILE_HOMING_ENABLED, 0);
final int projectileSpeed = unitType.getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
final int range = unitType.getFieldAsInteger(ATTACK2_RANGE, 0);
final float rangeMotionBuffer = unitType.getFieldAsFloat(ATTACK2_RANGE_MOTION_BUFFER, 0);
final boolean showUI = unitType.getFieldAsBoolean(ATTACK2_SHOW_UI, 0);
final EnumSet<CTargetType> targetsAllowed = CTargetType
.parseTargetTypeSet(unitType.getFieldAsString(ATTACK2_TARGETS_ALLOWED, 0));
final String weaponSound = unitType.getFieldAsString(ATTACK2_WEAPON_SOUND, 0);
final CWeaponType weaponType = CWeaponType
.parseWeaponType(unitType.getFieldAsString(ATTACK2_WEAPON_TYPE, 0));
attacks.add(createAttack(animationBackswingPoint, animationDamagePoint, areaOfEffectFullDamage,
areaOfEffectMediumDamage, areaOfEffectSmallDamage, areaOfEffectTargets, attackType,
cooldownTime, damageBase, damageFactorMedium, damageFactorSmall, damageLossFactor,
damageDice, damageSidesPerDie, damageSpillDistance, damageSpillRadius, damageUpgradeAmount,
maximumNumberOfTargets, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed, range, rangeMotionBuffer, showUI, targetsAllowed, weaponSound,
weaponType));
}
catch (final Exception exc) {
System.err.println("Attack 2 failed to parse with: " + exc.getClass() + ":" + exc.getMessage());
}
}
final int deathType = unitType.getFieldAsInteger(DEATH_TYPE, 0);
final boolean raise = (deathType & 0x1) != 0;
final boolean decay = (deathType & 0x2) != 0;
final String armorType = unitType.getFieldAsString(ARMOR_TYPE, 0);
final float impactZ = unitType.getFieldAsFloat(PROJECTILE_IMPACT_Z, 0);
final CDefenseType defenseType = CDefenseType.parseDefenseType(unitType.getFieldAsString(DEFENSE_TYPE, 0));
final float deathTime = unitType.getFieldAsFloat(DEATH_TIME, 0);
final int goldCost = unitType.getFieldAsInteger(GOLD_COST, 0);
final int lumberCost = unitType.getFieldAsInteger(LUMBER_COST, 0);
final int buildTime = unitType.getFieldAsInteger(BUILD_TIME, 0);
public boolean isBuilding(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsBoolean(IS_BLDG, 0);
}
final String structuresBuiltString = unitType.getFieldAsString(STRUCTURES_BUILT, 0);
final String[] structuresBuiltStringItems = structuresBuiltString.split(",");
final List<War3ID> structuresBuilt = new ArrayList<>();
for (final String structuresBuiltStringItem : structuresBuiltStringItems) {
if (structuresBuiltStringItem.length() == 4) {
structuresBuilt.add(War3ID.fromString(structuresBuiltStringItem));
}
}
public String getName(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getName();
}
final String raceString = unitType.getFieldAsString(UNIT_RACE, 0);
final CUnitRace unitRace = CUnitRace.parseRace(raceString);
public int getA1MinDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0);
}
unitTypeInstance = new CUnitType(unitName, isBldg, movementType, moveHeight, collisionSize, classifications,
attacks, armorType, raise, decay, defenseType, impactZ, buildingPathingPixelMap, deathTime,
targetedAs, acquisitionRange, minimumAttackRange, structuresBuilt, unitRace, goldCost, lumberCost,
buildTime);
this.unitIdToUnitType.put(typeId, unitTypeInstance);
}
return unitTypeInstance;
}
public int getA1MaxDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0)
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0));
}
private CUnitAttack createAttack(final float animationBackswingPoint, final float animationDamagePoint,
final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage,
final EnumSet<CTargetType> areaOfEffectTargets, final CAttackType attackType, final float cooldownTime,
final int damageBase, final float damageFactorMedium, final float damageFactorSmall,
final float damageLossFactor, final int damageDice, final int damageSidesPerDie,
final float damageSpillDistance, final float damageSpillRadius, final int damageUpgradeAmount,
final int maximumNumberOfTargets, final float projectileArc, final String projectileArt,
final boolean projectileHomingEnabled, final int projectileSpeed, final int range,
final float rangeMotionBuffer, final boolean showUI, final EnumSet<CTargetType> targetsAllowed,
final String weaponSound, final CWeaponType weaponType) {
final CUnitAttack attack;
switch (weaponType) {
case MISSILE:
attack = new CUnitAttackMissile(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed);
break;
case MBOUNCE:
attack = new CUnitAttackMissileBounce(animationBackswingPoint, animationDamagePoint, attackType,
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
projectileHomingEnabled, projectileSpeed, damageLossFactor, maximumNumberOfTargets,
areaOfEffectFullDamage, areaOfEffectTargets);
break;
case MSPLASH:
case ARTILLERY:
attack = new CUnitAttackMissileSplash(animationBackswingPoint, animationDamagePoint, attackType,
cooldownTime, damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range,
rangeMotionBuffer, showUI, targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt,
projectileHomingEnabled, projectileSpeed, areaOfEffectFullDamage, areaOfEffectMediumDamage,
areaOfEffectSmallDamage, areaOfEffectTargets, damageFactorMedium, damageFactorSmall);
break;
case MLINE:
case ALINE:
attack = new CUnitAttackMissileLine(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType, projectileArc, projectileArt, projectileHomingEnabled,
projectileSpeed, damageSpillDistance, damageSpillRadius);
break;
case INSTANT:
attack = new CUnitAttackInstant(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType, projectileArt);
break;
default:
case NORMAL:
attack = new CUnitAttackNormal(animationBackswingPoint, animationDamagePoint, attackType, cooldownTime,
damageBase, damageDice, damageSidesPerDie, damageUpgradeAmount, range, rangeMotionBuffer, showUI,
targetsAllowed, weaponSound, weaponType);
break;
}
return attack;
}
public int getA2MinDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0);
}
public float getPropulsionWindow(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROPULSION_WINDOW, 0);
}
public int getA2MaxDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0)
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0));
}
public float getTurnRate(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(TURN_RATE, 0);
}
public int getDefense(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(DEFENSE, 0);
}
public boolean isBuilding(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsBoolean(IS_BLDG, 0);
}
public int getA1ProjectileSpeed(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
}
public String getName(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getName();
}
public float getA1ProjectileArc(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
}
public int getA1MinDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0);
}
public int getA2ProjectileSpeed(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
}
public int getA1MaxDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_BASE, 0)
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_DICE, 0)
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0));
}
public float getA2ProjectileArc(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
}
public int getA2MinDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
+ this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0);
}
public String getA1MissileArt(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK1_MISSILE_ART, 0);
}
public int getA2MaxDamage(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_BASE, 0)
+ (this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_DICE, 0)
* this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0));
}
public String getA2MissileArt(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK2_MISSILE_ART, 0);
}
public int getDefense(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(DEFENSE, 0);
}
public float getA1Cooldown(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_COOLDOWN, 0);
}
public int getA1ProjectileSpeed(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_PROJECTILE_SPEED, 0);
}
public float getA2Cooldown(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_COOLDOWN, 0);
}
public float getA1ProjectileArc(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_PROJECTILE_ARC, 0);
}
public float getProjectileLaunchX(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_X, 0);
}
public int getA2ProjectileSpeed(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_PROJECTILE_SPEED, 0);
}
public float getProjectileLaunchY(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Y, 0);
}
public float getA2ProjectileArc(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_PROJECTILE_ARC, 0);
}
public float getProjectileLaunchZ(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Z, 0);
}
public String getA1MissileArt(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK1_MISSILE_ART, 0);
}
public String getA2MissileArt(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsString(ATTACK2_MISSILE_ART, 0);
}
public float getA1Cooldown(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK1_COOLDOWN, 0);
}
public float getA2Cooldown(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(ATTACK2_COOLDOWN, 0);
}
public float getProjectileLaunchX(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_X, 0);
}
public float getProjectileLaunchY(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Y, 0);
}
public float getProjectileLaunchZ(final War3ID unitTypeId) {
return this.unitData.get(unitTypeId).getFieldAsFloat(PROJECTILE_LAUNCH_Z, 0);
}
public CUnitType getUnitType(final War3ID rawcode) {
final CUnitType unitTypeInstance = this.unitIdToUnitType.get(rawcode);
if (unitTypeInstance != null) {
return unitTypeInstance;
}
final MutableGameObject unitType = this.unitData.get(rawcode);
if (unitType == null) {
return null;
}
final BufferedImage buildingPathingPixelMap = this.simulationRenderController
.getBuildingPathingPixelMap(rawcode);
return getUnitTypeInstance(rawcode, buildingPathingPixelMap, unitType);
}
}

View File

@ -0,0 +1,32 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.data;
import java.util.HashMap;
import java.util.Map;
public enum CUnitRace {
HUMAN,
ORC,
UNDEAD,
NIGHTELF,
NAGA,
CREEPS,
DEMON,
CRITTERS,
OTHER;
private static Map<String, CUnitRace> keyToRace = new HashMap<>();
static {
for (final CUnitRace race : CUnitRace.values()) {
keyToRace.put(race.name(), race);
}
}
public static CUnitRace parseRace(final String raceString) {
final CUnitRace race = keyToRace.get(raceString.toUpperCase());
if (race == null) {
return OTHER;
}
return race;
}
}

View File

@ -27,6 +27,10 @@ public class COrderNoTarget implements COrder {
@Override
public CBehavior begin(final CSimulation game, final CUnit caster) {
final CAbility ability = game.getAbility(this.abilityHandleId);
if ((ability == null) && (this.orderId == OrderIds.stop)) {
// stop
return caster.getStopBehavior();
}
return ability.beginNoTarget(game, caster, this.orderId);
}

View File

@ -3,7 +3,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util;
public interface AbilityActivationReceiver {
void useOk();
void notEnoughResources(ResourceType resource, int amount);
void notEnoughResources(ResourceType resource);
void notAnActiveAbility();

View File

@ -10,7 +10,7 @@ public class BooleanAbilityActivationReceiver implements AbilityActivationReceiv
}
@Override
public void notEnoughResources(final ResourceType resource, final int amount) {
public void notEnoughResources(final ResourceType resource) {
this.ok = false;
}

View File

@ -1,5 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util;
import java.awt.image.BufferedImage;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
@ -16,4 +19,6 @@ public interface SimulationRenderController {
void spawnUnitDamageSound(CUnit damagedUnit, final String weaponSound, String armorType);
void removeUnit(CUnit unit);
BufferedImage getBuildingPathingPixelMap(War3ID rawcode);
}

View File

@ -30,8 +30,8 @@ public class StringMsgAbilityActivationReceiver implements AbilityActivationRece
}
@Override
public void notEnoughResources(final ResourceType resource, final int amount) {
this.message = "NOTEXTERN: Requires " + amount + " " + resource.name().toLowerCase() + ".";
public void notEnoughResources(final ResourceType resource) {
this.message = "NOTEXTERN: Requires more " + resource.name().toLowerCase() + ".";
}
@Override

View File

@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.warsmash.parsers.fdf.GameUI;
import com.etheller.warsmash.parsers.fdf.frames.AbstractRenderableFrame;
import com.etheller.warsmash.parsers.fdf.frames.SpriteFrame;
import com.etheller.warsmash.parsers.fdf.frames.TextureFrame;
@ -26,6 +27,7 @@ public class CommandCardIcon extends AbstractRenderableFrame {
private int autoCastOrderId;
private boolean autoCastActive;
private final CommandCardCommandListener commandCardCommandListener;
private boolean menuButton;
public CommandCardIcon(final String name, final UIFrame parent,
final CommandCardCommandListener commandCardCommandListener) {
@ -70,7 +72,8 @@ public class CommandCardIcon extends AbstractRenderableFrame {
}
public void setCommandButtonData(final Texture texture, final int abilityHandleId, final int orderId,
final int autoCastOrderId, final boolean active, final boolean autoCastActive) {
final int autoCastOrderId, final boolean active, final boolean autoCastActive, final boolean menuButton) {
this.menuButton = menuButton;
this.iconFrame.setVisible(true);
this.activeHighlightFrame.setVisible(active);
this.cooldownFrame.setVisible(false);
@ -111,14 +114,46 @@ public class CommandCardIcon extends AbstractRenderableFrame {
@Override
public UIFrame touchDown(final float screenX, final float screenY, final int button) {
if (this.renderBounds.contains(screenX, screenY)) {
if (button == Input.Buttons.LEFT) {
this.commandCardCommandListener.startUsingAbility(this.abilityHandleId, this.orderId);
}
else if (button == Input.Buttons.RIGHT) {
this.commandCardCommandListener.startUsingAbility(this.abilityHandleId, this.autoCastOrderId);
}
return this;
}
return null;
return super.touchDown(screenX, screenY, button);
}
@Override
public UIFrame touchUp(final float screenX, final float screenY, final int button) {
if (this.renderBounds.contains(screenX, screenY)) {
return this;
}
return super.touchUp(screenX, screenY, button);
}
public boolean isMenuButton() {
return this.menuButton;
}
public void onClick(final int button) {
if (button == Input.Buttons.LEFT) {
if (this.menuButton) {
this.commandCardCommandListener.openMenu(this.orderId);
}
else {
this.commandCardCommandListener.startUsingAbility(this.abilityHandleId, this.orderId);
}
}
else if (button == Input.Buttons.RIGHT) {
this.commandCardCommandListener.startUsingAbility(this.abilityHandleId, this.autoCastOrderId);
}
}
public void mouseDown(final Viewport uiViewport) {
this.iconFrame.setWidth(GameUI.convertX(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_PRESSED_WIDTH));
this.iconFrame.setHeight(GameUI.convertY(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_PRESSED_WIDTH));
positionBounds(uiViewport);
}
public void mouseUp(final Viewport uiViewport) {
this.iconFrame.setWidth(GameUI.convertX(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_WIDTH));
this.iconFrame.setHeight(GameUI.convertY(uiViewport, MeleeUI.DEFAULT_COMMAND_CARD_ICON_WIDTH));
positionBounds(uiViewport);
}
}

View File

@ -1,6 +1,7 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
@ -38,6 +39,7 @@ import com.etheller.warsmash.viewer5.handlers.mdx.MdxModel;
import com.etheller.warsmash.viewer5.handlers.mdx.ReplaceableIds;
import com.etheller.warsmash.viewer5.handlers.mdx.SequenceLoopMode;
import com.etheller.warsmash.viewer5.handlers.tga.TgaFile;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound;
import com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer;
@ -46,6 +48,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.camera.CameraRates;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.GameCameraManager;
import com.etheller.warsmash.viewer5.handlers.w3x.camera.PortraitCameraManager;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.RenderUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.IconUI;
import com.etheller.warsmash.viewer5.handlers.w3x.rendersim.commandbuttons.CommandButtonListener;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitClassification;
@ -69,6 +73,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.StringMsgAbili
import com.etheller.warsmash.viewer5.handlers.w3x.ui.command.CommandCardCommandListener;
public class MeleeUI implements CUnitStateListener, CommandButtonListener, CommandCardCommandListener {
public static final float DEFAULT_COMMAND_CARD_ICON_WIDTH = 0.039f;
public static final float DEFAULT_COMMAND_CARD_ICON_PRESSED_WIDTH = 0.037f;
private static final int COMMAND_CARD_WIDTH = 4;
private static final int COMMAND_CARD_HEIGHT = 3;
@ -120,6 +126,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private final CommandCardIcon[][] commandCard = new CommandCardIcon[COMMAND_CARD_HEIGHT][COMMAND_CARD_WIDTH];
private RenderUnit selectedUnit;
private final List<Integer> subMenuOrderIdStack = new ArrayList<>();
// TODO remove this & replace with FDF
private final Texture activeButtonTexture;
@ -140,6 +147,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
// probably remove them later
private final float widthRatioCorrection;
private final float heightRatioCorrection;
private CommandCardIcon mouseDownUIFrame;
public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport,
final FreeTypeFontGenerator fontGenerator, final Scene uiScene, final Scene portraitScene,
@ -325,25 +333,25 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
commandCardIcon.addAnchor(new AnchorDefinition(FramePoint.BOTTOMLEFT,
GameUI.convertX(this.uiViewport, 0.6175f + (0.0434f * i)),
GameUI.convertY(this.uiViewport, 0.095f - (0.044f * j))));
commandCardIcon.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
commandCardIcon.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
commandCardIcon.setWidth(GameUI.convertX(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
commandCardIcon.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
iconFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
iconFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
iconFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
iconFrame.setWidth(GameUI.convertX(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
iconFrame.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
iconFrame.setTexture(ImageUtils.DEFAULT_ICON_PATH, this.rootFrame);
activeHighlightFrame
.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
activeHighlightFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
activeHighlightFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
activeHighlightFrame.setWidth(GameUI.convertX(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
activeHighlightFrame.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
activeHighlightFrame.setTexture("CommandButtonActiveHighlight", this.rootFrame);
cooldownFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
this.rootFrame.setSpriteFrameModel(cooldownFrame, this.rootFrame.getSkinField("CommandButtonCooldown"));
cooldownFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
cooldownFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
cooldownFrame.setWidth(GameUI.convertX(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
cooldownFrame.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
autocastFrame.addSetPoint(new SetPoint(FramePoint.CENTER, commandCardIcon, FramePoint.CENTER, 0, 0));
this.rootFrame.setSpriteFrameModel(autocastFrame, this.rootFrame.getSkinField("CommandButtonAutocast"));
autocastFrame.setWidth(GameUI.convertX(this.uiViewport, 0.039f));
autocastFrame.setHeight(GameUI.convertY(this.uiViewport, 0.039f));
autocastFrame.setWidth(GameUI.convertX(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
autocastFrame.setHeight(GameUI.convertY(this.uiViewport, DEFAULT_COMMAND_CARD_ICON_WIDTH));
commandCardIcon.set(iconFrame, activeHighlightFrame, cooldownFrame, autocastFrame);
this.commandCard[j][i] = commandCardIcon;
commandCardIcon.setCommandButton(null);
@ -395,9 +403,20 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.activeCommand = abilityToUse;
this.activeCommandOrderId = orderId;
this.activeCommandUnit = this.selectedUnit;
clearAndRepopulateCommandCard();
}
}
}
else {
this.unitOrderListener.issueImmediateOrder(this.selectedUnit.getSimulationUnit().getHandleId(),
abilityHandleId, orderId, isShiftDown());
}
}
@Override
public void openMenu(final int orderId) {
this.subMenuOrderIdStack.add(orderId);
clearAndRepopulateCommandCard();
}
public void showCommandError(final String message) {
@ -515,12 +534,12 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.portraitCameraManager.updateCamera();
if ((this.modelInstance != null)
&& (this.modelInstance.sequenceEnded || (this.modelInstance.sequence == -1))) {
SequenceUtils.randomPortraitSequence(this.modelInstance);
SequenceUtils.randomSequence(this.modelInstance, PrimaryTag.PORTRAIT, SequenceUtils.EMPTY, true);
}
}
public void talk() {
SequenceUtils.randomPortraitTalkSequence(this.modelInstance);
SequenceUtils.randomSequence(this.modelInstance, PrimaryTag.PORTRAIT, SequenceUtils.TALK, true);
}
public void setSelectedUnit(final RenderUnit unit) {
@ -539,7 +558,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
this.modelInstance = (MdxComplexInstance) portraitModel.addInstance();
this.portraitCameraManager.setModelInstance(this.modelInstance, portraitModel);
this.modelInstance.setSequenceLoopMode(SequenceLoopMode.MODEL_LOOP);
this.modelInstance.setSequenceLoopMode(SequenceLoopMode.NEVER_LOOP);
this.modelInstance.setScene(this.portraitScene);
this.modelInstance.setVertexColor(unit.instance.vertexColor);
this.modelInstance.setTeamColor(unit.playerIndex);
@ -549,6 +568,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
public void selectUnit(RenderUnit unit) {
this.subMenuOrderIdStack.clear();
if ((unit != null) && unit.getSimulationUnit().isDead()) {
unit = null;
}
@ -645,7 +665,8 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
localArmorIconBackdrop.setTexture(defenseTexture);
localArmorInfoPanelIconValue.setText(Integer.toString(unit.getSimulationUnit().getDefense()));
unit.populateCommandCard(this.war3MapViewer.simulation, this, this.war3MapViewer.getAbilityDataUI());
unit.populateCommandCard(this.war3MapViewer.simulation, this, this.war3MapViewer.getAbilityDataUI(),
getSubMenuOrderId());
}
}
@ -660,10 +681,11 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
@Override
public void commandButton(final int buttonPositionX, final int buttonPositionY, final Texture icon,
final int abilityHandleId, final int orderId, final int autoCastId, final boolean active,
final boolean autoCastActive) {
final boolean autoCastActive, final boolean menuButton) {
final int x = Math.max(0, Math.min(COMMAND_CARD_WIDTH - 1, buttonPositionX));
final int y = Math.max(0, Math.min(COMMAND_CARD_HEIGHT - 1, buttonPositionY));
this.commandCard[y][x].setCommandButtonData(icon, abilityHandleId, orderId, autoCastId, active, autoCastActive);
this.commandCard[y][x].setCommandButtonData(icon, abilityHandleId, orderId, autoCastId, active, autoCastActive,
menuButton);
}
public void resize(final Rectangle viewport) {
@ -755,9 +777,34 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
@Override
public void ordersChanged(final int abilityHandleId, final int orderId) {
clearAndRepopulateCommandCard();
}
private void clearAndRepopulateCommandCard() {
clearCommandCard();
this.selectedUnit.populateCommandCard(this.war3MapViewer.simulation, this,
this.war3MapViewer.getAbilityDataUI());
final AbilityDataUI abilityDataUI = this.war3MapViewer.getAbilityDataUI();
final int menuOrderId = getSubMenuOrderId();
if (this.activeCommand != null) {
final IconUI cancelUI = abilityDataUI.getCancelUI();
this.commandButton(cancelUI.getButtonPositionX(), cancelUI.getButtonPositionY(), cancelUI.getIcon(), 0,
menuOrderId, 0, false, false, true);
}
else {
if (menuOrderId != 0) {
final int exitOrderId = this.subMenuOrderIdStack.size() > 1
? this.subMenuOrderIdStack.get(this.subMenuOrderIdStack.size() - 2)
: 0;
final IconUI cancelUI = abilityDataUI.getCancelUI();
this.commandButton(cancelUI.getButtonPositionX(), cancelUI.getButtonPositionY(), cancelUI.getIcon(), 0,
exitOrderId, 0, false, false, true);
}
this.selectedUnit.populateCommandCard(this.war3MapViewer.simulation, this, abilityDataUI, menuOrderId);
}
}
private int getSubMenuOrderId() {
return this.subMenuOrderIdStack.isEmpty() ? 0
: this.subMenuOrderIdStack.get(this.subMenuOrderIdStack.size() - 1);
}
public RenderUnit getSelectedUnit() {
@ -794,6 +841,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
clearAndRepopulateCommandCard();
}
else {
final RenderUnit rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY,
@ -813,6 +861,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
clearAndRepopulateCommandCard();
}
}
else {
@ -843,6 +892,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.activeCommandUnit = null;
this.activeCommand = null;
this.activeCommandOrderId = -1;
clearAndRepopulateCommandCard();
}
}
@ -957,6 +1007,27 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
}
}
else {
if (clickedUIFrame instanceof CommandCardIcon) {
this.mouseDownUIFrame = (CommandCardIcon) clickedUIFrame;
this.mouseDownUIFrame.mouseDown(this.uiViewport);
}
}
return false;
}
public boolean touchUp(final int screenX, final int screenY, final float worldScreenY, final int button) {
screenCoordsVector.set(screenX, screenY);
this.uiViewport.unproject(screenCoordsVector);
final UIFrame clickedUIFrame = this.rootFrame.touchUp(screenCoordsVector.x, screenCoordsVector.y, button);
if (this.mouseDownUIFrame != null) {
if (clickedUIFrame == this.mouseDownUIFrame) {
this.mouseDownUIFrame.onClick(button);
this.war3MapViewer.getUiSounds().getSound("InterfaceClick").play(this.uiScene.audioContext, 0, 0);
}
this.mouseDownUIFrame.mouseUp(this.uiViewport);
}
this.mouseDownUIFrame = null;
return false;
}

View File

@ -2,4 +2,6 @@ package com.etheller.warsmash.viewer5.handlers.w3x.ui.command;
public interface CommandCardCommandListener {
void startUsingAbility(int abilityHandleId, int orderId);
void openMenu(int orderId);
}

View File

@ -0,0 +1,29 @@
package com.etheller.warsmash.viewer5.handlers.w3x.ui.sound;
import java.util.HashMap;
import java.util.Map;
import com.etheller.warsmash.datasources.DataSource;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.viewer5.handlers.w3x.UnitSound;
public class KeyedSounds {
private final DataTable uiSoundsTable;
private final DataSource dataSource;
private final Map<String, UnitSound> keyToSound;
public KeyedSounds(final DataTable uiSoundsTable, final DataSource dataSource) {
this.uiSoundsTable = uiSoundsTable;
this.dataSource = dataSource;
this.keyToSound = new HashMap<>();
}
public UnitSound getSound(final String key) {
UnitSound sound = this.keyToSound.get(key);
if (sound == null) {
sound = UnitSound.create(this.dataSource, this.uiSoundsTable, key, "");
this.keyToSound.put(key, sound);
}
return sound;
}
}