diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java index a3f003dfb..5dd147278 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnit.java @@ -36,6 +36,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorMove; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorPatrol; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehaviorStop; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build.CBehaviorNightElfBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build.ConstructionFlag; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.attacks.CUnitAttack; @@ -86,6 +88,8 @@ public class CUnit extends CWidget { private int deathTurnTick; private boolean corpse; private boolean boneCorpse; + //addedByMFromAz - my fault if it's bad + private boolean consumed; private transient CUnitAnimationListener unitAnimationListener; @@ -106,6 +110,9 @@ public class CUnit extends CWidget { private transient CBehaviorHoldPosition holdPositionBehavior; private boolean constructing = false; private float constructionProgress; + //added by MfromAz - if it's bad that's on me + private ConstructionFlag constuctionProcessType; + private boolean constructionPowerBuild = false; private boolean hidden = false; private boolean paused = false; private boolean acceptingOrders = true; @@ -117,6 +124,7 @@ public class CUnit extends CWidget { private final QueueItemType[] buildQueueTypes = new QueueItemType[WarsmashConstants.BUILD_QUEUE_SIZE]; private boolean queuedUnitFoodPaid = false; private AbilityTarget rallyPoint; + private boolean constructionCanceled = false; private int foodMade; private int foodUsed; @@ -126,8 +134,8 @@ public class CUnit extends CWidget { private transient Set priorContainingRegions = new LinkedHashSet<>(); public CUnit(final int handleId, final int playerIndex, final float x, final float y, final float life, - final War3ID typeId, final float facing, final float mana, final int maximumLife, final int maximumMana, - final int speed, final CUnitType unitType, final RemovablePathingMapInstance pathingInstance) { + final War3ID typeId, final float facing, final float mana, final int maximumLife, final int maximumMana, + final int speed, final CUnitType unitType, final RemovablePathingMapInstance pathingInstance) { super(handleId, x, y, life); this.playerIndex = playerIndex; this.typeId = typeId; @@ -144,6 +152,8 @@ public CUnit(final int handleId, final int playerIndex, final float x, final flo this.stopBehavior = new CBehaviorStop(this); this.defaultBehavior = this.stopBehavior; this.currentBehavior = this.defaultBehavior; + + this.consumed = false; } private void computeDerivedFields() { @@ -248,6 +258,27 @@ public int getSpeed() { return this.speed; } + public boolean isConsumed(){ + return consumed; + } + + public void setConsumed(boolean consumed){ + this.consumed = consumed; + } + + public ConstructionFlag getConstuctionProcessType(){return constuctionProcessType;} + + public void setConstuctionProcessType(ConstructionFlag flag) {this.constuctionProcessType = flag;} + + public void setConstructionPowerBuild(boolean constructionPowerBuild){this.constructionPowerBuild= constructionPowerBuild;} + + public boolean isConstructionPowerBuilding(){return constructionPowerBuild;} + + public void setConstructionCanceled(boolean constructionCanceled){this.constructionCanceled= constructionCanceled;} + + public boolean isConstructionCanceled(){return constructionCanceled;} + + /** * Updates one tick of simulation logic and return true if it's time to remove * this unit from the game. @@ -255,14 +286,20 @@ public int getSpeed() { public boolean update(final CSimulation game) { for (final StateListenerUpdate update : this.stateListenersUpdates) { switch (update.getUpdateType()) { - case ADD: - this.stateNotifier.subscribe(update.listener); - break; - case REMOVE: - this.stateNotifier.unsubscribe(update.listener); - break; + case ADD: + this.stateNotifier.subscribe(update.listener); + break; + case REMOVE: + this.stateNotifier.unsubscribe(update.listener); + break; } } + if(isConsumed()){ + //Food is subtracted when building process starts + int resetFoodWithUsageAddedBack = game.getPlayer(this.getPlayerIndex()).getFoodUsed()+this.getFoodUsed(); + game.getPlayer(this.getPlayerIndex()).setFoodUsed(resetFoodWithUsageAddedBack); + return true; + } if (isDead()) { if (this.collisionRectangle != null) { // Moved this here because doing it on "kill" was able to happen in some cases @@ -317,15 +354,31 @@ else if (!this.paused) { setRallyPoint(this); } if (this.constructing) { - this.constructionProgress += WarsmashConstants.SIMULATION_STEP_TIME; final int buildTime = this.unitType.getBuildTime(); - final float healthGain = (WarsmashConstants.SIMULATION_STEP_TIME / buildTime) - * (this.maximumLife * (1.0f - WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE)); - setLife(game, Math.min(this.life + healthGain, this.maximumLife)); + //ignore this for human build (MFROMAZ) + if(this.constuctionProcessType==null||this.constuctionProcessType!=ConstructionFlag.REQURIE_REPAIR) { + this.constructionProgress += WarsmashConstants.SIMULATION_STEP_TIME; + final float healthGain = (WarsmashConstants.SIMULATION_STEP_TIME / buildTime) + * (this.maximumLife * (1.0f - WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE)); + setLife(game, Math.min(this.life + healthGain, this.maximumLife)); + }else{ + this.constructionPowerBuild = false; + //resetting here every frame so that workers can set it to true on the next one again + } if (this.constructionProgress >= buildTime) { this.constructing = false; this.constructionProgress = 0; - popoutWorker(game); + CUnit worker = getWorkerInside(); + + //removing wisp here (MFROMAZ) + if(this.constuctionProcessType!=null&&this.constuctionProcessType==ConstructionFlag.CONSUME_WORKER){ + worker.setConsumed(true); + }else{ + popoutWorker(game); + } + + //create Blight here (MFROMAZ) + final Iterator abilityIterator = this.abilities.iterator(); while (abilityIterator.hasNext()) { final CAbility ability = abilityIterator.next(); @@ -773,7 +826,7 @@ else if (this.collisionRectangle != null) { } public void setPoint(final float newX, final float newY, final CWorldCollision collision, - final CRegionManager regionManager) { + final CRegionManager regionManager) { final float prevX = getX(); final float prevY = getY(); setX(newX); @@ -863,7 +916,7 @@ public double distance(final float x, final float y) { @Override public void damage(final CSimulation simulation, final CUnit source, final CAttackType attackType, - final String weaponType, final float damage) { + final String weaponType, final float damage) { final boolean wasDead = isDead(); if (!this.invulnerable) { final float damageRatioFromArmorClass = simulation.getGameplayConstants().getDamageRatioAgainst(attackType, @@ -931,7 +984,20 @@ private void kill(final CSimulation simulation, final CUnit source) { this.pathingInstance.remove(); this.pathingInstance = null; } - popoutWorker(simulation); + if(!(this.getConstuctionProcessType()!=null&&this.getConstuctionProcessType()==ConstructionFlag.CONSUME_WORKER)){ + popoutWorker(simulation); + }else{ + if(workerInside!=null) { + if (this.isConstructionCanceled()) { + int resetFoodWithUsageAddedBack = simulation.getPlayer(this.getPlayerIndex()).getFoodUsed() + workerInside.getFoodUsed(); + popoutWorker(simulation); + simulation.getPlayer(this.getPlayerIndex()).setFoodUsed(resetFoodWithUsageAddedBack); + } else { + workerInside.setConsumed(true); + } + } + } + final CPlayer player = simulation.getPlayer(this.playerIndex); if (this.foodMade != 0) { player.setUnitFoodMade(this, 0); @@ -960,16 +1026,16 @@ private void kill(final CSimulation simulation, final CUnit source) { final int heroExpRange = gameplayConstants.getHeroExpRange(); simulation.getWorldCollision().enumUnitsInRect(new Rectangle(this.getX() - heroExpRange, this.getY() - heroExpRange, heroExpRange * 2, heroExpRange * 2), new CUnitEnumFunction() { - @Override - public boolean call(final CUnit unit) { - if ((unit.distance(killedUnit) <= heroExpRange) - && sourcePlayer.hasAlliance(unit.getPlayerIndex(), CAllianceType.SHARED_XP) - && (unit.getHeroData() != null)) { - xpReceivingHeroes.add(unit); - } - return false; - } - }); + @Override + public boolean call(final CUnit unit) { + if ((unit.distance(killedUnit) <= heroExpRange) + && sourcePlayer.hasAlliance(unit.getPlayerIndex(), CAllianceType.SHARED_XP) + && (unit.getHeroData() != null)) { + xpReceivingHeroes.add(unit); + } + return false; + } + }); if (xpReceivingHeroes.isEmpty()) { if (gameplayConstants.isGlobalExperience()) { for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) { @@ -1023,7 +1089,7 @@ public boolean canReach(final float x, final float y, final float range) { } public boolean canReachToPathing(final float range, final float rotationForPathing, - final BufferedImage buildingPathingPixelMap, final float targetX, final float targetY) { + final BufferedImage buildingPathingPixelMap, final float targetX, final float targetY) { final int rotation = ((int) rotationForPathing + 450) % 360; final float relativeOffsetX = getX() - targetX; final float relativeOffsetY = getY() - targetY; @@ -1071,28 +1137,28 @@ public boolean canReachToPathing(final float range, final float rotationForPathi } private int getRGBFromPixelData(final BufferedImage buildingPathingPixelMap, final int checkX, final int checkY, - final int rotation) { + final int rotation) { // Below: y is downwards (:() int x; int y; switch (rotation) { - case 90: - x = checkY; - y = buildingPathingPixelMap.getWidth() - 1 - checkX; - break; - case 180: - x = buildingPathingPixelMap.getWidth() - 1 - checkX; - y = buildingPathingPixelMap.getHeight() - 1 - checkY; - break; - case 270: - x = buildingPathingPixelMap.getHeight() - 1 - checkY; - y = checkX; - break; - default: - case 0: - x = checkX; - y = checkY; + case 90: + x = checkY; + y = buildingPathingPixelMap.getWidth() - 1 - checkX; + break; + case 180: + x = buildingPathingPixelMap.getWidth() - 1 - checkX; + y = buildingPathingPixelMap.getHeight() - 1 - checkY; + break; + case 270: + x = buildingPathingPixelMap.getHeight() - 1 - checkY; + y = checkX; + break; + default: + case 0: + x = checkX; + y = checkY; } return buildingPathingPixelMap.getRGB(x, buildingPathingPixelMap.getHeight() - 1 - y); } @@ -1115,7 +1181,7 @@ public boolean isBoneCorpse() { @Override public boolean canBeTargetedBy(final CSimulation simulation, final CUnit source, - final EnumSet targetsAllowed) { + final EnumSet targetsAllowed) { if (targetsAllowed.containsAll(this.unitType.getTargetedAs()) || (!targetsAllowed.contains(CTargetType.GROUND) && (!targetsAllowed.contains(CTargetType.STRUCTURE) && !targetsAllowed.contains(CTargetType.AIR)))) { final int sourcePlayerIndex = source.getPlayerIndex(); @@ -1158,7 +1224,7 @@ private static final class AutoAttackTargetFinderEnum implements CUnitEnumFuncti private boolean foundAnyTarget; private AutoAttackTargetFinderEnum reset(final CSimulation game, final CUnit source, - final boolean disableMove) { + final boolean disableMove) { this.game = game; this.source = source; this.disableMove = disableMove; @@ -1346,20 +1412,20 @@ public float getBuildQueueTimeRemaining(final CSimulation simulation) { return 0; } switch (this.buildQueueTypes[0]) { - case RESEARCH: - return 999; // TODO - case UNIT: { - final CUnitType trainedUnitType = simulation.getUnitData().getUnitType(this.buildQueue[0]); - return trainedUnitType.getBuildTime(); - } - case HERO_REVIVE: { - final CUnit hero = simulation.getUnit(this.buildQueue[0].getValue()); - final CUnitType trainedUnitType = hero.getUnitType(); - return simulation.getGameplayConstants().getHeroReviveTime(trainedUnitType.getBuildTime(), - hero.getHeroData().getHeroLevel()); - } - default: - return 0; + case RESEARCH: + return 999; // TODO + case UNIT: { + final CUnitType trainedUnitType = simulation.getUnitData().getUnitType(this.buildQueue[0]); + return trainedUnitType.getBuildTime(); + } + case HERO_REVIVE: { + final CUnit hero = simulation.getUnit(this.buildQueue[0].getValue()); + final CUnitType trainedUnitType = hero.getUnitType(); + return simulation.getGameplayConstants().getHeroReviveTime(trainedUnitType.getBuildTime(), + hero.getHeroData().getHeroLevel()); + } + default: + return 0; } } @@ -1371,44 +1437,44 @@ public void cancelBuildQueueItem(final CSimulation game, final int cancelIndex) if (cancelIndex == 0) { this.constructionProgress = 0.0f; switch (cancelledType) { + case RESEARCH: + break; + case UNIT: { + final CPlayer player = game.getPlayer(this.playerIndex); + final CUnitType unitType = game.getUnitData().getUnitType(this.buildQueue[cancelIndex]); + player.setFoodUsed(player.getFoodUsed() - unitType.getFoodUsed()); + break; + } + case HERO_REVIVE: { + final CPlayer player = game.getPlayer(this.playerIndex); + final CUnitType unitType = game.getUnit(this.buildQueue[cancelIndex].getValue()).getUnitType(); + player.setFoodUsed(player.getFoodUsed() - unitType.getFoodUsed()); + break; + } + } + } + switch (cancelledType) { case RESEARCH: break; case UNIT: { final CPlayer player = game.getPlayer(this.playerIndex); final CUnitType unitType = game.getUnitData().getUnitType(this.buildQueue[cancelIndex]); - player.setFoodUsed(player.getFoodUsed() - unitType.getFoodUsed()); + player.refundFor(unitType); break; } case HERO_REVIVE: { final CPlayer player = game.getPlayer(this.playerIndex); - final CUnitType unitType = game.getUnit(this.buildQueue[cancelIndex].getValue()).getUnitType(); - player.setFoodUsed(player.getFoodUsed() - unitType.getFoodUsed()); + final CUnit hero = game.getUnit(this.buildQueue[cancelIndex].getValue()); + final CUnitType unitType = hero.getUnitType(); + final CAbilityHero heroData = hero.getHeroData(); + heroData.setReviving(false); + final CGameplayConstants gameplayConstants = game.getGameplayConstants(); + player.refund( + gameplayConstants.getHeroReviveGoldCost(unitType.getGoldCost(), heroData.getHeroLevel()), + gameplayConstants.getHeroReviveLumberCost(unitType.getLumberCost(), + heroData.getHeroLevel())); break; } - } - } - switch (cancelledType) { - case RESEARCH: - break; - case UNIT: { - final CPlayer player = game.getPlayer(this.playerIndex); - final CUnitType unitType = game.getUnitData().getUnitType(this.buildQueue[cancelIndex]); - player.refundFor(unitType); - break; - } - case HERO_REVIVE: { - final CPlayer player = game.getPlayer(this.playerIndex); - final CUnit hero = game.getUnit(this.buildQueue[cancelIndex].getValue()); - final CUnitType unitType = hero.getUnitType(); - final CAbilityHero heroData = hero.getHeroData(); - heroData.setReviving(false); - final CGameplayConstants gameplayConstants = game.getGameplayConstants(); - player.refund( - gameplayConstants.getHeroReviveGoldCost(unitType.getGoldCost(), heroData.getHeroLevel()), - gameplayConstants.getHeroReviveLumberCost(unitType.getLumberCost(), - heroData.getHeroLevel())); - break; - } } for (int i = cancelIndex; i < (this.buildQueueTypes.length - 1); i++) { setBuildQueueItem(game, i, this.buildQueue[i + 1], this.buildQueueTypes[i + 1]); @@ -1420,7 +1486,7 @@ public void cancelBuildQueueItem(final CSimulation game, final int cancelIndex) } public void setBuildQueueItem(final CSimulation game, final int index, final War3ID rawcode, - final QueueItemType queueItemType) { + final QueueItemType queueItemType) { this.buildQueue[index] = rawcode; this.buildQueueTypes[index] = queueItemType; if (index == 0) { @@ -1519,7 +1585,7 @@ private static final class UseAbilityOnTargetByIdVisitor implements AbilityTarge private int rallyOrderId; private UseAbilityOnTargetByIdVisitor reset(final CSimulation game, final CUnit trainedUnit, - final int rallyOrderId) { + final int rallyOrderId) { this.game = game; this.trainedUnit = trainedUnit; this.rallyOrderId = rallyOrderId; @@ -1554,7 +1620,7 @@ public Void accept(final CUnit targetUnit) { } private Void acceptWidget(final CSimulation game, final CUnit trainedUnit, final int rallyOrderId, - final CWidget target) { + final CWidget target) { CAbility abilityToUse = null; for (final CAbility ability : trainedUnit.getAbilities()) { ability.checkCanUse(game, trainedUnit, rallyOrderId, BooleanAbilityActivationReceiver.INSTANCE); @@ -1744,4 +1810,4 @@ public StateListenerUpdateType getUpdateType() { return this.updateType; } } -} +} \ No newline at end of file diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java index cea6b5f2a..0409763d9 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CUnitType.java @@ -78,22 +78,22 @@ public class CUnitType { private final boolean revivesHeroes; public CUnitType(final String name, final String legacyName, final War3ID typeId, final int maxLife, - final int manaInitial, final int manaMaximum, final int speed, final int defense, final String abilityList, - final boolean isBldg, final MovementType movementType, final float defaultFlyingHeight, - final float collisionSize, final EnumSet classifications, - final List attacks, final String armorType, final boolean raise, final boolean decay, - final CDefenseType defenseType, final float impactZ, final BufferedImage buildingPathingPixelMap, - final float deathTime, final EnumSet targetedAs, final float defaultAcquisitionRange, - final float minimumAttackRange, final List structuresBuilt, final List unitsTrained, - final List researchesAvailable, final CUnitRace unitRace, final int goldCost, final int lumberCost, - final int foodUsed, final int foodMade, final int buildTime, - final EnumSet preventedPathingTypes, - final EnumSet requiredPathingTypes, final float propWindow, final float turnRate, - final List requirements, final int level, final boolean hero, final int strength, - final float strengthPerLevel, final int agility, final float agilityPerLevel, final int intelligence, - final float intelligencePerLevel, final CPrimaryAttribute primaryAttribute, - final List heroAbilityList, final List heroProperNames, final int properNamesCount, - final boolean canFlee, final int priority, final boolean revivesHeroes) { + final int manaInitial, final int manaMaximum, final int speed, final int defense, final String abilityList, + final boolean isBldg, final MovementType movementType, final float defaultFlyingHeight, + final float collisionSize, final EnumSet classifications, + final List attacks, final String armorType, final boolean raise, final boolean decay, + final CDefenseType defenseType, final float impactZ, final BufferedImage buildingPathingPixelMap, + final float deathTime, final EnumSet targetedAs, final float defaultAcquisitionRange, + final float minimumAttackRange, final List structuresBuilt, final List unitsTrained, + final List researchesAvailable, final CUnitRace unitRace, final int goldCost, final int lumberCost, + final int foodUsed, final int foodMade, final int buildTime, + final EnumSet preventedPathingTypes, + final EnumSet requiredPathingTypes, final float propWindow, final float turnRate, + final List requirements, final int level, final boolean hero, final int strength, + final float strengthPerLevel, final int agility, final float agilityPerLevel, final int intelligence, + final float intelligencePerLevel, final CPrimaryAttribute primaryAttribute, + final List heroAbilityList, final List heroProperNames, final int properNamesCount, + final boolean canFlee, final int priority, final boolean revivesHeroes) { this.name = name; this.legacyName = legacyName; this.typeId = typeId; @@ -365,4 +365,4 @@ public int getPriority() { public boolean isRevivesHeroes() { return this.revivesHeroes; } -} +} \ No newline at end of file diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java index 7c9c08590..cdb5ebc45 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityBuildInProgress.java @@ -37,6 +37,7 @@ public void onTick(final CSimulation game, final CUnit unit) { public boolean checkBeforeQueue(final CSimulation game, final CUnit caster, final int orderId, AbilityTarget target) { final CPlayer player = game.getPlayer(caster.getPlayerIndex()); player.refundFor(caster.getUnitType()); + caster.setConstructionCanceled(true); caster.setLife(game, 0); return false; } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanBuild.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanBuild.java index b6f420ff9..a7dce6549 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanBuild.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanBuild.java @@ -1,21 +1,26 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build; +import java.awt.image.BufferedImage; import java.util.List; 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.CAbilityVisitor; 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.build.CBehaviorHumanBuild; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build.CBehaviorNightElfBuild; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; public class CAbilityHumanBuild extends AbstractCAbilityBuild { + private CBehaviorHumanBuild buildBehavior; public CAbilityHumanBuild(final int handleId, final List structuresBuilt) { super(handleId, structuresBuilt); - // TODO Auto-generated constructor stub } @Override @@ -25,8 +30,7 @@ public int getBaseOrderId() { @Override public void onAdd(final CSimulation game, final CUnit unit) { - // TODO Auto-generated method stub - + this.buildBehavior = new CBehaviorHumanBuild(unit); } @Override @@ -37,21 +41,37 @@ 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) { - // TODO Auto-generated method stub - return null; + return caster.pollNextOrderBehavior(game); } @Override public CBehavior begin(final CSimulation game, final CUnit caster, final int orderId, final AbilityPointTarget point) { // caster.getMoveBehavior().reset(point.x, point.y, ) - return null; + final War3ID orderIdAsRawtype = new War3ID(orderId); + final CUnitType unitType = game.getUnitData().getUnitType(orderIdAsRawtype); + final BufferedImage buildingPathingPixelMap = unitType.getBuildingPathingPixelMap(); + if (buildingPathingPixelMap != null) { + point.x = (float) Math.floor(point.x / 64f) * 64f; + point.y = (float) Math.floor(point.y / 64f) * 64f; + if (((buildingPathingPixelMap.getWidth() / 2) % 2) == 1) { + point.x += 32f; + } + if (((buildingPathingPixelMap.getHeight() / 2) % 2) == 1) { + point.y += 32f; + } + } + final CPlayer player = game.getPlayer(caster.getPlayerIndex()); + player.chargeFor(unitType); + if (unitType.getFoodUsed() != 0) { + player.setFoodUsed(player.getFoodUsed() + unitType.getFoodUsed()); + } + return this.buildBehavior.reset(point, orderId, getBaseOrderId()); } @Override public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final int orderId) { - // TODO Auto-generated method stub - return null; + return caster.pollNextOrderBehavior(game); } @Override diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanRepair.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanRepair.java index 3b1ec1400..f2f3a9df5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanRepair.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityHumanRepair.java @@ -21,8 +21,12 @@ public class CAbilityHumanRepair extends AbstractGenericSingleIconActiveAbility private final float repairCostRatio; private final float repairTimeRatio; private final float castRange; + private final float powerBuildCostRatio; + private final float powerBuildTimeRatio; private CBehaviorHumanRepair behaviorRepair; + /* + //old version left in for compatibility public CAbilityHumanRepair(int handleId, War3ID alias, EnumSet targetsAllowed, float navalRangeBonus, float repairCostRatio, float repairTimeRatio, float castRange) { @@ -32,6 +36,21 @@ public CAbilityHumanRepair(int handleId, War3ID alias, EnumSet targ this.repairCostRatio = repairCostRatio; this.repairTimeRatio = repairTimeRatio; this.castRange = castRange; + this.powerBuildCostRatio = 0; + this.powerBuildTimeRatio = 0; + }*/ + + public CAbilityHumanRepair(int handleId, War3ID alias, EnumSet targetsAllowed, + float navalRangeBonus, float repairCostRatio, float repairTimeRatio, + float castRange, float powerBuildCostRatio, float powerBuildTimeRatio) { + super(handleId, alias); + this.targetsAllowed = targetsAllowed; + this.navalRangeBonus = navalRangeBonus; + this.repairCostRatio = repairCostRatio; + this.repairTimeRatio = repairTimeRatio; + this.castRange = castRange; + this.powerBuildCostRatio = powerBuildCostRatio; + this.powerBuildTimeRatio = powerBuildTimeRatio; } @Override @@ -132,4 +151,8 @@ public float getRepairTimeRatio() { public float getCastRange() { return castRange; } + + public float getPowerBuildCostRatio() { return powerBuildCostRatio; } + + public float getPowerBuildTimeRatio() { return powerBuildTimeRatio; } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityNightElfBuild.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityNightElfBuild.java index 9fd0a2ada..ce49a0566 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityNightElfBuild.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/build/CAbilityNightElfBuild.java @@ -11,12 +11,13 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbilityVisitor; 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.build.CBehaviorNightElfBuild; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build.CBehaviorOrcBuild; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.orders.OrderIds; import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; public class CAbilityNightElfBuild extends AbstractCAbilityBuild { - private CBehaviorOrcBuild buildBehavior; + private CBehaviorNightElfBuild buildBehavior; public CAbilityNightElfBuild(final int handleId, final List structuresBuilt) { super(handleId, structuresBuilt); @@ -29,7 +30,7 @@ public T visit(final CAbilityVisitor visitor) { @Override public void onAdd(final CSimulation game, final CUnit unit) { - this.buildBehavior = new CBehaviorOrcBuild(unit); + this.buildBehavior = new CBehaviorNightElfBuild(unit); } @Override @@ -74,4 +75,9 @@ public CBehavior beginNoTarget(final CSimulation game, final CUnit caster, final public int getBaseOrderId() { return OrderIds.nightelfbuild; } + + @Override + public void onCancelFromQueue(CSimulation game, CUnit unit, int orderId) { + super.onCancelFromQueue(game, unit, orderId); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionHumanRepair.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionHumanRepair.java index 758d6ad0d..0660d25f1 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionHumanRepair.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/definitions/impl/CAbilityTypeDefinitionHumanRepair.java @@ -15,6 +15,8 @@ public class CAbilityTypeDefinitionHumanRepair extends AbstractCAbilityTypeDefin implements CAbilityTypeDefinition { protected static final War3ID COST_RATIO = War3ID.fromString("Rep1"); protected static final War3ID TIME_RATIO = War3ID.fromString("Rep2"); + protected static final War3ID POWER_COST_RATIO = War3ID.fromString("Rep3"); + protected static final War3ID POWER_TIME_RATIO = War3ID.fromString("Rep4"); protected static final War3ID NAVAL_RANGE_BONUS = War3ID.fromString("Rep5"); @Override @@ -23,9 +25,11 @@ protected CAbilityTypeHumanRepairLevelData createLevelData(final MutableGameObje final EnumSet targetsAllowedAtLevel = CTargetType.parseTargetTypeSet(targetsAllowedAtLevelString); final float costRatio = abilityEditorData.getFieldAsFloat(COST_RATIO, level); final float timeRatio = abilityEditorData.getFieldAsFloat(TIME_RATIO, level); + final float powerBuildCostRatio = abilityEditorData.getFieldAsFloat(POWER_COST_RATIO,level); + final float powerBuildTimeRatio = abilityEditorData.getFieldAsFloat(POWER_TIME_RATIO,level); final float navalRangeBonus = abilityEditorData.getFieldAsFloat(NAVAL_RANGE_BONUS, level); final float castRange = abilityEditorData.getFieldAsFloat(CAST_RANGE, level); - return new CAbilityTypeHumanRepairLevelData(targetsAllowedAtLevel, navalRangeBonus, costRatio, timeRatio, castRange); + return new CAbilityTypeHumanRepairLevelData(targetsAllowedAtLevel, navalRangeBonus, costRatio, timeRatio, castRange, powerBuildCostRatio, powerBuildTimeRatio); } @Override diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepair.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepair.java index e1c769221..3b6767f12 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepair.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepair.java @@ -17,9 +17,10 @@ public CAbilityTypeHumanRepair(final War3ID alias, final War3ID code, @Override public CAbility createAbility(final int handleId) { final CAbilityTypeHumanRepairLevelData levelData = getLevelData(0); + //System.out.println("Time: "+levelData.getPowerbuildTimeRatio() + " Cost: " + levelData.getPowerbuildCostRatio() ); return new CAbilityHumanRepair(handleId, getAlias(), levelData.getTargetsAllowed(), levelData.getNavalRangeBonus(), levelData.getRepairCostRatio(), levelData.getRepairTimeRatio(), - levelData.getCastRange()); + levelData.getCastRange(), levelData.getPowerbuildCostRatio(), levelData.getPowerbuildTimeRatio()); } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepairLevelData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepairLevelData.java index 834bf8798..6535c00f5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepairLevelData.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/types/impl/CAbilityTypeHumanRepairLevelData.java @@ -10,13 +10,18 @@ public class CAbilityTypeHumanRepairLevelData extends CAbilityTypeLevelData { private final float navalRangeBonus; private final float repairCostRatio; private final float repairTimeRatio; + private final float powerbuildCostRatio; + private final float powerbuildTimeRatio; private final float castRange; - public CAbilityTypeHumanRepairLevelData(EnumSet targetsAllowed, float navalRangeBonus, float repairCostRatio, float repairTimeRatio, float castRange) { + public CAbilityTypeHumanRepairLevelData(EnumSet targetsAllowed, float navalRangeBonus, float repairCostRatio, + float repairTimeRatio, float castRange, float powerBuildCostRatio, float powerBuildTimeRatio) { super(targetsAllowed); this.navalRangeBonus = navalRangeBonus; this.repairCostRatio = repairCostRatio; this.repairTimeRatio = repairTimeRatio; + this.powerbuildCostRatio = powerBuildCostRatio; + this.powerbuildTimeRatio = powerBuildTimeRatio; this.castRange = castRange; } @@ -35,4 +40,8 @@ public float getRepairCostRatio() { public float getRepairTimeRatio() { return repairTimeRatio; } + + public float getPowerbuildCostRatio(){ return powerbuildCostRatio; }; + + public float getPowerbuildTimeRatio() { return powerbuildTimeRatio; } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorHumanBuild.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorHumanBuild.java new file mode 100644 index 000000000..d3c8b0aac --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorHumanBuild.java @@ -0,0 +1,164 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build; + +import com.etheller.warsmash.util.War3ID; +import com.etheller.warsmash.util.WarsmashConstants; +import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens; +import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils; +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.abilities.CAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityHumanRepair; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget; +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.pathing.CBuildingPathingType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; + +import java.awt.image.BufferedImage; +import java.util.EnumSet; + +public class CBehaviorHumanBuild extends CAbstractRangedBehavior { + private static int delayAnimationTicks = (int) (2.267f / WarsmashConstants.SIMULATION_STEP_TIME); + private int highlightOrderId; + private War3ID orderId; + private boolean unitCreated = false; + private boolean done = false; + private CUnit constructedStructure = null; + + public CBehaviorHumanBuild(CUnit unit) { + super(unit); + } + + public CBehavior reset(final AbilityPointTarget target, final int orderId, final int highlightOrderId) { + this.highlightOrderId = highlightOrderId; + this.orderId = new War3ID(orderId); + this.unitCreated = false; + this.done = false; + return innerReset(target); + } + + @Override + public boolean isWithinRange(final CSimulation simulation) { + if (this.done != false) { + return true; + } + final CUnitType unitType = simulation.getUnitData().getUnitType(this.orderId); + final BufferedImage buildingPathingPixelMap = unitType.getBuildingPathingPixelMap(); + if (buildingPathingPixelMap == null) { + return this.unit.canReach(this.target.getX(), this.target.getY(), unitType.getCollisionSize()); + } + return this.unit.canReachToPathing(0, simulation.getGameplayConstants().getBuildingAngle(), + buildingPathingPixelMap, this.target.getX(), this.target.getY()); + } + + @Override + public int getHighlightOrderId() { + return this.highlightOrderId; + } + + @Override + protected CBehavior update(final CSimulation simulation, final boolean withinFacingWindow) { + if (this.done) { + if(this.constructedStructure==null){ + return this.unit.pollNextOrderBehavior(simulation); + }else{ + CBehaviorHumanRepair repair = new CBehaviorHumanRepair(this.unit,this.unit.getFirstAbilityOfType(CAbilityHumanRepair.class)); + repair.reset(this.constructedStructure); + return repair; + } + } + else if (!this.unitCreated) { + this.unitCreated = true; + final CUnitType unitTypeToCreate = simulation.getUnitData().getUnitType(this.orderId); + final BufferedImage buildingPathingPixelMap = unitTypeToCreate.getBuildingPathingPixelMap(); + boolean buildLocationObstructed = false; + if (buildingPathingPixelMap != null) { + final EnumSet preventedPathingTypes = unitTypeToCreate.getPreventedPathingTypes(); + final EnumSet requiredPathingTypes = unitTypeToCreate.getRequiredPathingTypes(); + + if (!simulation.getPathingGrid().checkPathingTexture(this.target.getX(), this.target.getY(), + (int) simulation.getGameplayConstants().getBuildingAngle(), buildingPathingPixelMap, + preventedPathingTypes, requiredPathingTypes, simulation.getWorldCollision(), this.unit)) { + buildLocationObstructed = true; + } + } + final int playerIndex = this.unit.getPlayerIndex(); + if (!buildLocationObstructed) { + constructedStructure = simulation.createUnit(this.orderId, playerIndex, this.target.getX(), + this.target.getY(), simulation.getGameplayConstants().getBuildingAngle()); + constructedStructure.setConstructing(true); + constructedStructure.setLife(simulation, + constructedStructure.getMaximumLife() * WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE); + constructedStructure.setFoodUsed(unitTypeToCreate.getFoodUsed()); + constructedStructure.add(simulation, + new CAbilityBuildInProgress(simulation.getHandleIdAllocator().createId())); + for (final CAbility ability : constructedStructure.getAbilities()) { + ability.visit(AbilityDisableWhileUnderConstructionVisitor.INSTANCE); + } + final float deltaX = this.unit.getX() - this.target.getX(); + final float deltaY = this.unit.getY() - this.target.getY(); + final float delta = (float) Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)); + this.unit.setPoint(this.target.getX() + ((deltaX / delta) * unitTypeToCreate.getCollisionSize()), + this.target.getY() + ((deltaY / delta) * unitTypeToCreate.getCollisionSize()), + simulation.getWorldCollision(), simulation.getRegionManager()); + constructedStructure.setConstuctionProcessType(ConstructionFlag.REQURIE_REPAIR); + simulation.unitRepositioned(this.unit); + simulation.unitConstructedEvent(this.unit, constructedStructure); + this.done = true; + } + else { + final CPlayer player = simulation.getPlayer(playerIndex); + refund(player, unitTypeToCreate); + simulation.getCommandErrorListener(playerIndex).showCantPlaceError(); + return this.unit.pollNextOrderBehavior(simulation); + } + } + this.unit.getUnitAnimationListener().playAnimation(false, AnimationTokens.PrimaryTag.STAND, SequenceUtils.WORK, 1.0f, true); + return this; + } + + @Override + protected boolean checkTargetStillValid(final CSimulation simulation) { + return true; + } + + @Override + protected CBehavior updateOnInvalidTarget(final CSimulation simulation) { + return this.unit.pollNextOrderBehavior(simulation); + } + + @Override + protected void resetBeforeMoving(final CSimulation simulation) { + + } + + @Override + public void begin(final CSimulation game) { + + } + + @Override + public void end(final CSimulation game, final boolean interrupted) { + if (!this.unitCreated && interrupted) { + final CPlayer player = game.getPlayer(this.unit.getPlayerIndex()); + final CUnitType unitTypeToCreate = game.getUnitData().getUnitType(this.orderId); + refund(player, unitTypeToCreate); + } + } + + private void refund(final CPlayer player, final CUnitType unitTypeToCreate) { + player.setFoodUsed(player.getFoodUsed() - unitTypeToCreate.getFoodUsed()); + player.refundFor(unitTypeToCreate); + } + + @Override + public void endMove(final CSimulation game, final boolean interrupted) { + if (!this.unitCreated && interrupted) { + final CPlayer player = game.getPlayer(this.unit.getPlayerIndex()); + final CUnitType unitTypeToCreate = game.getUnitData().getUnitType(this.orderId); + refund(player, unitTypeToCreate); + } + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorHumanRepair.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorHumanRepair.java index 330555451..a4cef475a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorHumanRepair.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorHumanRepair.java @@ -1,5 +1,6 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build; +import com.etheller.warsmash.util.WarsmashConstants; import com.etheller.warsmash.viewer5.handlers.w3x.AnimationTokens; import com.etheller.warsmash.viewer5.handlers.w3x.SequenceUtils; import com.etheller.warsmash.viewer5.handlers.w3x.environment.PathingGrid; @@ -12,6 +13,7 @@ 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.players.CPlayer; public class CBehaviorHumanRepair extends CAbstractRangedBehavior { private final CAbilityHumanRepair ability; @@ -42,17 +44,72 @@ public boolean isWithinRange(CSimulation simulation) { @Override protected CBehavior update(CSimulation simulation, boolean withinFacingWindow) { - unit.getUnitAnimationListener().playAnimation(false, AnimationTokens.PrimaryTag.STAND, - SequenceUtils.WORK, 1.0f, true); if(this.target instanceof CWidget) { CWidget targetWidget = (CWidget) this.target; - float newLifeValue = targetWidget.getLife() + 1; - boolean done = newLifeValue > targetWidget.getMaxLife(); - if(done) { - newLifeValue = targetWidget.getMaxLife(); - } - targetWidget.setLife(simulation, newLifeValue); - if(done) { + //progress construction here (MFROMAZ) + if(targetWidget.getClass()==CUnit.class) { + CUnit targetUnit = ((CUnit) targetWidget); + final CPlayer player = simulation.getPlayer(unit.getPlayerIndex()); + float newLifeValue = targetWidget.getLife() + + ((WarsmashConstants.SIMULATION_STEP_TIME / (targetUnit.getUnitType().getBuildTime()*this.ability.getRepairTimeRatio())) + * (targetUnit.getMaxLife())); + float costs_gold = ((WarsmashConstants.SIMULATION_STEP_TIME / (targetUnit.getUnitType().getBuildTime()*this.ability.getRepairTimeRatio())) + * (targetUnit.getUnitType().getGoldCost()*this.ability.getRepairCostRatio())); + float costs_lumber = ((WarsmashConstants.SIMULATION_STEP_TIME / (targetUnit.getUnitType().getBuildTime()*this.ability.getRepairTimeRatio())) + * (targetUnit.getUnitType().getLumberCost()*this.ability.getRepairCostRatio())); + + unit.getUnitAnimationListener().playAnimation(false, AnimationTokens.PrimaryTag.STAND, + SequenceUtils.WORK, 1.0f, true); + + float healthGain = (WarsmashConstants.SIMULATION_STEP_TIME / targetUnit.getUnitType().getBuildTime())* (ability.getRepairTimeRatio() + * (targetUnit.getMaxLife() * (1.0f - WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE)) ); + + if (targetUnit.getConstuctionProcessType() != null + && targetUnit.getConstuctionProcessType().equals(ConstructionFlag.REQURIE_REPAIR) + && targetUnit.isConstructing() + && targetUnit.getConstructionProgress() < targetUnit.getUnitType().getBuildTime() /*targetUnit.getClassifications().contains(CUnitClassification.BUILDING) &&*/) { + float constructionProgressGain = WarsmashConstants.SIMULATION_STEP_TIME; + healthGain = (WarsmashConstants.SIMULATION_STEP_TIME / targetUnit.getUnitType().getBuildTime()) + * (targetUnit.getMaxLife() * (1.0f - WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE)); + if(targetUnit.isConstructionPowerBuilding()){ + costs_gold = ((WarsmashConstants.SIMULATION_STEP_TIME / (targetUnit.getUnitType().getBuildTime()*this.ability.getPowerBuildTimeRatio())) + * (targetUnit.getUnitType().getGoldCost()*this.ability.getPowerBuildCostRatio())); + costs_lumber = ((WarsmashConstants.SIMULATION_STEP_TIME / (targetUnit.getUnitType().getBuildTime()*this.ability.getPowerBuildTimeRatio())) + * (targetUnit.getUnitType().getLumberCost()*this.ability.getPowerBuildCostRatio())); + constructionProgressGain = WarsmashConstants.SIMULATION_STEP_TIME * this.ability.getPowerBuildTimeRatio(); + healthGain = (WarsmashConstants.SIMULATION_STEP_TIME* ability.getPowerBuildTimeRatio() / targetUnit.getUnitType().getBuildTime()) + * (targetUnit.getMaxLife() * (1.0f - WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE)); + }else{ + costs_gold = 0.0f; + costs_lumber = 0.0f; + targetUnit.setConstructionPowerBuild(true); + } + if(costs_gold > player.getGold() || costs_lumber > player.getLumber()) { + + return unit.pollNextOrderBehavior(simulation); + } + targetUnit.setConstructionProgress(targetUnit.getConstructionProgress() +constructionProgressGain); + } + + newLifeValue = Math.min(targetUnit.getLife() + healthGain, targetUnit.getMaximumLife()); + if(costs_gold > player.getGold() || costs_lumber > player.getLumber()){ + + return unit.pollNextOrderBehavior(simulation); + } + boolean done = (newLifeValue >= ((CUnit) targetWidget).getUnitType().getMaxLife()); + if (done) { + newLifeValue = targetWidget.getMaxLife(); + } + if(player.charge(costs_gold,costs_lumber)) { + targetWidget.setLife(simulation, newLifeValue); + }else{ + return unit.pollNextOrderBehavior(simulation); + } + if (done && ((targetUnit.getConstructionProgress()>= targetUnit.getUnitType().getBuildTime())||!targetUnit.isConstructing())) { + return unit.pollNextOrderBehavior(simulation); + } + }else{ + return unit.pollNextOrderBehavior(simulation); } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorNightElfBuild.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorNightElfBuild.java new file mode 100644 index 000000000..3b09b51ef --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorNightElfBuild.java @@ -0,0 +1,89 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build; + +import com.etheller.warsmash.util.WarsmashConstants; +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.CUnitClassification; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.CBehavior; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.pathing.CBuildingPathingType; +import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; + +import java.awt.image.BufferedImage; +import java.util.EnumSet; + +public class CBehaviorNightElfBuild extends CBehaviorOrcBuild{ + private CUnit constructedStructure; + + public CBehaviorNightElfBuild(CUnit unit) { + super(unit); + } + + @Override + protected CBehavior update(final CSimulation simulation, final boolean withinFacingWindow) { + if (!this.unitCreated) { + this.unitCreated = true; + final CUnitType unitTypeToCreate = simulation.getUnitData().getUnitType(this.orderId); + final BufferedImage buildingPathingPixelMap = unitTypeToCreate.getBuildingPathingPixelMap(); + boolean buildLocationObstructed = false; + if (buildingPathingPixelMap != null) { + final EnumSet preventedPathingTypes = unitTypeToCreate.getPreventedPathingTypes(); + final EnumSet requiredPathingTypes = unitTypeToCreate.getRequiredPathingTypes(); + + if (!simulation.getPathingGrid().checkPathingTexture(this.target.getX(), this.target.getY(), + (int) simulation.getGameplayConstants().getBuildingAngle(), buildingPathingPixelMap, + preventedPathingTypes, requiredPathingTypes, simulation.getWorldCollision(), this.unit)) { + buildLocationObstructed = true; + } + } + final int playerIndex = this.unit.getPlayerIndex(); + if (!buildLocationObstructed) { + final CUnit constructedStructure = simulation.createUnit(this.orderId, playerIndex, this.target.getX(), + this.target.getY(), simulation.getGameplayConstants().getBuildingAngle()); + constructedStructure.setConstructing(true); + constructedStructure.setWorkerInside(this.unit); + constructedStructure.setLife(simulation, + constructedStructure.getMaximumLife() * WarsmashConstants.BUILDING_CONSTRUCT_START_LIFE); + constructedStructure.setFoodUsed(unitTypeToCreate.getFoodUsed()); + constructedStructure.add(simulation, + new CAbilityBuildInProgress(simulation.getHandleIdAllocator().createId())); + for (final CAbility ability : constructedStructure.getAbilities()) { + ability.visit(AbilityDisableWhileUnderConstructionVisitor.INSTANCE); + } + this.unit.setHidden(true); + this.unit.setPaused(true); + this.unit.setInvulnerable(true); + if(constructedStructure.getUnitType().getClassifications().contains(CUnitClassification.ANCIENT)) { + constructedStructure.setConstuctionProcessType(ConstructionFlag.CONSUME_WORKER); + simulation.getPlayer(playerIndex).setFoodUsed(simulation.getPlayer(playerIndex).getFoodUsed()-this.unit.getFoodUsed()); + } + this.constructedStructure = constructedStructure; + simulation.unitConstructedEvent(this.unit, constructedStructure); + } + else { + final CPlayer player = simulation.getPlayer(playerIndex); + refund(player, unitTypeToCreate); + simulation.getCommandErrorListener(playerIndex).showCantPlaceError(); + } + } + return this.unit.pollNextOrderBehavior(simulation); + } + + /*@Override + public void end(CSimulation game, boolean interrupted) { + if(this.constructedStructure!=null) { + this.constructedStructure.setConstructionCanceled(true); + } + super.end(game, interrupted); + } + + @Override + public void endMove(CSimulation game, boolean interrupted){ + if(this.constructedStructure!=null) { + this.constructedStructure.setConstructionCanceled(true); + } + super.end(game, interrupted); + }*/ +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorOrcBuild.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorOrcBuild.java index 9f7cd1b9f..335652b41 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorOrcBuild.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/CBehaviorOrcBuild.java @@ -17,9 +17,9 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CPlayer; public class CBehaviorOrcBuild extends CAbstractRangedBehavior { - private int highlightOrderId; - private War3ID orderId; - private boolean unitCreated = false; + protected int highlightOrderId; + protected War3ID orderId; + protected boolean unitCreated = false; public CBehaviorOrcBuild(final CUnit unit) { super(unit); @@ -118,7 +118,7 @@ public void end(final CSimulation game, final boolean interrupted) { } } - private void refund(final CPlayer player, final CUnitType unitTypeToCreate) { + protected void refund(final CPlayer player, final CUnitType unitTypeToCreate) { player.setFoodUsed(player.getFoodUsed() - unitTypeToCreate.getFoodUsed()); player.refundFor(unitTypeToCreate); } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/ConstructionFlag.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/ConstructionFlag.java new file mode 100644 index 000000000..065dfab5a --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/behaviors/build/ConstructionFlag.java @@ -0,0 +1,5 @@ +package com.etheller.warsmash.viewer5.handlers.w3x.simulation.behaviors.build; + +public enum ConstructionFlag { + NONE, CONSUME_WORKER, REQURIE_REPAIR; +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java index abfb4e450..8754146ee 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/data/CUnitData.java @@ -180,7 +180,7 @@ public class CUnitData { private final SimulationRenderController simulationRenderController; public CUnitData(final CGameplayConstants gameplayConstants, final MutableObjectData unitData, - final CAbilityData abilityData, final SimulationRenderController simulationRenderController) { + final CAbilityData abilityData, final SimulationRenderController simulationRenderController) { this.gameplayConstants = gameplayConstants; this.unitData = unitData; this.abilityData = abilityData; @@ -188,8 +188,8 @@ public CUnitData(final CGameplayConstants gameplayConstants, final MutableObject } 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 HandleIdAllocator handleIdAllocator, final RemovablePathingMapInstance pathingInstance) { + final float y, final float facing, final BufferedImage buildingPathingPixelMap, + final HandleIdAllocator handleIdAllocator, final RemovablePathingMapInstance pathingInstance) { final MutableGameObject unitType = this.unitData.get(typeId); final int handleId = handleIdAllocator.createId(); @@ -217,27 +217,27 @@ public CUnit create(final CSimulation simulation, final int playerIndex, final W final List 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 CAbilityOrcBuild(handleIdAllocator.createId(), structuresBuilt)); - break; + 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 CAbilityOrcBuild(handleIdAllocator.createId(), structuresBuilt)); + break; } } final List unitsTrained = unitTypeInstance.getUnitsTrained(); @@ -269,7 +269,7 @@ public CUnit create(final CSimulation simulation, final int playerIndex, final W } private CUnitType getUnitTypeInstance(final War3ID typeId, final BufferedImage buildingPathingPixelMap, - final MutableGameObject unitType) { + final MutableGameObject unitType) { CUnitType unitTypeInstance = this.unitIdToUnitType.get(typeId); if (unitTypeInstance == null) { final String legacyName = getLegacyName(unitType); @@ -423,10 +423,10 @@ private CUnitType getUnitTypeInstance(final War3ID typeId, final BufferedImage b final CUnitAttack otherAttack = attacks.get(0); if ((otherAttack.getAttackType() == attackType) && (targetsAllowed.size() == 1) && (targetsAllowed.contains(CTargetType.TREE) - || (targetsAllowed.contains(CTargetType.STRUCTURE) - && (otherAttack.getDamageBase() == damageBase) - && (otherAttack.getDamageSidesPerDie() == damageSidesPerDie) - && (otherAttack.getDamageDice() == damageDice)))) { + || (targetsAllowed.contains(CTargetType.STRUCTURE) + && (otherAttack.getDamageBase() == damageBase) + && (otherAttack.getDamageSidesPerDie() == damageSidesPerDie) + && (otherAttack.getDamageDice() == damageDice)))) { showUI = false; } } @@ -582,56 +582,56 @@ private static int[] populateHeroStatTable(final int maxHeroLevel, final float s } private CUnitAttack createAttack(final float animationBackswingPoint, final float animationDamagePoint, - final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage, - final EnumSet 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 targetsAllowed, - final String weaponSound, final CWeaponType weaponType) { + final int areaOfEffectFullDamage, final int areaOfEffectMediumDamage, final int areaOfEffectSmallDamage, + final EnumSet 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 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; + 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; } @@ -660,7 +660,7 @@ public int getA1MinDamage(final War3ID unitTypeId) { 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)); + * this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK1_DMG_SIDES_PER_DIE, 0)); } public int getA2MinDamage(final War3ID unitTypeId) { @@ -671,7 +671,7 @@ public int getA2MinDamage(final War3ID unitTypeId) { 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)); + * this.unitData.get(unitTypeId).getFieldAsInteger(ATTACK2_DMG_SIDES_PER_DIE, 0)); } public int getDefense(final War3ID unitTypeId) { @@ -753,4 +753,4 @@ public CUnitType getUnitTypeByJassLegacyName(final String jassLegacyName) { } return getUnitType(typeId); } -} +} \ No newline at end of file diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java index 0bf8ea423..ca12e9fbf 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java @@ -29,6 +29,8 @@ public class CPlayer extends CBasePlayer { private final List heroes = new ArrayList<>(); private final EnumMap> eventTypeToEvents = new EnumMap<>( JassGameEventsWar3.class); + private float accumulatedLumberCost = 0.0f; + private float accumulatedGoldCost = 0.0f; // if you use triggers for this then the transient tag here becomes really // questionable -- it already was -- but I meant for those to inform us @@ -143,6 +145,19 @@ public boolean charge(final int gold, final int lumber) { return false; } + public boolean charge(final float gold, final float lumber){ + this.accumulatedLumberCost += lumber; + this.accumulatedGoldCost += gold; + int newGoldCost = (int)accumulatedGoldCost; + int newLumberCost = (int)accumulatedLumberCost; + if(this.charge(newGoldCost,newLumberCost)) { + this.accumulatedLumberCost -= newLumberCost; + this.accumulatedGoldCost -= newGoldCost; + return true; + } + return false; + } + public void refundFor(final CUnitType unitType) { this.lumber += unitType.getLumberCost(); this.gold += unitType.getGoldCost(); diff --git a/resources.mpq b/resources.mpq new file mode 100644 index 000000000..8435df744 Binary files /dev/null and b/resources.mpq differ diff --git a/warsmash.ini b/warsmash.ini new file mode 100644 index 000000000..a94197463 --- /dev/null +++ b/warsmash.ini @@ -0,0 +1,14 @@ +[DataSources] +Count=6 +Type00=MPQ +Path00="..\..\war3.mpq" +Type01=MPQ +Path01="..\..\War3x.mpq" +Type02=MPQ +Path02="..\..\War3xlocal.mpq" +Type03=MPQ +Path03="..\..\War3Patch.mpq" +Type04=MPQ +Path04="resources.mpq" +Type05=Folder +Path05="." \ No newline at end of file