Spawn Style L2Damage

EmptyPirsys

Vassal
Customer
This code implements a spawn shop system in a game where players can receive items based on their selection. The items are defined in a rewardMap and assigned to different reward groups (e.g., Flaming Sword, Mystic Wand, etc.). When a player enters the game, the system checks if they have already received a reward and displays an HTML menu based on their status. If the player hasn't received a reward, they can choose an item from the menu and receive it. The player's status is updated in the database to reflect the reward.


I need assistance understanding how to apply the correct bypass line in the HTML file to trigger the handleItemSelection method from the ModSpawnShop class. The action should pass the correct selection value (1, 2, 3, etc.) depending on which item the player selects. Could you help me understand how to properly create the bypass for this?

Code:
package Spawn;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import l2.gameserver.database.DatabaseFactory;
import l2.gameserver.listener.actor.player.OnPlayerEnterListener;
import l2.gameserver.model.Player;
import l2.gameserver.model.actor.listener.CharListenerList;
import l2.gameserver.model.items.ItemInstance;
import l2.gameserver.network.l2.s2c.NpcHtmlMessage;
import l2.gameserver.network.l2.s2c.SystemMessage;
import l2.gameserver.scripts.Functions;
import l2.gameserver.scripts.ScriptFile;
import l2.gameserver.utils.ItemFunctions;

public class ModSpawnShop extends Functions implements ScriptFile, OnPlayerEnterListener {

    // Mapa de recompensas configurado de forma más flexible
    private static final Map<Integer, int[][]> rewardMap = new HashMap<>();

    static {
        rewardMap.put(1, new int[][] {
            {7575, 1, 15},  // Flaming Sword: {ID, Count, Enchant}
            {6660, 1, 15},    // Mystic Wand: {ID, Count, Enchant}
            {6658, 1, 15},    // Mystic Wand: {ID, Count, Enchant}
        });
        rewardMap.put(2, new int[][] {
            {6367, 1, 15},   // Example Item 1: {ID, Count, Enchant}
            {6660, 1, 15}    // Another Example Item: {ID, Count, Enchant}
        });
        rewardMap.put(3, new int[][] {
            {6579, 1, 15}    // Yet Another Example Item: {ID, Count, Enchant}
        });
    }

    private void giveItems(Player player, String rewardVar, int[][] itemsToGive, String alreadyRewardedMessage) {
        if (!player.getVarB(rewardVar) && !checkUsedCheckFromDatabase(player)) {
            // Otorgar los ítems
            for (int[] itemData : itemsToGive) {
                ItemInstance item = ItemFunctions.createItem(itemData[0]);
                item.setCount(itemData[1]);
                item.setEnchantLevel(itemData[2]);
                player.getInventory().addItem(item);
                player.sendPacket(SystemMessage.obtainItems(item.getItemId(), item.getCount(), item.getEnchantLevel()));
                player.sendMessage("You have received: " + item.getTemplate().getName() + " x" + item.getCount());
            }

            // Marcar que el jugador ha usado el check y actualizar la base de datos
            setUsedCheck(player);
            player.setVar(rewardVar, "true", -1);

            // Mostrar un mensaje HTML al jugador para seleccionar otra entrega
            showHtmlMenu(player);
        } else {
            player.sendMessage(alreadyRewardedMessage);
        }
    }

    private void showHtmlMenu(Player player) {
        // Definir los nombres de los archivos
        String htmlFile;
        
        // Comprobamos el valor de 'used_check' desde la base de datos
        boolean hasUsedCheck = checkUsedCheckFromDatabase(player);

        if (hasUsedCheck) {
            htmlFile = "si.htm";  // Si 'used_check' es 1
        } else {
            htmlFile = "no.htm";  // Si 'used_check' es 0
        }

        // Aquí usamos la ruta correcta del archivo
        String filePath = "data/html-en/mods/spelogin/" + htmlFile;  // Ruta completa

        // Mostrar la ruta en la consola
        System.out.println("HTML file path: " + filePath);

        File file = new File(filePath);  // Ruta completa del archivo HTML

        if (!file.exists()) {
            player.sendMessage("Error: HTML file not found.");
            return;
        }

        // Cargar el contenido del archivo HTML y enviarlo al jugador
        try {
            String htmlContent = Files.readString(Paths.get(file.getPath()), StandardCharsets.UTF_8);
            
            // Enviar el HTML al jugador
            NpcHtmlMessage npcHtmlMessage = new NpcHtmlMessage(0);
            npcHtmlMessage.setHtml(htmlContent);
            player.sendPacket(npcHtmlMessage);
            
        } catch (IOException e) {
            player.sendMessage("Error reading HTML file.");
            e.printStackTrace();
        }
    }

    // Unificado el código de verificación del 'used_check' de la base de datos
    private boolean checkUsedCheckFromDatabase(Player player) {
        try (Connection con = DatabaseFactory.getInstance().getConnection();
             PreparedStatement ps = con.prepareStatement("SELECT `used_check` FROM `characters` WHERE `obj_Id` = ?")) {
            ps.setInt(1, player.getObjectId());
            try (ResultSet rs = ps.executeQuery()) {
                return rs.next() && rs.getInt("used_check") == 1;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return false;
        }
    }

    // Método para actualizar el estado del check (usado o no)
    private void setUsedCheck(Player player) {
        try (Connection con = DatabaseFactory.getInstance().getConnection();
             PreparedStatement ps = con.prepareStatement("UPDATE `characters` SET `used_check` = 1 WHERE `obj_Id` = ?")) {
            ps.setInt(1, player.getObjectId());
            ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // Método para manejar la elección del jugador en base a la selección del ítem
    public void handleItemSelection(Player player, int selection) {
        if (checkUsedCheckFromDatabase(player)) {
            player.sendMessage("You have already used this reward. You cannot use it again.");
            return;
        }

        int[][] itemsToGive = rewardMap.getOrDefault(selection, new int[0][0]);
        if (itemsToGive.length == 0) {
            player.sendMessage("Invalid selection, no items to give.");
            return;
        }

        // Dar los ítems y marcar que el jugador ha usado el check
        giveItems(player, "multiple_items_rewarded", itemsToGive, "Items already rewarded");
    }

    @Override
    public void onPlayerEnter(Player activeChar) {
        showHtmlMenu(activeChar);
    }

    public void onLoad() {
        CharListenerList.addGlobal(this);
    }

    public void onReload() {
        // Implementa aquí la lógica de recarga, si es necesario
    }

    @Override
    public void onShutdown() {
        // Implementa aquí la lógica de apagado, si es necesario
    }
}
 
1. HTML File: Add the bypass link for each item selection.
HTML:
<html>
<body>
    <h1>Select Your Reward</h1>
    <button action="bypass -h script_HandleItemSelection 1">Select Item 1</button>
    <button action="bypass -h script_HandleItemSelection 2">Select Item 2</button>
    <button action="bypass -h script_HandleItemSelection 3">Select Item 3</button>
</body>
</html>

2. Java Code: Implement the method to handle the bypass command.Ensure your ModSpawnShop class correctly interprets the bypass command and calls handleItemSelection with the appropriate parameters.

Code:
public void onBypassFeedback(Player player, String command) {
    if (command.startsWith("script_HandleItemSelection")) {
        String[] parts = command.split(" ");
        int selection = Integer.parseInt(parts[1]);
        handleItemSelection(player, selection);
    }
}

In this example:

  • The HTML file contains buttons that use the bypass -h command to trigger the onBypassFeedback method in your Java class.
  • When a player clicks a button, the server receives the bypass command and calls onBypassFeedback with the corresponding selection value (1, 2, 3, etc.).
  • The onBypassFeedback method extracts the selection value from the command string and calls handleItemSelection to process the player's choice.
This should help you link your HTML file to the handleItemSelection method in the ModSpawnShop class effectively.
 
Back
Top