diff --git a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java index 93798e8d4..b54745014 100644 --- a/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java +++ b/source/core/src/main/com/csse3200/game/ai/tasks/AITaskComponent.java @@ -46,8 +46,8 @@ public AITaskComponent addTask(PriorityTask task) { */ public T getTask(Class task) { for (PriorityTask priorityTask : priorityTasks) { - if (priorityTask.getClass() == task) { - return (T) priorityTask; + if (task.isInstance(priorityTask)) { + return task.cast(priorityTask); } } logger.info("Task {} not found", task); @@ -83,12 +83,8 @@ public void dispose() { */ public void disposeAll() { currentTask = null; - for (int i = 0; i < priorityTasks.size(); i++) { - priorityTasksToBeRestored.add(priorityTasks.get(i)); - } - for (int i = 0; i < priorityTasks.size(); i++) { - priorityTasks.remove(i); - } + priorityTasksToBeRestored.addAll(priorityTasks); + priorityTasks.clear(); } /** @@ -96,12 +92,8 @@ public void disposeAll() { * back into priorityTasks. */ public void restore() { - for (int i = 0; i < priorityTasksToBeRestored.size(); i++) { - priorityTasks.add(priorityTasksToBeRestored.get(i)); - } - for (int i = 0; i < priorityTasksToBeRestored.size(); i++) { - priorityTasksToBeRestored.remove(i); - } + priorityTasks.addAll(priorityTasksToBeRestored); + priorityTasksToBeRestored.clear(); this.update(); } diff --git a/source/core/src/main/com/csse3200/game/components/EffectComponent.java b/source/core/src/main/com/csse3200/game/components/EffectComponent.java index 32b32e3d3..db110417e 100644 --- a/source/core/src/main/com/csse3200/game/components/EffectComponent.java +++ b/source/core/src/main/com/csse3200/game/components/EffectComponent.java @@ -54,9 +54,6 @@ public void update() { // apply slow effect if (mob) { - if (target == null) { - return; - } if (slowFlag) { isSlowed = true; Vector2 half_speed = new Vector2(defaultTargetSpeed.x / 2, defaultTargetSpeed.y / 2); @@ -85,9 +82,6 @@ public void update() { } targetPhysics.setSpeed(STUN_SPEED); } else if (isStunned) { - if (target == null) { - return; - } isStunned = false; targetPhysics.setSpeed(defaultTargetSpeed); } diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java index 7444dfc4f..b110de999 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/CurrencyDisplay.java @@ -61,12 +61,12 @@ private void addActors() { table.add(crystalsTb).width(crystalsTb.getWidth() * 0.5f).height(crystalsTb.getHeight() * 0.5f); stage.addActor(table); - scrapsTb.setPosition(table.getX() - 200, Gdx.graphics.getHeight() - 205); - scrapsTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20, Gdx.graphics.getHeight() - 205, + scrapsTb.setPosition(table.getX() - 200f, Gdx.graphics.getHeight() - 205f); + scrapsTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20f, Gdx.graphics.getHeight() - 205f, 1f, Interpolation.fastSlow))); - crystalsTb.setPosition(table.getX() - 200, Gdx.graphics.getHeight() - 268); - crystalsTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20, Gdx.graphics.getHeight() - 268, + crystalsTb.setPosition(table.getX() - 200f, Gdx.graphics.getHeight() - 268f); + crystalsTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20f, Gdx.graphics.getHeight() - 268f, 1f, Interpolation.fastSlow))); } diff --git a/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java b/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java index 5c809a649..09d2d3d73 100644 --- a/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/gamearea/EngineerCountDisplay.java @@ -60,8 +60,8 @@ private void addActors() { stage.addActor(table); // Animate the engineer count label - engineerTb.setPosition(table.getX() - 200, Gdx.graphics.getHeight() - 145); - engineerTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20, Gdx.graphics.getHeight() - 145, + engineerTb.setPosition(table.getX() - 200f, Gdx.graphics.getHeight() - 145f); + engineerTb.addAction(new SequenceAction(Actions.moveTo(table.getX() + 20f, Gdx.graphics.getHeight() - 145, 1f, Interpolation.fastSlow))); } diff --git a/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java b/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java index ec5c56489..bb0e32a50 100644 --- a/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/maingame/MainGameDisplay.java @@ -239,9 +239,9 @@ private TextButton createPauseButton() { TextButton pauseBtn = ButtonFactory.createButton("Pause"); // Starting animation for pause button - pauseBtn.setPosition(Gdx.graphics.getWidth(), (float)(Gdx.graphics.getHeight() - 150)); - pauseBtn.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 200, - Gdx.graphics.getHeight() - 150, 1f, Interpolation.fastSlow))); + pauseBtn.setPosition((float)Gdx.graphics.getWidth(), (Gdx.graphics.getHeight() - 150f)); + pauseBtn.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 200f, + Gdx.graphics.getHeight() - 150f, 1f, Interpolation.fastSlow))); // Spawns a pause menu when the button is pressed. pauseBtn.addListener( diff --git a/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java b/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java index c3e9d24ff..cd005fe8b 100644 --- a/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java +++ b/source/core/src/main/com/csse3200/game/components/maingame/UIElementsDisplay.java @@ -37,9 +37,9 @@ private void addActors() { remainingMobsButton = ButtonFactory.createButton("Mobs:" + ServiceLocator.getWaveService().getEnemyCount()); - remainingMobsButton.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 230); - remainingMobsButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 217, - Gdx.graphics.getHeight() - 230, 1f, Interpolation.fastSlow))); + remainingMobsButton.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 230f); + remainingMobsButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 217f, + Gdx.graphics.getHeight() - 230f, 1f, Interpolation.fastSlow))); buttonTable.top().right().padTop(160f).padRight(80f); buttonTable.setFillParent(true); @@ -74,9 +74,9 @@ public void createTimerButton() { timerButton = ButtonFactory.createButton("Next wave in:" + (ServiceLocator.getWaveService().getNextWaveTime() / 1000)); - timerButton.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 300); - timerButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 435, - Gdx.graphics.getHeight() - 300, 1f, Interpolation.fastSlow))); + timerButton.setPosition(Gdx.graphics.getWidth(), Gdx.graphics.getHeight() - 300f); + timerButton.addAction(new SequenceAction(Actions.moveTo(Gdx.graphics.getWidth() - 435f, + Gdx.graphics.getHeight() - 300f, 1f, Interpolation.fastSlow))); timerButton.setDisabled(true); buttonTable.row(); buttonTable.add(timerButton); diff --git a/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java index b40cfa0db..9ed70defe 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/FireworksTowerCombatTask.java @@ -13,6 +13,8 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import static java.lang.Math.round; + /** * The FireworksTowerCombatTask runs the AI for the FireworksTower class. The tower scans for mobs and targets in a @@ -38,6 +40,7 @@ public class FireworksTowerCombatTask extends DefaultTask implements PriorityTas private final Vector2 maxRangePosition = new Vector2(); private PhysicsEngine physics; private GameTime timeSource; + private float fireRateInterval; private long endTime; private final RaycastHit hit = new RaycastHit(); private boolean shoot = true; @@ -54,6 +57,7 @@ public enum STATE { public FireworksTowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; + this.fireRateInterval = 1; physics = ServiceLocator.getPhysicsService().getPhysics(); timeSource = ServiceLocator.getTimeSource(); } @@ -81,7 +85,12 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); - endTime = timeSource.getTime() + (INTERVAL * 1000); + if (towerState == STATE.ATTACK) { + endTime = timeSource.getTime() + round(fireRateInterval * 1000); + } else { + endTime = timeSource.getTime() + (INTERVAL * 1000); + } + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java index 5782ca8f9..85d29c15b 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobDeathTask.java @@ -1,5 +1,6 @@ package com.csse3200.game.components.tasks; +import com.badlogic.gdx.math.MathUtils; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; import com.csse3200.game.components.CombatStatsComponent; @@ -11,6 +12,8 @@ import com.csse3200.game.services.GameTime; +/// THIS CODE IS REDUNDANT /// + /** * Task that prints a message to the terminal whenever it is called. */ @@ -97,10 +100,18 @@ private void killMob() { } private void dropCurrency() { + float randomValue = MathUtils.random(0,1); + Entity currency; + if (randomValue <= 0.1f) { + currency = DropFactory.createCrystalDrop(); + + } + else { + currency = DropFactory.createScrapDrop(); - Entity scrap = DropFactory.createScrapDrop(); - scrap.setPosition(mobPosition.x,mobPosition.y); - ServiceLocator.getEntityService().register(scrap); + } + currency.setPosition(mobPosition.x,mobPosition.y); + ServiceLocator.getEntityService().register(currency); } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java b/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java index 2cc103bd8..150414c5a 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/MobTask/MobTask.java @@ -1,5 +1,6 @@ package com.csse3200.game.components.tasks.MobTask; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Timer; import com.csse3200.game.ai.tasks.DefaultTask; @@ -9,6 +10,7 @@ import com.csse3200.game.components.npc.DodgingComponent; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.DropFactory; import com.csse3200.game.entities.factories.ProjectileFactory; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.HitboxComponent; @@ -16,6 +18,10 @@ import com.csse3200.game.rendering.AnimationRenderComponent; import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.csse3200.game.components.tasks.MobTask.MobType; /** @@ -34,8 +40,15 @@ public class MobTask extends DefaultTask implements PriorityTask { private static final long RANGE_ATTACK_SPEED = 5000; private static final float MELEE_ATTACK_RANGE = 0.2f; + private static final float CRYSTAL_DROP_RATE = 0.1f; + private static final float SCRAP_DROP_RATE = 0.6f; + + private static final Logger logger = LoggerFactory.getLogger(MobTask.class); + + // Private variables private final MobType mobType; + private State state = State.DEFAULT; private Entity mob; private AnimationRenderComponent animation; @@ -131,6 +144,7 @@ public void update() { } else if (deathFlag && animation.isFinished()) { ServiceLocator.getWaveService().updateEnemyCount(); mob.setFlagForDelete(true); + dropCurrency(); } // Uhhh @@ -293,4 +307,25 @@ public int getPriority() { public void setDodge(boolean dodgeFlag) { this.canDodge = dodgeFlag; } + + private void dropCurrency() { + float randomValue = MathUtils.random(0f,1f); + logger.info("Random value: " + randomValue); + Entity currency; + if (randomValue <= CRYSTAL_DROP_RATE) { + currency = DropFactory.createCrystalDrop(); + currency.setPosition(mob.getPosition().x,mob.getPosition().y); + ServiceLocator.getEntityService().register(currency); + + } + else if (randomValue <= SCRAP_DROP_RATE) { + currency = DropFactory.createScrapDrop(); + currency.setPosition(mob.getPosition().x,mob.getPosition().y); + ServiceLocator.getEntityService().register(currency); + + } + + + + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java index 75268d9b6..ba1954a87 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/PierceTowerCombatTask.java @@ -13,6 +13,8 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import static java.lang.Math.round; + /** * The PierceTowerCombatTask runs the AI for the PierceTower class. The tower scans for mobs and targets in a straight * line from its centre coordinate and executes the trigger phrases for animations depeending on the current state of @@ -31,6 +33,7 @@ public class PierceTowerCombatTask extends DefaultTask implements PriorityTask { // Class attributes private final int priority; + private float fireRateInterval; private final float maxRange; private Vector2 towerPosition = new Vector2(10, 10); private final Vector2 maxRangePosition = new Vector2(); @@ -52,6 +55,7 @@ public enum STATE { public PierceTowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; + this.fireRateInterval = 1; physics = ServiceLocator.getPhysicsService().getPhysics(); timeSource = ServiceLocator.getTimeSource(); } @@ -79,6 +83,9 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); + if (towerState == STATE.ATTACK) { + endTime = timeSource.getTime() + round(fireRateInterval * 1000); + } endTime = timeSource.getTime() + (INTERVAL * 1000); } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java b/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java index 6e60bf01d..a0083a9c5 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/RicochetTowerCombatTask.java @@ -13,6 +13,8 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +import static java.lang.Math.round; + /** * The RicochetTowerCombatTask runs the AI for the RicochetTower class. The tower scans for mobs and targets in a @@ -37,6 +39,7 @@ public class RicochetTowerCombatTask extends DefaultTask implements PriorityTask private final Vector2 maxRangePosition = new Vector2(); private PhysicsEngine physics; private GameTime timeSource; + private float fireRateInterval; private long endTime; private final RaycastHit hit = new RaycastHit(); private boolean shoot = true; @@ -54,6 +57,7 @@ public enum STATE { public RicochetTowerCombatTask(int priority, float maxRange) { this.priority = priority; this.maxRange = maxRange; + this.fireRateInterval = 1; physics = ServiceLocator.getPhysicsService().getPhysics(); timeSource = ServiceLocator.getTimeSource(); } @@ -81,7 +85,11 @@ public void start() { public void update() { if (timeSource.getTime() >= endTime) { updateTowerState(); - endTime = timeSource.getTime() + (INTERVAL * 1000); + if (towerState == STATE.ATTACK) { + endTime = timeSource.getTime() + round(fireRateInterval * 1000); + } else { + endTime = timeSource.getTime() + (INTERVAL * 1000); + } } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java index 38896b2b4..a861a3a5c 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/DemonBossTask.java @@ -10,6 +10,7 @@ import com.csse3200.game.components.ProjectileEffects; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.DropFactory; import com.csse3200.game.entities.factories.MobBossFactory; import com.csse3200.game.entities.factories.ProjectileFactory; import com.csse3200.game.physics.PhysicsLayer; @@ -140,6 +141,8 @@ public void update() { slimey.setScale(5f, 5f); ServiceLocator.getEntityService().register(slimey); demon.setFlagForDelete(true); + dropCurrency(); + } // detect half health @@ -495,4 +498,19 @@ public void run() { }, (float) (i + 1) * 2); } } + + private void dropCurrency() { + // Create and register 5 crystal drops around the bossPosition + for (int i = 0; i < 5; i++) { + Entity crystal = DropFactory.createCrystalDrop(); + + // Calculate positions around the bossPosition + float offsetX = MathUtils.random(-1f, 1f); // Adjust the range as needed + float offsetY = MathUtils.random(-1f, 1f); + float dropX = owner.getEntity().getPosition().x + offsetX; + float dropY = owner.getEntity().getPosition().y + offsetY; + crystal.setPosition(dropX, dropY); + ServiceLocator.getEntityService().register(crystal); + } + } } \ No newline at end of file diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/IceBabyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/IceBabyTask.java index 4b298c059..b4f5c8451 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/IceBabyTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/IceBabyTask.java @@ -9,6 +9,7 @@ import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.DropFactory; import com.csse3200.game.entities.factories.NPCFactory; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.HitboxComponent; @@ -114,6 +115,7 @@ public void update() { animate(); if (animation.isFinished()) { iceBaby.setFlagForDelete(true); + dropCurrency(); } } @@ -318,4 +320,20 @@ public int getPriority() { return PRIORITY; } + + private void dropCurrency() { + // Create and register 5 crystal drops around the bossPosition + for (int i = 0; i < 5; i++) { + Entity crystal = DropFactory.createCrystalDrop(); + + // Calculate positions around the bossPosition + float offsetX = MathUtils.random(-1f, 1f); // Adjust the range as needed + float offsetY = MathUtils.random(-1f, 1f); + float dropX = owner.getEntity().getPosition().x + offsetX; + float dropY = owner.getEntity().getPosition().y + offsetY; + crystal.setPosition(dropX, dropY); + ServiceLocator.getEntityService().register(crystal); + } + } + } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/MobBossDeathTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/MobBossDeathTask.java index 719c2436a..1bc2db0c3 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/MobBossDeathTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/MobBossDeathTask.java @@ -1,5 +1,6 @@ package com.csse3200.game.components.tasks.bosstask; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; @@ -9,6 +10,8 @@ import com.csse3200.game.services.GameTime; import com.csse3200.game.services.ServiceLocator; +//CODE IS REDUNDANT /// + /** * Task that prints a message to the terminal whenever it is called. */ @@ -93,10 +96,18 @@ private void killboss() { } private void dropCurrency() { + // Create and register 5 crystal drops around the bossPosition + for (int i = 0; i < 5; i++) { + Entity crystal = DropFactory.createCrystalDrop(); + + // Calculate positions around the bossPosition + float offsetX = MathUtils.random(-1f, 1f); // Adjust the range as needed - Entity scrap = DropFactory.createScrapDrop(); - scrap.setPosition(bossPosition.x,bossPosition.y); - ServiceLocator.getEntityService().register(scrap.setScale(2,2)); + float dropX = bossPosition.x + offsetX; + crystal.setPosition(dropX, bossPosition.y); + ServiceLocator.getEntityService().register(crystal); + } } + } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickDeathTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickDeathTask.java index 97f7dacc4..92da2af17 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickDeathTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/PatrickDeathTask.java @@ -1,8 +1,12 @@ package com.csse3200.game.components.tasks.bosstask; +import com.badlogic.gdx.math.MathUtils; import com.csse3200.game.ai.tasks.DefaultTask; import com.csse3200.game.ai.tasks.PriorityTask; +import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.DropFactory; import com.csse3200.game.rendering.AnimationRenderComponent; +import com.csse3200.game.services.ServiceLocator; public class PatrickDeathTask extends DefaultTask implements PriorityTask { @@ -27,6 +31,8 @@ public void update() { if (startFlag && owner.getEntity().getComponent(AnimationRenderComponent.class). isFinished()) { owner.getEntity().setFlagForDelete(true); + ServiceLocator.getGameEndService().updateEngineerCount(); + dropCurrency(); } } @@ -37,4 +43,19 @@ public void update() { public int getPriority() { return PRIORITY; } + + private void dropCurrency() { + // Create and register 5 crystal drops around the bossPosition + for (int i = 0; i < 5; i++) { + Entity crystal = DropFactory.createCrystalDrop(); + + // Calculate positions around the bossPosition + float offsetX = MathUtils.random(-1f, 1f); // Adjust the range as needed + float offsetY = MathUtils.random(-1f, 1f); + float dropX = owner.getEntity().getPosition().x + offsetX; + float dropY = owner.getEntity().getPosition().y + offsetY; + crystal.setPosition(dropX, dropY); + ServiceLocator.getEntityService().register(crystal); + } + } } diff --git a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java index fe8cefae4..bf607a123 100644 --- a/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java +++ b/source/core/src/main/com/csse3200/game/components/tasks/bosstask/SlimeyBoyTask.java @@ -1,5 +1,6 @@ package com.csse3200.game.components.tasks.bosstask; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Timer; @@ -8,6 +9,7 @@ import com.csse3200.game.components.CombatStatsComponent; import com.csse3200.game.components.tasks.MovementTask; import com.csse3200.game.entities.Entity; +import com.csse3200.game.entities.factories.DropFactory; import com.csse3200.game.physics.PhysicsLayer; import com.csse3200.game.physics.components.PhysicsMovementComponent; import com.csse3200.game.rendering.AnimationRenderComponent; @@ -186,4 +188,6 @@ private void applyAoeDamage(Array targets, int damage) { public int getPriority() { return PRIORITY; } + + } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/FireworksTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/FireworksTowerConfig.java index c1bde5dd3..d01f0b5c8 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/FireworksTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/FireworksTowerConfig.java @@ -2,8 +2,8 @@ public class FireworksTowerConfig { public int health = 1; - public int baseAttack = 0; + public int baseAttack = 1; public int cost = 1; - public int attackRate =0; + public int attackRate =1; public int incomeRate =0; } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/PierceTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/PierceTowerConfig.java index 8baf1cb52..0a44bec79 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/PierceTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/PierceTowerConfig.java @@ -2,6 +2,7 @@ public class PierceTowerConfig { public int health = 1; - public int baseAttack = 0; + public int baseAttack = 1; public int cost = 1; + public float attackRate = 1; } diff --git a/source/core/src/main/com/csse3200/game/entities/configs/RicochetTowerConfig.java b/source/core/src/main/com/csse3200/game/entities/configs/RicochetTowerConfig.java index 3a637c7e2..f86d48569 100644 --- a/source/core/src/main/com/csse3200/game/entities/configs/RicochetTowerConfig.java +++ b/source/core/src/main/com/csse3200/game/entities/configs/RicochetTowerConfig.java @@ -2,6 +2,7 @@ public class RicochetTowerConfig { public int health = 1; - public int baseAttack = 0; + public int baseAttack = 1; public int cost = 1; + public float attackRate = 1; } diff --git a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java index f42babb8a..136dba625 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/MobBossFactory.java @@ -216,6 +216,7 @@ public static Entity createIceBoss(int health) { * @return a base mob boss entity */ public static Entity createBaseBoss() { + return new Entity() .addComponent(new PhysicsComponent()) // .addComponent(new ColliderComponent()) diff --git a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java index b98c5bde0..43cce2dd8 100644 --- a/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java +++ b/source/core/src/main/com/csse3200/game/entities/factories/TowerFactory.java @@ -203,7 +203,6 @@ public static Entity createTNTTower() { TNTTower .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) - .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) .addComponent(new TNTDamageComponent(PhysicsLayer.NPC,TNT_KNOCK_BACK_FORCE,TNT_TOWER_RANGE)) .addComponent(aiTaskComponent) @@ -211,6 +210,7 @@ public static Entity createTNTTower() { .addComponent(new TNTAnimationController()); TNTTower.getComponent(AnimationRenderComponent.class).scaleEntity(); + TNTTower.removeComponent(TowerUpgraderComponent.class); return TNTTower; } @@ -282,7 +282,6 @@ public static Entity createWeaponTower() { .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CostComponent(config.cost)) - .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(aiTaskComponent) .addComponent(animator) .addComponent(new TowerAnimationController()); @@ -376,6 +375,7 @@ public static Entity createFireworksTower() { fireworksTower .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent((new CostComponent(config.cost))) .addComponent(aiTaskComponent) .addComponent(animator) @@ -408,6 +408,7 @@ public static Entity createPierceTower() { pierceTower .addComponent(animator) .addComponent(new PierceTowerAnimationController()) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent((new CostComponent(config.cost))) .addComponent(aiTaskComponent); @@ -435,6 +436,7 @@ public static Entity createRicochetTower() { ricochetTower .addComponent(animator) .addComponent(new RicochetTowerAnimationController()) + .addComponent(new UpgradableStatsComponent(config.attackRate)) .addComponent(new CombatStatsComponent(config.health, config.baseAttack)) .addComponent((new CostComponent(config.cost))) .addComponent(aiTaskComponent); diff --git a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java index 9d4c42f50..b68cc1205 100644 --- a/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java +++ b/source/core/src/main/com/csse3200/game/input/UpgradeUIComponent.java @@ -1,5 +1,6 @@ package com.csse3200.game.input; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Camera; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; @@ -33,7 +34,25 @@ import java.util.Iterator; import java.util.Map; +import static java.lang.Math.round; + public class UpgradeUIComponent extends InputComponent { + + // CONSTANTS + + /** + * The cost for all upgrades are 10 crystals + */ + private static final int UPGRADE_COST = 10; // Crystal + + /** + * The cost for repairing a turret is 50 scrap + */ + private static final int REPAIR_COST = 50; // Scrap + private static final float ATTACK_RATE_INCREASE = 0.2f; + private static final int ATTACK_INCREASE = 10; // Damage + private static final int HEALTH_INCREASE = 10; // Health + private static final int TIME_DECREASE = 5; // Scrap private static final Logger logger = LoggerFactory.getLogger(ForestGameArea.class); private final EntityService entityService; private final Camera camera; @@ -85,21 +104,10 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { Vector2 cursorPosition = new Vector2(worldCoordinates.x, worldCoordinates.y); Entity clickedEntity = entityService.getEntityAtPosition(cursorPosition.x, cursorPosition.y); - //temp fix to prevent upgrading of new towers - if (clickedEntity!= null && (clickedEntity.getComponent(RicochetTowerAnimationController.class) != null || - clickedEntity.getComponent(PierceTowerAnimationController.class) != null || - clickedEntity.getComponent(FireworksTowerAnimationController.class) != null)) { - return false; - } - // - // If the clicked position contains a turret, and the turret is upgradable and not a TNT tower if (clickedEntity != null && clickedEntity.getComponent(TowerUpgraderComponent.class) != null - && clickedEntity.getComponent(TNTDamageComponent.class) == null) { - // TNT TowerUpgraderComponent can be removed later, but possibly useful for future sprint. - // Clear all existing upgrade tables - logger.info("clickedEntity: " + clickedEntity); - + ) { +// clearUpgradeTables(); // Check if there is an existing upgrade table for this turret entity Table existingUpgradeTable = upgradeTables.get(clickedEntity); @@ -110,8 +118,6 @@ public boolean touchDown(int screenX, int screenY, int pointer, int button) { } else { // If no upgrade table exists, create and store a new one Table newUpgradeTable = createUpgradeTable(clickedEntity); - Vector2 UICoordinates = stage.screenToStageCoordinates(new Vector2(screenX, screenY)); - newUpgradeTable.setPosition(UICoordinates.x, UICoordinates.y); stage.addActor(newUpgradeTable); // Store the new upgrade table in the map @@ -149,9 +155,11 @@ private void clearUpgradeTables() { private Table createUpgradeTable(Entity turretEntity) { // This is the overarching table that contains the close button, the inner table, and the cost display Table upgradeTable = new Table(); - upgradeTable.top(); + upgradeTable.top().left(); upgradeTable.defaults().pad(0).space(0); upgradeTable.setSize(60, 60); + upgradeTable.padTop(30f).padLeft(5f); + upgradeTable.setPosition(0, round((float) Gdx.graphics.getHeight() / 1.3f)); // The inner table contains the upgrade buttons and the stats display Table innerUpgradeTable = new Table(); @@ -180,11 +188,12 @@ private Table createUpgradeTable(Entity turretEntity) { costDisplay.setWidth(0); costDisplay.setBackground(drawableBackground); // Create an Image for the scrap icon - Drawable costDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/economy/scrap.png"))); + Drawable costDrawable = new TextureRegionDrawable(new TextureRegion(new Texture("images/economy/crystal.png"))); + Drawable costDrawableScrap = new TextureRegionDrawable(new TextureRegion(new Texture("images/economy/scrap.png"))); Image costImage = new Image(costDrawable); costDisplay.add(costImage).center(); costImage.setScaling(Scaling.none); - Label costDisplayLabel = new Label("100", createLabelStyle()); + Label costDisplayLabel = new Label("You shouldn't see this", createLabelStyle()); costDisplay.add(costDisplayLabel).padLeft(0); TextButton closeButton = new TextButton("X", style); @@ -217,14 +226,15 @@ public void clicked(InputEvent event, float x, float y) { upgradeHealth.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { - value = ServiceLocator.getCurrencyService().getScrap().getAmount(); + value = ServiceLocator.getCurrencyService().getCrystal().getAmount(); logger.info("clicked"); - if (value >= 100) { - value -= 100; - ServiceLocator.getCurrencyService().getScrap().setAmount(value); - ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); + if (value >= UPGRADE_COST) { + value -= UPGRADE_COST; + ServiceLocator.getCurrencyService().getCrystal().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateCrystalsStats(); - turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.MAXHP, 10); + turretEntity.getComponent(TowerUpgraderComponent.class) + .upgradeTower(TowerUpgraderComponent.UPGRADE.MAXHP, HEALTH_INCREASE); int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); int maxHealth = turretEntity.getComponent(CombatStatsComponent.class).getMaxHealth(); healthLabel.setText(String.format("%d/%d", currentHealth, maxHealth)); @@ -232,7 +242,7 @@ public void clicked(InputEvent event, float x, float y) { } @Override public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { - costDisplayLabel.setText("10"); + costDisplayLabel.setText(String.format("%d", UPGRADE_COST)); costDisplay.setVisible(true); } @Override @@ -247,12 +257,13 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) upgradeAttack.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { - value = ServiceLocator.getCurrencyService().getScrap().getAmount(); - if (value >= 10) { - value -= 10; - ServiceLocator.getCurrencyService().getScrap().setAmount(value); - ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.ATTACK, 5); + value = ServiceLocator.getCurrencyService().getCrystal().getAmount(); + if (value >= UPGRADE_COST) { + value -= UPGRADE_COST; + ServiceLocator.getCurrencyService().getCrystal().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateCrystalsStats(); + turretEntity.getComponent(TowerUpgraderComponent.class) + .upgradeTower(TowerUpgraderComponent.UPGRADE.ATTACK, ATTACK_INCREASE); int attack = turretEntity.getComponent(CombatStatsComponent.class).getBaseAttack(); attackLabel.setText(String.format("%d", attack)); @@ -260,7 +271,7 @@ public void clicked(InputEvent event, float x, float y) { } @Override public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { - costDisplayLabel.setText("10"); + costDisplayLabel.setText(String.format("%d", UPGRADE_COST)); costDisplay.setVisible(true); } @Override @@ -276,14 +287,18 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) upgradeFireRate.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { - value = ServiceLocator.getCurrencyService().getScrap().getAmount(); - if (value >= 10) { - value -= 10; - ServiceLocator.getCurrencyService().getScrap().setAmount(value); - ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - float newFireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate() + 0.2f; - turretEntity.getComponent(UpgradableStatsComponent.class).setAttackRate(newFireRate); - turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, (int) newFireRate * 5); + value = ServiceLocator.getCurrencyService().getCrystal().getAmount(); + if (value >= UPGRADE_COST) { + value -= UPGRADE_COST; + ServiceLocator.getCurrencyService().getCrystal().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateCrystalsStats(); + float newFireRate = turretEntity.getComponent(UpgradableStatsComponent.class) + .getAttackRate() + ATTACK_RATE_INCREASE; + turretEntity.getComponent(UpgradableStatsComponent.class) + .setAttackRate(newFireRate); + turretEntity.getComponent(TowerUpgraderComponent.class) + .upgradeTower(TowerUpgraderComponent.UPGRADE.FIRERATE, + (int) newFireRate * 5); float fireRate = turretEntity.getComponent(UpgradableStatsComponent.class).getAttackRate(); fireRateLabel.setText(String.format("%.2f", fireRate)); @@ -293,7 +308,7 @@ public void clicked(InputEvent event, float x, float y) { @Override public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { - costDisplayLabel.setText("10"); + costDisplayLabel.setText(String.format("%d", UPGRADE_COST)); costDisplay.setVisible(true); } @Override @@ -309,11 +324,12 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) @Override public void clicked(InputEvent event, float x, float y) { value = ServiceLocator.getCurrencyService().getScrap().getAmount(); - if (value >= 100) { - value -= 100; + if (value >= REPAIR_COST) { + value -= REPAIR_COST; ServiceLocator.getCurrencyService().getScrap().setAmount(value); ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.REPAIR, 0); + turretEntity.getComponent(TowerUpgraderComponent.class) + .upgradeTower(TowerUpgraderComponent.UPGRADE.REPAIR, 0); int currentHealth = turretEntity.getComponent(CombatStatsComponent.class).getHealth(); healthLabel.setText(String.format("%d/%d", currentHealth, maxHealth)); } @@ -321,11 +337,13 @@ public void clicked(InputEvent event, float x, float y) { @Override public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { - costDisplayLabel.setText("10"); + costDisplayLabel.setText(String.format("%d", REPAIR_COST)); + costImage.setDrawable(costDrawableScrap); costDisplay.setVisible(true); } @Override public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) { + costImage.setDrawable(costDrawable); costDisplay.setVisible(false); } @@ -353,12 +371,12 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) upgradeIncome.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { - value = ServiceLocator.getCurrencyService().getScrap().getAmount(); - if (value >= 10 && turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() >= 10) { - value -= 10; - ServiceLocator.getCurrencyService().getScrap().setAmount(value); - ServiceLocator.getCurrencyService().getDisplay().updateScrapsStats(); - float newIncome = turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() - 5; + value = ServiceLocator.getCurrencyService().getCrystal().getAmount(); + if (value >= UPGRADE_COST && turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() >= 10) { + value -= UPGRADE_COST; + ServiceLocator.getCurrencyService().getCrystal().setAmount(value); + ServiceLocator.getCurrencyService().getDisplay().updateCrystalsStats(); + float newIncome = turretEntity.getComponent(IncomeUpgradeComponent.class).getIncomeRate() - TIME_DECREASE; turretEntity.getComponent(IncomeUpgradeComponent.class).setIncomeRate(newIncome); turretEntity.getComponent(TowerUpgraderComponent.class).upgradeTower(TowerUpgraderComponent.UPGRADE.INCOME, (int) newIncome); incomeLabel.setText(String.format("%.2f", newIncome)); @@ -369,7 +387,7 @@ public void clicked(InputEvent event, float x, float y) { @Override public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) { - costDisplayLabel.setText("10"); + costDisplayLabel.setText(String.format("%d", UPGRADE_COST)); costDisplay.setVisible(true); } @Override @@ -378,6 +396,7 @@ public void exit(InputEvent event, float x, float y, int pointer, Actor toActor) } }); } + logger.info(String.valueOf(attack)); if (attack != 0) { innerUpgradeTable.add(attackIconImage).padRight(5).width(32).height(32); // Add attack icon innerUpgradeTable.add(attackLabel).expandX().left();