Share Remove Skill when Learn New; Удаление навыка при изучении нового

Жаба

Heir
Customer
JavaScript:
package services;

import l2.commons.listener.EventListener;
import l2.gameserver.GameServer;
import l2.gameserver.model.Player;
import l2.gameserver.model.Skill;
import l2.gameserver.scripts.Functions;
import l2.gameserver.scripts.ScriptFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("unused")
public class SkillRemove extends Functions implements ScriptFile, EventListener {

private static final Logger _log = LoggerFactory.getLogger(SkillRemove.class);
private static final String EVENT_LEARN_SKILL = "onSkillLearned";
private static final Map<Integer, List<Integer>> REMOVAL_DATA = new HashMap<>();

@Override
    public String[] listeningEventTypes() {
return new String[]{EVENT_LEARN_SKILL};
    }

@Override
    public void onEvent(String eventType, Object... args) {
if (EVENT_LEARN_SKILL.equals(eventType) && args.length >= 2) {
if (args[0] instanceof Player && args[1] instanceof Skill) {
checkAndRemove((Player) args[0], (Skill) args[1]);
            }
        }
    }

private void checkAndRemove(Player player, Skill learnedSkill) {
if (player == null || learnedSkill == null) return;

List<Integer> toRemove = REMOVAL_DATA.get(learnedSkill.getId());
if (toRemove != null && !toRemove.isEmpty()) {
boolean updated = false;
 for (Integer id : toRemove) {
                Skill old = player.getKnownSkill(id);
if (old != null) {
player.removeSkill(old, false);
player.sendMessage("При изучении " + learnedSkill.getName() + ", магические потоки вытеснили умение " + old.getName() + ".");
updated = true;
                }
            }

 if (updated) {
                player.sendSkillList();
                player.updateStats();
player.store(true);
            }
        }
    }

@Override
    public void onLoad() {
        loadXmlData();
if (!REMOVAL_DATA.isEmpty()) {
GameServer.getInstance().getListeners().addEventListener(this);
_log.info("SkillRemove: Loaded {} skill removal rules.", REMOVAL_DATA.size());
} else {
_log.warn("SkillRemove: No data loaded! Check SkillRemove.xml");
        }
    }

private void loadXmlData() {
 REMOVAL_DATA.clear();
File file = new File("data/SkillRemove.xml");

 if (!file.exists()) {
_log.error("SkillRemove: File not found: {}", file.getAbsolutePath());
 return;
        }

 try {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
Node listNode = doc.getElementsByTagName("list").item(0);
if (listNode != null) {
for (Node d = listNode.getFirstChild(); d != null; d = d.getNextSibling()) {
if ("skill".equalsIgnoreCase(d.getNodeName())) {
                        NamedNodeMap attrs = d.getAttributes();
if (attrs == null) continue;

Node idAttr = attrs.getNamedItem("id");
Node removeAttr = attrs.getNamedItem("remove");

if (idAttr != null && removeAttr != null) {
 try {
int id = Integer.parseInt(idAttr.getNodeValue());
String[] removeIds = removeAttr.getNodeValue().split(",");
List<Integer> list = new ArrayList<>();
 for (String s : removeIds) {
list.add(Integer.parseInt(s.trim()));
                                }
 REMOVAL_DATA.put(id, list);
} catch (NumberFormatException e) {
_log.error("SkillRemove: Error parsing ID in XML: {}", idAttr.getNodeValue());
                            }
                        }
                    }
                }
            }
} catch (Exception e) {
_log.error("SkillRemove: Error while reading XML:", e);
        }
    }

@Override
    public void onReload() {
    }

@Override
    public void onShutdown() {
    }
}

Удаляем способность если изучили другую, кому нужно придумает что с этим делать.
Compile for Lucera 2 Legacy (525)
 

Attachments

Code:
package services;

import l2.commons.listener.EventListener;
import l2.gameserver.GameServer;
import l2.gameserver.listener.actor.player.OnPlayerEnterListener;
import l2.gameserver.model.Player;
import l2.gameserver.model.Skill;
import l2.gameserver.model.actor.listener.PlayerListenerList;
import l2.gameserver.scripts.Functions;
import l2.gameserver.scripts.ScriptFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

@SuppressWarnings("unused")
public class SkillRemove extends Functions implements ScriptFile, EventListener, OnPlayerEnterListener {
    private static final Logger _log = LoggerFactory.getLogger(SkillRemove.class);
    private static final String EVENT_LEARN_SKILL = "onSkillLearned";
    private static final Map<Integer, List<Integer>> DATA = new HashMap<>();

    @Override
    public void onPlayerEnter(Player player) {
        if (player == null || DATA.isEmpty()) return;

        boolean updated = false;
        for (var entry : DATA.entrySet()) {
            int mainId = entry.getKey();
            List<Integer> targets = entry.getValue();
            List<Integer> found = new ArrayList<>();

            if (player.getKnownSkill(mainId) != null) found.add(mainId);
            for (int id : targets) {
                if (player.getKnownSkill(id) != null) found.add(id);
            }

            if (found.size() > 1) {
                int keptId = found.get(ThreadLocalRandom.current().nextInt(found.size()));
                for (int id : found) {
                    if (id != keptId) {
                        if (remove(player, id)) updated = true;
                    }
                }
            }
        }
        if (updated) refresh(player);
    }

    private boolean remove(Player player, int id) {
        Skill s = player.getKnownSkill(id);
        if (s != null) {
            String name = s.getName();
            player.removeSkillById(id);
            player.sendMessage("Конфликт: умение " + name + " полностью удалено.");
            _log.info("SkillRemove: Fully removed skill {} from {}", name, player.getName());
            return true;
        }
        return false;
    }

    private void refresh(Player player) {
        player.sendSkillList();
        player.updateStats();
    }

    @Override
    public void onEvent(String event, Object... args) {
        if (EVENT_LEARN_SKILL.equals(event) && args[0] instanceof Player p && args[1] instanceof Skill s) {
            List<Integer> targets = DATA.get(s.getId());
            if (targets != null) {
                boolean updated = false;
                for (int id : targets) {
                    if (remove(p, id)) updated = true;
                }
                if (updated) refresh(p);
            }
        }
    }

    @Override
    public String[] listeningEventTypes() {
        return new String[]{EVENT_LEARN_SKILL};
    }

    @Override
    public void onLoad() {
        load();
        if (!DATA.isEmpty()) {
            GameServer.getInstance().getListeners().addEventListener(this);
            PlayerListenerList.addGlobal(this);
            _log.info("SkillRemove: Loaded {} rules.", DATA.size());
        }
    }

    @Override
    public void onReload() {}

    @Override
    public void onShutdown() {}

    private void load() {
        DATA.clear();
        File f = new File("data/SkillRemove.xml");
        if (!f.exists()) return;
        try {
            Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f);
            Node list = doc.getElementsByTagName("list").item(0);
            if (list == null) return;
            for (Node n = list.getFirstChild(); n != null; n = n.getNextSibling()) {
                if ("skill".equalsIgnoreCase(n.getNodeName())) {
                    NamedNodeMap a = n.getAttributes();
                    int id = Integer.parseInt(a.getNamedItem("id").getNodeValue());
                    String[] r = a.getNamedItem("remove").getNodeValue().split(",");
                    List<Integer> tl = new ArrayList<>();
                    for (String s : r) tl.add(Integer.parseInt(s.trim()));
                    DATA.put(id, tl);
                }
            }
        } catch (Exception e) {
            _log.error("SkillRemove: XML Error", e);
        }
    }
}

Добавлена проверка при входе в игру на конфликты, удаляет сразу все уровни
 
Back
Top