From 9ccd509b193b7c6a7733838b9f1bee683d892ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Fri, 26 Aug 2022 10:46:13 +0200 Subject: [PATCH] Add support for enemies' loot --- data.mv.db | Bin 28672 -> 28672 bytes maps/551e1afc-9cda-4d9f-8817-bfd831fc0a75.dat | Bin 25206 -> 42521 bytes project.bep | 3 +- .../bartlomiejpluta/demo/entity/Enemy.java | 42 ++++++++- .../bartlomiejpluta/demo/entity/Player.java | 42 ++++++--- .../demo/gui/EquipmentWindow.java | 8 +- .../bartlomiejpluta/demo/gui/LootWindow.java | 83 ++++++++++++++++++ .../demo/menu/MenuManager.java | 18 +++- .../demo/runner/DemoRunner.java | 5 ++ .../bartlomiejpluta/demo/util/ListUtil.java | 21 +++++ .../d78413cd-0dad-4b51-8dd1-54e33535fe53.xml | 27 ++++++ 11 files changed, 228 insertions(+), 21 deletions(-) create mode 100644 src/main/java/com/bartlomiejpluta/demo/gui/LootWindow.java create mode 100644 src/main/java/com/bartlomiejpluta/demo/util/ListUtil.java create mode 100644 widgets/d78413cd-0dad-4b51-8dd1-54e33535fe53.xml diff --git a/data.mv.db b/data.mv.db index 22f5f108daa71d4bb40c04ef7d3ade13bf296174..8d20fc067a793e757e4d132d9a69e3908fea1245 100644 GIT binary patch literal 28672 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 b=HHR#|4otR|1B(2jgn2wsWtNtF^3BP?hM=Y literal 28672 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 diff --git a/project.bep b/project.bep index 99e07bc..ef4d5bc 100644 --- a/project.bep +++ b/project.bep @@ -20,7 +20,8 @@ Start MenuB[ $56ca6b39-f949-4212-9c23-312db25887e0(56ca6b39-f949-4212-9c23-312db25887e0.xml Game MenuBU $00bd0625-b3b8-4abf-97b7-91f42bce28ec(00bd0625-b3b8-4abf-97b7-91f42bce28ec.xmlHUDB[ $c473a91a-ff25-4e71-9bec-b35e48102aeb(c473a91a-ff25-4e71-9bec-b35e48102aeb.xml EquipmentB^ -$53ca3e54-0f8d-44fa-8281-acd9c5bba743(53ca3e54-0f8d-44fa-8281-acd9c5bba743.xml Eq Item MenuJZ +$53ca3e54-0f8d-44fa-8281-acd9c5bba743(53ca3e54-0f8d-44fa-8281-acd9c5bba743.xml Eq Item MenuB[ +$d78413cd-0dad-4b51-8dd1-54e33535fe53(d78413cd-0dad-4b51-8dd1-54e33535fe53.xml Loot MenuJZ $e6f067f1-eba0-4e62-99c3-2fd867e6f142(e6f067f1-eba0-4e62-99c3-2fd867e6f142.pngPoof (J[ $312cc4e6-8c44-43e7-828a-e7e2a77836f3(312cc4e6-8c44-43e7-828a-e7e2a77836f3.pngArrow (J[ $54f657bd-8108-464c-9bbe-63944fc14f6b(54f657bd-8108-464c-9bbe-63944fc14f6b.pngPunch (J[ diff --git a/src/main/java/com/bartlomiejpluta/demo/entity/Enemy.java b/src/main/java/com/bartlomiejpluta/demo/entity/Enemy.java index 94361b4..8bb43a4 100644 --- a/src/main/java/com/bartlomiejpluta/demo/entity/Enemy.java +++ b/src/main/java/com/bartlomiejpluta/demo/entity/Enemy.java @@ -1,5 +1,7 @@ package com.bartlomiejpluta.demo.entity; +import DB.EnemyDropDAO; +import DB.dao; import com.bartlomiejpluta.base.api.ai.AI; import com.bartlomiejpluta.base.api.ai.NPC; import com.bartlomiejpluta.base.api.context.ContextHolder; @@ -7,20 +9,31 @@ import com.bartlomiejpluta.base.api.move.MoveEvent; import com.bartlomiejpluta.base.lib.ai.NoopAI; import com.bartlomiejpluta.base.lib.animation.AnimationRunner; import com.bartlomiejpluta.base.lib.animation.SimpleAnimationRunner; +import com.bartlomiejpluta.base.lib.db.Relop; import com.bartlomiejpluta.base.util.random.DiceRoller; import com.bartlomiejpluta.demo.ai.*; import com.bartlomiejpluta.demo.event.EnemyDiedEvent; -import com.bartlomiejpluta.demo.runner.DemoRunner; +import com.bartlomiejpluta.demo.world.item.Item; import com.bartlomiejpluta.demo.world.weapon.Ammunition; import com.bartlomiejpluta.demo.world.weapon.MeleeWeapon; import com.bartlomiejpluta.demo.world.weapon.RangedWeapon; import lombok.Getter; import lombok.NonNull; +import java.util.Random; + +import static com.bartlomiejpluta.demo.util.ListUtil.randomIntSequence; + public class Enemy extends Creature implements NPC { + public static final int MAX_LOOT = 4 * 4; + + private final Random random = new Random(); private final DB.model.EnemyModel template; private final AnimationRunner dieAnimation; + + @Getter + private final Item[] loot = new Item[MAX_LOOT]; @Getter private final String name; private AI ai = NoopAI.INSTANCE; @@ -78,8 +91,35 @@ public class Enemy extends Creature implements NPC { dieAnimation.run(context, getLayer(), this); context.playSound(A.sounds.get(template.getDieSound()).uid); context.fireEvent(new EnemyDiedEvent(this)); + + drawLoot(); } + private void drawLoot() { + var def = dao.enemy_drop.query() + .where(EnemyDropDAO.Column.ENEMY, Relop.EQ, template.getId()) + .orderBy("rand()") + .find(); + + var indexesIterator = randomIntSequence(0, loot.length).iterator(); + for (var d : def) { + if (!indexesIterator.hasNext()) { + break; + } + + var index = indexesIterator.next(); + + var split = d.getItem().split(":"); + loot[index] = switch (split[0]) { + case "melee_weapon" -> new MeleeWeapon(split[1]); + case "ranged_weapon" -> new RangedWeapon(split[1]); + case "ammo" -> new Ammunition(split[1], DiceRoller.of(d.getAmount()).roll()); + default -> throw new IllegalArgumentException("Unsupported item type"); + }; + } + } + + public Enemy followAndAttack(Creature target, int range) { var ai = new SimpleEnemyAI(this, target, range); diff --git a/src/main/java/com/bartlomiejpluta/demo/entity/Player.java b/src/main/java/com/bartlomiejpluta/demo/entity/Player.java index 677ae29..b4b1076 100644 --- a/src/main/java/com/bartlomiejpluta/demo/entity/Player.java +++ b/src/main/java/com/bartlomiejpluta/demo/entity/Player.java @@ -7,9 +7,11 @@ import com.bartlomiejpluta.demo.world.weapon.Weapon; import lombok.NonNull; import org.joml.Vector2i; +import java.util.List; + public class Player extends Creature { private final Item[] equipment = new Item[4 * 4]; - private int pickingItemToEquipmentCooldown = 0; + private int interactionCooldown = 0; public Player(@NonNull Character entity) { super(entity); @@ -18,32 +20,50 @@ public class Player extends Creature { } public void interact() { + if (interactionCooldown > 0) { + return; + } + var coords = getCoordinates().add(getFaceDirection().vector, new Vector2i()); var entities = getLayer().getEntities(); for (var i = 0; i < entities.size(); ++i) { var entity = entities.get(i); + // Use some map object which player is looking at if (entity.getCoordinates().equals(coords) && entity instanceof MapObject object) { object.interact(this); return; } - if (pickingItemToEquipmentCooldown == 0 && entity.getCoordinates().equals(getCoordinates()) && entity instanceof Item item) { - pushItemToEquipment(item); - getLayer().removeEntity(item); - pickingItemToEquipmentCooldown = PICKING_ITEM_TO_EQUIPMENT_COOLDOWN; - return; + if (entity.getCoordinates().equals(getCoordinates())) { + + // Pick some item from the ground + if (entity instanceof Item item) { + pushItemToEquipment(item); + getLayer().removeEntity(item); + interactionCooldown = INTERACTION_COOLDOWN; + return; + } + + // Search the enemy corpse + if (entity instanceof Enemy enemy && !enemy.isAlive()) { + runner.openLootWindow(enemy); + interactionCooldown = INTERACTION_COOLDOWN; + return; + } } } } - private void pushItemToEquipment(@NonNull Item item) { + public boolean pushItemToEquipment(@NonNull Item item) { for (int i = 0; i < equipment.length; ++i) { if (equipment[i] == null) { equipment[i] = item; - return; + return true; } } + + return false; } public Item getEquipmentItem(int index) { @@ -124,10 +144,10 @@ public class Player extends Creature { public void update(float dt) { super.update(dt); - if (pickingItemToEquipmentCooldown > 0) { - pickingItemToEquipmentCooldown = (int) Math.max(0, pickingItemToEquipmentCooldown - dt * 1000); + if (interactionCooldown > 0) { + interactionCooldown = (int) Math.max(0, interactionCooldown - dt * 1000); } } - private static final int PICKING_ITEM_TO_EQUIPMENT_COOLDOWN = 300; + private static final int INTERACTION_COOLDOWN = 300; } \ No newline at end of file diff --git a/src/main/java/com/bartlomiejpluta/demo/gui/EquipmentWindow.java b/src/main/java/com/bartlomiejpluta/demo/gui/EquipmentWindow.java index 4cf49f9..b3d84f0 100644 --- a/src/main/java/com/bartlomiejpluta/demo/gui/EquipmentWindow.java +++ b/src/main/java/com/bartlomiejpluta/demo/gui/EquipmentWindow.java @@ -55,8 +55,8 @@ public class EquipmentWindow extends DecoratedWindow { } @Override - public void onOpen(WindowManager manager) { - super.onOpen(manager); + public void onOpen(WindowManager manager, Object... args) { + super.onOpen(manager, args); cancelBtn.setAction(manager::close); eqGrid.setOnSelect(this::updateItemDetails); @@ -72,14 +72,14 @@ public class EquipmentWindow extends DecoratedWindow { for (var child : eqGrid.getChildren()) { var slot = (ItemIconView) child; slot.setItem(player.getEquipmentItem(i++)); - slot.setAction(handleItem(slot)); + slot.setAction(handleClick(slot)); } weapon.setItem(player.getWeapon()); ammo.setItem(player.getAmmunition()); } - private Consumer handleItem(ItemIconView slot) { + private Consumer handleClick(ItemIconView slot) { return item -> { useBtn.setText(getButtonTitle(item)); eqItemMenu.select(0); diff --git a/src/main/java/com/bartlomiejpluta/demo/gui/LootWindow.java b/src/main/java/com/bartlomiejpluta/demo/gui/LootWindow.java new file mode 100644 index 0000000..c3a5d23 --- /dev/null +++ b/src/main/java/com/bartlomiejpluta/demo/gui/LootWindow.java @@ -0,0 +1,83 @@ +package com.bartlomiejpluta.demo.gui; + +import com.bartlomiejpluta.base.api.context.Context; +import com.bartlomiejpluta.base.api.gui.*; +import com.bartlomiejpluta.base.lib.gui.VGridOptionChoice; +import com.bartlomiejpluta.demo.entity.Enemy; +import com.bartlomiejpluta.demo.entity.Player; +import com.bartlomiejpluta.demo.runner.DemoRunner; +import com.bartlomiejpluta.demo.world.item.Item; + +import java.util.Map; + +public class LootWindow extends DecoratedWindow implements Inflatable { + private final Player player; + + @Ref("loot") + private VGridOptionChoice lootMenu; + + private Item[] loot; + + private ItemIconView[] slots = new ItemIconView[Enemy.MAX_LOOT]; + + public LootWindow(Context context, GUI gui, Map refs) { + super(context, gui, refs); + this.player = ((DemoRunner) context.getGameRunner()).getPlayer(); + } + + @Override + public void onInflate() { + for (int i = 0; i < Enemy.MAX_LOOT; ++i) { + var itemView = new ItemIconView(context, gui, Map.of()); + itemView.setMargin(5f); + lootMenu.add(itemView); + slots[i] = itemView; + itemView.setAction(this::handleClick); + } + } + + @Override + public void onOpen(WindowManager manager, Object[] args) { + super.onOpen(manager, args); + + var creature = (Enemy) args[0]; + this.loot = creature.getLoot(); + updateSlots(); + } + + @Override + public void onClose(WindowManager manager) { + super.onClose(manager); + + clearSlots(); + this.loot = null; + } + + private void handleClick(Item item) { + if (item == null) { + return; + } + + if (player.pushItemToEquipment(item)) { + for (int i = 0; i < Enemy.MAX_LOOT; i++) { + if (loot[i] == item) { + loot[i] = null; + slots[i].setItem(null); + break; + } + } + } + } + + private void updateSlots() { + for (int i = 0; i < Enemy.MAX_LOOT; ++i) { + slots[i].setItem(loot[i]); + } + } + + private void clearSlots() { + for (var slot : slots) { + slot.setItem(null); + } + } +} diff --git a/src/main/java/com/bartlomiejpluta/demo/menu/MenuManager.java b/src/main/java/com/bartlomiejpluta/demo/menu/MenuManager.java index 8698e9e..6382758 100644 --- a/src/main/java/com/bartlomiejpluta/demo/menu/MenuManager.java +++ b/src/main/java/com/bartlomiejpluta/demo/menu/MenuManager.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.demo.menu; +import A.widgets; import com.bartlomiejpluta.base.api.context.Context; import com.bartlomiejpluta.base.api.gui.DisplayMode; import com.bartlomiejpluta.base.api.gui.GUI; @@ -8,8 +9,10 @@ import com.bartlomiejpluta.base.api.gui.WindowManager; import com.bartlomiejpluta.base.api.input.Key; import com.bartlomiejpluta.base.api.input.KeyAction; import com.bartlomiejpluta.base.api.input.KeyEvent; +import com.bartlomiejpluta.demo.entity.Enemy; import com.bartlomiejpluta.demo.gui.EquipmentWindow; import com.bartlomiejpluta.demo.gui.GameMenuWindow; +import com.bartlomiejpluta.demo.gui.LootWindow; import com.bartlomiejpluta.demo.gui.StartMenuWindow; import com.bartlomiejpluta.demo.runner.DemoRunner; import lombok.NonNull; @@ -25,7 +28,7 @@ public class MenuManager { private final StartMenuWindow startMenu; private final GameMenuWindow gameMenu; private final EquipmentWindow equipment; - + private final LootWindow loot; private final Consumer gameMenuHandler = this::handleGameMenuKeyEvent; public MenuManager(@NonNull DemoRunner runner, @NonNull Context context) { @@ -36,16 +39,17 @@ public class MenuManager { this.gui.setRoot(this.manager); - this.startMenu = (StartMenuWindow) gui.inflateWindow(A.widgets.start_menu.uid); + this.startMenu = gui.inflateWindow(A.widgets.start_menu.uid, StartMenuWindow.class); this.startMenu.getNewGameBtn().setAction(runner::newGame); this.startMenu.getExitBtn().setAction(runner::exit); - this.gameMenu = (GameMenuWindow) gui.inflateWindow(A.widgets.game_menu.uid); + this.gameMenu = gui.inflateWindow(A.widgets.game_menu.uid, GameMenuWindow.class); this.gameMenu.getResumeGameBtn().setAction(this::resumeGame); this.gameMenu.getStartMenuBtn().setAction(runner::returnToStartMenu); this.gameMenu.getExitBtn().setAction(runner::exit); - this.equipment = (EquipmentWindow) gui.inflateWindow(A.widgets.equipment.uid); + this.equipment = gui.inflateWindow(A.widgets.equipment.uid, EquipmentWindow.class); + this.loot = gui.inflateWindow(widgets.loot_menu.uid, LootWindow.class); } private void handleGameMenuKeyEvent(KeyEvent event) { @@ -97,6 +101,12 @@ public class MenuManager { manager.setDisplayMode(DisplayMode.DISPLAY_TOP); } + public void openLootWindow(@NonNull Enemy enemy) { + manager.closeAll(); + + manager.open(loot, enemy); + } + public void closeAll() { manager.closeAll(); } diff --git a/src/main/java/com/bartlomiejpluta/demo/runner/DemoRunner.java b/src/main/java/com/bartlomiejpluta/demo/runner/DemoRunner.java index 862a8ec..acf15d5 100644 --- a/src/main/java/com/bartlomiejpluta/demo/runner/DemoRunner.java +++ b/src/main/java/com/bartlomiejpluta/demo/runner/DemoRunner.java @@ -5,6 +5,7 @@ import com.bartlomiejpluta.base.api.gui.GUI; import com.bartlomiejpluta.base.api.runner.GameRunner; import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.util.profiler.FPSProfiler; +import com.bartlomiejpluta.demo.entity.Enemy; import com.bartlomiejpluta.demo.entity.Player; import com.bartlomiejpluta.demo.menu.MenuManager; import com.bartlomiejpluta.demo.world.weapon.RangedWeapon; @@ -96,6 +97,10 @@ public class DemoRunner implements GameRunner { menu.showStartMenu(); } + public void openLootWindow(Enemy enemy) { + menu.openLootWindow(enemy); + } + public void exit() { context.close(); } diff --git a/src/main/java/com/bartlomiejpluta/demo/util/ListUtil.java b/src/main/java/com/bartlomiejpluta/demo/util/ListUtil.java new file mode 100644 index 0000000..28633f3 --- /dev/null +++ b/src/main/java/com/bartlomiejpluta/demo/util/ListUtil.java @@ -0,0 +1,21 @@ +package com.bartlomiejpluta.demo.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.stream.IntStream; + +public class ListUtil { + private static final Random random = new Random(); + + public static T sample(List list) { + return list.get(random.nextInt(list.size())); + } + + public static List randomIntSequence(int startInclusive, int endExclusive) { + var ints = new ArrayList<>(IntStream.range(startInclusive, endExclusive).boxed().toList()); + Collections.shuffle(ints); + return ints; + } +} diff --git a/widgets/d78413cd-0dad-4b51-8dd1-54e33535fe53.xml b/widgets/d78413cd-0dad-4b51-8dd1-54e33535fe53.xml new file mode 100644 index 0000000..887729f --- /dev/null +++ b/widgets/d78413cd-0dad-4b51-8dd1-54e33535fe53.xml @@ -0,0 +1,27 @@ + + + + + + Loot + + + + + + + \ No newline at end of file