commit fb7ef81d9936ff189b860c1e764d5f32a134d8f4
Author: yaohunya <1763917516@qq.com>
Date: Mon Jul 14 13:03:15 2025 +0800
1.3.4
diff --git a/libs/Citizens.jar b/libs/Citizens.jar
new file mode 100644
index 0000000..085149f
Binary files /dev/null and b/libs/Citizens.jar differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..dae922b
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,67 @@
+
+
+ 4.0.0
+
+ com.yaohun.guaji.AuGuaJi
+ DemonSkills
+ 1.0-SNAPSHOT
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+ public-rpg
+ https://repo.aurora-pixels.com/repository/public-rpg/
+
+
+
+
+
+ org.spigotmc
+ spigot-api
+ 1.12.2
+
+
+ me.Demon.DemonPlugin
+ DemonAPI
+ 2.2.9
+
+
+ me.clip.placeholderapi
+ PlaceholderAPI
+ 2.9.2
+
+
+ lk.vexview
+ VexView
+ 2.6.10
+
+
+ eos.moe.dragoncore
+ DragonCore
+ 2.6.2.0
+
+
+ org.serverct.ersha.jd
+ AttributePlus
+ 2.3.7
+
+
+ me.Demon.DemonTeam
+ DemonTeam
+ 1.2.0
+
+
+ me.Demon.DemonSoulBind
+ DemonSoulBind
+ 1.5.9
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/com/yaohun/demonskills/PapiExpansion.java b/src/main/java/com/yaohun/demonskills/PapiExpansion.java
new file mode 100644
index 0000000..0d74c66
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/PapiExpansion.java
@@ -0,0 +1,103 @@
+package com.yaohun.demonskills;
+
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.util.CDTimeAPI;
+import me.clip.placeholderapi.expansion.PlaceholderExpansion;
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.Plugin;
+
+import java.util.UUID;
+
+/**
+ * @Author: Baka
+ * @Date: 2019/12/23 13:20
+ */
+public class PapiExpansion extends PlaceholderExpansion {
+ private Plugin plugin;
+
+ public PapiExpansion(Plugin plugin) {
+ this.plugin = plugin;
+ }
+
+ @Override
+ public boolean persist() {
+ return true;
+ }
+
+ @Override
+ public boolean canRegister() {
+ return true;
+ }
+
+ @Override
+ public String getAuthor() {
+ return plugin.getDescription().getAuthors().toString();
+ }
+
+ @Override
+ public String getIdentifier() {
+ return "auskill";
+ }
+
+ @Override
+ public String getVersion() {
+ return plugin.getDescription().getVersion();
+ }
+
+ @Override
+ public String onPlaceholderRequest(Player player, String identifier) {
+ UUID uuid = player.getUniqueId();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ if (identifier.contains("_")) {
+ PlayerData playerData = playerManager.getPlayerData(player.getName());
+ String[] sp = identifier.split("_");
+ return getSkillCooldow(uuid,playerData,sp);
+ }
+ return "";
+ }
+
+ private String getSkillCooldow(UUID uuid,PlayerData playerData,String[] sp){
+ String papiType = sp[0];
+ String skillKey = sp[1];
+ if(papiType.equalsIgnoreCase("cd")){
+ if(skillKey.equalsIgnoreCase("翻滚")){
+ String cooldownKey = "skill_翻滚";
+ double time = (double) CDTimeAPI.getCD(uuid, cooldownKey) / 1000L;
+ if(time <= 0){
+ time = 0;
+ }
+ return String.format("%.1f",time);
+ } else {
+ int keyBoard = Integer.parseInt(sp[1]);
+ String skillName = playerData.getSkillNameBind(keyBoard);
+ if(skillName.equalsIgnoreCase("default")){
+ return "0.0";
+ }
+ String cooldownKey = "skill_"+skillName;
+ double time = (double) CDTimeAPI.getCD(uuid, cooldownKey) / 1000L;
+ if(time <= 0){
+ time = 0;
+ }
+ return String.format("%.1f",time);
+ }
+ }
+ if(papiType.equalsIgnoreCase("cdmax")){
+ if(skillKey.equalsIgnoreCase("翻滚")){
+ return "5.0";
+ } else {
+ int keyBoard = Integer.parseInt(sp[1]);
+ String skillName = playerData.getSkillNameBind(keyBoard);
+ if(skillName.equalsIgnoreCase("default")){
+ return "10.0";
+ }
+ return String.format("%.1f",playerData.getCooldownData(skillName));
+ }
+ }
+ if (sp[0].equalsIgnoreCase("icon")){
+ int keyBoard = Integer.parseInt(sp[1]);
+ return playerData.getSkillNameBind(keyBoard);
+ }
+ return "0.0";
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/yaohun/demonskills/SkillsMain.java b/src/main/java/com/yaohun/demonskills/SkillsMain.java
new file mode 100644
index 0000000..e38c0cc
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/SkillsMain.java
@@ -0,0 +1,234 @@
+package com.yaohun.demonskills;
+
+import com.yaohun.demonskills.config.Config;
+import com.yaohun.demonskills.config.MessageUtil;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.core.SkillStoneUpgrade;
+import com.yaohun.demonskills.data.SkillData;
+import com.yaohun.demonskills.gui.StoneEquipGui;
+import com.yaohun.demonskills.manage.SkillManager;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.gui.SkillStoneGui;
+import com.yaohun.demonskills.gui.SkillsGui;
+import com.yaohun.demonskills.listener.PlayerListener;
+import com.yaohun.demonskills.listener.SkillKeyListener;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.util.CDTimeAPI;
+import me.Demon.DemonPlugin.DemonAPI;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SkillsMain extends JavaPlugin {
+
+ private static SkillsMain instance;
+ private static PlayerManager playerManager;
+
+
+ @Override
+ public void onEnable() {
+ instance = this;
+ SkillManager.init();
+ Config.reloadConfig(this);
+ playerManager = new PlayerManager();
+ getServer().getPluginManager().registerEvents(new SkillsGui(),this);
+ getServer().getPluginManager().registerEvents(new SkillKeyListener(),this);
+ getServer().getPluginManager().registerEvents(new PlayerListener(),this);
+ getServer().getPluginManager().registerEvents(new SkillStoneGui(),this);
+ getServer().getPluginManager().registerEvents(new StoneEquipGui(),this);
+ // getServer().getPluginManager().registerEvents(new CommonAttackListener(),this);
+ if(getServer().getPluginManager().getPlugin("PlaceholderAPI") != null){
+ new PapiExpansion(this).register();
+ }
+ Bukkit.getConsoleSender().sendMessage("§b[魂式技能] §a插件成功载入Server!");
+ Bukkit.getConsoleSender().sendMessage("§b[魂式技能] §a妖魂QQ: §b1763917516");
+ }
+
+ @Override
+ public void onDisable() {
+ playerManager.SaveAllPlayerData();
+ }
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command cmd, String Command, String[] args) {
+ if (args.length == 1 && args[0].equalsIgnoreCase("open")) {
+ SkillsGui.OpenGui((Player) sender);
+ return true;
+ }
+ if (!sender.isOp()) {
+ return true;
+ }
+ if (args.length == 0) {
+ sender.sendMessage("");
+ sender.sendMessage("§e------- ======= §6技能系统 §e======= -------");
+ sender.sendMessage("§2/" + Command + " open §f- §2打开界面");
+ sender.sendMessage("§2/" + Command + " admin §f- §2灵石仓库");
+ sender.sendMessage("§2/" + Command + " upgrade §f- §2进阶灵石");
+ sender.sendMessage("§2/" + Command + " reduce §f- §2降级灵石");
+ sender.sendMessage("§2/" + Command + " stone §e[等级] §2<玩家> §f- §2随机一枚");
+ sender.sendMessage("§2/" + Command + " give §e[灵石] §2<等级> §b<玩家> §f- §2给予灵石");
+ sender.sendMessage("§2/" + Command + " mail §e[灵石] §2<等级> §b<玩家> §f- §2给予灵石");
+ sender.sendMessage("§e------- ======= §6技能系统 §e======= -------");
+ return true;
+ }
+ if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
+ SkillManager.skillDataMap.clear();
+ SkillManager.init();
+ DemonAPI.sendMessage(sender, "配置文件已重载.");
+ return true;
+ }
+ if (args.length == 1 && args[0].equalsIgnoreCase("upgrade")) {
+ SkillStoneUpgrade.carryOut((Player) sender,true);
+ return true;
+ }
+ if (args.length == 1 && args[0].equalsIgnoreCase("reduce")) {
+ SkillStoneUpgrade.carryOut((Player) sender,false);
+ return true;
+ }
+ if (args[0].equalsIgnoreCase("admin")) {
+ int level = 1;
+ String playerName = sender.getName();
+ if(args.length == 2) {
+ level = Integer.parseInt(args[1]);
+ }
+ if(args.length == 3) {
+ playerName = args[2];
+ }
+ SkillStoneGui.OpenGui((Player) sender,playerName,level);
+ return true;
+ }
+ if (args[0].equalsIgnoreCase("give")) {
+ if(args.length == 1){
+ List stringList = new ArrayList<>(SkillManager.skillDataMap.keySet());
+ sendMessage(sender,"灵石方案: §6"+String.join("§7, §6", stringList));
+ return true;
+ }
+ String skillName = args[1];
+ int skillLevel = 1;
+ String playerName = sender.getName();
+ if(args.length >= 3){
+ skillLevel = Integer.parseInt(args[2]);
+ }
+ if(args.length >= 4){
+ playerName = args[3];
+ }
+ Player player = Bukkit.getPlayer(playerName);
+ if(player == null){
+ player = (Player) sender;
+ }
+ if (!SkillManager.isSkillDataExit(skillName)) {
+ sendMessage(sender,"技能石 §6"+skillName+" §a不存在.");
+ return true;
+ }
+ SkillData skillData = SkillManager.skillDataMap.get(skillName);
+ ItemStack itemStack = skillData.getItemStack(playerName,skillLevel);
+ player.getInventory().addItem(itemStack);
+ String itemName = DemonAPI.getItemName(itemStack);
+ String message = Config.langData.getMessage("getNotification").replace("{name}",itemName);
+ MessageUtil.sendMessage(player,message,Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ sender.sendMessage("[技能系统] 玩家 "+playerName+" 获得 "+skillName+"[Lv."+skillLevel+"] [背包]");
+ return true;
+ }
+ if (args[0].equalsIgnoreCase("mail")) {
+ if(args.length == 1){
+ List stringList = new ArrayList<>(SkillManager.skillDataMap.keySet());
+ sendMessage(sender,"灵石方案: §6"+String.join("§7, §6", stringList));
+ return true;
+ }
+ String skillName = args[1];
+ int skillLevel = 1;
+ String playerName = sender.getName();
+ if(args.length >= 3){
+ skillLevel = Integer.parseInt(args[2]);
+ }
+ if(args.length >= 4){
+ playerName = args[3];
+ }
+ if (!SkillManager.isSkillDataExit(skillName)) {
+ sendMessage(sender,"技能石 §6"+skillName+" §a不存在.");
+ return true;
+ }
+ SkillData skillData = SkillManager.skillDataMap.get(skillName);
+ ItemStack itemStack = skillData.getItemStack(playerName,skillLevel);
+ DemonAPI.giveMailItem(playerName,itemStack);
+ sender.sendMessage("[技能系统] 玩家 "+playerName+" 获得 "+skillName+"[Lv."+skillLevel+"] [邮箱]");
+ return true;
+ }
+ if (args[0].equalsIgnoreCase("stone")) {
+ int skillLevel = 1;
+ String playerName = sender.getName();
+ if(args.length >= 2){
+ skillLevel = Integer.parseInt(args[1]);
+ }
+ String skillName = SkillManager.getRandomStone();
+ if (!SkillManager.isSkillDataExit(skillName)) {
+ sendMessage(sender,"技能石 §6"+skillName+" §a不存在.");
+ return true;
+ }
+ if(args.length >= 3){
+ playerName = args[2];
+ }
+ Player player = Bukkit.getPlayer(playerName);
+ SkillData skillData = SkillManager.skillDataMap.get(skillName);
+ ItemStack itemStack = skillData.getItemStack(playerName,skillLevel);
+ if(player == null){
+ DemonAPI.giveMailItem(playerName,itemStack);
+ sender.sendMessage("[技能系统] 玩家 "+playerName+" 获得 "+skillName+"[Lv."+skillLevel+"] [邮箱]");
+ } else {
+ player.getInventory().addItem(itemStack);
+ sender.sendMessage("[技能系统] 玩家 "+playerName+" 获得 "+skillName+"[Lv."+skillLevel+"] [背包]");
+ String itemName = DemonAPI.getItemName(itemStack);
+ String message = Config.langData.getMessage("getNotification").replace("{name}",itemName);
+ MessageUtil.sendMessage(player,message,Sound.ENTITY_EXPERIENCE_ORB_PICKUP);
+ }
+ return true;
+ }
+ if (args[0].equalsIgnoreCase("info")) {
+ String playerName = sender.getName();
+ if(args.length == 2){
+ playerName = args[1];
+ }
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ sendMessage(sender,"正在<§b"+playerName+"§a>查看技能数据:");
+ sender.sendMessage("§7- §a魔法值: §e"+playerData.getMagicNow()+"§7/§6"+playerData.getMagicMax());
+ sender.sendMessage("§7- §a技能按键绑定: ");
+ sender.sendMessage("§7- §r19§e(R) §7>> §6"+playerData.getSkillNameBind(19));
+ sender.sendMessage("§7- §r44§e(Z) §7>> §6"+playerData.getSkillNameBind(44));
+ sender.sendMessage("§7- §r45§e(X) §7>> §6"+playerData.getSkillNameBind(45));
+ sender.sendMessage("§7- §r46§e(C) §7>> §6"+playerData.getSkillNameBind(46));
+ sender.sendMessage("§7- §r47§e(V) §7>> §6"+playerData.getSkillNameBind(47));
+ return true;
+ } else {
+ String skillName = args[0];
+ Player player = (Player) sender;
+ Skill skill = SkillManager.getNameConvertSkill(player,skillName);
+ if(skill == null){
+ sender.sendMessage("§f[§c技能§f] §a技能 §c"+skillName+" §a貌似不存在.");
+ return true;
+ }
+ String cooldownKey = "skill_"+skill.name;
+ CDTimeAPI.setPlayerCD(player.getUniqueId(),cooldownKey,-1000);
+ SkillManager.castSkill(player, skill);
+ }
+ return false;
+ }
+
+ public static SkillsMain inst() {
+ return instance;
+ }
+
+ public static PlayerManager getPlayerManager() {
+ return playerManager;
+ }
+
+ public static void sendMessage(CommandSender sender, String message) {
+ sender.sendMessage("§f[§c技能§f] §a"+message);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/api/SkillComponent.java b/src/main/java/com/yaohun/demonskills/api/SkillComponent.java
new file mode 100644
index 0000000..ee09435
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/api/SkillComponent.java
@@ -0,0 +1,7 @@
+package com.yaohun.demonskills.api;
+
+import org.bukkit.entity.Player;
+
+public interface SkillComponent {
+ void execute(Player caster);
+}
diff --git a/src/main/java/com/yaohun/demonskills/api/SkillStoneAPI.java b/src/main/java/com/yaohun/demonskills/api/SkillStoneAPI.java
new file mode 100644
index 0000000..1a68d2a
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/api/SkillStoneAPI.java
@@ -0,0 +1,19 @@
+package com.yaohun.demonskills.api;
+
+import com.yaohun.demonskills.data.SkillData;
+import com.yaohun.demonskills.manage.SkillManager;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+public class SkillStoneAPI {
+
+ public static ItemStack getStoneStack(String playerName,String skillName){
+ SkillData skillData = SkillManager.skillDataMap.get(skillName);
+ return skillData.getItemStack(playerName,1);
+ }
+ public static ItemStack getStoneStack(String playerName,String skillName,int skillLevel){
+ SkillData skillData = SkillManager.skillDataMap.get(skillName);
+ return skillData.getItemStack(playerName,skillLevel);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/api/TargetSelector.java b/src/main/java/com/yaohun/demonskills/api/TargetSelector.java
new file mode 100644
index 0000000..c50b0ed
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/api/TargetSelector.java
@@ -0,0 +1,10 @@
+package com.yaohun.demonskills.api;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+
+public interface TargetSelector {
+ List selectTargets(Player caster);
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/CdTimeComponent.java b/src/main/java/com/yaohun/demonskills/component/CdTimeComponent.java
new file mode 100644
index 0000000..c0fdef7
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/CdTimeComponent.java
@@ -0,0 +1,21 @@
+package com.yaohun.demonskills.component;
+
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.util.CDTimeAPI;
+import org.bukkit.entity.Player;
+
+public class CdTimeComponent implements SkillComponent {
+
+ private final String cdKey;
+ private final long cdMillis;
+
+ public CdTimeComponent(String cdKey, long cdMillis) {
+ this.cdKey = cdKey;
+ this.cdMillis = cdMillis;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ CDTimeAPI.setPlayerCD(caster.getUniqueId(),cdKey,cdMillis);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/DelayComponent.java b/src/main/java/com/yaohun/demonskills/component/DelayComponent.java
new file mode 100644
index 0000000..5af1bbc
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/DelayComponent.java
@@ -0,0 +1,27 @@
+package com.yaohun.demonskills.component;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+
+public class DelayComponent implements SkillComponent {
+ private final long delayTicks;
+ private final List children;
+
+ public DelayComponent(long delayTicks, List children) {
+ this.delayTicks = delayTicks;
+ this.children = children;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ Bukkit.getScheduler().runTaskLater(SkillsMain.inst(), () -> {
+ for (SkillComponent child : children) {
+ child.execute(caster);
+ }
+ }, delayTicks);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/PotionEffectComponent.java b/src/main/java/com/yaohun/demonskills/component/PotionEffectComponent.java
new file mode 100644
index 0000000..d9876c5
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/PotionEffectComponent.java
@@ -0,0 +1,45 @@
+package com.yaohun.demonskills.component;
+
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+
+public class PotionEffectComponent implements SkillComponent {
+
+ private final PotionEffectType effectType;
+ private final int ticks;
+ private final int level;
+ private TargetSelector targetSelector = new SelfSelector();
+
+ public PotionEffectComponent(PotionEffectType effectType, int ticks, int level) {
+ this.effectType = effectType;
+ this.ticks = ticks;
+ this.level = level;
+ }
+
+ public PotionEffectComponent(PotionEffectType effectType, int ticks, int level, TargetSelector targetSelector) {
+ this.effectType = effectType;
+ this.ticks = ticks;
+ this.level = level;
+ this.targetSelector = targetSelector;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ if (targetSelector.equals(new SelfSelector())) {
+ caster.addPotionEffect(new PotionEffect(effectType, ticks, level, true, true));
+ } else {
+ for (Entity entity : targetSelector.selectTargets(caster)){
+ if(entity instanceof LivingEntity){
+ LivingEntity living = (LivingEntity) entity;
+ living.addPotionEffect(new PotionEffect(effectType, ticks, level, true, true));
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/SoundComponent.java b/src/main/java/com/yaohun/demonskills/component/SoundComponent.java
new file mode 100644
index 0000000..a66f3be
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/SoundComponent.java
@@ -0,0 +1,50 @@
+package com.yaohun.demonskills.component;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import eos.moe.dragoncore.network.PacketSender;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class SoundComponent implements SkillComponent {
+
+ private final String sound;
+ private final float pitch;
+ private final float volume;
+ private long stopTick = -1;
+
+ public SoundComponent(Sound sound, float pitch, float volume) {
+ this.sound = String.valueOf(sound);
+ this.pitch = pitch;
+ this.volume = volume;
+ }
+
+ public SoundComponent(String sound, float pitch, float volume) {
+ this.sound = sound;
+ this.pitch = pitch;
+ this.volume = volume;
+ }
+
+ public SoundComponent(String sound, float pitch, float volume,long stopTick) {
+ this.sound = sound;
+ this.pitch = pitch;
+ this.volume = volume;
+ this.stopTick = stopTick;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ if (sound.contains("_")) {
+ caster.playSound(caster.getLocation(), Sound.valueOf(sound), pitch, volume);
+ } else {
+ PacketSender.sendPlaySound(caster,sound,pitch,volume,false,0,0,0);
+ if(stopTick >= 5) {
+ Bukkit.getScheduler().runTaskLater(SkillsMain.inst(), () -> {
+ PacketSender.sendStopSound(caster,sound);
+ },stopTick);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/damage/DamageComponent.java b/src/main/java/com/yaohun/demonskills/component/damage/DamageComponent.java
new file mode 100644
index 0000000..1a26dcc
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/damage/DamageComponent.java
@@ -0,0 +1,67 @@
+package com.yaohun.demonskills.component.damage;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+
+public class DamageComponent implements SkillComponent {
+
+ private final double hurtValue;
+ private final TargetSelector selector;
+ private boolean armorPenetrate = false;
+ private int numberCount = 1;
+ private long delayTick = 1;
+
+ public DamageComponent(double hurtValue, TargetSelector selector) {
+ this.hurtValue = hurtValue;
+ this.selector = selector;
+ }
+
+ public DamageComponent(double hurtValue, TargetSelector selector,boolean armorPenetrate) {
+ this.hurtValue = hurtValue;
+ this.selector = selector;
+ this.armorPenetrate = armorPenetrate;
+ }
+
+ public DamageComponent(double hurtValue, TargetSelector selector,boolean armorPenetrate,int numberCount) {
+ this.hurtValue = hurtValue;
+ this.selector = selector;
+ this.armorPenetrate = armorPenetrate;
+ this.numberCount = numberCount;
+ }
+
+ public DamageComponent(double hurtValue, TargetSelector selector,boolean armorPenetrate,int numberCount,long delayTick) {
+ this.hurtValue = hurtValue;
+ this.selector = selector;
+ this.armorPenetrate = armorPenetrate;
+ this.numberCount = numberCount;
+ this.delayTick = delayTick;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ for (int i = 0; i < numberCount; i++) {
+ Bukkit.getScheduler().runTaskLater(SkillsMain.inst(), () -> {
+ for (Entity target : selector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ if (!armorPenetrate) {
+ living.damage(hurtValue, caster);
+ living.damage(1,caster);
+ } else {
+ double bloodVolume = living.getHealth();
+ double newBloodVolume = Math.max(0.0D, bloodVolume - hurtValue);
+ living.setHealth(newBloodVolume);
+ living.damage(1,caster);
+ }
+ }
+ }
+ }, i * delayTick);
+ }
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/damage/DamageContinuedComponent.java b/src/main/java/com/yaohun/demonskills/component/damage/DamageContinuedComponent.java
new file mode 100644
index 0000000..494a5dd
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/damage/DamageContinuedComponent.java
@@ -0,0 +1,58 @@
+package com.yaohun.demonskills.component.damage;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class DamageContinuedComponent implements SkillComponent {
+
+ private final double hurtValue;
+ private final TargetSelector selector;
+ private final int numberCount;
+ private final long delayTicks;
+ private double radius = 10;
+
+ public DamageContinuedComponent(double hurtValue, TargetSelector selector, int numberCount,long delayTicks) {
+ this.hurtValue = hurtValue;
+ this.selector = selector;
+ this.numberCount = numberCount;
+ this.delayTicks = delayTicks;
+ }
+
+ public DamageContinuedComponent(double hurtValue, TargetSelector selector, int numberCount,long delayTicks, double radius) {
+ this.hurtValue = hurtValue;
+ this.selector = selector;
+ this.numberCount = numberCount;
+ this.delayTicks = delayTicks;
+ this.radius = radius;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ for (Entity target : selector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ new BukkitRunnable() {
+ int count = numberCount;
+ @Override
+ public void run() {
+ if (!living.getWorld().equals(caster.getWorld()) ||
+ living.getLocation().distance(caster.getLocation()) > radius) {
+ cancel();
+ return;
+ }
+ if(count-- <= 0){
+ cancel();
+ return;
+ }
+ living.damage(hurtValue, caster);
+ }
+ }.runTaskTimer(SkillsMain.inst(),0L, delayTicks);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/dragoncore/ParticleSpawnCommponent.java b/src/main/java/com/yaohun/demonskills/component/dragoncore/ParticleSpawnCommponent.java
new file mode 100644
index 0000000..45d965d
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/dragoncore/ParticleSpawnCommponent.java
@@ -0,0 +1,47 @@
+package com.yaohun.demonskills.component.dragoncore;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.util.RandomUtil;
+import eos.moe.dragoncore.network.PacketSender;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+
+import java.util.UUID;
+
+public class ParticleSpawnCommponent implements SkillComponent {
+
+ private final String particleName;
+ private final int spawnTimer;
+ private int spawnCount = 1;
+ private TargetSelector selector = null;
+
+ public ParticleSpawnCommponent(final String particleName, int spawnTimer) {
+ this.particleName = particleName;
+ this.spawnTimer = spawnTimer;
+ }
+
+ public ParticleSpawnCommponent(final String particleName, int spawnTimer,int spawnCount) {
+ this.particleName = particleName;
+ this.spawnTimer = spawnTimer;
+ this.spawnCount = spawnCount;
+ }
+
+
+ @Override
+ public void execute(Player caster) {
+ UUID entityUUID = caster.getUniqueId();
+ if (spawnCount == 1) {
+ String particleUUID = UUID.randomUUID().toString();
+ PacketSender.addParticle(caster, particleName + ".particle", particleUUID, entityUUID.toString(), "0,0,0", spawnTimer);
+ } else {
+ for (int i = 0; i < spawnCount; i++) {
+ Bukkit.getScheduler().runTaskLater(SkillsMain.inst(), () -> {
+ String particleUUID = UUID.randomUUID().toString();
+ PacketSender.addParticle(caster, particleName + ".particle", particleUUID, entityUUID.toString(), "0,0,0", spawnTimer);
+ },i*20L);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/dragoncore/ParticleSpawnContinuedComponent.java b/src/main/java/com/yaohun/demonskills/component/dragoncore/ParticleSpawnContinuedComponent.java
new file mode 100644
index 0000000..f1faba4
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/dragoncore/ParticleSpawnContinuedComponent.java
@@ -0,0 +1,70 @@
+package com.yaohun.demonskills.component.dragoncore;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.util.RandomUtil;
+import eos.moe.dragoncore.network.PacketSender;
+import org.bukkit.Particle;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.UUID;
+
+public class ParticleSpawnContinuedComponent implements SkillComponent {
+
+ private final String particleName;
+ private final TargetSelector selector;
+ private final int numberCount;
+ private final long delayTicks;
+ private double radius = 3;
+
+ public ParticleSpawnContinuedComponent(String particleName, TargetSelector selector, int numberCount, long delayTicks) {
+ this.particleName = particleName;
+ this.selector = selector;
+ this.numberCount = numberCount;
+ this.delayTicks = delayTicks;
+ }
+
+ public ParticleSpawnContinuedComponent(String particleName, TargetSelector selector, int numberCount, long delayTicks, double radius) {
+ this.particleName = particleName;
+ this.selector = selector;
+ this.numberCount = numberCount;
+ this.delayTicks = delayTicks;
+ this.radius = radius;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ for (Entity target : selector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ UUID entityUUID = living.getUniqueId();
+ new BukkitRunnable() {
+ int count = numberCount;
+ @Override
+ public void run() {
+ if (!living.getWorld().equals(caster.getWorld()) ||
+ living.getLocation().distance(caster.getLocation()) > radius) {
+ cancel();
+ return;
+ }
+ if(count-- < 0){
+ cancel();
+ return;
+ }
+ if(particleName.contains("Particle#")){
+ Particle particle = Particle.valueOf(particleName.replace("Particle#", ""));
+ caster.getWorld().spawnParticle(particle, RandomUtil.getRandomLocation(caster,radius), 5, 0, 0, 0, 0);
+ } else {
+ String particleUUID = UUID.randomUUID().toString();
+ PacketSender.addParticle(caster, particleName + ".particle", particleUUID, entityUUID.toString(), "0,0,0", 100);
+ }
+ }
+ }.runTaskTimer(SkillsMain.inst(),0L, delayTicks);
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/dragoncore/PlayerAnimationComponent.java b/src/main/java/com/yaohun/demonskills/component/dragoncore/PlayerAnimationComponent.java
new file mode 100644
index 0000000..6a71fea
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/dragoncore/PlayerAnimationComponent.java
@@ -0,0 +1,39 @@
+package com.yaohun.demonskills.component.dragoncore;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import eos.moe.dragoncore.api.CoreAPI;
+import eos.moe.dragoncore.network.PacketSender;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.UUID;
+
+public class PlayerAnimationComponent implements SkillComponent {
+
+ private String animationKey;
+ private long stopTick = -1;
+
+ public PlayerAnimationComponent(String animationKey) {
+ this.animationKey = animationKey;
+ }
+
+ public PlayerAnimationComponent(String animationKey, long stopTick) {
+ this.animationKey = animationKey;
+ this.stopTick = stopTick;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ PacketSender.setPlayerAnimation(caster, animationKey);
+ if(stopTick >= 5) {
+ Bukkit.getScheduler().runTaskLater(SkillsMain.inst(), () -> {
+ PacketSender.removePlayerAnimation(caster);
+ }, stopTick);
+ }
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/dragoncore/StandAnimationComponent.java b/src/main/java/com/yaohun/demonskills/component/dragoncore/StandAnimationComponent.java
new file mode 100644
index 0000000..ae7c54a
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/dragoncore/StandAnimationComponent.java
@@ -0,0 +1,69 @@
+package com.yaohun.demonskills.component.dragoncore;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import eos.moe.dragoncore.DragonCore;
+import eos.moe.dragoncore.api.CoreAPI;
+import eos.moe.dragoncore.network.PacketSender;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.Random;
+import java.util.UUID;
+
+public class StandAnimationComponent implements SkillComponent {
+
+ private String entityName;
+ private String animationKey;
+ private long delay;
+ private long deleteTime;
+ private double add_y = 1.1;
+
+ public StandAnimationComponent(String entityName,String animationKey, long delay, long deleteTime) {
+ this.entityName = entityName;
+ this.animationKey = animationKey;
+ this.delay = delay;
+ this.deleteTime = deleteTime;
+ }
+
+ public StandAnimationComponent(String entityName,String animationKey, long delay, long deleteTime,double add_y) {
+ this.entityName = entityName;
+ this.animationKey = animationKey;
+ this.delay = delay;
+ this.deleteTime = deleteTime;
+ this.add_y = add_y;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ Location location = caster.getLocation().clone().add(0,add_y,0);
+ // 生成隐身的盔甲架
+ ArmorStand armorStand = location.getWorld().spawn(location, ArmorStand.class, stand -> {
+ stand.setCustomName(entityName);
+ stand.setGravity(false); // 取消重力,不会下落
+ stand.setAI(false); // 没有 AI(其实盔甲架本身就没 AI,写了也没影响)
+ stand.setMarker(true); // 不占空间、不可推挤,推荐设置
+ stand.setCollidable(false); // 禁止与实体碰撞
+ stand.setInvulnerable(true); // 不被误伤
+ });
+ new BukkitRunnable() {
+ public void run() {
+ PacketSender.setModelEntityAnimation(armorStand,animationKey,0);
+ }
+ }.runTaskLater(SkillsMain.inst(), delay);
+ Bukkit.getScheduler().runTaskLater(SkillsMain.inst(), armorStand::remove, deleteTime);
+ new BukkitRunnable() {
+ public void run() {
+ if(armorStand == null || armorStand.isDead()) {
+ cancel();
+ return;
+ }
+ armorStand.teleport(caster.getLocation().clone().add(0,add_y,0));
+ }
+ }.runTaskTimer(SkillsMain.inst(), 2L, 2L);
+
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/effects/StunPlayerComponent.java b/src/main/java/com/yaohun/demonskills/component/effects/StunPlayerComponent.java
new file mode 100644
index 0000000..fb629e6
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/effects/StunPlayerComponent.java
@@ -0,0 +1,40 @@
+package com.yaohun.demonskills.component.effects;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import eos.moe.dragoncore.network.PacketSender;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.Vector;
+
+public class StunPlayerComponent implements SkillComponent {
+
+ private final long stunTicks;
+ private final TargetSelector selector;
+
+ public StunPlayerComponent(TargetSelector targetSelector, long stunTicks) {
+ this.selector = targetSelector;
+ this.stunTicks = stunTicks;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ for (Entity target : selector.selectTargets(caster)) {
+ if (target instanceof Player) {
+ Player player = (Player) target;
+ PacketSender.sendOpenGui(player,"禁止操作");
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ player.closeInventory();
+ cancel();
+ }
+ }.runTaskLater(SkillsMain.inst(), stunTicks);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/particles/CircleParticlesComponent.java b/src/main/java/com/yaohun/demonskills/component/particles/CircleParticlesComponent.java
new file mode 100644
index 0000000..f35da5e
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/particles/CircleParticlesComponent.java
@@ -0,0 +1,55 @@
+package com.yaohun.demonskills.component.particles;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import org.bukkit.Location;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class CircleParticlesComponent implements SkillComponent {
+
+ private final Particle particle;
+ private final int amount; // 每点粒子数量(通常为1)
+ private final double radius; // 圆圈半径
+ private final int points; //粒子分布密度(推荐 20~60)
+ private int playCount = 1;
+
+ public CircleParticlesComponent(Particle particle, int amount, double radius, int points) {
+ this.particle = particle;
+ this.amount = amount;
+ this.radius = radius;
+ this.points = points;
+ }
+
+ public CircleParticlesComponent(Particle particle, int amount, double radius, int points, int playCount) {
+ this.particle = particle;
+ this.amount = amount;
+ this.radius = radius;
+ this.points = points;
+ this.playCount = playCount;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ new BukkitRunnable() {
+ private int count = 0;
+ @Override
+ public void run() {
+ if(count++ >= playCount) {
+ cancel();
+ return;
+ }
+ Location center = caster.getLocation().add(0, 0.05, 0);
+ double angleStep = 2 * Math.PI / points;
+ for (int i = 0; i < points; i++) {
+ double angle = i * angleStep;
+ double x = Math.cos(angle) * radius;
+ double z = Math.sin(angle) * radius;
+ Location particleLoc = center.clone().add(x, 0, z);
+ caster.getWorld().spawnParticle(particle, particleLoc, amount, 0, 0, 0, 0);
+ }
+ }
+ }.runTaskTimer(SkillsMain.inst(),0L,5L);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/particles/DiscParticlesComponent.java b/src/main/java/com/yaohun/demonskills/component/particles/DiscParticlesComponent.java
new file mode 100644
index 0000000..b02b602
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/particles/DiscParticlesComponent.java
@@ -0,0 +1,51 @@
+package com.yaohun.demonskills.component.particles;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import org.bukkit.Location;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.Vector;
+
+public class DiscParticlesComponent implements SkillComponent {
+
+ private final Particle particle;
+ private final int amount;
+ private int playCount = 10;
+
+ public DiscParticlesComponent(Particle particle, int amount) {
+ this.particle = particle;
+ this.amount = amount;
+ }
+
+ public DiscParticlesComponent(Particle particle, int amount, int playCount) {
+ this.particle = particle;
+ this.amount = amount;
+ this.playCount = playCount;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ Location origin = caster.getLocation().add(0,0.05,0);
+ double angleStep = 360.0 / 20;
+ for (int i = 0; i < 20; i++) {
+ double angle = Math.toRadians(i * angleStep);
+ Vector dir = new Vector(Math.cos(angle), 0, Math.sin(angle)).normalize().multiply(0.3);
+ Location start = origin.clone();
+ new BukkitRunnable() {
+ int ticks = 0;
+ Location pos = start.clone();
+ @Override
+ public void run() {
+ if (ticks++ > playCount) {
+ cancel();
+ return;
+ }
+ pos.add(dir);
+ caster.getWorld().spawnParticle(particle, pos, amount, 0, 0, 0, 0);
+ }
+ }.runTaskTimer(SkillsMain.inst(), 0L, 1L);
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/particles/ParticlesComponent.java b/src/main/java/com/yaohun/demonskills/component/particles/ParticlesComponent.java
new file mode 100644
index 0000000..7198201
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/particles/ParticlesComponent.java
@@ -0,0 +1,80 @@
+package com.yaohun.demonskills.component.particles;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import com.yaohun.demonskills.util.RandomUtil;
+import org.bukkit.Location;
+import org.bukkit.Particle;
+import org.bukkit.World;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class ParticlesComponent implements SkillComponent {
+
+ private final Particle particle;
+ private final int amount; // 每次出现粒子数量
+ private final double radius; // 半径范围
+ private final int playCount; // 播放次数
+ private TargetSelector targetSelector = new SelfSelector();
+
+ public ParticlesComponent(Particle particle, int amount, double radius, int playCount) {
+ this.particle = particle;
+ this.amount = amount;
+ this.radius = radius;
+ this.playCount = playCount;
+ }
+
+ public ParticlesComponent(Particle particle, int amount, double radius, int playCount,TargetSelector targetSelector) {
+ this.particle = particle;
+ this.amount = amount;
+ this.radius = radius;
+ this.playCount = playCount;
+ this.targetSelector = targetSelector;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ if(targetSelector.equals(new SelfSelector())) {
+ new BukkitRunnable() {
+ private int count = 0;
+ @Override
+ public void run() {
+ if (count++ >= playCount) {
+ cancel();
+ return;
+ }
+ Location center = caster.getLocation().add(0, 1, 0); // 调高粒子位置
+ World world = center.getWorld();
+ for (int i = 0; i < amount; i++) {
+ world.spawnParticle(particle, RandomUtil.getRandomLocation(caster,radius), 1, 0, 0, 0, 0);
+ }
+ }
+ }.runTaskTimer(SkillsMain.inst(), 0L, 1L);
+ } else {
+ for (Entity target : targetSelector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ new BukkitRunnable() {
+ private int count = 0;
+ @Override
+ public void run() {
+ if (count++ >= playCount) {
+ cancel();
+ return;
+ }
+ Location center = living.getLocation().add(0, 1, 0); // 调高粒子位置
+ World world = center.getWorld();
+ for (int i = 0; i < amount; i++) {
+ world.spawnParticle(particle, RandomUtil.getRandomLocation(living,radius), 1, 0, 0, 0, 0);
+ }
+ }
+ }.runTaskTimer(SkillsMain.inst(), 0L, 1L);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/particles/RotatingCircle.java b/src/main/java/com/yaohun/demonskills/component/particles/RotatingCircle.java
new file mode 100644
index 0000000..431fcc1
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/particles/RotatingCircle.java
@@ -0,0 +1,46 @@
+package com.yaohun.demonskills.component.particles;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.api.SkillComponent;
+import org.bukkit.Location;
+import org.bukkit.Particle;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class RotatingCircle implements SkillComponent {
+
+ private final Particle particle;
+ private final double radius;
+ private final int totalTicks;
+
+ public RotatingCircle(Particle particle, double radius, int totalTicks) {
+ this.particle = particle;
+ this.radius = radius;
+ this.totalTicks = totalTicks;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ Location center = caster.getLocation().add(0, 0.05, 0);
+
+ new BukkitRunnable() {
+ int tick = 0;
+
+ @Override
+ public void run() {
+ if (tick++ >= totalTicks) {
+ cancel();
+ return;
+ }
+
+ double angle = (tick % 360) * Math.PI / 180;
+ double x = Math.cos(angle) * radius;
+ double z = Math.sin(angle) * radius;
+
+ Location particleLoc = center.clone().add(x, 0, z);
+ caster.getWorld().spawnParticle(particle, particleLoc, 2, 0, 0, 0, 0);
+ }
+ }.runTaskTimer(SkillsMain.inst(), 0L, 1L);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileAdvanceComponent.java b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileAdvanceComponent.java
new file mode 100644
index 0000000..729a666
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileAdvanceComponent.java
@@ -0,0 +1,46 @@
+package com.yaohun.demonskills.component.projectile;
+
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public class ProjectileAdvanceComponent implements SkillComponent {
+
+ private final double vigor;
+ private final double y;
+ private TargetSelector targetSelector = new SelfSelector();
+
+ public ProjectileAdvanceComponent(final double vigor, final double y) {
+ this.vigor = vigor;
+ this.y = y;
+ }
+
+ public ProjectileAdvanceComponent(final double vigor, final double y,TargetSelector targetSelector) {
+ this.vigor = vigor;
+ this.y = y;
+ this.targetSelector = targetSelector;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ if(targetSelector.equals(new SelfSelector())) {
+ Location origin = caster.getEyeLocation();
+ Vector direction = origin.getDirection().normalize();
+ caster.setVelocity(direction.multiply(vigor).setY(y));
+ } else {
+ for (Entity target : targetSelector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ Location origin = living.getEyeLocation();
+ Vector direction = origin.getDirection().normalize();
+ living.setVelocity(direction.multiply(vigor).setY(y));
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileAroundComponent.java b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileAroundComponent.java
new file mode 100644
index 0000000..101d4b7
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileAroundComponent.java
@@ -0,0 +1,74 @@
+package com.yaohun.demonskills.component.projectile;
+
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public class ProjectileAroundComponent implements SkillComponent {
+
+ private final double vigor;
+ private final double y;
+ private TargetSelector targetSelector = new SelfSelector();
+ private boolean LeftDirection = true;
+
+ public ProjectileAroundComponent(final double vigor, final double y) {
+ this.vigor = vigor;
+ this.y = y;
+ }
+ public ProjectileAroundComponent(final double vigor, final double y,boolean LeftDirection) {
+ this.vigor = vigor;
+ this.y = y;
+ this.LeftDirection = LeftDirection;
+ }
+
+
+ public ProjectileAroundComponent(final double vigor, final double y, TargetSelector targetSelector) {
+ this.vigor = vigor;
+ this.y = y;
+ this.targetSelector = targetSelector;
+ }
+
+ public ProjectileAroundComponent(final double vigor, final double y, TargetSelector targetSelector,boolean LeftDirection) {
+ this.vigor = vigor;
+ this.y = y;
+ this.targetSelector = targetSelector;
+ this.LeftDirection = LeftDirection;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ if(targetSelector.equals(new SelfSelector())) {
+ Location origin = caster.getEyeLocation();
+ Vector direction = origin.getDirection().setY(0).normalize();
+ Vector right;
+ if(this.LeftDirection){
+ right = new Vector(direction.getZ(), 0, -direction.getX());
+ } else {
+ right = new Vector(-direction.getZ(), 0, direction.getX());
+ }
+ Vector velocity = right.multiply(vigor).setY(y);
+ caster.setVelocity(velocity);
+ } else {
+ for (Entity target : targetSelector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ Location origin = living.getEyeLocation();
+ Vector direction = origin.getDirection().setY(0).normalize();
+ Vector right;
+ if(this.LeftDirection){
+ right = new Vector(direction.getZ(), 0, -direction.getX());
+ } else {
+ right = new Vector(-direction.getZ(), 0, direction.getX());
+ }
+ Vector velocity = right.multiply(vigor).setY(y);
+ living.setVelocity(velocity);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/projectile/ProjectilePullComponent.java b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectilePullComponent.java
new file mode 100644
index 0000000..843db56
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectilePullComponent.java
@@ -0,0 +1,36 @@
+package com.yaohun.demonskills.component.projectile;
+
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public class ProjectilePullComponent implements SkillComponent {
+
+ private final double pullStrength;
+ private final double y;
+ private final TargetSelector targetSelector;
+
+ public ProjectilePullComponent(final double pullStrength, final double y, TargetSelector targetSelector) {
+ this.pullStrength = pullStrength;
+ this.y = y;
+ this.targetSelector = targetSelector;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ Location center = caster.getLocation();
+ for (Entity target : targetSelector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ Vector direction = center.toVector().subtract(living.getLocation().toVector()).normalize();
+ Vector pullVector = direction.multiply(pullStrength);
+ living.setVelocity(pullVector.setY(y));
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileVectorComponent.java b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileVectorComponent.java
new file mode 100644
index 0000000..804451f
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/component/projectile/ProjectileVectorComponent.java
@@ -0,0 +1,57 @@
+package com.yaohun.demonskills.component.projectile;
+
+import com.yaohun.demonskills.api.SkillComponent;
+import com.yaohun.demonskills.api.TargetSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+public class ProjectileVectorComponent implements SkillComponent {
+
+ private final Vector vector;
+ private final double x;
+ private final double y;
+ private final double z;
+ private TargetSelector targetSelector = new SelfSelector();
+
+ public ProjectileVectorComponent(Vector vector, double x, double y, double z) {
+ this.vector = vector;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public ProjectileVectorComponent(Vector vector, double x, double y, double z,TargetSelector targetSelector) {
+ this.vector = vector;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.targetSelector = targetSelector;
+ }
+
+ @Override
+ public void execute(Player caster) {
+ if(x != 0){
+ this.vector.setX(x);
+ }
+ if(y != 0){
+ this.vector.setY(y);
+ }
+ if(z != 0){
+ this.vector.setZ(z);
+ }
+ if(targetSelector.equals(new SelfSelector())) {
+ caster.setVelocity(vector);
+ } else {
+ for (Entity target : targetSelector.selectTargets(caster)) {
+ if (target instanceof LivingEntity) {
+ LivingEntity living = (LivingEntity) target;
+ living.setVelocity(vector);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/config/Config.java b/src/main/java/com/yaohun/demonskills/config/Config.java
new file mode 100644
index 0000000..a90044d
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/config/Config.java
@@ -0,0 +1,42 @@
+package com.yaohun.demonskills.config;
+
+import com.yaohun.demonskills.SkillsMain;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.LangData;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.command.CommandSender;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.entity.Player;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Config {
+ public static LangData langData;
+ private static List disableWorlds = new ArrayList<>();
+
+ public static void reloadConfig(SkillsMain plugin) {
+ langData = DemonAPI.getLangData("DemonSkills");
+ File file = new File(plugin.getDataFolder(), "settings.yml");
+ if (!file.exists()) {
+ file.getParentFile().mkdirs();
+ try {
+ file.createNewFile();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ FileConfiguration config = YamlConfiguration.loadConfiguration(file);
+ disableWorlds = config.getStringList("Disable-Worlds");
+ Bukkit.getConsoleSender().sendMessage("§d[技能系统] §7禁用世界: §7"+String.join("§f, §7", disableWorlds));
+ }
+
+ public static boolean isDisableWorld(String world) {
+ return disableWorlds.contains(world);
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/config/MessageUtil.java b/src/main/java/com/yaohun/demonskills/config/MessageUtil.java
new file mode 100644
index 0000000..a6606e6
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/config/MessageUtil.java
@@ -0,0 +1,28 @@
+package com.yaohun.demonskills.config;
+
+import org.bukkit.Sound;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class MessageUtil {
+
+ public static void sendMessage(CommandSender sender, String message) {
+ if(sender instanceof Player){
+ Player player = (Player) sender;
+ player.sendMessage(message);
+ } else {
+ sender.sendMessage(message);
+ }
+ }
+
+ public static void sendMessage(CommandSender sender, String message, Sound sound) {
+ if(sender instanceof Player){
+ Player player = (Player) sender;
+ player.sendMessage(message);
+ player.playSound(player.getLocation(), sound, 0.5f, 1.2f);
+ } else {
+ sender.sendMessage(message);
+ }
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/core/Skill.java b/src/main/java/com/yaohun/demonskills/core/Skill.java
new file mode 100644
index 0000000..1a459d7
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/core/Skill.java
@@ -0,0 +1,29 @@
+package com.yaohun.demonskills.core;
+
+import com.yaohun.demonskills.api.SkillComponent;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+
+public class Skill {
+
+ public final String name;
+ public final int needMagic;
+ public final double cooldownTime;
+ public final double coreCooldown;
+ private final List skillComponents;
+
+ public Skill(String name,int needMagic,double cooldownTime,double coreCooldown,List skillComponents) {
+ this.name = name;
+ this.needMagic = needMagic;
+ this.cooldownTime = cooldownTime;
+ this.coreCooldown = coreCooldown;
+ this.skillComponents = skillComponents;
+ }
+
+ public void cast(Player caster){
+ for (SkillComponent skillComponent : skillComponents) {
+ skillComponent.execute(caster);
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/core/SkillStoneUpgrade.java b/src/main/java/com/yaohun/demonskills/core/SkillStoneUpgrade.java
new file mode 100644
index 0000000..0f064dd
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/core/SkillStoneUpgrade.java
@@ -0,0 +1,55 @@
+package com.yaohun.demonskills.core;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.config.Config;
+import com.yaohun.demonskills.config.MessageUtil;
+import com.yaohun.demonskills.data.SkillData;
+import com.yaohun.demonskills.manage.SkillManager;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+
+public class SkillStoneUpgrade {
+
+ public static void carryOut(Player player,boolean upgradeMode){
+ ItemStack itemStack = player.getInventory().getItemInMainHand();
+ if(DemonAPI.itemIsNull(itemStack) || DemonAPI.itemIsLore(itemStack)){
+ MessageUtil.sendMessage(player, Config.langData.getMessage("handItemError"),Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ NbtItem nbtItem = new NbtItem(itemStack);
+ if(!nbtItem.hasKey("skillName")){
+ MessageUtil.sendMessage(player, Config.langData.getMessage("handItemError"),Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ if(upgradeMode){
+ int levelLimit = 10;
+ int skillLevel = nbtItem.getInteger("skillLevel") + 1;
+ if(skillLevel > levelLimit){
+ MessageUtil.sendMessage(player, Config.langData.getMessage("handItemError").replace("{levelLimit}",String.valueOf(levelLimit)),Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ player.getInventory().setItemInMainHand(upgradeLevel(nbtItem));
+ } else {
+ player.getInventory().setItemInMainHand(reduceLevel(nbtItem));
+ }
+ }
+
+ private static ItemStack upgradeLevel(NbtItem nbtItem){
+ String playerName = nbtItem.getString("skillOwner");
+ String skillName = nbtItem.getString("skillName");
+ int skillLevel = nbtItem.getInteger("skillLevel") + 1;
+ SkillData skillData = SkillManager.skillDataMap.get(skillName);
+ return skillData.getItemStack(playerName, skillLevel);
+ }
+
+ private static ItemStack reduceLevel(NbtItem nbtItem){
+ String playerName = nbtItem.getString("skillOwner");
+ String skillName = nbtItem.getString("skillName");
+ int skillLevel = nbtItem.getInteger("skillLevel") - 1;
+ SkillData skillData = SkillManager.skillDataMap.get(skillName);
+ return skillData.getItemStack(playerName, Math.max(1, skillLevel));
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/data/PlayerData.java b/src/main/java/com/yaohun/demonskills/data/PlayerData.java
new file mode 100644
index 0000000..50ba5f9
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/data/PlayerData.java
@@ -0,0 +1,151 @@
+package com.yaohun.demonskills.data;
+
+import com.yaohun.demonskills.core.Skill;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.inventory.ItemStack;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+
+public class PlayerData {
+
+ private File file;
+ private FileConfiguration configuration;
+ private String name;
+ private int magicNow;
+ private int magicMax;
+ private HashMap skillLevelMap = new HashMap<>(); // 获取技能等级
+ private HashMap cooldownMap = new HashMap<>();
+ private HashMap skillBindMap = new HashMap<>(); // 技能按键绑定
+ private HashMap keyBoardStackMap = new HashMap<>(); // 技能按键绑定物品
+
+ public PlayerData(String name) {
+ this.name = name;
+ this.file = new File("plugins/DemonSkills/PlayerData", name + ".yml");
+ if(!file.exists()) {
+ this.file.getParentFile().mkdirs();
+ this.configuration = YamlConfiguration.loadConfiguration(this.file);
+ } else {
+ this.configuration = YamlConfiguration.loadConfiguration(this.file);
+ }
+ this.magicMax = this.configuration.getInt("Magic",50);
+ this.magicNow = this.magicMax;
+ loadSkillsKeyBoard();
+ }
+
+ private void loadSkillsKeyBoard(){
+ ConfigurationSection section = this.configuration.getConfigurationSection("KeyBoard");
+ if(section == null) {
+ return;
+ }
+ for (String key : section.getKeys(false)) {
+ int keyBoard = Integer.parseInt(key);
+ ItemStack stack = section.getItemStack(key);
+ if(!DemonAPI.itemIsNull(stack) && !DemonAPI.itemIsLore(stack)){
+ NbtItem nbtItem = new NbtItem(stack);
+ if(nbtItem.hasKey("skillName")) {
+ String skillName = nbtItem.getString("skillName");
+ int skillLevel = nbtItem.getInteger("skillLevel");
+ skillBindMap.put(keyBoard, skillName);
+ skillLevelMap.put(skillName, skillLevel);
+ keyBoardStackMap.put(keyBoard, stack);
+ System.out.println("#[Load] skillName: "+key+" level: "+skillName+" keyBoard: "+keyBoard);
+ }
+ }
+ }
+ }
+
+ public void SavePlayerData(){
+ this.configuration.set("Magic",this.magicMax);
+ this.configuration.set("KeyBoard",null);
+ for (Integer keyBoard : keyBoardStackMap.keySet()) {
+ ItemStack keyBoardStack = keyBoardStackMap.get(keyBoard);
+ this.configuration.set("KeyBoard."+keyBoard,keyBoardStack);
+ }
+ try {
+ this.configuration.save(this.file);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getPlayerName() {
+ return name;
+ }
+
+ public int getMagicNow() {
+ return magicNow;
+ }
+ public boolean hasMagic(int amount) {
+ if(this.magicNow >= amount) {
+ return true;
+ }
+ return false;
+ }
+
+ public void takeMagicNow(int amount) {
+ magicNow -= amount;
+ }
+
+ public void setMagicNow(int magicNow) {
+ this.magicNow = magicNow;
+ }
+
+ public int getMagicMax() {
+ return magicMax;
+ }
+
+ public void resetSkillDataMap(){
+ skillLevelMap = new HashMap<>();
+ keyBoardStackMap = new HashMap<>();
+ }
+
+ public int getSkillLevel(String skill){
+ if(this.skillLevelMap.containsKey(skill)) {
+ return this.skillLevelMap.get(skill);
+ }
+ return 1;
+ }
+
+ public void setSkillLevel(String skillName, int level) {
+ this.skillLevelMap.put(skillName, level);
+ }
+
+ public void setSkillBindMap(int keyBoard,String skillName){
+ skillBindMap.put(keyBoard,skillName);
+ if(skillName.equalsIgnoreCase("default")){
+ keyBoardStackMap.remove(keyBoard);
+ }
+ }
+
+ public String getSkillNameBind(int keyBoard){
+ if(skillBindMap.containsKey(keyBoard)) {
+ return skillBindMap.get(keyBoard);
+ }
+ return "default";
+ }
+
+ public void setKeyBoardStackMap(int keyBoard, ItemStack keyBoardStack){
+ keyBoardStackMap.put(keyBoard,keyBoardStack);
+ }
+
+ public HashMap getKeyBoardStackMap() {
+ return keyBoardStackMap;
+ }
+
+ public void setCooldownData(String skillName, double cooldown){
+ this.cooldownMap.put(skillName,cooldown);
+ }
+
+ public double getCooldownData(String skillName){
+ if(this.cooldownMap.containsKey(skillName)) {
+ return this.cooldownMap.get(skillName);
+ }
+ return 60.0;
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/data/SkillData.java b/src/main/java/com/yaohun/demonskills/data/SkillData.java
new file mode 100644
index 0000000..48e8f54
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/data/SkillData.java
@@ -0,0 +1,94 @@
+package com.yaohun.demonskills.data;
+
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.manage.SkillManager;
+import com.yaohun.demonskills.util.RandomUtil;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Material;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SkillData {
+
+ private String skillName;
+ private String itemName;
+ private List itemLore;
+ private String itemNbt;
+ private ItemStack itemStack;
+
+ public SkillData(String skillName, ConfigurationSection section) {
+ this.skillName = skillName;
+ this.itemNbt = section.getString(skillName+".nbt","default");
+ String type = section.getString(skillName+".type");
+ this.itemName = section.getString(skillName+".name");
+ this.itemLore = section.getStringList(skillName+".lore");
+ this.itemStack = new ItemStack(Material.valueOf(type),1);
+ }
+
+ public ItemStack getItemStack(String playerName, int skillLevel) {
+ ItemStack stack = itemStack.clone();
+ ItemMeta meta = stack.getItemMeta();
+ Skill skill = SkillManager.getGuiSkillStack(skillName,skillLevel);
+ int needMagic = 10;
+ double cooldown = 60.0;
+ if(skill != null){
+ needMagic = skill.needMagic;
+ cooldown = skill.cooldownTime;
+ }
+ String levelName = "I";
+ if (skillLevel == 2) {
+ levelName = "II";
+ } else if (skillLevel == 3) {
+ levelName = "III";
+ } else if (skillLevel == 4) {
+ levelName = "IV";
+ } else if (skillLevel == 5) {
+ levelName = "V";
+ } else if (skillLevel == 6) {
+ levelName = "VI";
+ } else if (skillLevel == 7) {
+ levelName = "VII";
+ } else if (skillLevel == 8) {
+ levelName = "VIII";
+ } else if (skillLevel == 9) {
+ levelName = "IX";
+ } else if (skillLevel == 10) {
+ levelName = "X";
+ }
+ String itemName = this.itemName.replace("{level}", levelName);
+ List lore = new ArrayList<>();
+ for (int i = 0; i < itemLore.size(); i++) {
+ String s = itemLore.get(i);
+ if(s.contains("{magic}")){
+ s = s.replace("{magic}",String.valueOf(needMagic));
+ }
+ if(s.contains("{player}")){
+ s = s.replace("{player}",playerName);
+ }
+ if(s.contains("{cooldown}")){
+ s = s.replace("{cooldown}",String.format("%.1f",cooldown));
+ }
+ lore.add(s);
+ }
+ meta.setDisplayName(itemName);
+ meta.setLore(lore);
+ stack.setItemMeta(meta);
+ NbtItem nbtItem = new NbtItem(stack);
+ nbtItem.setString("skillOwner",playerName);
+ nbtItem.setString("skillName",skillName);
+ nbtItem.setInteger("skillLevel",skillLevel);
+ nbtItem.setInteger("skillNumber", RandomUtil.getRandomInt(1000,9999));
+ if(!itemNbt.equalsIgnoreCase("default")) {
+ String[] split = itemNbt.split("#");
+ String key = split[0];
+ String value = split[1];
+ nbtItem.setString(key,value);
+ }
+ return nbtItem.getItem();
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/event/SkillCastEvent.java b/src/main/java/com/yaohun/demonskills/event/SkillCastEvent.java
new file mode 100644
index 0000000..5aaa962
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/event/SkillCastEvent.java
@@ -0,0 +1,35 @@
+package com.yaohun.demonskills.event;
+
+import com.yaohun.demonskills.core.Skill;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+public class SkillCastEvent extends Event {
+
+ private static HandlerList handlers = new HandlerList();
+
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ private Player player;
+ private Skill skill;
+
+ public SkillCastEvent(Player player, Skill skill) {
+ this.player = player;
+ this.skill = skill;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public Skill getSkill() {
+ return skill;
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/gui/SkillStoneGui.java b/src/main/java/com/yaohun/demonskills/gui/SkillStoneGui.java
new file mode 100644
index 0000000..65e02ce
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/gui/SkillStoneGui.java
@@ -0,0 +1,60 @@
+package com.yaohun.demonskills.gui;
+
+import com.yaohun.demonskills.manage.SkillManager;
+import com.yaohun.demonskills.data.SkillData;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.HashMap;
+
+public class SkillStoneGui implements Listener {
+
+ private static String invTitle;
+
+ public SkillStoneGui() {
+ invTitle = "技能系统 - 灵石列表";
+ }
+
+ public static void OpenGui(Player player,String playerName,int skillLevel){
+ Inventory inv = Bukkit.createInventory(null,54,invTitle);
+ HashMap skillDataMap = SkillManager.skillDataMap;
+ for (SkillData skillData : skillDataMap.values()) {
+ inv.addItem(skillData.getItemStack(playerName,skillLevel));
+ }
+ player.openInventory(inv);
+ }
+
+ @EventHandler
+ public void onClick(InventoryClickEvent e){
+ int rawSlot = e.getRawSlot();
+ Player player = (Player) e.getWhoClicked();
+ if(e.getView().getTitle().equals(invTitle)){
+ e.setCancelled(true);
+ if(rawSlot >= 0 && rawSlot < 54){
+ ItemStack item = e.getCurrentItem().clone();
+ if(!DemonAPI.itemIsNull(item)){
+ NbtItem nbtItem = new NbtItem(item);
+ if(nbtItem.hasKey("skillName")){
+ if(e.getClick() == ClickType.LEFT) {
+ item.setAmount(1);
+ player.getInventory().addItem(item);
+ }else if(e.getClick() == ClickType.RIGHT){
+ item.setAmount(10);
+ player.getInventory().addItem(item);
+ }
+ player.playSound(player.getLocation(), Sound.ENTITY_CHICKEN_EGG,1,2);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/gui/SkillsGui.java b/src/main/java/com/yaohun/demonskills/gui/SkillsGui.java
new file mode 100644
index 0000000..a58f250
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/gui/SkillsGui.java
@@ -0,0 +1,167 @@
+package com.yaohun.demonskills.gui;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.config.Config;
+import com.yaohun.demonskills.config.MessageUtil;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.util.StackUtil;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.HashMap;
+
+public class SkillsGui implements Listener {
+
+ private static final String invTitle = Config.langData.getMessage("Skills-Title");
+
+ public static void OpenGui(Player player){
+ int pLevel = player.getLevel();
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ Inventory inv = Bukkit.createInventory(null,45,invTitle);
+ setInvGlass(inv);
+ inv.setItem(11, StackUtil.getSkillSlot(pLevel,10));
+ inv.setItem(13, StackUtil.getSkillSlot(pLevel,30));
+ inv.setItem(15, StackUtil.getSkillSlot(pLevel,50));
+ inv.setItem(30, StackUtil.getSkillSlot(pLevel,70));
+ inv.setItem(32, StackUtil.getSkillSlot(pLevel,90));
+ HashMap stackHashMap = playerData.getKeyBoardStackMap();
+ for (Integer keyBoard : stackHashMap.keySet()) {
+ int slot = 11;
+ if(keyBoard == 44){
+ slot = 13;
+ }else if(keyBoard == 45){
+ slot = 15;
+ }else if(keyBoard == 46){
+ slot = 30;
+ }else if(keyBoard == 47){
+ slot = 32;
+ }
+ inv.setItem(slot, stackHashMap.get(keyBoard));
+ }
+ player.openInventory(inv);
+ }
+
+ private static void setInvGlass(Inventory inv){
+ for (int slot = 10; slot < 35;slot++){
+ inv.setItem(slot, DemonAPI.glass(8,"§r"));
+ }
+ for (int slot = 0; slot < 10;slot++){
+ inv.setItem(slot, DemonAPI.glass(15,"§r"));
+ }
+ for (int slot = 35; slot < 45;slot++){
+ inv.setItem(slot, DemonAPI.glass(15,"§r"));
+ }
+ for (int slot : new int[]{17,18,26,27}){
+ inv.setItem(slot, DemonAPI.glass(15,"§r"));
+ }
+ }
+
+
+ @EventHandler
+ public void onCllick(InventoryClickEvent e){
+ int rawSlot = e.getRawSlot();
+ Player player = (Player) e.getWhoClicked();
+ int pLevel = player.getLevel();
+ ItemStack stack = e.getCurrentItem();
+ Inventory inv = e.getInventory();
+ if(e.getView().getTitle().equalsIgnoreCase(invTitle)){
+ e.setCancelled(true);
+ if (rawSlot == 11) {
+ setItemSlotGui(player,inv,rawSlot,stack,10);
+ }
+ if(rawSlot == 13){
+ setItemSlotGui(player,inv,rawSlot,stack,30);
+ }
+ if(rawSlot == 15){
+ setItemSlotGui(player,inv,rawSlot,stack,50);
+ }
+ if(rawSlot == 30){
+ setItemSlotGui(player,inv,rawSlot,stack,70);
+ }
+ if(rawSlot == 32){
+ setItemSlotGui(player,inv,rawSlot,stack,90);
+ }
+ }
+ }
+
+ private static void setItemSlotGui(Player player,Inventory inv,int rawSlot,ItemStack stack,int needLevel){
+ if(needLevel > player.getLevel()){
+ String message = Config.langData.getMessage("levelNotSatisfied");
+ MessageUtil.sendMessage(player,message,Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ // 判断玩家点击的物品
+ if(!DemonAPI.itemIsNull(stack)){
+ NbtItem nbtItem = new NbtItem(stack);
+ // 若点击的物品是技能石则自动退回到背包
+ if(nbtItem.hasKey("skillName")){
+ player.getInventory().addItem(stack);
+ inv.setItem(rawSlot, StackUtil.getSkillSlot(player.getLevel(),needLevel));
+ player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1);
+ return;
+ }
+ // 若是其他物品则打开宝石界面
+ StoneEquipGui.OpenGui(player,rawSlot);
+ }
+ }
+
+
+
+
+ @EventHandler
+ public void onInventoryClose(InventoryCloseEvent e){
+ Player player = (Player) e.getPlayer();
+ String playerName = player.getName();
+ if(e.getView().getTitle().equalsIgnoreCase(invTitle)){
+ Inventory inv = e.getInventory();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ playerData.resetSkillDataMap();
+ checkItemSetBindKeyBoard(playerData,inv.getItem(11),11);
+ checkItemSetBindKeyBoard(playerData,inv.getItem(13),13);
+ checkItemSetBindKeyBoard(playerData,inv.getItem(15),15);
+ checkItemSetBindKeyBoard(playerData,inv.getItem(30),30);
+ checkItemSetBindKeyBoard(playerData,inv.getItem(32),32);
+ }
+ }
+
+ public static void checkItemSetBindKeyBoard(PlayerData playerData,ItemStack itemStack, int slot){
+ int keyBoard = 19;
+ if(slot == 13){
+ keyBoard = 44;
+ } else if(slot == 15){
+ keyBoard = 45;
+ } else if(slot == 30){
+ keyBoard = 46;
+ } else if(slot == 32){
+ keyBoard = 47;
+ }
+ if(!DemonAPI.itemIsNull(itemStack) && !DemonAPI.itemIsLore(itemStack)){
+ NbtItem nbtItem = new NbtItem(itemStack);
+ if(nbtItem.hasKey("skillName")){
+ String skillName = nbtItem.getString("skillName");
+ int skillLevel = nbtItem.getInteger("skillLevel");
+ playerData.setSkillLevel(skillName,skillLevel);
+ playerData.setSkillBindMap(keyBoard,skillName);
+ playerData.setKeyBoardStackMap(keyBoard,itemStack);
+ } else {
+ playerData.setSkillBindMap(keyBoard,"default");
+ }
+ } else {
+ playerData.setSkillBindMap(keyBoard,"default");
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/gui/StoneEquipGui.java b/src/main/java/com/yaohun/demonskills/gui/StoneEquipGui.java
new file mode 100644
index 0000000..e5333e9
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/gui/StoneEquipGui.java
@@ -0,0 +1,103 @@
+package com.yaohun.demonskills.gui;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.config.Config;
+import com.yaohun.demonskills.config.MessageUtil;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.util.StackUtil;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Bukkit;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class StoneEquipGui implements Listener {
+
+ private static String invTitle = "§s§k§e§q§u§i§p§r";
+
+ public static void OpenGui(Player player,int rawSlot) {
+ List stackList = new ArrayList();
+ Inventory pinv = player.getInventory();
+ for (int i = 0;i < 36;i++) {
+ ItemStack item = pinv.getItem(i);
+ if(!DemonAPI.itemIsNull(item)) {
+ NbtItem nbtItem = new NbtItem(item);
+ if(nbtItem.hasKey("skillName")){
+ stackList.add(item);
+ pinv.setItem(i,null);
+ }
+ }
+ }
+ if(stackList.isEmpty()){
+ player.closeInventory();
+ MessageUtil.sendMessage(player,Config.langData.getMessage("equipFail"),Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ Inventory inv = Bukkit.createInventory(null,18,invTitle+ Config.langData.getMessage("Equip-Title"));
+ for (ItemStack stack : stackList) {
+ inv.addItem(stack);
+ }
+ inv.setItem(17, StackUtil.tagSkillStack(rawSlot));
+ player.openInventory(inv);
+ }
+
+ @EventHandler
+ public void onClick(InventoryClickEvent e){
+ int slot = e.getRawSlot();
+ Player player = (Player) e.getWhoClicked();
+ String playerName = player.getName();
+ Inventory inv = e.getInventory();
+ ItemStack skillStone = e.getCurrentItem();
+ if(e.getView().getTitle().contains(invTitle)){
+ e.setCancelled(true);
+ if(slot >= 0 && slot < 16) {
+ ItemStack stack = inv.getItem(17);
+ if (!DemonAPI.itemIsNull(stack)) {
+ NbtItem nbtItem = new NbtItem(stack);
+ int rawSlot = nbtItem.getInteger("RawSlot");
+ NbtItem skNbtItem = new NbtItem(skillStone);
+ if (skNbtItem.hasKey("skillName")) {
+ inv.setItem(slot,null);
+ player.closeInventory();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+
+ SkillsGui.checkItemSetBindKeyBoard(playerData, skillStone, rawSlot);
+ player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK,1,1);
+ new BukkitRunnable() {
+ @Override
+ public void run() {
+ SkillsGui.OpenGui(player);
+ }
+ }.runTaskLater(SkillsMain.inst(), 5L);
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onClose(InventoryCloseEvent event) {
+ Player player = (Player) event.getPlayer();
+ Inventory inv = event.getInventory();
+ if(event.getView().getTitle().contains(invTitle)) {
+ for (int i = 0;i < 16;i++) {
+ ItemStack item = inv.getItem(i);
+ if(!DemonAPI.itemIsNull(item)){
+ player.getInventory().addItem(item);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/listener/CommonAttackListener.java b/src/main/java/com/yaohun/demonskills/listener/CommonAttackListener.java
new file mode 100644
index 0000000..cb4951a
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/listener/CommonAttackListener.java
@@ -0,0 +1,58 @@
+package com.yaohun.demonskills.listener;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.manage.ComboManager;
+import com.yaohun.demonskills.skills.attack.Skill_普通攻击;
+import com.yaohun.demonskills.util.CDTimeAPI;
+import me.Demon.DemonPlugin.DemonAPI;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class CommonAttackListener implements Listener {
+
+ @EventHandler
+ public void onAttack(PlayerInteractEvent e){
+ Player player = e.getPlayer();
+ UUID uuid = player.getUniqueId();
+ Action action = e.getAction();
+ // 左键判断
+ if (action != Action.LEFT_CLICK_AIR && action != Action.LEFT_CLICK_BLOCK) return;
+ ItemStack item = player.getInventory().getItemInMainHand();
+ if (!DemonAPI.itemIsNull(item) && item.getType().equals(Material.DIAMOND_SWORD)) {
+ if(CDTimeAPI.isCD(uuid,"attack_cd"))return;
+ // 当前连段阶段
+ int stage = ComboManager.getComboStage(player);
+ switch (stage) {
+ case 0:
+ CDTimeAPI.setPlayerCD(uuid,"attack_cd",1230);
+ Skill_普通攻击.getAttack1().cast(player);
+ break;
+ case 1:
+ CDTimeAPI.setPlayerCD(uuid,"attack_cd",1530);
+ Skill_普通攻击.getAttack2().cast(player);
+ break;
+ case 2:
+ CDTimeAPI.setPlayerCD(uuid,"attack_cd",930);
+ Skill_普通攻击.getAttack3().cast(player);
+ break;
+ default:
+ CDTimeAPI.setPlayerCD(uuid,"attack_cd",1170);
+ Skill_普通攻击.getAttack4().cast(player);
+ ComboManager.resetCombo(player); // 打完第4段重置
+ return;
+ }
+ ComboManager.nextComboStage(player);
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/listener/PlayerListener.java b/src/main/java/com/yaohun/demonskills/listener/PlayerListener.java
new file mode 100644
index 0000000..d0f992b
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/listener/PlayerListener.java
@@ -0,0 +1,68 @@
+package com.yaohun.demonskills.listener;
+
+import com.yaohun.demonskills.gui.SkillsGui;
+import com.yaohun.demonskills.util.CDTimeAPI;
+import eos.moe.dragoncore.api.event.KeyPressEvent;
+import eos.moe.dragoncore.api.event.KeyReleaseEvent;
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.Location;
+import org.bukkit.Sound;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.UUID;
+
+public class PlayerListener implements Listener {
+
+ @EventHandler
+ public void onDamage(EntityDamageEvent e) {
+ if (e.getEntity() instanceof Player) {
+ Player player = (Player) e.getEntity();
+ UUID uuid = player.getUniqueId();
+ if(e.getCause() == EntityDamageEvent.DamageCause.FALL) {
+ if(CDTimeAPI.isCD(uuid,"anti_fall")){
+ e.setCancelled(true);
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onImmunityDamage(EntityDamageByEntityEvent e){
+ if(e.getEntity() instanceof Player){
+ UUID uuid = e.getEntity().getUniqueId();
+ if(CDTimeAPI.isCD(uuid,"skill_ImmunityDamage")){
+ e.setCancelled(true);
+ }
+ }
+ }
+
+
+ @EventHandler
+ public void onMutual(PlayerInteractEvent e) {
+ if (e.getAction().equals(Action.RIGHT_CLICK_AIR) || e.getAction().equals(Action.RIGHT_CLICK_BLOCK)) {
+ if (e.getHand().equals(EquipmentSlot.HAND)) {
+ Player player = e.getPlayer();
+ ItemStack stack = player.getInventory().getItemInMainHand();
+ if (!DemonAPI.itemIsNull(stack) && !DemonAPI.itemIsLore(stack)) {
+ NbtItem nbtItem = new NbtItem(stack);
+ if (nbtItem.hasKey("skillName")) {
+ String skillName = nbtItem.getString("skillName");
+ SkillsGui.OpenGui(player);
+ player.playSound(player.getLocation(), Sound.BLOCK_COMPARATOR_CLICK, 1, 1);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/listener/SkillKeyListener.java b/src/main/java/com/yaohun/demonskills/listener/SkillKeyListener.java
new file mode 100644
index 0000000..c449586
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/listener/SkillKeyListener.java
@@ -0,0 +1,146 @@
+package com.yaohun.demonskills.listener;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.config.Config;
+import com.yaohun.demonskills.config.MessageUtil;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.event.SkillCastEvent;
+import com.yaohun.demonskills.gui.SkillsGui;
+import com.yaohun.demonskills.manage.SkillManager;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.skills.skillsapi.Skill_前翻滚;
+import com.yaohun.demonskills.skills.skillsapi.Skill_右翻滚;
+import com.yaohun.demonskills.skills.skillsapi.Skill_后翻滚;
+import com.yaohun.demonskills.skills.skillsapi.Skill_左翻滚;
+import com.yaohun.demonskills.util.CDTimeAPI;
+import lk.vexview.event.KeyBoardPressEvent;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Sound;
+import org.bukkit.World;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.util.Vector;
+
+import java.util.*;
+
+public class SkillKeyListener implements Listener {
+
+ @EventHandler
+ public void onKey(KeyBoardPressEvent e){
+ if(!e.getEventKeyState()){return;}
+ Player player = e.getPlayer();
+ UUID uuid = player.getUniqueId();
+ if (e.getKey() == 19) {
+ if(CDTimeAPI.isCD(uuid,"keyBoardCd")){return;}
+ castSkill(player,e.getKey());
+ }
+ if (e.getKey() == 44) {
+ if(CDTimeAPI.isCD(uuid,"keyBoardCd")){return;}
+ castSkill(player,e.getKey());
+ }
+ if (e.getKey() == 45) {
+ if(CDTimeAPI.isCD(uuid,"keyBoardCd")){return;}
+ castSkill(player,e.getKey());
+ }
+ if (e.getKey() == 46) {
+ if(CDTimeAPI.isCD(uuid,"keyBoardCd")){return;}
+ castSkill(player,e.getKey());
+ }
+ if (e.getKey() == 47) {
+ if(CDTimeAPI.isCD(uuid,"keyBoardCd")){return;}
+ castSkill(player,e.getKey());
+ }
+ if(e.getKey() == 29){ // Ctrl键
+ String cooldownKey = "skill_翻滚";
+ if(CDTimeAPI.isCD(uuid,cooldownKey))return;
+ if(CDTimeAPI.isCD(uuid,"coreSkillCd")){return;}
+ CDTimeAPI.setPlayerCD(uuid,"翻滚激活",500);
+ }
+ }
+
+
+ private final Map> rollTimestamps = new HashMap<>();
+
+ @EventHandler
+ public void onPlayerMove(PlayerMoveEvent event) {
+ Player player = event.getPlayer();
+ UUID uuid = player.getUniqueId();
+ Location from = event.getFrom();
+ Location to = event.getTo();
+ if (to == null) return;
+ if(CDTimeAPI.isCD(uuid,"翻滚激活")) {
+ String cooldownKey = "skill_翻滚";
+ if(CDTimeAPI.isCD(uuid,cooldownKey)) {
+ return;
+ }
+ CDTimeAPI.setPlayerCD(uuid,"翻滚激活",-1);
+ Vector moveVec = to.toVector().subtract(from.toVector());
+ moveVec.setY(0); // 忽略Y轴,判断水平面
+
+ if (moveVec.length() < 0.01) return; // 几乎没动,忽略
+
+ Vector direction = event.getPlayer().getLocation().getDirection().setY(0).normalize();
+ Vector right = new Vector(direction.getZ(), 0, -direction.getX()); // 右侧方向
+
+ double forwardDot = moveVec.normalize().dot(direction); // 与面朝方向夹角余弦
+ double rightDot = moveVec.normalize().dot(right); // 与右侧方向夹角余弦
+
+ // 记录时间戳
+ long now = System.currentTimeMillis();
+ List timestamps = rollTimestamps.computeIfAbsent(uuid, k -> new ArrayList<>());
+ timestamps.removeIf(t -> now - t > 5000); // 只保留5秒内的
+ timestamps.add(now);
+
+ // 判断方向(你可以设置一个容错范围 0.7~1.0 表示大致方向)
+ Skill skill;
+ if (forwardDot > 0.7) {
+ skill = Skill_前翻滚.getSkillData();
+ } else if (forwardDot < -0.7) {
+ skill = Skill_后翻滚.getSkillData();
+ } else if (rightDot > 0.7) {
+ skill = Skill_左翻滚.getSkillData();
+ } else {
+ skill = Skill_右翻滚.getSkillData();
+ }
+ // 执行技能
+ skill.cast(player);
+ if (timestamps.size() >= 3) {
+ // 满足条件,设置CD
+ CDTimeAPI.setPlayerCD(uuid, cooldownKey, (long) (skill.cooldownTime * 1000L));
+ rollTimestamps.remove(uuid); // 重置次数
+ }
+ CDTimeAPI.setPlayerCD(uuid,"coreSkillCd", (long) (skill.coreCooldown * 800L));
+ }
+ }
+
+ public void castSkill(Player player,int keyBoard){
+ World world = player.getWorld();
+ if(Config.isDisableWorld(world.getName())){
+ MessageUtil.sendMessage(player,Config.langData.getMessage("disableWorldSkills"), Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ if(playerData == null){
+ return;
+ }
+ String skillName = playerData.getSkillNameBind(keyBoard);
+ if(skillName.equalsIgnoreCase("default")){
+ if(keyBoard == 19){
+ SkillsGui.OpenGui(player);
+ }
+ return;
+ }
+ CDTimeAPI.setPlayerCD(player.getUniqueId(),"keyBoardCd",500L);
+ Skill skill = SkillManager.getNameConvertSkill(player,skillName);
+ if(skill == null){return;}
+ SkillManager.castSkill(player, skill);
+ SkillCastEvent skillCastEvent = new SkillCastEvent(player, skill);
+ Bukkit.getPluginManager().callEvent(skillCastEvent);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/manage/ComboManager.java b/src/main/java/com/yaohun/demonskills/manage/ComboManager.java
new file mode 100644
index 0000000..1208f60
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/manage/ComboManager.java
@@ -0,0 +1,47 @@
+package com.yaohun.demonskills.manage;
+
+import com.yaohun.demonskills.SkillsMain;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class ComboManager {
+ private static final Map comboStage = new HashMap<>();
+ private static final Map resetTaskMap = new HashMap<>();
+ private static final int COMBO_TIMEOUT_TICKS = 20 * 3; // 2秒未连段自动重置
+
+ public static int getComboStage(Player player) {
+ return comboStage.getOrDefault(player.getUniqueId(), 0);
+ }
+
+ public static void nextComboStage(Player player) {
+ int current = getComboStage(player);
+ comboStage.put(player.getUniqueId(), current + 1);
+ resetComboTimeout(player);
+ }
+
+ public static void resetCombo(Player player) {
+ comboStage.remove(player.getUniqueId());
+ BukkitRunnable task = resetTaskMap.remove(player.getUniqueId());
+ if (task != null) task.cancel();
+ }
+
+ private static void resetComboTimeout(Player player) {
+ // 清理旧任务
+ BukkitRunnable oldTask = resetTaskMap.remove(player.getUniqueId());
+ if (oldTask != null) oldTask.cancel();
+
+ // 新任务
+ BukkitRunnable task = new BukkitRunnable() {
+ @Override
+ public void run() {
+ resetCombo(player);
+ }
+ };
+ task.runTaskLater(SkillsMain.inst(), COMBO_TIMEOUT_TICKS);
+ resetTaskMap.put(player.getUniqueId(), task);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/manage/PlayerManager.java b/src/main/java/com/yaohun/demonskills/manage/PlayerManager.java
new file mode 100644
index 0000000..1a10d9a
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/manage/PlayerManager.java
@@ -0,0 +1,27 @@
+package com.yaohun.demonskills.manage;
+
+import com.yaohun.demonskills.data.PlayerData;
+
+import java.util.HashMap;
+
+public class PlayerManager {
+
+ private HashMap playerDataMap = new HashMap<>();
+
+ public PlayerManager() {
+
+ }
+
+ public void SaveAllPlayerData() {
+ for (PlayerData playerData : playerDataMap.values()) {
+ playerData.SavePlayerData();
+ }
+ }
+
+ public PlayerData getPlayerData(String playerName) {
+ if(!playerDataMap.containsKey(playerName)) {
+ this.playerDataMap.put(playerName, new PlayerData(playerName));
+ }
+ return playerDataMap.get(playerName);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/manage/SkillManager.java b/src/main/java/com/yaohun/demonskills/manage/SkillManager.java
new file mode 100644
index 0000000..f27a5da
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/manage/SkillManager.java
@@ -0,0 +1,168 @@
+package com.yaohun.demonskills.manage;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.config.Config;
+import com.yaohun.demonskills.config.MessageUtil;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.data.SkillData;
+import com.yaohun.demonskills.skills.*;
+import com.yaohun.demonskills.skills.skillsapi.Skill_BaoHuoLongJi;
+import com.yaohun.demonskills.skills.skillsapi.Skill_ZhongLiYaZhi;
+import com.yaohun.demonskills.skills.skillsapi.Skill_左翻滚;
+import com.yaohun.demonskills.skills.youling.*;
+import com.yaohun.demonskills.util.CDTimeAPI;
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Sound;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.FileConfiguration;
+import org.bukkit.entity.Player;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.*;
+
+public class SkillManager {
+
+ public static HashMap skillDataMap = new HashMap<>();
+
+ public static void init() {
+ FileConfiguration config = SkillsMain.inst().getConfig();
+ ConfigurationSection section = config.getConfigurationSection("SkillStone");
+ if(section == null) return;
+ for (String key : section.getKeys(false)) {
+ skillDataMap.put(key,new SkillData(key,section));
+ }
+ Bukkit.getConsoleSender().sendMessage("§d[技能系统] §7载入技能: §6"+skillDataMap.size()+"个");
+ }
+
+ public static String getRandomStone(){
+ // 获取skillDataMap的键集
+ Set keys = skillDataMap.keySet();
+ // 如果键集为空,返回null或者抛出异常(根据需求)
+ if (keys.isEmpty()) return null;
+
+ // 创建Random对象
+ Random rand = new Random();
+ // 随机选择一个键
+ int index = rand.nextInt(keys.size());
+ // 将Set转换为列表,获取随机索引的元素
+ return (String) keys.toArray()[index];
+
+ }
+
+ public static boolean isSkillDataExit(String skillName){
+ if(skillDataMap.containsKey(skillName)){
+ return true;
+ }
+ return false;
+ }
+
+ public static void castSkill(Player caster, Skill skill) {
+ UUID uuid = caster.getUniqueId();
+ String cooldownKey = "skill_"+skill.name;
+ String playerName = caster.getName();
+ PlayerData playerData = SkillsMain.getPlayerManager().getPlayerData(playerName);
+ // 首先判断冷却
+ if(CDTimeAPI.isCD(uuid,cooldownKey)){
+ double time = (double) CDTimeAPI.getCD(uuid, cooldownKey) / 1000L;
+ String message = Config.langData.getMessage("castSkillCooldown");
+ message = message.replace("{name}",skill.name);
+ message = message.replace("{cooldown}",String.format("%.1f",time));
+ MessageUtil.sendMessage(caster, message,Sound.ENTITY_VILLAGER_NO);
+ return;
+ }
+ if(CDTimeAPI.isCD(uuid,"coreSkillCd")){return;}
+ /*// 然后是魔法值消耗
+ int nowMagic = playerData.getMagicNow();
+ int needMagic = skill.needMagic;
+ if(!playerData.hasMagic(needMagic)){
+ SkillsMain.sendMessage(caster,"魔法值不足,还需要§e["+(needMagic - nowMagic)+"]§a才能触发该技能...", Sound.ENTITY_VILLAGER_NO);
+ return;
+ }*/
+ // 扣除消耗并执行效果
+ double coolingReduction = AttributeAPI.getAttrData(caster).getAttributeValue("冷却缩减:") / 100;
+ if(coolingReduction >= 0.5){
+ coolingReduction = 0.5;
+ }
+ CDTimeAPI.setPlayerCD(uuid,"coreSkillCd", (long) (skill.coreCooldown * 1000L));
+ long newCoolDownTime = (long) (skill.cooldownTime * 1000L * (1.0 - coolingReduction));
+ CDTimeAPI.setPlayerCD(uuid,cooldownKey,newCoolDownTime);
+ // playerData.takeMagicNow(needMagic); // 扣除魔法值
+ skill.cast(caster);
+ String message = Config.langData.getMessage("castSkillMessage");
+ message = message.replace("{name}",skill.name);
+ message = message.replace("{player}",playerName);
+ // 给玩家 caster 周围10格范围内所有玩家发送这条消息
+ double radius = 10.0;
+ Location center = caster.getLocation();
+ for (Player nearbyPlayer : Bukkit.getOnlinePlayers()) {
+ if (nearbyPlayer.getWorld().equals(center.getWorld()) &&
+ nearbyPlayer.getLocation().distance(center) <= radius) {
+ nearbyPlayer.sendMessage(message);
+ }
+ }
+ }
+
+ public static Skill getNameConvertSkill(Player player,String skillName) {
+ if(skillName.equalsIgnoreCase("狱炎怒吼")){
+ return Skill_狱炎怒吼.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("爆火龙疾")){
+ return Skill_BaoHuoLongJi.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("重力压制")){
+ return Skill_ZhongLiYaZhi.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("赤焰旋风斩")){
+ return Skill_赤焰旋风斩.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("斩空陨击")){
+ return Skill_斩空陨击.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("崩地裂刺")){
+ return Skill_崩地裂刺.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("牵魂法阵")){
+ return Skill_牵魂法阵.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("逐风三式")){
+ return Skill_逐风三式.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("破空闪击")){
+ return Skill_破空闪击.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("苍锋剑气")){
+ return Skill_苍锋剑气.getSkillData(player);
+ } else if(skillName.equalsIgnoreCase("剑舞八荒")){
+ return Skill_剑舞八荒.getSkillData(player);
+ } else if (skillName.equalsIgnoreCase("逐影破空斩")) {
+ return Skill_逐影破空斩.getSkillData(player);
+ }else if (skillName.equalsIgnoreCase("幻刃屠龙舞")) {
+ return Skill_幻刃屠龙舞.getSkillData(player);
+ }
+ return null;
+ }
+
+ public static Skill getGuiSkillStack(String skillName,int skillLevel) {
+ if (skillName.equalsIgnoreCase("狱炎怒吼")) {
+ return Skill_狱炎怒吼.getSkillItemStack(skillLevel);
+ } else if (skillName.equalsIgnoreCase("爆火龙疾")) {
+ return Skill_BaoHuoLongJi.getSkillItemStack(skillLevel);
+ } else if (skillName.equalsIgnoreCase("重力压制")) {
+ return Skill_ZhongLiYaZhi.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("赤焰旋风斩")) {
+ return Skill_赤焰旋风斩.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("斩空陨击")) {
+ return Skill_斩空陨击.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("崩地裂刺")) {
+ return Skill_崩地裂刺.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("牵魂法阵")) {
+ return Skill_牵魂法阵.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("逐风三式")) {
+ return Skill_逐风三式.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("破空闪击")) {
+ return Skill_破空闪击.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("苍锋剑气")) {
+ return Skill_苍锋剑气.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("剑舞八荒")) {
+ return Skill_剑舞八荒.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("逐影破空斩")) {
+ return Skill_逐影破空斩.getSkillItemStack(skillLevel);
+ }else if (skillName.equalsIgnoreCase("幻刃屠龙舞")) {
+ return Skill_幻刃屠龙舞.getSkillItemStack(skillLevel);
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/Skill_崩地裂刺.java b/src/main/java/com/yaohun/demonskills/skills/Skill_崩地裂刺.java
new file mode 100644
index 0000000..f0256b6
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/Skill_崩地裂刺.java
@@ -0,0 +1,86 @@
+package com.yaohun.demonskills.skills;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_崩地裂刺 {
+
+ private static final String skillName = "崩地裂刺";
+ private static final double cooldownTime = 35;
+ private static final double cdReducePerLevel = 1.6; // 每级减少1.2秒冷却
+ private static final double minCooldown = 25.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(1, 1);
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 2);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 2.2,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 2.2,
+ Arrays.asList(
+ // 技能组件列表
+ new StunPlayerComponent(new SelfSelector(), 26L), // 定身2.0秒
+ new PlayerAnimationComponent("崩山击",34),
+ new StandAnimationComponent("战士技能", "崩山击", 1, 38),
+ new ParticleSpawnCommponent("战士暴雪/怒吼效果", 200, 2),
+ new SoundComponent("战士音效/怒吼音效.ogg", 0.5f, 1.8f),
+ new DelayComponent(15L,Arrays.asList(
+ new ParticlesComponent(Particle.LAVA,8,2,12),
+ new DamageComponent(damage,new ConeEnemiesSelector(4.5,180)),
+ new SoundComponent("战士音效/崩山击音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L,Arrays.asList(
+ new DamageComponent(damage,new ConeEnemiesSelector(6,180)),
+ new SoundComponent("战士音效/崩山击音效.ogg", 0.5f, 1.0f,10)
+ )
+ ))
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/Skill_斩空陨击.java b/src/main/java/com/yaohun/demonskills/skills/Skill_斩空陨击.java
new file mode 100644
index 0000000..2d0e3a8
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/Skill_斩空陨击.java
@@ -0,0 +1,89 @@
+package com.yaohun.demonskills.skills;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_斩空陨击 {
+
+ private static final String skillName = "斩空陨击";
+ private static final double cooldownTime = 20;
+ private static final double cdReducePerLevel = 1.2; // 每级减少1.2秒冷却
+ private static final double minCooldown = 13.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(1, 1);
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 2);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown,1.2, new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 1.2,
+ Arrays.asList(
+ // 技能组件列表
+ new PlayerAnimationComponent("俯冲"),
+ new StandAnimationComponent("战士技能", "俯冲", 1, 20),
+ new SoundComponent("战士音效/俯冲音效.ogg", 0.5f, 1.0f,10),
+ new ParticleSpawnCommponent("战士暴雪/俯冲效果", 200, 2),
+ new ProjectileAdvanceComponent(2,-0.1),
+ new DamageComponent(damage,new ConeEnemiesSelector(3,90)),
+ new DelayComponent(8L,Arrays.asList(
+ new ProjectileAdvanceComponent(2,-0.1),
+ new SoundComponent("战士音效/俯冲音效.ogg", 0.5f, 1.0f),
+ new DamageComponent(damage,new ConeEnemiesSelector(3,90)),
+ new DelayComponent(10L,Arrays.asList(
+ new ParticlesComponent(Particle.REDSTONE, 3, 1.5, 10),
+ new SoundComponent("战士音效/俯冲音效.ogg", 0.5f, 1.0f),
+ new ProjectileAdvanceComponent(-2,0.2,new NearestEnemiesSelector(3)),
+ new DamageComponent(damage,new NearestEnemiesSelector(3,2))
+ ))
+ ))
+ ));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/Skill_牵魂法阵.java b/src/main/java/com/yaohun/demonskills/skills/Skill_牵魂法阵.java
new file mode 100644
index 0000000..bd16e31
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/Skill_牵魂法阵.java
@@ -0,0 +1,111 @@
+package com.yaohun.demonskills.skills;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.CdTimeComponent;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.PotionEffectComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.component.projectile.ProjectilePullComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileVectorComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_牵魂法阵 {
+
+ private static final String skillName = "牵魂法阵";
+ private static final double cooldownTime = 38;
+ private static final double cdReducePerLevel = 1.2; // 每级减少1.2秒冷却
+ private static final double minCooldown = 30.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(1, 1);
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 2);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 4.0,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 4.0,
+ Arrays.asList(
+ // 技能组件列表
+ new StunPlayerComponent(new SelfSelector(), 60L), // 定身3.0秒
+ new CdTimeComponent("skill_ImmunityDamage",3000),
+ new PotionEffectComponent(PotionEffectType.SPEED,20 * 3,2),
+ new PlayerAnimationComponent("灵吸",60),
+ new StandAnimationComponent("战士技能", "灵吸", 1, 70),
+ new ParticleSpawnCommponent("战士暴雪/怒吼效果", 200, 2),
+ new ParticleSpawnCommponent("战士暴雪/灵吸效果", 200, 1),
+ new SoundComponent("战士音效/灵吸音效.ogg", 0.5f, 1.8f),
+ new DelayComponent(50L,Arrays.asList(
+ new ProjectileAdvanceComponent(2,0.2,new NearestEnemiesSelector(5)),
+ new DamageComponent(damage,new NearestEnemiesSelector(5))
+ )
+ ),
+ new DelayComponent(10L,Arrays.asList(
+ new ParticlesComponent(Particle.LAVA,8,2,5),
+ new ProjectilePullComponent(1,-0.1,new NearestEnemiesSelector(8,3)),
+ new DelayComponent(10L,Arrays.asList(
+ new ParticlesComponent(Particle.LAVA,8,2,5),
+ new ProjectilePullComponent(1,-0.1,new NearestEnemiesSelector(8,3)),
+ new DelayComponent(10L,Arrays.asList(
+ new ParticlesComponent(Particle.LAVA,8,2,5),
+ new ProjectilePullComponent(1,-0.1,new NearestEnemiesSelector(6,3)),
+ new DelayComponent(10L,Arrays.asList(
+ new ParticlesComponent(Particle.LAVA,8,2,5),
+ new ProjectilePullComponent(1,-0.1,new NearestEnemiesSelector(6,3)),
+ new DelayComponent(10L,Arrays.asList(
+ new ParticlesComponent(Particle.LAVA,8,2,5),
+ new ProjectilePullComponent(1,-0.1,new NearestEnemiesSelector(4,3))
+ ))
+ )
+ ))
+ ))
+ ))
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/Skill_狱炎怒吼.java b/src/main/java/com/yaohun/demonskills/skills/Skill_狱炎怒吼.java
new file mode 100644
index 0000000..04ab3d8
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/Skill_狱炎怒吼.java
@@ -0,0 +1,88 @@
+package com.yaohun.demonskills.skills;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.PotionEffectComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageContinuedComponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnContinuedComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_狱炎怒吼 {
+
+ private static final String skillName = "狱炎怒吼";
+ private static final double cooldownTime = 25;
+ private static final double cdReducePerLevel = 1.2; // 每级减少1.2秒冷却
+ private static final double minCooldown = 18.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 1);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 2);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 3);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 1.5,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 2.0, // 核心技能冷却(冷却中无法施展其他技能 包括翻滚)
+ Arrays.asList(
+ // 技能组件列表
+ new StunPlayerComponent(new SelfSelector(), 30L), // 定身1.5秒
+ new PlayerAnimationComponent("怒吼"),
+ new StandAnimationComponent("战士技能", "怒吼", 1, 39),
+ new SoundComponent("战士音效/怒吼音效.ogg", 1, 1),
+ new DelayComponent(5L, Arrays.asList(
+ new DamageComponent(damage,new NearestEnemiesSelector(3)),
+ new DamageContinuedComponent(damage*0.1,new NearestEnemiesSelector(4),5+skillLevel,15L,5),
+ new ParticleSpawnContinuedComponent("战士暴雪/怒吼效果",new NearestEnemiesSelector(4),5+skillLevel,15L,5),
+ new ParticleSpawnCommponent("战士暴雪/怒吼效果", 200, 1),
+ new ParticlesComponent(Particle.REDSTONE, 3, 1.5, 6 * 20),
+ new PotionEffectComponent(PotionEffectType.SPEED, 6 * 20, 1)
+ ))
+ )
+ );
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/Skill_赤焰旋风斩.java b/src/main/java/com/yaohun/demonskills/skills/Skill_赤焰旋风斩.java
new file mode 100644
index 0000000..28c9ca5
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/Skill_赤焰旋风斩.java
@@ -0,0 +1,123 @@
+package com.yaohun.demonskills.skills;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.PotionEffectComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_赤焰旋风斩 {
+
+ private static final String skillName = "赤焰旋风斩";
+ private static final double cooldownTime = 35;
+ private static final double cdReducePerLevel = 1.6; // 每级减少1.6秒冷却
+ private static final double minCooldown = 25.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(3, 1);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 0);
+ return new Skill(skillName, realNeedMagic, realCooldown, 4.0,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 0);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 4.5, // 核心技能冷却(冷却中无法施展其他技能 包括翻滚)
+ Arrays.asList(
+ // 技能组件列表
+ new PlayerAnimationComponent("旋风斩"),
+ new StandAnimationComponent("战士技能", "旋风斩", 1, 86),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(8L, Arrays.asList(
+ new PotionEffectComponent(PotionEffectType.SLOW,70,2),
+ new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
+ new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L, Arrays.asList(
+
+ new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
+ new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L, Arrays.asList(
+
+ new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
+ new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L, Arrays.asList(
+
+ new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
+ new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L, Arrays.asList(
+
+ new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
+ new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L,Arrays.asList(
+
+ new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
+ new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L,Arrays.asList(
+
+ new DamageComponent(damage*0.2,new NearestEnemiesSelector(5)),
+ new ProjectileAdvanceComponent(0.5,0.2,new NearestEnemiesSelector(5)),
+ new SoundComponent("战士音效/旋风斩音效.ogg", 0.5f, 1.0f,10),
+ new DelayComponent(10L,Arrays.asList(
+ // 播放爆炸音效
+ new SoundComponent("ENTITY_GENERIC_EXPLODE",1.0f,1.0f),
+ // 播放 跟随岩浆粒子 5次
+ new ParticlesComponent(Particle.LAVA,5,0.2,5),
+ new ProjectileAdvanceComponent(0.6,0.8,new NearestEnemiesSelector(3))
+ ))
+ ))
+ ))
+ )
+ ))
+ ))
+ ))
+ ))
+ ))
+ );
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/attack/Skill_普通攻击.java b/src/main/java/com/yaohun/demonskills/skills/attack/Skill_普通攻击.java
new file mode 100644
index 0000000..3ef4735
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/attack/Skill_普通攻击.java
@@ -0,0 +1,90 @@
+package com.yaohun.demonskills.skills.attack;
+
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.core.Skill;
+
+import java.util.Arrays;
+
+public class Skill_普通攻击 {
+
+ private static final String skillName = "普通攻击";
+ private static final double cooldownTime = 1;
+ private static final int needMagic = 10;
+
+ public static Skill getAttack1() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 0.2,
+ Arrays.asList(
+ // 技能组件列表
+ new SoundComponent("挥舞.ogg", 0.6f, 1.0f),
+ new PlayerAnimationComponent("youling_attack1",25),
+ new StandAnimationComponent("@游灵普通攻击", "youling_attack1", 1, 25,0.1),
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAdvanceComponent(0.1,0.0)
+ ))
+ ));
+ return skill;
+ }
+
+ public static Skill getAttack2() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 0.2,
+ Arrays.asList(
+ // 技能组件列表
+ new SoundComponent("挥舞.ogg", 0.6f, 1.0f),
+ new PlayerAnimationComponent("youling_attack2",31),
+ new StandAnimationComponent("@游灵普通攻击", "youling_attack2", 1, 31,0.1),
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAdvanceComponent(0.1,0.0)
+ ))
+ ));
+ return skill;
+ }
+
+ public static Skill getAttack3() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 0.2,
+ Arrays.asList(
+ // 技能组件列表
+ new SoundComponent("挥舞.ogg", 0.6f, 1.2f),
+ new PlayerAnimationComponent("youling_attack3",18),
+ new StandAnimationComponent("@游灵普通攻击", "youling_attack3", 1, 18,0.1),
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAdvanceComponent(0.1,0.0)
+ ))
+ ));
+ return skill;
+ }
+
+ public static Skill getAttack4() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 0.2,
+ Arrays.asList(
+ // 技能组件列表
+ new SoundComponent("挥舞.ogg", 0.6f, 1.4f),
+ new PlayerAnimationComponent("youling_attac4",23),
+ new StandAnimationComponent("@游灵普通攻击", "youling_attack4", 1, 23,0.1),
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAdvanceComponent(0.1,0.0)
+ ))
+ ));
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_BaoHuoLongJi.java b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_BaoHuoLongJi.java
new file mode 100644
index 0000000..99898d4
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_BaoHuoLongJi.java
@@ -0,0 +1,97 @@
+package com.yaohun.demonskills.skills.skillsapi;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.*;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.particles.CircleParticlesComponent;
+import com.yaohun.demonskills.component.particles.DiscParticlesComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_BaoHuoLongJi {
+
+ private static final String skillName = "爆火龙疾";
+ private static final double cooldownTime = 60;
+ private static final double cdReducePerLevel = 3.0; // 每级减少1.2秒冷却
+ private static final double minCooldown = 30.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(1, 1);
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 2);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 0);
+ return new Skill(skillName, realNeedMagic, realCooldown,2.5, new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 0);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = 100 + (damageValue * 1.3) * skillLevel;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 2.5,
+ Arrays.asList(
+ // 实现漂浮效果 26L
+ new PotionEffectComponent(PotionEffectType.LEVITATION,26,0),
+ // 玩家向前冲刺 力度0.3 高度0.8
+ new ProjectileAdvanceComponent(0.3,0.8),
+ // 播放声音
+ new SoundComponent("ENTITY_ENDERDRAGON_FLAP",1.0f,1.0f),
+ // 播放 跟随粒子每次出现6个 范围2 播放次数 15次
+ new ParticlesComponent(Particle.REDSTONE,6,2,15),
+ // 生成脚下一圈粒子
+ new CircleParticlesComponent(Particle.REDSTONE,2,2,36,2),
+ // 延迟 16L
+ new DelayComponent(26L,Arrays.asList(
+ // 添加防摔CD
+ new CdTimeComponent("anti_fall",500),
+ // 玩家镶嵌冲刺 位移0.5 高度-1.5
+ new ProjectileAdvanceComponent(0.8,-1.0),
+ // 播放爆炸音效
+ new SoundComponent("ENTITY_GENERIC_EXPLODE",1.0f,1.0f),
+ // 播放 跟随岩浆粒子 5次
+ new ParticlesComponent(Particle.LAVA,5,0.2,5),
+ // 对周围3格范围内生物造成伤害
+ new DamageComponent(damage,new NearestEnemiesSelector(5)),
+ // 延迟5L
+ new DelayComponent(5L,Arrays.asList(
+ // 播放 圆形粒子
+ new DiscParticlesComponent(Particle.SMOKE_LARGE,1,20)
+ ))
+ ))
+ )
+ );
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_ZhongLiYaZhi.java b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_ZhongLiYaZhi.java
new file mode 100644
index 0000000..1be75fa
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_ZhongLiYaZhi.java
@@ -0,0 +1,91 @@
+package com.yaohun.demonskills.skills.skillsapi;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.*;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.damage.DamageContinuedComponent;
+import com.yaohun.demonskills.component.particles.CircleParticlesComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileVectorComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.util.Vector;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_ZhongLiYaZhi {
+
+ private static final String skillName = "重力压制";
+ private static final double cooldownTime = 65;
+ private static final double cdReducePerLevel = 3.0; // 每级减少1.2秒冷却
+ private static final double minCooldown = 30.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(1, 1);
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 2);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 0);
+ return new Skill(skillName, realNeedMagic, realCooldown, 2.0,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 0);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = 100 + (damageValue * 1.3) * skillLevel;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 2.0,
+ Arrays.asList(
+ // 玩家向前冲刺 力度0.3 高度0.8
+ new ProjectileVectorComponent(new Vector(0,0.5,0),0,0.5,0),
+ // 播放声音
+ new SoundComponent("ENTITY_BAT_TAKEOFF",1.0f,1.0f),
+ // 播放 跟随粒子每次出现6个 范围2 播放次数 15次
+ new ParticlesComponent(Particle.CRIT,6,2,30),
+ // 延迟 16L
+ new DelayComponent(12L,Arrays.asList(
+ // 添加防摔CD // 播放爆炸音效
+ new CdTimeComponent("anti_fall",500),
+ new SoundComponent("ENTITY_GENERIC_EXPLODE",1.0f,1.2f),
+ new ParticlesComponent(Particle.LAVA,8,1,2),
+ // 生成脚下一圈粒子
+ new CircleParticlesComponent(Particle.SPELL_WITCH,2,2,36,3),
+ new CircleParticlesComponent(Particle.SPELL_WITCH,2,3,36,3),
+ new CircleParticlesComponent(Particle.SPELL_WITCH,2,4,36,3),
+ // 对周围5格范围内生物造成减速2秒
+ new DamageContinuedComponent(damage,new NearestEnemiesSelector(5),5,4,5),
+ new PotionEffectComponent(PotionEffectType.SLOW,20,4,new NearestEnemiesSelector(5)),
+ new ParticlesComponent(Particle.PORTAL,6,2.0,60,new NearestEnemiesSelector(5))
+ ))
+ )
+ );
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_前翻滚.java b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_前翻滚.java
new file mode 100644
index 0000000..74031aa
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_前翻滚.java
@@ -0,0 +1,44 @@
+package com.yaohun.demonskills.skills.skillsapi;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAroundComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class Skill_前翻滚 {
+
+ private static final String skillName = "翻滚";
+ private static final double cooldownTime = 5;
+ private static final int needMagic = 10;
+
+ public static Skill getSkillData() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 1.0,
+ Arrays.asList(
+ // 技能组件列表
+ new SoundComponent("翻滚音效.ogg", 0.8f, 1.0f),
+ new DelayComponent(4L,Arrays.asList(
+ new PlayerAnimationComponent("动作_前翻滚",16),
+ new StandAnimationComponent("@特效_前翻滚", "idle", 1, 16,0.1),
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAdvanceComponent(1.5,0.15)
+ ))
+ ))
+ ));
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_右翻滚.java b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_右翻滚.java
new file mode 100644
index 0000000..5a4a615
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_右翻滚.java
@@ -0,0 +1,42 @@
+package com.yaohun.demonskills.skills.skillsapi;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAroundComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class Skill_右翻滚 {
+
+ private static final String skillName = "翻滚";
+ private static final double cooldownTime = 5;
+ private static final int needMagic = 10;
+ public static Skill getSkillData() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 1.0,
+ Arrays.asList(
+ // 技能组件列表
+ new SoundComponent("翻滚音效.ogg", 0.8f, 1.0f),
+ new DelayComponent(4L,Arrays.asList(
+ new PlayerAnimationComponent("动作_右翻滚",16),
+ new StandAnimationComponent("@特效_右翻滚", "idle", 1, 16,0.1),
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAroundComponent(1.5,0.15,false)
+ ))
+ ))
+ ));
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_后翻滚.java b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_后翻滚.java
new file mode 100644
index 0000000..dc97f07
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_后翻滚.java
@@ -0,0 +1,44 @@
+package com.yaohun.demonskills.skills.skillsapi;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class Skill_后翻滚 {
+
+ private static final String skillName = "翻滚";
+ private static final double cooldownTime = 5;
+ private static final int needMagic = 10;
+
+
+ public static Skill getSkillData() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 1.0,
+ Arrays.asList(
+ // 技能组件列表
+ new SoundComponent("翻滚音效.ogg", 0.8f, 1.0f),
+ new DelayComponent(4L,Arrays.asList(
+ new PlayerAnimationComponent("动作_后翻滚",16),
+ new StandAnimationComponent("@特效_后翻滚", "idle", 1, 16,0.1),
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAdvanceComponent(-1.5,0.15)
+ ))
+ ))
+ ));
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_左翻滚.java b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_左翻滚.java
new file mode 100644
index 0000000..9f9287b
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_左翻滚.java
@@ -0,0 +1,53 @@
+package com.yaohun.demonskills.skills.skillsapi;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAroundComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileVectorComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class Skill_左翻滚 {
+
+ private static final String skillName = "翻滚";
+ private static final double cooldownTime = 5;
+ private static final int needMagic = 10;
+
+ public static Skill getSkillData() {
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ needMagic, // 魔力需求
+ cooldownTime, // 冷却时间
+ 1.0,
+ Arrays.asList(
+ new SoundComponent("翻滚音效.ogg", 0.8f, 1.0f), // 播放翻滚音效
+ new DelayComponent(4L,Arrays.asList( // 延迟4tick
+ new PlayerAnimationComponent("动作_左翻滚",16), // 播放玩家动作 并在16tick停止播放
+ // 生成盔甲架并添加模型 同时延迟1tick 播放动画并在16tick后关闭动画
+ new StandAnimationComponent("@特效_左翻滚", "idle", 1, 16,0.1),
+ // 延迟1tick执行 Vector 位移
+ new DelayComponent(1L,Arrays.asList(
+ new ProjectileAroundComponent(1.5,0.15)
+ ))
+ ))
+ ));
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_魔法值技能示范.java b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_魔法值技能示范.java
new file mode 100644
index 0000000..923543e
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/skillsapi/Skill_魔法值技能示范.java
@@ -0,0 +1,72 @@
+package com.yaohun.demonskills.skills.skillsapi;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import org.bukkit.entity.Player;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_魔法值技能示范 {
+
+ private static final String skillName = "逐风三式";
+ private static final double cooldownTime = 20;
+ private static final int needMagic = 10;
+ private static final double cdReducePerLevel = 2.6; // 每级减少1.2秒冷却
+ private static final int mpIncreasePerLevel = 4; // 每级增加3点魔力消耗
+ private static final double minCooldown = 1.3; // 最低冷却限制
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = needMagic + mpIncreasePerLevel * (skillLevel - 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 1.5,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = needMagic + mpIncreasePerLevel * (skillLevel - 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 1.5,
+ Arrays.asList(
+ // 技能组件列表
+ new PlayerAnimationComponent("逐风三式",25),
+ new StandAnimationComponent("@游灵剑技1", "youling_skill1", 1, 25,0.1),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f),
+ new DelayComponent(5L,Arrays.asList(
+ new DamageComponent(damage * 0.2 ,new ConeEnemiesSelector(6.5,45)),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f),
+ new DelayComponent(5L,Arrays.asList(
+ new DamageComponent(damage * 0.2,new ConeEnemiesSelector(6.5,45)),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f),
+ new DelayComponent(5L,Arrays.asList(
+ new DamageComponent(damage * 0.2,new ConeEnemiesSelector(6.5,45)),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f)
+ ))
+ )
+ ))
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/youling/Skill_剑舞八荒.java b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_剑舞八荒.java
new file mode 100644
index 0000000..0889cf8
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_剑舞八荒.java
@@ -0,0 +1,88 @@
+package com.yaohun.demonskills.skills.youling;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_剑舞八荒 {
+
+ private static final String skillName = "剑舞八荒";
+ private static final double cooldownTime = 25;
+ private static final double cdReducePerLevel = 1.2; // 每级减少1.2秒冷却
+ private static final double minCooldown = 20.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 1);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 2);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 3);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 1.2,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 1.2,
+ Arrays.asList(
+ // 技能组件列表
+ new StunPlayerComponent(new SelfSelector(), 20L), // 定身2.0秒
+ new PlayerAnimationComponent("剑舞八荒",20),
+ new StandAnimationComponent("@游灵剑技4", "youling_skill4", 1, 20,0.1),
+ new SoundComponent("刀飞舞.ogg", 0.4f, 1.0f),
+ new DelayComponent(4L,Arrays.asList(
+ new DamageComponent(damage * 0.2 ,new NearestEnemiesSelector(8.0)),
+ new DelayComponent(4L,Arrays.asList(
+ new DamageComponent(damage * 0.2 ,new NearestEnemiesSelector(8.0)),
+ new DelayComponent(4L,Arrays.asList(
+ new DamageComponent(damage * 0.2 ,new NearestEnemiesSelector(8.0)),
+ new ParticlesComponent(Particle.END_ROD,6,2,10),
+ new DelayComponent(4L,Arrays.asList(
+ new DamageComponent(damage * 0.2 ,new NearestEnemiesSelector(8.0))
+ ))
+ ))
+ )
+ ))
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/youling/Skill_幻刃屠龙舞.java b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_幻刃屠龙舞.java
new file mode 100644
index 0000000..40fb607
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_幻刃屠龙舞.java
@@ -0,0 +1,100 @@
+package com.yaohun.demonskills.skills.youling;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.PotionEffectComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.damage.DamageContinuedComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.component.projectile.ProjectilePullComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileVectorComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.util.Vector;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_幻刃屠龙舞 {
+
+ private static final String skillName = "幻刃屠龙舞";
+ private static final double cooldownTime = 40;
+ private static final double cdReducePerLevel = 1.6; // 每级减少1.2秒冷却
+ private static final double minCooldown = 30.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(1, 1);
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 2);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 3.2,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 3.2,
+ Arrays.asList(
+ // 技能组件列表
+ new StunPlayerComponent(new SelfSelector(), 60L), // 定身2.0秒
+ new PlayerAnimationComponent("幻刃屠龙舞",60),
+ new StandAnimationComponent("@游灵剑技6", "youling_skill6", 1, 56,0.1),
+ new DelayComponent(10L,Arrays.asList(
+ new SoundComponent("挥舞剑气1.ogg", 0.4f, 1.0f),
+ new DamageComponent(damage * 0.2 ,new ConeEnemiesSelector(7.0,90)),
+ new ParticlesComponent(Particle.SPELL_WITCH,6,2,50,new ConeEnemiesSelector(7.0,90)),
+ new PotionEffectComponent(PotionEffectType.SLOW,50,5,new ConeEnemiesSelector(10.0,90)),
+ new DelayComponent(8L,Arrays.asList(
+ new DamageComponent(damage * 0.2 ,new ConeEnemiesSelector(10.,90)),
+ new SoundComponent("幻刃屠龙舞.ogg", 0.4f, 1.0f),
+ new DamageContinuedComponent(damage*0.2,new ConeEnemiesSelector(10.,90),5,5L,10),
+ new DelayComponent(20L,Arrays.asList(
+ new ProjectileVectorComponent(new Vector(0,1,0),0,1.0,0,new ConeEnemiesSelector(10.0,90)),
+ new DelayComponent(3L,Arrays.asList(
+ new DamageComponent(damage * 0.6,new ConeEnemiesSelector(13.0,90))
+ ))
+ ))
+ ))
+ )
+ )
+ )
+ );
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/youling/Skill_破空闪击.java b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_破空闪击.java
new file mode 100644
index 0000000..899c2c8
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_破空闪击.java
@@ -0,0 +1,79 @@
+package com.yaohun.demonskills.skills.youling;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.NearestEnemiesSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_破空闪击 {
+
+ private static final String skillName = "破空闪击";
+ private static final double cooldownTime = 25;
+ private static final double cdReducePerLevel = 1.6; // 每级减少1.2秒冷却
+ private static final double minCooldown = 30.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(3, 1);
+ skillMagicMap.put(4, 1);
+ skillMagicMap.put(5, 2);
+ skillMagicMap.put(6, 2);
+ skillMagicMap.put(7, 3);
+ skillMagicMap.put(8, 3);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown,1.2, new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 1.2,
+ Arrays.asList(
+ // 技能组件列表
+ new PlayerAnimationComponent("破空闪击"),
+ new SoundComponent("破空闪击.ogg", 0.5f, 1.0f),
+ new DelayComponent(10L,Arrays.asList(
+ new ProjectileAdvanceComponent(3,-0.1),
+ new StandAnimationComponent("@游灵剑技2", "youling_skill2", 1, 17,0.1),
+ new ParticlesComponent(Particle.REDSTONE, 3, 1.5, 10),
+ new DelayComponent(5L,Arrays.asList(
+ new DamageComponent(damage,new ConeEnemiesSelector(4,60))
+ )))
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/youling/Skill_苍锋剑气.java b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_苍锋剑气.java
new file mode 100644
index 0000000..0cbe899
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_苍锋剑气.java
@@ -0,0 +1,79 @@
+package com.yaohun.demonskills.skills.youling;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.PotionEffectComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_苍锋剑气 {
+
+ private static final String skillName = "苍锋剑气";
+ private static final double cooldownTime = 25;
+ private static final double cdReducePerLevel = 1.6; // 每级减少1.2秒冷却
+ private static final double minCooldown = 16.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(3, 1);
+ skillMagicMap.put(4, 1);
+ skillMagicMap.put(5, 2);
+ skillMagicMap.put(6, 2);
+ skillMagicMap.put(7, 3);
+ skillMagicMap.put(8, 3);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 1.2,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 1.2,
+ Arrays.asList(
+ // 技能组件列表
+ new PlayerAnimationComponent("苍锋剑气"),
+ new SoundComponent("破空闪击.ogg", 0.8f, 1.4f),
+ new StandAnimationComponent("@游灵剑技3", "youling_skill3", 1, 17,0.1),
+ new DelayComponent(10L,Arrays.asList(
+ new DamageComponent(damage,new ConeEnemiesSelector(10,60,2)),
+ new PotionEffectComponent(PotionEffectType.SLOW,60,5,new ConeEnemiesSelector(10,60,2)),
+ new ParticlesComponent(Particle.SPELL_WITCH,1,1.5,50,new ConeEnemiesSelector(10,60,2))
+ )
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/youling/Skill_逐影破空斩.java b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_逐影破空斩.java
new file mode 100644
index 0000000..d3a8282
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_逐影破空斩.java
@@ -0,0 +1,108 @@
+package com.yaohun.demonskills.skills.youling;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.PotionEffectComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.component.projectile.ProjectileAdvanceComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.bukkit.potion.PotionEffectType;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_逐影破空斩 {
+
+ private static final String skillName = "逐影破空斩";
+ private static final double cooldownTime = 35;
+ private static final double cdReducePerLevel = 1.6; // 每级减少1.2秒冷却
+ private static final double minCooldown = 25.0; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(1, 1);
+ skillMagicMap.put(2, 1);
+ skillMagicMap.put(3, 2);
+ skillMagicMap.put(4, 2);
+ skillMagicMap.put(5, 3);
+ skillMagicMap.put(6, 3);
+ skillMagicMap.put(7, 4);
+ skillMagicMap.put(8, 4);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 3.0,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 3.0,
+ Arrays.asList(
+ // 技能组件列表
+ new StunPlayerComponent(new SelfSelector(), 40L), // 定身2.0秒
+ new PlayerAnimationComponent("逐影破空斩",48),
+ new StandAnimationComponent("@游灵剑技5", "youling_skill5", 1, 48,0.1),
+ new SoundComponent("刀剑挥舞1.ogg", 0.4f, 1.0f),
+ new DelayComponent(8L,Arrays.asList(
+ new ParticlesComponent(Particle.ENCHANTMENT_TABLE,8,2,8,new ConeEnemiesSelector(8.0,45)),
+ new DamageComponent(damage * 0.1 ,new ConeEnemiesSelector(12.0,45)),
+ new SoundComponent("刀剑挥舞1.ogg", 0.4f, 1.0f),
+ new DelayComponent(9L,Arrays.asList(
+ new ParticlesComponent(Particle.ENCHANTMENT_TABLE,8,2,8,new ConeEnemiesSelector(8.0,45)),
+ new DamageComponent(damage * 0.1 ,new ConeEnemiesSelector(12.0,45)),
+ new SoundComponent("刀剑挥舞1.ogg", 0.4f, 1.0f),
+ new DelayComponent(4L,Arrays.asList(
+ new ParticlesComponent(Particle.ENCHANTMENT_TABLE,8,2,8,new ConeEnemiesSelector(8.0,45)),
+ new DamageComponent(damage * 0.1,new ConeEnemiesSelector(12.0,45)),
+ new SoundComponent("刀剑挥舞1.ogg", 0.4f, 1.0f),
+ new DelayComponent(7L,Arrays.asList(
+ new ParticlesComponent(Particle.ENCHANTMENT_TABLE,8,2,8,new ConeEnemiesSelector(8.0,45)),
+ new DamageComponent(damage * 0.1,new ConeEnemiesSelector(12.0,45)),
+ new SoundComponent("刀剑挥舞1.ogg", 0.4f, 1.0f),
+ new DelayComponent(6L,Arrays.asList(
+ new DamageComponent(damage * 0.1,new ConeEnemiesSelector(12.0,45)),
+ new ParticlesComponent(Particle.ENCHANTMENT_TABLE,8,2,8,new ConeEnemiesSelector(8.0,45)),
+ new PotionEffectComponent(PotionEffectType.SLOW,10,5,new ConeEnemiesSelector(10.0,45)),
+ new SoundComponent("挥舞剑气1.ogg", 0.6f, 1.0f),
+ new DelayComponent(8L,Arrays.asList(
+ new ProjectileAdvanceComponent(-2,0.2,new ConeEnemiesSelector(10.0,45)),
+ new DamageComponent(damage * 0.2,new ConeEnemiesSelector(10.0,45))
+ ))
+ ))
+ ))
+ ))
+ )
+ ))
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/skills/youling/Skill_逐风三式.java b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_逐风三式.java
new file mode 100644
index 0000000..fed0181
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/skills/youling/Skill_逐风三式.java
@@ -0,0 +1,85 @@
+package com.yaohun.demonskills.skills.youling;
+
+import com.yaohun.demonskills.SkillsMain;
+import com.yaohun.demonskills.component.DelayComponent;
+import com.yaohun.demonskills.component.SoundComponent;
+import com.yaohun.demonskills.component.damage.DamageComponent;
+import com.yaohun.demonskills.component.dragoncore.ParticleSpawnCommponent;
+import com.yaohun.demonskills.component.dragoncore.PlayerAnimationComponent;
+import com.yaohun.demonskills.component.dragoncore.StandAnimationComponent;
+import com.yaohun.demonskills.component.effects.StunPlayerComponent;
+import com.yaohun.demonskills.component.particles.ParticlesComponent;
+import com.yaohun.demonskills.core.Skill;
+import com.yaohun.demonskills.data.PlayerData;
+import com.yaohun.demonskills.manage.PlayerManager;
+import com.yaohun.demonskills.target.ConeEnemiesSelector;
+import com.yaohun.demonskills.target.SelfSelector;
+import org.bukkit.Particle;
+import org.bukkit.entity.Player;
+import org.serverct.ersha.jd.AttributeAPI;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Skill_逐风三式 {
+
+ private static final String skillName = "逐风三式";
+ private static final double cooldownTime = 15;
+ private static final double cdReducePerLevel = 1.6; // 每级减少1.2秒冷却
+ private static final double minCooldown = 5.5; // 最低冷却限制
+
+ private static final Map skillMagicMap = new HashMap<>();
+ static {
+ skillMagicMap.put(3, 1);
+ skillMagicMap.put(4, 1);
+ skillMagicMap.put(5, 2);
+ skillMagicMap.put(6, 2);
+ skillMagicMap.put(7, 3);
+ skillMagicMap.put(8, 3);
+ }
+
+ public static Skill getSkillItemStack(int skillLevel){
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ return new Skill(skillName, realNeedMagic, realCooldown, 1.5,new ArrayList<>());
+ }
+
+ public static Skill getSkillData(Player player) {
+ String playerName = player.getName();
+ PlayerManager playerManager = SkillsMain.getPlayerManager();
+ PlayerData playerData = playerManager.getPlayerData(playerName);
+ int skillLevel = playerData.getSkillLevel(skillName);
+ double realCooldown = Math.max(cooldownTime - cdReducePerLevel * (skillLevel - 1), minCooldown);
+ int realNeedMagic = skillMagicMap.getOrDefault(skillLevel, 1);
+ double damageValue = AttributeAPI.getAttrData(player).getAttributeRandomValue("物理伤害");
+ double damage = ((0.2 * skillLevel) * damageValue + 50) + damageValue;
+ Skill skill = new Skill( // 技能 ID
+ skillName, // 技能名称
+ realNeedMagic, // 魔力需求
+ realCooldown, // 冷却时间
+ 1.5,
+ Arrays.asList(
+ // 技能组件列表
+ new PlayerAnimationComponent("逐风三式",25),
+ new StandAnimationComponent("@游灵剑技1", "youling_skill1", 1, 25,0.1),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f),
+ new DelayComponent(5L,Arrays.asList(
+ new DamageComponent(damage * 0.2 ,new ConeEnemiesSelector(6.5,45)),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f),
+ new DelayComponent(5L,Arrays.asList(
+ new DamageComponent(damage * 0.2,new ConeEnemiesSelector(6.5,45)),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f),
+ new DelayComponent(5L,Arrays.asList(
+ new DamageComponent(damage * 0.2,new ConeEnemiesSelector(6.5,45)),
+ new SoundComponent("宝剑挥舞.ogg", 0.4f, 1.0f)
+ ))
+ )
+ ))
+ )));
+ playerData.setCooldownData(skillName, realCooldown);
+ return skill;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/target/ConeEnemiesSelector.java b/src/main/java/com/yaohun/demonskills/target/ConeEnemiesSelector.java
new file mode 100644
index 0000000..72cd7eb
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/target/ConeEnemiesSelector.java
@@ -0,0 +1,63 @@
+package com.yaohun.demonskills.target;
+
+import com.yaohun.demonskills.api.TargetSelector;
+import net.citizensnpcs.api.CitizensAPI;
+import org.bukkit.Location;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.util.Vector;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class ConeEnemiesSelector implements TargetSelector {
+ private final double radius; // 范围
+ private final double angle; // 角度(如 60°)
+ private int limit = -1;
+
+ public ConeEnemiesSelector(double radius, double angle) {
+ this.radius = radius;
+ this.angle = angle;
+ }
+
+ public ConeEnemiesSelector(double radius, double angle, int limit) {
+ this.radius = radius;
+ this.angle = angle;
+ this.limit = limit;
+ }
+
+ @Override
+ public List selectTargets(Player caster) {
+ List entityList = new ArrayList<>();
+ Vector forward = caster.getLocation().getDirection().setY(0).normalize(); // 只考虑水平朝向
+ Location eyeLoc = caster.getEyeLocation();
+ Vector eyeVec = eyeLoc.toVector();
+ for (Entity entity : caster.getNearbyEntities(radius, 3, radius)) {
+ if (!(entity instanceof LivingEntity) || entity.equals(caster)) continue;
+ if (entity instanceof ArmorStand) continue;
+ if (CitizensAPI.getNPCRegistry().isNPC(entity)) continue;
+
+ Vector toTarget = entity.getLocation().toVector().subtract(eyeVec);
+ toTarget.setY(0);
+
+ if (toTarget.length() > radius) continue;
+ toTarget.normalize();
+
+ double angleBetween = Math.toDegrees(Math.acos(forward.dot(toTarget)));
+ if (angleBetween <= angle / 2.0) {
+ entityList.add(entity);
+ }
+ }
+ /*List strings = new ArrayList<>();
+ for (Entity entity : entityList) {
+ strings.add(entity.getType().name());
+ }
+ System.out.println("# "+String.join(", ", strings));*/
+ return entityList;
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/target/NearestEnemiesSelector.java b/src/main/java/com/yaohun/demonskills/target/NearestEnemiesSelector.java
new file mode 100644
index 0000000..b24e3ed
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/target/NearestEnemiesSelector.java
@@ -0,0 +1,45 @@
+package com.yaohun.demonskills.target;
+
+import com.yaohun.demonskills.api.TargetSelector;
+import net.citizensnpcs.api.CitizensAPI;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class NearestEnemiesSelector implements TargetSelector {
+ private final double radius;
+ private int limit = 0;
+
+ public NearestEnemiesSelector(double radius) {
+ this.radius = radius;
+ }
+
+ public NearestEnemiesSelector(double radius, int limit) {
+ this.radius = radius;
+ this.limit = limit;
+ }
+
+ @Override
+ public List selectTargets(Player caster) {
+ if(limit != 0) {
+ return caster.getNearbyEntities(radius, radius, radius).stream()
+ .filter(e -> !(e instanceof ArmorStand))
+ .filter(e -> e instanceof LivingEntity && !e.equals(caster))
+ .filter(e -> !CitizensAPI.getNPCRegistry().isNPC(e)) // 排除NPC
+ .sorted(Comparator.comparingDouble(e -> e.getLocation().distanceSquared(caster.getLocation())))
+ .limit(limit)
+ .collect(Collectors.toList());
+ } else {
+ return caster.getNearbyEntities(radius, radius, radius).stream()
+ .filter(e -> !(e instanceof ArmorStand))
+ .filter(e -> !CitizensAPI.getNPCRegistry().isNPC(e)) // 排除NPC
+ .filter(e -> e instanceof LivingEntity && !e.equals(caster))
+ .collect(Collectors.toList());
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/target/SelfSelector.java b/src/main/java/com/yaohun/demonskills/target/SelfSelector.java
new file mode 100644
index 0000000..74461bc
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/target/SelfSelector.java
@@ -0,0 +1,15 @@
+package com.yaohun.demonskills.target;
+
+import com.yaohun.demonskills.api.TargetSelector;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SelfSelector implements TargetSelector {
+ @Override
+ public List selectTargets(Player caster) {
+ return Collections.singletonList(caster);
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/target/TeamPlayerSelector.java b/src/main/java/com/yaohun/demonskills/target/TeamPlayerSelector.java
new file mode 100644
index 0000000..65136d4
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/target/TeamPlayerSelector.java
@@ -0,0 +1,89 @@
+package com.yaohun.demonskills.target;
+
+import com.yaohun.demonskills.api.TargetSelector;
+import me.Demon.DemonTeam.DTeamAPI;
+import me.Demon.DemonTeam.TeamData;
+import net.citizensnpcs.api.CitizensAPI;
+import org.bukkit.entity.ArmorStand;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.LivingEntity;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class TeamPlayerSelector implements TargetSelector {
+ private final double radius;
+ private final int limit;
+ private final boolean teamBuff;
+
+ // 默认构造:1个目标,团队增益开启
+ public TeamPlayerSelector(double radius) {
+ this(radius, 1, true);
+ }
+
+ // 指定数量,默认团队增益开启
+ public TeamPlayerSelector(double radius, int limit) {
+ this(radius, limit, true);
+ }
+
+ // 全参构造
+ public TeamPlayerSelector(double radius, int limit, boolean teamBuff) {
+ this.radius = radius;
+ this.limit = Math.max(0, limit); // 限制不能为负数
+ this.teamBuff = teamBuff;
+ }
+
+ @Override
+ public List selectTargets(Player caster) {
+ TeamData teamData = DTeamAPI.getPlayerTeam(caster.getName());
+
+ List result = new ArrayList<>();
+ // 无队伍:teamBuff = true → 空,teamBuff = false → 所有生物
+ if (teamData == null) {
+ if (!teamBuff) {
+ for (Entity entity : caster.getNearbyEntities(radius, radius, radius)) {
+ if(entity instanceof ArmorStand) {
+ continue;
+ }
+ if(CitizensAPI.getNPCRegistry().isNPC(entity)){
+ continue;
+ }
+ if (entity instanceof LivingEntity && !entity.equals(caster)) {
+ result.add(entity);
+ if (limit > 0 && result.size() >= limit) break;
+ }
+ }
+ }
+ return result;
+ }
+ // 有队伍 → 根据 teamBuff 决定筛选规则
+ List members = teamData.getMemberList();
+ for (Entity entity : caster.getNearbyEntities(radius, radius, radius)) {
+ if(entity instanceof ArmorStand) {
+ continue;
+ }
+ if(CitizensAPI.getNPCRegistry().isNPC(entity)){
+ continue;
+ }
+ if (limit > 0 && result.size() >= limit) break;
+ if (entity.equals(caster)) continue;
+ if (entity instanceof Player) {
+ Player player = (Player) entity;
+ boolean isTeammate = members.contains(player.getName());
+ if (teamBuff && isTeammate) {
+ result.add(player);
+ } else if (!teamBuff && !isTeammate) {
+ result.add(player);
+ }
+ } else {
+ if (!teamBuff) {
+ result.add(entity);
+ }
+ }
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/yaohun/demonskills/util/CDTimeAPI.java b/src/main/java/com/yaohun/demonskills/util/CDTimeAPI.java
new file mode 100644
index 0000000..401479f
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/util/CDTimeAPI.java
@@ -0,0 +1,59 @@
+package com.yaohun.demonskills.util;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.UUID;
+
+public class CDTimeAPI {
+
+ private static HashSet cdData = new HashSet<>();
+
+ public static void setPlayerCD(UUID uuid, String key, long mills) {
+ CDData data = getCDData(uuid);
+ long now = System.currentTimeMillis();
+ data.setCD(key, now + mills);
+ }
+
+ public static long getCD(UUID uuid, String key) {
+ CDData data = getCDData(uuid);
+ long now = System.currentTimeMillis();
+ return data.getCD(key) - now;
+ }
+
+ public static boolean isCD(UUID uuid, String key) {
+ return (getCD(uuid, key) > 0L);
+ }
+
+ public static CDData getCDData(UUID uuid) {
+ for (CDData cDData : cdData) {
+ if (cDData.getUuid().equals(uuid))
+ return cDData;
+ }
+ CDData data = new CDData(uuid);
+ cdData.add(data);
+ return data;
+ }
+
+ public static class CDData{
+ private final UUID uuid;
+
+ private final HashMap cdTime;
+
+ public CDData(UUID uuid) {
+ this.uuid = uuid;
+ this.cdTime = new HashMap<>();
+ }
+
+ public UUID getUuid() {
+ return this.uuid;
+ }
+
+ public void setCD(String key, long time) {
+ this.cdTime.put(key, time);
+ }
+
+ public long getCD(String key) {
+ return this.cdTime.getOrDefault(key,-1L);
+ }
+ }
+}
diff --git a/src/main/java/com/yaohun/demonskills/util/RandomUtil.java b/src/main/java/com/yaohun/demonskills/util/RandomUtil.java
new file mode 100644
index 0000000..7adac24
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/util/RandomUtil.java
@@ -0,0 +1,52 @@
+package com.yaohun.demonskills.util;
+
+import org.bukkit.Location;
+import org.bukkit.World;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+import java.util.Random;
+
+public class RandomUtil {
+
+ public static boolean random(double d) {
+ return d >= new Random().nextFloat();
+ }
+
+ public static int getRandomInt(int min, int max) {
+ if (min == max) {
+ return max;
+ }
+ Random r = new Random();
+ int i = min < max ? min : max;
+ int a = min < max ? max : min;
+ return r.nextInt(a - i + 1) + i;
+ }
+
+ public static double getRandomDouble(double min, double max, int scl) {
+ int pow = (int) Math.pow(10, scl);
+ return Math.floor((Math.random() * (max - min) + min) * pow) / pow;
+ }
+
+ public static Location getRandomLocation(World world, double minX, double maxX, double minY, double maxY, double minZ, double maxZ) {
+ double rx = getRandomDouble(minX, maxX, 3);
+ double ry = getRandomDouble(minY, maxY, 3);
+ double rz = getRandomDouble(minZ, maxZ, 3);
+ return new Location(world, rx, ry, rz);
+ }
+
+ public static Location getRandomLocation(Entity player, double radius) {
+ Location loc = player.getLocation();
+ double minX = loc.getX() - radius;
+ double maxX = loc.getX() + radius;
+ double minY = loc.getY() - radius;
+ double maxY = loc.getY() + radius;
+ double minZ = loc.getZ() - radius;
+ double maxZ = loc.getZ() + radius;
+ double rx = getRandomDouble(minX, maxX, 1);
+ double ry = getRandomDouble(minY, maxY, 1);
+ double rz = getRandomDouble(minZ, maxZ, 1);
+ return new Location(loc.getWorld(), rx, ry, rz);
+ }
+
+}
diff --git a/src/main/java/com/yaohun/demonskills/util/StackUtil.java b/src/main/java/com/yaohun/demonskills/util/StackUtil.java
new file mode 100644
index 0000000..9c5c0cf
--- /dev/null
+++ b/src/main/java/com/yaohun/demonskills/util/StackUtil.java
@@ -0,0 +1,38 @@
+package com.yaohun.demonskills.util;
+
+import me.Demon.DemonPlugin.DemonAPI;
+import me.Demon.DemonPlugin.data.NbtItem;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.meta.ItemMeta;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class StackUtil {
+
+ public static ItemStack getSkillSlot(int pLevel,int needLevel) {
+ ItemStack item = DemonAPI.getAirItems().clone();
+ ItemMeta meta = item.getItemMeta();
+ meta.setDisplayName("§8« §6点击放入灵技石 §8»");
+ if (pLevel < needLevel) {
+ List lore = new ArrayList<>();
+ lore.add("§c§l★ §7等级需求: §cLv." + needLevel);
+ item.setAmount(3);
+ meta.setLore(lore);
+ } else {
+ item.setAmount(2);
+ }
+ item.setItemMeta(meta);
+ NbtItem nbtItem = new NbtItem(item);
+ nbtItem.setInteger("NeedLevel",needLevel);
+ return nbtItem.getItem();
+ }
+
+ public static ItemStack tagSkillStack(int rawSlot){
+ ItemStack stack = DemonAPI.getAirItems().clone();
+ NbtItem nbtItem = new NbtItem(stack);
+ nbtItem.setInteger("RawSlot",rawSlot);
+ return nbtItem.getItem();
+ }
+}
diff --git a/src/main/resources/PlayerData/妖魂.yml b/src/main/resources/PlayerData/妖魂.yml
new file mode 100644
index 0000000..e69de29
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
new file mode 100644
index 0000000..5ca33cc
--- /dev/null
+++ b/src/main/resources/config.yml
@@ -0,0 +1,18 @@
+SkillStone:
+ 狱炎怒吼:
+ nbt: cl#狱炎怒吼
+ type: PAPER
+ name: §e§l灵石§f§l·§6§l狱炎怒吼 §c§l{level}
+ lore:
+ - §8§l§m-------------------
+ - '§e▶ §7类型: §c主动技能'
+ - '§e▶ §7品质: §6传说'
+ - '§e▶ §7消耗: §d{magic} 魔法'
+ - '§e▶ §7来源: §a{player}'
+ - §8§l§m-------------------
+ - '§8§l[§4§l!§8§l] §7灵石效果:'
+ - §6§l» §7释放 §c狱炎怒吼 §f({cooldown}s)
+ - §7具体效果可在社区查看
+ - ''
+ - '§c提示: §7手持灵石右键打开'
+ - §7灵石背包,点击槽位绑定
\ No newline at end of file
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
new file mode 100644
index 0000000..fe89b71
--- /dev/null
+++ b/src/main/resources/plugin.yml
@@ -0,0 +1,8 @@
+name: DemonSkills
+main: com.yaohun.demonskills.SkillsMain
+version: 1.3.4
+depend:
+ - DemonAPI
+commands:
+ dskills:
+ castskill:
\ No newline at end of file
diff --git a/src/main/resources/settings.yml b/src/main/resources/settings.yml
new file mode 100644
index 0000000..29e15f1
--- /dev/null
+++ b/src/main/resources/settings.yml
@@ -0,0 +1,4 @@
+Disable-Worlds:
+ - 'hub'
+ - 'hsjjc'
+ - 'fish'
\ No newline at end of file