From e77533b47798819a642f838aceb21099efb0fd60 Mon Sep 17 00:00:00 2001 From: jdrueckert Date: Sat, 4 Dec 2021 15:49:08 +0000 Subject: [PATCH 1/2] feat: add in-game shop in pregame phase (#253) --- .../systems/ClientPregameSystem.java | 74 +++++++++++++++++++ .../systems/ClientStatisticsSystem.java | 14 +++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/terasology/module/lightandshadow/systems/ClientPregameSystem.java b/src/main/java/org/terasology/module/lightandshadow/systems/ClientPregameSystem.java index 3b209b12..f9eb5cdf 100644 --- a/src/main/java/org/terasology/module/lightandshadow/systems/ClientPregameSystem.java +++ b/src/main/java/org/terasology/module/lightandshadow/systems/ClientPregameSystem.java @@ -2,25 +2,43 @@ // SPDX-License-Identifier: Apache-2.0 package org.terasology.module.lightandshadow.systems; +import org.terasology.economy.components.AllowShopScreenComponent; +import org.terasology.economy.ui.MarketUiClientSystem; +import org.terasology.engine.core.SimpleUri; import org.terasology.engine.entitySystem.entity.EntityManager; import org.terasology.engine.entitySystem.entity.EntityRef; +import org.terasology.engine.entitySystem.entity.lifecycleEvents.OnAddedComponent; +import org.terasology.engine.entitySystem.event.EventPriority; import org.terasology.engine.entitySystem.event.ReceiveEvent; import org.terasology.engine.entitySystem.systems.BaseComponentSystem; import org.terasology.engine.entitySystem.systems.RegisterMode; import org.terasology.engine.entitySystem.systems.RegisterSystem; +import org.terasology.engine.input.InputSystem; import org.terasology.engine.logic.players.LocalPlayer; +import org.terasology.engine.logic.players.event.LocalPlayerInitializedEvent; +import org.terasology.engine.network.ClientComponent; import org.terasology.engine.registry.In; import org.terasology.engine.rendering.nui.NUIManager; +import org.terasology.engine.unicode.EnclosedAlphanumerics; import org.terasology.gestalt.assets.ResourceUrn; +import org.terasology.input.ButtonState; +import org.terasology.input.Input; +import org.terasology.module.inventory.input.InventoryButton; import org.terasology.module.lightandshadow.events.GameStartMessageEvent; import org.terasology.module.lightandshadow.events.TimerEvent; +import org.terasology.notifications.events.ExpireNotificationEvent; +import org.terasology.notifications.events.ShowNotificationEvent; +import org.terasology.notifications.model.Notification; import org.terasology.notify.ui.DialogNotificationOverlay; +import org.terasology.nui.Color; +import org.terasology.nui.FontColor; import java.util.Timer; import java.util.TimerTask; @RegisterSystem(RegisterMode.CLIENT) public class ClientPregameSystem extends BaseComponentSystem { + private static final String NOTIFICATION_ID = "LightAndShadow:firstTimeShop"; public static final ResourceUrn ASSET_URI = new ResourceUrn("LightAndShadow:Timer"); @@ -28,6 +46,9 @@ public class ClientPregameSystem extends BaseComponentSystem { private static Timer timer; + @In + InputSystem inputSystem; + @In private EntityManager entityManager; @In @@ -52,6 +73,7 @@ public void shutdown() { public void onPregameStart(GameStartMessageEvent event, EntityRef entity) { if (localPlayer.getClientEntity().equals(entity)) { window.addNotification(PREGAME_MESSAGE); + entity.upsertComponent(AllowShopScreenComponent.class, c -> c.orElse(new AllowShopScreenComponent())); } } @@ -81,5 +103,57 @@ public void run() { } } + /** + * Handles the button event if in-game shop is enabled. + * Needs to have a higher priority than {@link MarketUiClientSystem#onToggleInventory(InventoryButton, EntityRef)} + * to receive the {@link InventoryButton} event before it is consumed. + * + * @param event the help button event. + * @param entity the entity to display the help screen to. + */ + @ReceiveEvent(components = {ClientComponent.class, AllowShopScreenComponent.class}, priority = EventPriority.PRIORITY_CRITICAL) + public void onInGameShopButton(InventoryButton event, EntityRef entity) { + if (event.getState() == ButtonState.DOWN) { + entity.send(new ExpireNotificationEvent(NOTIFICATION_ID)); + } + } + /** + * Get a formatted representation of the primary {@link Input} associated with the given button binding. + * + * If the display name of the primary bound key is a single character this representation will be the encircled + * character. Otherwise the full display name is used. The bound key will be printed in yellow. + * + * If no key binding was found the text "n/a" in red color is returned. + * + * @param button the URI of a bindable button + * @return a formatted text to be used as representation for the player + */ + //TODO: put this in a common place? Duplicated in Dialogs, EventualSkills, and InGameHelp + private String getActivationKey(SimpleUri button) { + return inputSystem.getInputsForBindButton(button).stream() + .findFirst() + .map(Input::getDisplayName) + .map(key -> { + if (key.length() == 1) { + // print the key in yellow within a circle + int off = key.charAt(0) - 'A'; + char code = (char) (EnclosedAlphanumerics.CIRCLED_LATIN_CAPITAL_LETTER_A + off); + return String.valueOf(code); + } else { + return key; + } + }) + .map(key -> FontColor.getColored(key, Color.yellow)) + .orElse(FontColor.getColored("n/a", Color.red)); + } + + @ReceiveEvent(components = AllowShopScreenComponent.class) + public void onShopComponentAdded(OnAddedComponent event, EntityRef entity) { + Notification notification = new Notification(NOTIFICATION_ID, + "Shut Up and Take My Money!", + "Press " + getActivationKey(new SimpleUri("Inventory:inventory")) + " to buy items", + "Economy:GoldCoin"); + localPlayer.getClientEntity().send(new ShowNotificationEvent(notification)); + } } diff --git a/src/main/java/org/terasology/module/lightandshadow/systems/ClientStatisticsSystem.java b/src/main/java/org/terasology/module/lightandshadow/systems/ClientStatisticsSystem.java index 58f099cf..42c782f7 100644 --- a/src/main/java/org/terasology/module/lightandshadow/systems/ClientStatisticsSystem.java +++ b/src/main/java/org/terasology/module/lightandshadow/systems/ClientStatisticsSystem.java @@ -31,7 +31,7 @@ */ @RegisterSystem(RegisterMode.CLIENT) public class ClientStatisticsSystem extends BaseComponentSystem { - private static final String NOTIFICATION_ID = "LightAndShadow:firstTime"; + private static final String NOTIFICATION_ID = "LightAndShadow:firstTimeStatistics"; @In InputSystem inputSystem; @@ -88,6 +88,18 @@ public void onTab(TapButton event, EntityRef entity) { } } + /** + * Get a formatted representation of the primary {@link Input} associated with the given button binding. + * + * If the display name of the primary bound key is a single character this representation will be the encircled + * character. Otherwise the full display name is used. The bound key will be printed in yellow. + * + * If no key binding was found the text "n/a" in red color is returned. + * + * @param button the URI of a bindable button + * @return a formatted text to be used as representation for the player + */ + //TODO: put this in a common place? Duplicated in Dialogs, EventualSkills, and InGameHelp private String getActivationKey(SimpleUri button) { return inputSystem.getInputsForBindButton(button).stream() .findFirst() From eb642ca0784dccc316baf4cb4133ffc8f64170b9 Mon Sep 17 00:00:00 2001 From: jdrueckert Date: Sat, 4 Dec 2021 19:15:29 +0000 Subject: [PATCH 2/2] chore: move CombatSystem deltas from LaSR to LaS (#255) --- deltas/CombatSystem/prefabs/items/staff.prefab | 5 +++++ deltas/CombatSystem/prefabs/items/sword.prefab | 9 +++++++++ deltas/CombatSystem/prefabs/items/waraxe.prefab | 9 +++++++++ deltas/CombatSystem/prefabs/projectiles/fireBall.prefab | 5 +++++ .../CombatSystem/prefabs/projectiles/spearThrow.prefab | 5 +++++ 5 files changed, 33 insertions(+) create mode 100644 deltas/CombatSystem/prefabs/items/staff.prefab create mode 100644 deltas/CombatSystem/prefabs/items/sword.prefab create mode 100644 deltas/CombatSystem/prefabs/items/waraxe.prefab create mode 100644 deltas/CombatSystem/prefabs/projectiles/fireBall.prefab create mode 100644 deltas/CombatSystem/prefabs/projectiles/spearThrow.prefab diff --git a/deltas/CombatSystem/prefabs/items/staff.prefab b/deltas/CombatSystem/prefabs/items/staff.prefab new file mode 100644 index 00000000..f9e8e118 --- /dev/null +++ b/deltas/CombatSystem/prefabs/items/staff.prefab @@ -0,0 +1,5 @@ +{ + "Item": { + "cooldownTime": 300 + } +} diff --git a/deltas/CombatSystem/prefabs/items/sword.prefab b/deltas/CombatSystem/prefabs/items/sword.prefab new file mode 100644 index 00000000..95634817 --- /dev/null +++ b/deltas/CombatSystem/prefabs/items/sword.prefab @@ -0,0 +1,9 @@ +{ + "Item": { + "cooldownTime": 500 + }, + "RandomDamage": { + "minDamage": 20, + "maxDamage": 25 + } +} diff --git a/deltas/CombatSystem/prefabs/items/waraxe.prefab b/deltas/CombatSystem/prefabs/items/waraxe.prefab new file mode 100644 index 00000000..4f966e86 --- /dev/null +++ b/deltas/CombatSystem/prefabs/items/waraxe.prefab @@ -0,0 +1,9 @@ +{ + "Item": { + "cooldownTime": 1000 + }, + "RandomDamage": { + "minDamage": 30, + "maxDamage": 40 + } +} diff --git a/deltas/CombatSystem/prefabs/projectiles/fireBall.prefab b/deltas/CombatSystem/prefabs/projectiles/fireBall.prefab new file mode 100644 index 00000000..04b00861 --- /dev/null +++ b/deltas/CombatSystem/prefabs/projectiles/fireBall.prefab @@ -0,0 +1,5 @@ +{ + "Hurting": { + "amount": 10 + } +} diff --git a/deltas/CombatSystem/prefabs/projectiles/spearThrow.prefab b/deltas/CombatSystem/prefabs/projectiles/spearThrow.prefab new file mode 100644 index 00000000..398002e4 --- /dev/null +++ b/deltas/CombatSystem/prefabs/projectiles/spearThrow.prefab @@ -0,0 +1,5 @@ +{ + "Hurting": { + "amount": 90 + } +}