Add new harvest ability

This commit is contained in:
Retera 2021-01-11 01:59:25 -05:00
parent 29c58be930
commit eeed5953cc
21 changed files with 639 additions and 113 deletions

View File

@ -1,24 +1,37 @@
[DataSources]
Count=5
Type00=Folder
Path00="D:\Games\Warcraft III CASC 1.31\war3.w3mod"
Type01=Folder
Path01="D:\Games\Warcraft III CASC 1.31\war3.w3mod\_locales\enus.w3mod"
Type02=Folder
Path02="..\..\resources"
Type03=Folder
Path03="D:\Backups\Warsmash\Data"
Count=7
Type00=MPQ
Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq"
Type01=MPQ
Path01="D:\Games\Warcraft III Patch 1.22\War3x.mpq"
Type02=MPQ
Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq"
Type03=MPQ
Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq"
Type04=Folder
Path04="."
Path04="..\..\resources"
Type05=Folder
Path05="D:\Backups\Warsmash\Data"
Type06=Folder
Path06="."
[Map]
//FilePath="CombatUnitTests.w3x"
//FilePath="PitchRoll.w3x"
//FilePath="ReforgedGeorgeVacation.w3x"
FilePath="PeonStartingBase.w3x"
//FilePath="ColdArrows.w3m"
//FilePath="DungeonGoldMine.w3m"
//FilePath="PlayerPeasants.w3m"
//FilePath="FireLord.w3x"
//FilePath="Maps\Campaign\NightElf03.w3m"
//FilePath="PrivateDontShare/Cult 8.w3x"
//FilePath="PhoenixAttack.w3x"
//FilePath="LightEnvironmentTest.w3x"
//FilePath="TorchLight2.w3x"
//FilePath="OrcAssault.w3x"
FilePath="PeonStartingBase.w3x"
//FilePath="PhoenixAttack.w3x"
//FilePath="OperationReforged.w3x"
//FilePath="AzerothRoleplay1.909t03DecoratedV2.w3x"
//FilePath="FrostyVsFarm.w3m"
//FilePath="ModelTest.w3x"
//FilePath="SpinningSample.w3x"
//FilePath="Maps\Campaign\Prologue02.w3m"
//FilePath="Pathing.w3x"
//FilePath="ItemFacing.w3x"
//FilePath=SomeParticleTests.w3x

View File

@ -1,37 +0,0 @@
[DataSources]
Count=7
Type00=MPQ
Path00="D:\Games\Warcraft III Patch 1.22\war3.mpq"
Type01=MPQ
Path01="D:\Games\Warcraft III Patch 1.22\War3x.mpq"
Type02=MPQ
Path02="D:\Games\Warcraft III Patch 1.22\War3xlocal.mpq"
Type03=MPQ
Path03="D:\Games\Warcraft III Patch 1.22\War3Patch.mpq"
Type04=Folder
Path04="..\..\resources"
Type05=Folder
Path05="D:\Backups\Warsmash\Data"
Type06=Folder
Path06="."
[Map]
//FilePath="CombatUnitTests.w3x"
//FilePath="PitchRoll.w3x"
FilePath="PeonStartingBase.w3x"
//FilePath="ColdArrows.w3m"
//FilePath="DungeonGoldMine.w3m"
//FilePath="PlayerPeasants.w3m"
//FilePath="FireLord.w3x"
//FilePath="Maps\Campaign\NightElf03.w3m"
//FilePath="PhoenixAttack.w3x"
//FilePath="LightEnvironmentTest.w3x"
//FilePath="TorchLight2.w3x"
//FilePath="OrcAssault.w3x"
//FilePath="FrostyVsFarm.w3m"
//FilePath="ModelTest.w3x"
//FilePath="SpinningSample.w3x"
//FilePath="Maps\Campaign\Prologue02.w3m"
//FilePath="Pathing.w3x"
//FilePath="ItemFacing.w3x"
//FilePath=SomeParticleTests.w3x

View File

@ -0,0 +1,24 @@
[DataSources]
Count=5
Type00=Folder
Path00="D:\Games\Warcraft III CASC 1.31\war3.w3mod"
Type01=Folder
Path01="D:\Games\Warcraft III CASC 1.31\war3.w3mod\_locales\enus.w3mod"
Type02=Folder
Path02="..\..\resources"
Type03=Folder
Path03="D:\Backups\Warsmash\Data"
Type04=Folder
Path04="."
[Map]
//FilePath="PitchRoll.w3x"
//FilePath="ReforgedGeorgeVacation.w3x"
//FilePath="Maps\Campaign\NightElf03.w3m"
//FilePath="PrivateDontShare/Cult 8.w3x"
//FilePath="TorchLight2.w3x"
//FilePath="OrcAssault.w3x"
FilePath="PeonStartingBase.w3x"
//FilePath="PhoenixAttack.w3x"
//FilePath="OperationReforged.w3x"
//FilePath="AzerothRoleplay1.909t03DecoratedV2.w3x"

View File

@ -1,7 +1,7 @@
package com.etheller.warsmash.util;
public class WarsmashConstants {
public static final int MAX_PLAYERS = 28;
public static final int MAX_PLAYERS = 16;
public static final int REPLACEABLE_TEXTURE_LIMIT = 64;
public static final float SIMULATION_STEP_TIME = 1 / 20f;
public static final int PORT_NUMBER = 6115;

View File

@ -164,6 +164,9 @@ public class RenderUnit {
else {
this.instance.show();
if (wasHidden) {
if (this.selectionCircle != null) {
this.selectionCircle.show(map.terrain.centerOffset);
}
if (this.shadow != null) {
this.shadow.show(map.terrain.centerOffset);
}
@ -430,12 +433,14 @@ public class RenderUnit {
this.instance = instance;
}
@Override
public void addSecondaryTag(final AnimationTokens.SecondaryTag tag) {
this.secondaryAnimationTags.add(tag);
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, this.currentSpeedRatio,
this.currentlyAllowingRarityVariations);
}
@Override
public void removeSecondaryTag(final AnimationTokens.SecondaryTag tag) {
this.secondaryAnimationTags.remove(tag);
playAnimation(true, this.currentAnimation, this.currentAnimationSecondaryTags, this.currentSpeedRatio,

View File

@ -18,6 +18,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid;
import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid.RemovablePathingMapInstance;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitStateListener.CUnitStateNotifier;
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.abilities.build.CAbilityBuildInProgress;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
@ -88,7 +89,8 @@ public class CUnit extends CWidget {
private boolean constructing = false;
private float constructionProgress;
private boolean hidden = false;
private boolean updating = true;
private boolean paused = false;
private boolean acceptingOrders = true;
private boolean invulnerable = false;
private CUnit workerInside;
private final War3ID[] buildQueue = new War3ID[WarsmashConstants.BUILD_QUEUE_SIZE];
@ -230,7 +232,7 @@ public class CUnit extends CWidget {
return true;
}
}
else if (this.updating) {
else if (!this.paused) {
if (this.constructing) {
this.constructionProgress += WarsmashConstants.SIMULATION_STEP_TIME;
final int buildTime = this.unitType.getBuildTime();
@ -322,7 +324,7 @@ public class CUnit extends CWidget {
if (this.workerInside != null) {
this.workerInside.setInvulnerable(false);
this.workerInside.setHidden(false);
this.workerInside.setUpdating(true);
this.workerInside.setPaused(false);
this.workerInside.nudgeAround(game, this);
this.workerInside = null;
}
@ -367,7 +369,7 @@ public class CUnit extends CWidget {
}
}
if (queue && (this.currentOrder != null)) {
if ((queue || !this.acceptingOrders) && (this.currentOrder != null)) {
this.orderQueue.add(order);
}
else {
@ -408,6 +410,25 @@ public class CUnit extends CWidget {
return this.abilities;
}
public <T> T getAbility(final CAbilityVisitor<T> visitor) {
for (final CAbility ability : this.abilities) {
final T visited = ability.visit(visitor);
if (visited != null) {
return visited;
}
}
return null;
}
public <T extends CAbility> T getFirstAbilityOfType(final Class<T> cAbilityClass) {
for (final CAbility ability : this.abilities) {
if (cAbilityClass.isAssignableFrom(ability.getClass())) {
return (T) ability;
}
}
return null;
}
public void setCooldownEndTime(final int cooldownEndTime) {
this.cooldownEndTime = cooldownEndTime;
}
@ -875,8 +896,12 @@ public class CUnit extends CWidget {
this.hidden = hidden;
}
public void setUpdating(final boolean updating) {
this.updating = updating;
public void setPaused(final boolean paused) {
this.paused = paused;
}
public void setAcceptingOrders(final boolean acceptingOrders) {
this.acceptingOrders = acceptingOrders;
}
public boolean isHidden() {

View File

@ -11,4 +11,8 @@ public interface CUnitAnimationListener {
void queueAnimation(final PrimaryTag animationName, final EnumSet<SecondaryTag> secondaryAnimationTags,
boolean allowRarityVariations);
void addSecondaryTag(SecondaryTag secondaryTag);
void removeSecondaryTag(SecondaryTag secondaryTag);
}

View File

@ -4,24 +4,36 @@ 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.generic.AbstractGenericSingleIconActiveAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest.CBehaviorHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
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 class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
private final int damageToTree;
private final int goldCapacity;
private final int lumberCapacity;
private CBehaviorHarvest behaviorHarvest;
private int carriedResourceAmount;
private ResourceType carriedResourceType;
public CAbilityHarvest(final int handleId, final War3ID alias) {
public CAbilityHarvest(final int handleId, final War3ID alias, final int damageToTree, final int goldCapacity,
final int lumberCapacity) {
super(handleId, alias);
this.damageToTree = damageToTree;
this.goldCapacity = goldCapacity;
this.lumberCapacity = lumberCapacity;
}
@Override
public void onAdd(final CSimulation game, final CUnit unit) {
this.behaviorHarvest = new CBehaviorHarvest(unit, this);
}
@Override
@ -30,7 +42,7 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final CWidget target) {
return caster.pollNextOrderBehavior(game);
return this.behaviorHarvest.reset(target);
}
@Override
@ -65,13 +77,21 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
final CWidget target, final AbilityTargetCheckReceiver<CWidget> receiver) {
if (target instanceof CUnit) {
final CUnit targetUnit = (CUnit) target;
if (targetUnit.getGold() > 0) {
for (final CAbility ability : targetUnit.getAbilities()) {
if (ability instanceof CAbilityGoldMine) {
receiver.targetOk(target);
return;
}
else if ((this.carriedResourceType != null) && (ability instanceof CAbilityReturnResources)) {
final CAbilityReturnResources abilityReturn = (CAbilityReturnResources) ability;
if (abilityReturn.accepts(this.carriedResourceType)) {
receiver.targetOk(target);
return;
}
}
}
else {
receiver.mustTargetResources();
}
}
else {
receiver.mustTargetResources();
}
@ -89,4 +109,29 @@ public class CAbilityHarvest extends AbstractGenericSingleIconActiveAbility {
}
public int getDamageToTree() {
return this.damageToTree;
}
public int getGoldCapacity() {
return this.goldCapacity;
}
public int getLumberCapacity() {
return this.lumberCapacity;
}
public int getCarriedResourceAmount() {
return this.carriedResourceAmount;
}
public ResourceType getCarriedResourceType() {
return this.carriedResourceType;
}
public void setCarriedResources(final ResourceType carriedResourceType, final int carriedResourceAmount) {
this.carriedResourceType = carriedResourceType;
this.carriedResourceAmount = carriedResourceAmount;
}
}

View File

@ -0,0 +1,81 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest;
import java.util.EnumSet;
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.generic.AbstractGenericNoIconAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
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;
/**
* Was probably named CAbilityReturn in 2002, idk
*/
public class CAbilityReturnResources extends AbstractGenericNoIconAbility {
private final EnumSet<ResourceType> acceptedResourceTypes;
public CAbilityReturnResources(final int handleId, final War3ID alias,
final EnumSet<ResourceType> acceptedResourceTypes) {
super(handleId, alias);
this.acceptedResourceTypes = acceptedResourceTypes;
}
@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 null;
}
@Override
public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId,
final AbilityPointTarget point) {
return null;
}
@Override
public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) {
return null;
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId, final CWidget target,
final AbilityTargetCheckReceiver<CWidget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityPointTarget target, final AbilityTargetCheckReceiver<AbilityPointTarget> receiver) {
receiver.orderIdNotAccepted();
}
@Override
public void checkCanTargetNoTarget(final CSimulation game, final CUnit unit, final int orderId,
final AbilityTargetCheckReceiver<Void> receiver) {
receiver.orderIdNotAccepted();
}
@Override
protected void innerCheckCanUse(final CSimulation game, final CUnit unit, final int orderId,
final AbilityActivationReceiver receiver) {
receiver.notAnActiveAbility();
}
public boolean accepts(final ResourceType resourceType) {
return this.acceptedResourceTypes.contains(resourceType);
}
}

View File

@ -12,6 +12,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetC
public class CAbilityGoldMine extends AbstractGenericNoIconAbility {
private int gold;
private int activeMiners;
private final float miningDuration;
private final int miningCapacity;
@ -81,6 +82,14 @@ public class CAbilityGoldMine extends AbstractGenericNoIconAbility {
this.gold = gold;
}
public int getActiveMiners() {
return this.activeMiners;
}
public void setActiveMiners(final int activeMiners) {
this.activeMiners = activeMiners;
}
public int getMiningCapacity() {
return this.miningCapacity;
}

View File

@ -0,0 +1,44 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting;
import java.util.EnumSet;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
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.combat.CTargetType;
public final class AbilityTargetStillAliveAndTargetableVisitor implements AbilityTargetVisitor<Boolean> {
private CSimulation simulation;
private CUnit unit;
private EnumSet<CTargetType> targetsAllowed;
public AbilityTargetStillAliveAndTargetableVisitor reset(final CSimulation simulation, final CUnit unit,
final EnumSet<CTargetType> targetsAllowed) {
this.simulation = simulation;
this.unit = unit;
this.targetsAllowed = targetsAllowed;
return this;
}
@Override
public Boolean accept(final AbilityPointTarget target) {
return Boolean.TRUE;
}
@Override
public Boolean accept(final CUnit target) {
return !target.isDead() && target.canBeTargetedBy(this.simulation, this.unit, this.targetsAllowed);
}
@Override
public Boolean accept(final CDestructable target) {
return !target.isDead() && target.canBeTargetedBy(this.simulation, this.unit, this.targetsAllowed);
}
@Override
public Boolean accept(final CItem target) {
return !target.isDead() && target.canBeTargetedBy(this.simulation, this.unit, this.targetsAllowed);
}
}

View File

@ -0,0 +1,36 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl;
import java.util.EnumSet;
import java.util.List;
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeHarvestLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeDefinitionHarvest extends AbstractCAbilityTypeDefinition<CAbilityTypeHarvestLevelData>
implements CAbilityTypeDefinition {
protected static final War3ID DAMAGE_TO_TREE = War3ID.fromString("Har1");
protected static final War3ID GOLD_CAPACITY = War3ID.fromString("Har2");
protected static final War3ID LUMBER_CAPACITY = War3ID.fromString("Har3");
@Override
protected CAbilityTypeHarvestLevelData createLevelData(final MutableGameObject abilityEditorData, final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final EnumSet<CTargetType> targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString);
final int damageToTree = abilityEditorData.getFieldAsInteger(DAMAGE_TO_TREE, level);
final int goldCapacity = abilityEditorData.getFieldAsInteger(GOLD_CAPACITY, level);
final int lumberCapacity = abilityEditorData.getFieldAsInteger(LUMBER_CAPACITY, level);
return new CAbilityTypeHarvestLevelData(targetsAllowedAtLevel, damageToTree, goldCapacity, lumberCapacity);
}
@Override
protected CAbilityType<?> innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData,
final List<CAbilityTypeHarvestLevelData> levelData) {
return new CAbilityTypeHarvest(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -0,0 +1,35 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl;
import java.util.EnumSet;
import java.util.List;
import com.etheller.warsmash.units.manager.MutableObjectData.MutableGameObject;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl.CAbilityTypeReturnResourcesLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeDefinitionReturnResources
extends AbstractCAbilityTypeDefinition<CAbilityTypeReturnResourcesLevelData> implements CAbilityTypeDefinition {
protected static final War3ID ACCEPTS_GOLD = War3ID.fromString("Rtn1");
protected static final War3ID ACCEPTS_LUMBER = War3ID.fromString("Rtn2");
@Override
protected CAbilityTypeReturnResourcesLevelData createLevelData(final MutableGameObject abilityEditorData,
final int level) {
final String targetsAllowedAtLevelString = abilityEditorData.getFieldAsString(TARGETS_ALLOWED, level);
final EnumSet<CTargetType> targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString);
final boolean acceptsGold = abilityEditorData.getFieldAsBoolean(ACCEPTS_GOLD, level);
final boolean acceptsLumber = abilityEditorData.getFieldAsBoolean(ACCEPTS_LUMBER, level);
return new CAbilityTypeReturnResourcesLevelData(targetsAllowedAtLevel, acceptsGold, acceptsLumber);
}
@Override
protected CAbilityType<?> innerCreateAbilityType(final War3ID alias, final MutableGameObject abilityEditorData,
final List<CAbilityTypeReturnResourcesLevelData> levelData) {
return new CAbilityTypeReturnResources(alias, abilityEditorData.getCode(), levelData);
}
}

View File

@ -0,0 +1,24 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.List;
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.harvest.CAbilityHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
public class CAbilityTypeHarvest extends CAbilityType<CAbilityTypeHarvestLevelData> {
public CAbilityTypeHarvest(final War3ID alias, final War3ID code,
final List<CAbilityTypeHarvestLevelData> levelData) {
super(alias, code, levelData);
}
@Override
public CAbility createAbility(final int handleId) {
final CAbilityTypeHarvestLevelData levelData = getLevelData(0);
return new CAbilityHarvest(handleId, getAlias(), levelData.getDamageToTree(), levelData.getGoldCapacity(),
levelData.getLumberCapacity());
}
}

View File

@ -0,0 +1,33 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.EnumSet;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeHarvestLevelData extends CAbilityTypeLevelData {
private final int damageToTree;
private final int goldCapacity;
private final int lumberCapacity;
public CAbilityTypeHarvestLevelData(final EnumSet<CTargetType> targetsAllowed, final int damageToTree,
final int goldCapacity, final int lumberCapacity) {
super(targetsAllowed);
this.damageToTree = damageToTree;
this.goldCapacity = goldCapacity;
this.lumberCapacity = lumberCapacity;
}
public int getDamageToTree() {
return this.damageToTree;
}
public int getGoldCapacity() {
return this.goldCapacity;
}
public int getLumberCapacity() {
return this.lumberCapacity;
}
}

View File

@ -0,0 +1,32 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.EnumSet;
import java.util.List;
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.harvest.CAbilityReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
public class CAbilityTypeReturnResources extends CAbilityType<CAbilityTypeReturnResourcesLevelData> {
public CAbilityTypeReturnResources(final War3ID alias, final War3ID code,
final List<CAbilityTypeReturnResourcesLevelData> levelData) {
super(alias, code, levelData);
}
@Override
public CAbility createAbility(final int handleId) {
final CAbilityTypeReturnResourcesLevelData levelData = getLevelData(0);
final EnumSet<ResourceType> acceptedResourceTypes = EnumSet.noneOf(ResourceType.class);
if (levelData.isAcceptsGold()) {
acceptedResourceTypes.add(ResourceType.GOLD);
}
if (levelData.isAcceptsLumber()) {
acceptedResourceTypes.add(ResourceType.LUMBER);
}
return new CAbilityReturnResources(handleId, getAlias(), acceptedResourceTypes);
}
}

View File

@ -0,0 +1,28 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.impl;
import java.util.EnumSet;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAbilityTypeLevelData;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
public class CAbilityTypeReturnResourcesLevelData extends CAbilityTypeLevelData {
private final boolean acceptsGold;
private final boolean acceptsLumber;
public CAbilityTypeReturnResourcesLevelData(final EnumSet<CTargetType> targetsAllowed, final boolean acceptsGold,
final boolean acceptsLumber) {
super(targetsAllowed);
this.acceptsGold = acceptsGold;
this.acceptsLumber = acceptsLumber;
}
public boolean isAcceptsGold() {
return this.acceptsGold;
}
public boolean isAcceptsLumber() {
return this.acceptsLumber;
}
}

View File

@ -3,13 +3,10 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.PrimaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
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.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveAndTargetableVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack;
public class CBehaviorAttack extends CAbstractRangedBehavior {
@ -54,7 +51,8 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
@Override
protected boolean checkTargetStillValid(final CSimulation simulation) {
return this.target.visit(this.abilityTargetStillAliveVisitor.reset(simulation, this.unit, this.unitAttack));
return this.target.visit(
this.abilityTargetStillAliveVisitor.reset(simulation, this.unit, this.unitAttack.getTargetsAllowed()));
}
@Override
@ -117,42 +115,4 @@ public class CBehaviorAttack extends CAbstractRangedBehavior {
return this;
}
public static class AbilityTargetStillAliveAndTargetableVisitor implements AbilityTargetVisitor<Boolean> {
private CSimulation simulation;
private CUnit unit;
private CUnitAttack unitAttack;
public AbilityTargetStillAliveAndTargetableVisitor reset(final CSimulation simulation, final CUnit unit,
final CUnitAttack unitAttack) {
this.simulation = simulation;
this.unit = unit;
this.unitAttack = unitAttack;
return this;
}
@Override
public Boolean accept(final AbilityPointTarget target) {
return Boolean.TRUE;
}
@Override
public Boolean accept(final CUnit target) {
return !target.isDead()
&& target.canBeTargetedBy(this.simulation, this.unit, this.unitAttack.getTargetsAllowed());
}
@Override
public Boolean accept(final CDestructable target) {
return !target.isDead()
&& target.canBeTargetedBy(this.simulation, this.unit, this.unitAttack.getTargetsAllowed());
}
@Override
public Boolean accept(final CItem target) {
return !target.isDead()
&& target.canBeTargetedBy(this.simulation, this.unit, this.unitAttack.getTargetsAllowed());
}
}
}

View File

@ -71,12 +71,12 @@ public class CBehaviorOrcBuild extends CAbstractRangedBehavior {
ability.visit(AbilityDisableWhileUnderConstructionVisitor.INSTANCE);
}
this.unit.setHidden(true);
this.unit.setUpdating(false);
this.unit.setPaused(true);
this.unit.setInvulnerable(true);
simulation.unitConstructedEvent(this.unit, constructedStructure);
}
else {
CPlayer player = simulation.getPlayer(this.unit.getPlayerIndex());
final CPlayer player = simulation.getPlayer(this.unit.getPlayerIndex());
player.setFoodUsed(player.getFoodUsed() - unitTypeToCreate.getFoodUsed());
simulation.getCommandErrorListener().showCantPlaceError();
}

View File

@ -0,0 +1,157 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.harvest;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens.SecondaryTag;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CDestructable;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CItem;
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.harvest.CAbilityHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.harvest.CAbilityReturnResources;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.mine.CAbilityGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetStillAliveVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTargetVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CAbstractRangedBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.ResourceType;
public class CBehaviorHarvest extends CAbstractRangedBehavior implements AbilityTargetVisitor<CBehavior> {
private final CAbilityHarvest abilityHarvest;
private CSimulation simulation;
private int popoutFromMineTurnTick = 0;
private CAbilityGoldMine abilityGoldMine;
public CBehaviorHarvest(final CUnit unit, final CAbilityHarvest abilityHarvest) {
super(unit);
this.abilityHarvest = abilityHarvest;
}
public CBehaviorHarvest reset(final CWidget target) {
innerReset(target);
this.abilityGoldMine = null;
if (this.popoutFromMineTurnTick != 0) {
// TODO this check is probably only for debug and should be removed after
// extensive testing
throw new IllegalStateException("A unit took action while within a gold mine.");
}
return this;
}
@Override
public boolean isWithinRange(final CSimulation simulation) {
// TODO this is probably not what the CloseEnoughRange constant is for
return this.unit.canReach(this.target, simulation.getGameplayConstants().getCloseEnoughRange());
}
@Override
public int getHighlightOrderId() {
return OrderIds.harvest;
}
@Override
protected CBehavior update(final CSimulation simulation, final boolean withinRange) {
this.simulation = simulation;
return this.target.visit(this);
}
@Override
public CBehavior accept(final AbilityPointTarget target) {
return CBehaviorHarvest.this.unit.pollNextOrderBehavior(this.simulation);
}
@Override
public CBehavior accept(final CUnit target) {
if (this.popoutFromMineTurnTick == 0) {
if ((this.abilityHarvest.getCarriedResourceAmount() == 0)
|| (this.abilityHarvest.getCarriedResourceType() != ResourceType.GOLD)) {
for (final CAbility ability : target.getAbilities()) {
if (ability instanceof CAbilityGoldMine) {
final CAbilityGoldMine abilityGoldMine = (CAbilityGoldMine) ability;
final int activeMiners = abilityGoldMine.getActiveMiners();
if (activeMiners < abilityGoldMine.getMiningCapacity()) {
abilityGoldMine.setActiveMiners(activeMiners + 1);
this.unit.setHidden(true);
this.unit.setInvulnerable(true);
this.popoutFromMineTurnTick = this.simulation.getGameTurnTick()
+ (int) (abilityGoldMine.getMiningDuration()
/ WarsmashConstants.SIMULATION_STEP_TIME);
this.abilityGoldMine = abilityGoldMine;
break;
}
}
}
}
else {
for (final CAbility ability : target.getAbilities()) {
if (ability instanceof CAbilityReturnResources) {
final CAbilityReturnResources abilityReturnResources = (CAbilityReturnResources) ability;
if (abilityReturnResources.accepts(this.abilityHarvest.getCarriedResourceType())) {
final CPlayer player = this.simulation.getPlayer(this.unit.getPlayerIndex());
switch (this.abilityHarvest.getCarriedResourceType()) {
case FOOD:
throw new IllegalStateException("Unit used Harvest skill to carry FOOD resource!");
case GOLD:
player.setGold(player.getGold() + this.abilityHarvest.getCarriedResourceAmount());
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.GOLD);
break;
case LUMBER:
player.setLumber(player.getLumber() + this.abilityHarvest.getCarriedResourceAmount());
this.unit.getUnitAnimationListener().removeSecondaryTag(SecondaryTag.LUMBER);
break;
}
this.abilityHarvest.setCarriedResources(null, 0);
return this.unit.pollNextOrderBehavior(this.simulation);
}
}
}
}
}
else {
if (this.simulation.getGameTurnTick() >= this.popoutFromMineTurnTick) {
this.popoutFromMineTurnTick = 0;
this.unit.setHidden(false);
this.unit.setInvulnerable(false);
this.abilityGoldMine.setActiveMiners(this.abilityGoldMine.getActiveMiners() - 1);
int mineGoldRemaining = this.abilityGoldMine.getGold();
final int goldMined = Math.min(mineGoldRemaining, this.abilityHarvest.getGoldCapacity());
this.abilityHarvest.setCarriedResources(ResourceType.GOLD, goldMined);
mineGoldRemaining -= goldMined;
this.abilityGoldMine.setGold(mineGoldRemaining);
if (mineGoldRemaining <= 0) {
target.setLife(this.simulation, 0);
}
this.unit.getUnitAnimationListener().addSecondaryTag(SecondaryTag.GOLD);
this.simulation.unitRepositioned(this.unit);
return this.unit.pollNextOrderBehavior(this.simulation);
}
}
return this;
}
@Override
public CBehavior accept(final CDestructable target) {
// TODO cut trees!
return this.unit.pollNextOrderBehavior(this.simulation);
}
@Override
public CBehavior accept(final CItem target) {
return this.unit.pollNextOrderBehavior(this.simulation);
}
@Override
protected boolean checkTargetStillValid(final CSimulation simulation) {
return this.target.visit(AbilityTargetStillAliveVisitor.INSTANCE);
}
@Override
protected void resetBeforeMoving(final CSimulation simulation) {
}
}

View File

@ -12,6 +12,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.CAb
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.CAbilityTypeDefinition;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionGoldMine;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionHarvest;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.types.definitions.impl.CAbilityTypeDefinitionReturnResources;
public class CAbilityData {
@ -22,11 +24,14 @@ public class CAbilityData {
public CAbilityData(final MutableObjectData abilityData) {
this.abilityData = abilityData;
this.aliasToAbilityType = new HashMap<>();
registerCodes();
}
private void registerCodes() {
this.codeToAbilityTypeDefinition.put(War3ID.fromString("ACcw"), new CAbilityTypeDefinitionColdArrows());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Agld"), new CAbilityTypeDefinitionGoldMine());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Artn"), new CAbilityTypeDefinitionReturnResources());
this.codeToAbilityTypeDefinition.put(War3ID.fromString("Ahar"), new CAbilityTypeDefinitionHarvest());
}
public CAbilityType<?> getAbilityType(final War3ID alias) {
@ -35,7 +40,10 @@ public class CAbilityData {
final MutableGameObject mutableGameObject = this.abilityData.get(alias);
final War3ID code = mutableGameObject.getCode();
final CAbilityTypeDefinition abilityTypeDefinition = this.codeToAbilityTypeDefinition.get(code);
if (abilityTypeDefinition != null) {
abilityType = abilityTypeDefinition.createAbilityType(alias, mutableGameObject);
this.aliasToAbilityType.put(alias, abilityType);
}
}
return abilityType;
}