diff --git a/psychics-abilities/ability-assassinate/gradle.properties b/psychics-abilities/ability-assassinate/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-assassinate/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-assassinate/src/main/kotlin/io.github.sincostan1122.psychics.ability.assassinate/AbilityAssassinate.kt b/psychics-abilities/ability-assassinate/src/main/kotlin/io.github.sincostan1122.psychics.ability.assassinate/AbilityAssassinate.kt new file mode 100644 index 00000000..00e28d46 --- /dev/null +++ b/psychics-abilities/ability-assassinate/src/main/kotlin/io.github.sincostan1122.psychics.ability.assassinate/AbilityAssassinate.kt @@ -0,0 +1,112 @@ +package io.github.sincostan1122.psychics.ability.assassinate + + + +import io.github.monun.psychics.ActiveAbility +import io.github.monun.psychics.AbilityConcept +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import net.kyori.adventure.text.Component.text +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType + + +@Name("assassin") +class AbilityConceptAssassinate : AbilityConcept() { + + @Config + var isskillon = 0 + + init { + cost = 0.0 + durationTime = 5000L + cooldownTime = 20000L + wand = ItemStack(Material.GOLD_INGOT) + displayName = "은신/습격" + + description = listOf( + text("사용 시 ${durationTime / 1000.0}초간 은신합니다."), + text("시전중 이동 속도가 상승하지만, 공격력, 공격 속도가 감소합니다."), + text("이때 이동 속도 증가량은 공격력에 비례합니다."), + text("지속시간이 끝나거나 재사용할 시 은신이 풀립니다."), + text("만약 재사용하였다면, 공격 속도와 공격력이 증가합니다."), + text("공격 속도와 공격력 증가량도 공격력에 비례합니다.") + + + ) + } +} +class AbilityAssassinate : ActiveAbility(), Listener { + override fun onInitialize() { + cooldownTime = 0 + } + override fun onEnable() { + psychic.registerEvents(this) + + psychic.runTaskTimer({ + if (durationTime == 0L) { + if (concept.isskillon == 1) { + cooldownTime = concept.cooldownTime + concept.isskillon = 0 + } + + + } + },0L, 1L) + } + + override fun onCast(event: PlayerEvent, action: WandAction, target: Any?) { + + if(concept.isskillon == 0) { + val world = esper.player.location.world + world.spawnParticle(Particle.SPELL_MOB_AMBIENT, esper.player.location, 30) + + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.INVISIBILITY, (concept.durationTime / 50.0).toInt(), 1, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SPEED, (concept.durationTime / 50.0).toInt(), 2 + esper.getStatistic(EsperStatistic.of(EsperAttribute.ATTACK_DAMAGE to 1.0)).toInt(), false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SLOW_DIGGING, (concept.durationTime / 50.0).toInt(), 20, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.WEAKNESS, (concept.durationTime / 50.0).toInt(), 20, false, false, false) + ) + durationTime = concept.durationTime + concept.isskillon = 1 + } + else if(concept.isskillon == 1) { + val world = esper.player.location.world + world.spawnParticle(Particle.CLOUD, esper.player.location, 5) + + esper.player.removePotionEffect(PotionEffectType.SLOW_DIGGING) + esper.player.removePotionEffect(PotionEffectType.WEAKNESS) + esper.player.removePotionEffect(PotionEffectType.SPEED) + esper.player.removePotionEffect(PotionEffectType.INVISIBILITY) + + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.INCREASE_DAMAGE, 40, 2 + esper.getStatistic(EsperStatistic.of(EsperAttribute.ATTACK_DAMAGE to 1.0)).toInt(), false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.FAST_DIGGING,40, 2 + esper.getStatistic(EsperStatistic.of(EsperAttribute.ATTACK_DAMAGE to 1.0)).toInt(), false, false, false) + ) + concept.isskillon = 0 + cooldownTime = concept.cooldownTime + + } + + } + + + + + +} \ No newline at end of file diff --git a/psychics-abilities/ability-assassinate/src/main/resources/ability.yml b/psychics-abilities/ability-assassinate/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-assassinate/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-ball/gradle.properties b/psychics-abilities/ability-ball/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-ball/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-ball/src/main/kotlin/io/github/sincostan1122/psychics/ability/ball/AbilityBall.kt b/psychics-abilities/ability-ball/src/main/kotlin/io/github/sincostan1122/psychics/ability/ball/AbilityBall.kt new file mode 100644 index 00000000..c97d3206 --- /dev/null +++ b/psychics-abilities/ability-ball/src/main/kotlin/io/github/sincostan1122/psychics/ability/ball/AbilityBall.kt @@ -0,0 +1,193 @@ +package io.github.sincostan1122.psychics.ability.ball + + + +import io.github.monun.psychics.ActiveAbility +import io.github.monun.psychics.AbilityConcept +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.psychics.damage.Damage +import io.github.monun.psychics.damage.DamageType +import io.github.monun.psychics.util.hostileFilter +import io.github.monun.tap.config.Name +import io.github.monun.tap.fake.FakeEntity +import net.kyori.adventure.text.Component.text +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.entity.* +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerEvent +import org.bukkit.event.player.PlayerToggleSneakEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType +import org.bukkit.util.BoundingBox + + +@Name("Ball") +class AbilityConceptBall : AbilityConcept() { + + + init { + range = 1.0 + cost = 50.0 + durationTime = 5000L + cooldownTime = 2000L + wand = ItemStack(Material.MAGMA_CREAM) + damage = Damage.of(DamageType.RANGED, EsperStatistic.of(EsperAttribute.ATTACK_DAMAGE to 6.5)) + displayName = "구체 조종" + + description = listOf( + text("구체 하나가 생성됩니다."), + text("구체에 닿은 적은 원거리 피해를 입습니다."), + text("스킬을 사용해 구체의 위치를 조종할 수 있습니다."), + text("웅크린 채로 스킬을 사용하면 구체가 시전자의 위치로 이동합니다."), + text("공격력이 크게 감소합니다.") + ) + } +} +class AbilityBall : ActiveAbility(), Listener { + lateinit var loca : Location + var playerdt = 0.0 + var fakeEntity: FakeEntity? = null + var objectball: FakeEntity? = null + var isskillon = 0 + lateinit var moveloc : Location + var num = 1 + var manafifty = 0 + + override fun onEnable() { + psychic.registerEvents(this) + moveloc = esper.player.location + loca = esper.player.location + fakeEntity = psychic.spawnFakeEntity(esper.player.location, ArmorStand::class.java).apply { + updateMetadata { + isVisible = false + } + } + objectball = psychic.spawnFakeEntity(esper.player.location, EnderCrystal::class.java).apply { + updateMetadata { + isVisible = true + } + } + val world = esper.player.world + psychic.runTaskTimer({ + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.WEAKNESS, 10, 5, false, false, false) + ) + + if (isskillon == 1) { + world.spawnParticle(Particle.COMPOSTER, ballloc(), 3) + playerdt += 1.2 + fakeEntity?.moveTo(ballloc()) + if (durationTime == 0L) { + if (isskillon == 1) { + if (manafifty == 1){ + psychic.consumeMana(concept.cost) + manafifty = 0 + } + moveloc = objectball!!.location + cooldownTime = concept.cooldownTime + loca = objectball!!.location + isskillon = 2 + + } + } + } + else if (isskillon == 2) { + + if (num != 11) { + + moveloc.apply { + x += (ballloc().x - loca.x) / 10 + y += (ballloc().y - loca.y) / 10 + z += (ballloc().z - loca.z) / 10 + } + objectball?.moveTo(moveloc) + num += 1 + } + else { + isskillon = 0 + num = 1 + } + damagef() + + } + + }, 1L, 1L) + } + override fun onDisable() { + // 제거 + fakeEntity?.let { fakeEntity -> + fakeEntity.remove() + this.fakeEntity = null + } + objectball?.let { objectball -> + objectball.remove() + this.objectball = null + } + } + fun damagef() { + val loc = moveloc + val box = loc?.let { BoundingBox.of(it, 1.2, 1.2, 1.2) } + val hostiles = box?.let { loc?.world.getNearbyEntities(it, esper.player.hostileFilter()) } + + if (hostiles != null) { + for (entity in hostiles) { + (entity as LivingEntity).psychicDamage() + } + } + } + + override fun onCast(event: PlayerEvent, action: WandAction, target: Any?) { + val concept = concept + + if (esper.player.isSneaking) { + playerdt = 0.0 + psychic.consumeMana(concept.cost) + cooldownTime = concept.cooldownTime + moveloc = objectball!!.location + loca = objectball!!.location + isskillon = 2 + } + + if(isskillon == 0) { + + playerdt = 0.0 + psychic.consumeMana(concept.cost) + durationTime = concept.durationTime + isskillon = 1 + if (esper.getAttribute(EsperAttribute.MANA) < 50) { + psychic.consumeMana(-(concept.cost)) + manafifty = 1 + } + + } + else if(isskillon == 1) { + moveloc = objectball!!.location + cooldownTime = concept.cooldownTime + loca = objectball!!.location + isskillon = 2 + if (manafifty == 1){ + psychic.consumeMana(concept.cost) + manafifty = 0 + } + } + + } + + + + private fun ballloc(): Location { + return esper.player.eyeLocation.apply { + add(direction.multiply(playerdt)) + } + } + + + + + +} diff --git a/psychics-abilities/ability-ball/src/main/resources/ability.yml b/psychics-abilities/ability-ball/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-ball/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-control/gradle.properties b/psychics-abilities/ability-control/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-control/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-control/src/main/kotlin/io/github/sincostan1122/psychics/ability/control/AbilityControl.kt b/psychics-abilities/ability-control/src/main/kotlin/io/github/sincostan1122/psychics/ability/control/AbilityControl.kt new file mode 100644 index 00000000..642b6ee4 --- /dev/null +++ b/psychics-abilities/ability-control/src/main/kotlin/io/github/sincostan1122/psychics/ability/control/AbilityControl.kt @@ -0,0 +1,187 @@ +package io.github.sincostan1122.psychics.ability.control + + + +import io.github.monun.psychics.ActiveAbility +import io.github.monun.psychics.AbilityConcept +import io.github.monun.psychics.Channel +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import io.github.monun.tap.fake.FakeEntity +import io.github.monun.tap.fake.invisible +import net.kyori.adventure.text.Component.text +import org.bukkit.FluidCollisionMode +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.entity.ArmorStand +import org.bukkit.entity.Entity +import org.bukkit.entity.LivingEntity +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType +import org.bukkit.util.BoundingBox + + +@Name("control") +class AbilityConceptControl : AbilityConcept() { + + init { + cost = 0.0 + range = 50.0 + castingTime = 500L + durationTime = 5000L + cooldownTime = 30000L + wand = ItemStack(Material.DIAMOND_SWORD) + displayName = "지배" + + + + description = listOf( + text("대상 하나를 지정하여 ${durationTime/ 1000}초 동안 조종합니다."), + text("조종하는 동안 육체에서 빠져나와 무적 상태가 됩니다."), + text("조종당하는 대상은 지속시간 동안 시야가 제한됩니다."), + text("만약 아무것도 없는 지면이나 벽에 시전했을 경우, 제자리에 고정됩니다.") + + ) + } +} +class AbilityControl : ActiveAbility(), Listener { + var pbody: FakeEntity? = null + var isskillon = 0 + lateinit var bodyloc : Location + lateinit var victim : LivingEntity + init{ + targeter = { + val player = esper.player + val start = player.eyeLocation + val direction = start.direction + val world = start.world + + world.rayTrace( + start, + direction, + concept.range, + FluidCollisionMode.NEVER, + true, + 0.5 + ) { entity -> + entity !== player && entity is LivingEntity + }?.let { result -> + result.hitEntity?.location ?: result.hitPosition.toLocation(world) + } + } + } + override fun onChannel(channel: Channel) { + val location = channel.target as Location + val world = location.world + + + + world.spawnParticle(Particle.SOUL, location, 5) + } + override fun onEnable() { + + psychic.registerEvents(this) + + pbody = psychic.spawnFakeEntity(esper.player.location, ArmorStand::class.java).apply { + updateMetadata { + isVisible = false + } + + updateEquipment { // 장비 업데이트 + helmet = ItemStack(Material.PLAYER_HEAD) + chestplate = ItemStack(Material.DIAMOND_CHESTPLATE) + leggings = ItemStack(Material.DIAMOND_LEGGINGS) + boots = ItemStack(Material.DIAMOND_BOOTS) + } + + + + } + victim = esper.player + psychic.runTaskTimer({ + if (isskillon == 0) { + pbody?.moveTo(esper.player.location) + pbody!!.isVisible = false + + } + else if (isskillon == 1) { + pbody!!.isVisible = true + esper.player.invisible = true + val world = esper.player.world + controlling(victim) + world.spawnParticle(Particle.SOUL_FIRE_FLAME, esper.player.location, 5) + esper.player.sendActionBar("육체로 돌아가기까지 ${(durationTime / 1000L).toInt()}초...") + + if (durationTime == 0L) { + esper.player.invisible = false + isskillon = 0 + esper.player.teleport(bodyloc) + victim = esper.player + } + } + },0L, 1L) + } + + override fun onCast(event: PlayerEvent, action: WandAction, target: Any?) { + if (target == null) return + + cooldownTime = concept.cooldownTime + val player = esper.player + val location = target as Location + val x = location.x + val y = location.y + val z = location.z + val w = 1 + val h = 1 + val box = BoundingBox(x - w, y, z - w, x + w, y + h, z + w) + val world = location.world + durationTime = concept.durationTime + bodyloc = esper.player.location + + + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.INVISIBILITY, (concept.durationTime / 50L).toInt(), 1, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, (concept.durationTime / 50L).toInt(), 10, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.WEAKNESS, (concept.durationTime / 50L).toInt(), 1, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SLOW_DIGGING, (concept.durationTime / 50L).toInt(), 10, false, false, false) + ) + + world.getNearbyEntities(box) { entity -> + entity is LivingEntity && entity !is ArmorStand + }.forEach { entity -> + + + victim = entity as LivingEntity + esper.player.teleport(victim.location) + if (entity == player) { + entity.sendActionBar(text("지배당하고 있습니다...")) + } + } + isskillon = 1 + } + fun controlling(entity: LivingEntity) { + entity.teleport(esper.player.location) + entity.addPotionEffect( + PotionEffect(PotionEffectType.BLINDNESS, 10, 5, false, false, false) + ) + entity.addPotionEffect( + PotionEffect(PotionEffectType.WEAKNESS, 10, 10, false, false, false) + ) + entity.addPotionEffect( + PotionEffect(PotionEffectType.SLOW_DIGGING, 10, 10, false, false, false) + ) + } + +} \ No newline at end of file diff --git a/psychics-abilities/ability-control/src/main/resources/ability.yml b/psychics-abilities/ability-control/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-control/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-flash/gradle.properties b/psychics-abilities/ability-flash/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-flash/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-flash/src/main/kotlin/io/github/sincostan1122/psychics/ability/flash/AbilityFlash.kt b/psychics-abilities/ability-flash/src/main/kotlin/io/github/sincostan1122/psychics/ability/flash/AbilityFlash.kt new file mode 100644 index 00000000..95dbf524 --- /dev/null +++ b/psychics-abilities/ability-flash/src/main/kotlin/io/github/sincostan1122/psychics/ability/flash/AbilityFlash.kt @@ -0,0 +1,80 @@ +package io.github.sincostan1122.psychics.ability.flash + + +import io.github.monun.psychics.ActiveAbility +import io.github.monun.psychics.AbilityConcept +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import io.github.monun.tap.fake.FakeEntity +import net.kyori.adventure.text.Component.text +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.entity.ArmorStand +import org.bukkit.event.Listener +import org.bukkit.event.player.PlayerEvent +import org.bukkit.inventory.ItemStack + + +@Name("Flash") +class AbilityConceptFlash : AbilityConcept() { + @Config + var trange = 0.0 + + init { + cost = 50.0 + cooldownTime = 10L + wand = ItemStack(Material.DIAMOND) + displayName = "점멸" + + description = listOf( + text("일정 거리를 순간이동 합니다."), + text("순간이동 거리는 현재 마나량에 비례합니다.") + ) + } +} +class AbilityFlash : ActiveAbility(), Listener { + var fakeEntity: FakeEntity? = null + + + override fun onEnable() { + psychic.registerEvents(this) + fakeEntity = psychic.spawnFakeEntity(teleportloc(), ArmorStand::class.java).apply { + updateMetadata { + isVisible = false + } + } + val world = teleportloc().world + psychic.runTaskTimer({ + fakeEntity?.moveTo(teleportloc()) + concept.trange = esper.getStatistic(EsperStatistic.of(EsperAttribute.MANA to 0.1)) + world.spawnParticle(Particle.COMPOSTER, teleportloc(), 3) + }, 0L, 1L) + } + override fun onDisable() { + // 제거 + fakeEntity?.let { fakeEntity -> + fakeEntity.remove() + this.fakeEntity = null + } + } + + override fun onCast(event: PlayerEvent, action: WandAction, target: Any?) { + val concept = concept + psychic.consumeMana(concept.cost) + cooldownTime = concept.cooldownTime + + esper.player.teleport(teleportloc()) + } + + private fun teleportloc(): Location { + return esper.player.eyeLocation.apply { + add(direction.multiply(concept.trange)) + } + } + + + +} diff --git a/psychics-abilities/ability-flash/src/main/resources/ability.yml b/psychics-abilities/ability-flash/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-flash/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-illusion/gradle.properties b/psychics-abilities/ability-illusion/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-illusion/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-illusion/src/main/kotlin/io/github/sincostan1122/psychics/ability/illusion/AbilityIllusion.kt b/psychics-abilities/ability-illusion/src/main/kotlin/io/github/sincostan1122/psychics/ability/illusion/AbilityIllusion.kt new file mode 100644 index 00000000..7a092bc9 --- /dev/null +++ b/psychics-abilities/ability-illusion/src/main/kotlin/io/github/sincostan1122/psychics/ability/illusion/AbilityIllusion.kt @@ -0,0 +1,99 @@ +package io.github.sincostan1122.psychics.ability.illusion + + +import io.github.monun.psychics.Ability +import io.github.monun.psychics.AbilityConcept +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import io.github.monun.tap.fake.FakeEntity +import net.kyori.adventure.text.Component.text +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.entity.ArmorStand +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType + + +@Name("Illusion") +class AbilityConceptIllusion : AbilityConcept() { + @Config + var illusiontime = 2 + + + init { + + wand = ItemStack(Material.PLAYER_HEAD) + displayName = "환상" + + description = listOf( + text("무한히 투명 상태가 됩니다."), + text("자신의 ${illusiontime}초전 위치에 잔상을 남깁니다."), + text("받는 피해가 5배 증가합니다.") + ) + } +} +class AbilityIllusion : Ability(), Listener { + var fakeEntity: FakeEntity? = null + lateinit var arraylocation : Array + + + + + override fun onEnable() { + psychic.registerEvents(this) + arraylocation = Array(concept.illusiontime * 20){esper.player.location} + + + fakeEntity = psychic.spawnFakeEntity(arraylocation[0], ArmorStand::class.java).apply { + updateMetadata { + isVisible = true + } + + updateEquipment { // 장비 업데이트 + helmet = ItemStack(Material.PLAYER_HEAD) + chestplate = ItemStack(Material.DIAMOND_CHESTPLATE) + leggings = ItemStack(Material.DIAMOND_LEGGINGS) + boots = ItemStack(Material.DIAMOND_BOOTS) + } + + + } + psychic.runTaskTimer(this::arrayreload, 0L, 1L) + + + } + + private fun arrayreload() { + val player = esper.player + player.addPotionEffect( + PotionEffect(PotionEffectType.INVISIBILITY, 10, 1, false, false, false) + ) + for (i in 0..concept.illusiontime * 20 - 2) { + arraylocation[i] = arraylocation[(i + 1)] + } + arraylocation[(concept.illusiontime * 20 - 1)] = esper.player.location + fakeEntity?.moveTo(arraylocation[0]) + } + + override fun onDisable() { + // 제거 + fakeEntity?.let { fakeEntity -> + fakeEntity.remove() + this.fakeEntity = null + } + esper.player.removePotionEffect(PotionEffectType.INVISIBILITY) + } + @EventHandler(ignoreCancelled = true) + fun onEntityDamage(event: EntityDamageEvent) { + + val damage = event.damage * 5 + event.damage = damage + + } + +} + diff --git a/psychics-abilities/ability-illusion/src/main/resources/ability.yml b/psychics-abilities/ability-illusion/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-illusion/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-mirror/gradle.properties b/psychics-abilities/ability-mirror/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-mirror/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-mirror/src/main/kotlin/io/github/sincostan1122/psychics/ability/mirror/AbilityMirror.kt b/psychics-abilities/ability-mirror/src/main/kotlin/io/github/sincostan1122/psychics/ability/mirror/AbilityMirror.kt new file mode 100644 index 00000000..fac978cf --- /dev/null +++ b/psychics-abilities/ability-mirror/src/main/kotlin/io/github/sincostan1122/psychics/ability/mirror/AbilityMirror.kt @@ -0,0 +1,119 @@ +package io.github.sincostan1122.psychics.ability.mirror + + +import io.github.monun.psychics.ActiveAbility +import io.github.monun.psychics.AbilityConcept +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import io.github.monun.tap.fake.FakeEntity +import net.kyori.adventure.text.Component.text +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.entity.ArmorStand +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.player.PlayerEvent +import org.bukkit.event.player.PlayerVelocityEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType + + +@Name("mirror") +class AbilityConceptMirror : AbilityConcept() { + + @Config + var burftime = 1 + + init { + cost = 0.0 + durationTime = 1000L + cooldownTime = 10000L + wand = ItemStack(Material.IRON_INGOT) + displayName = "응수" + + description = listOf( + text("사용 시 ${durationTime / 1000.0}초간 응수 상태가 됩니다."), + text("시전중 이동 속도, 공격력, 공격 속도가 감소합니다."), + text("단, 받는 피해가 줄어들고 넉백 효과에 면역이 생깁니다."), + text("응수 상태 동안 넉백 효과를 받을 시 다음 효과를 얻습니다:") , + text("이동 속도, 공격력, 공격 속도 감소효과 해제"), + text("공격력,이동 속도, 공격 속도 ${burftime}초 증가") + ) + } +} +class AbilityMirror : ActiveAbility(), Listener { + + override fun onEnable() { + psychic.registerEvents(this) + + } + + private fun particleloc(): Location { + return esper.player.location + } + override fun onCast(event: PlayerEvent, action: WandAction, target: Any?) { + val world = particleloc().world + world.spawnParticle(Particle.SPELL_INSTANT, particleloc(), 30) + + + + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SLOW, (concept.durationTime / 50.0).toInt(), 5, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SLOW_DIGGING, (concept.durationTime / 50.0).toInt(), 20, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.WEAKNESS, (concept.durationTime / 50.0).toInt(), 10, false, false, false) + ) + + cooldownTime = concept.cooldownTime + durationTime = concept.durationTime + + } + + @EventHandler(ignoreCancelled = true) + fun onEntityDamage(event: EntityDamageEvent) { + if (durationTime > 0L) { + val damage = event.damage * 0.1 + event.damage = damage + } + } + + @EventHandler(ignoreCancelled = true) + fun onVelocity(event: PlayerVelocityEvent) { + + if (durationTime > 0L) { + event.isCancelled = true + + + esper.player.removePotionEffect(PotionEffectType.SLOW_DIGGING) + esper.player.removePotionEffect(PotionEffectType.WEAKNESS) + esper.player.removePotionEffect(PotionEffectType.SLOW) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.INCREASE_DAMAGE, concept.burftime * 20, 5, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SPEED, concept.burftime * 20, 5, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.FAST_DIGGING, concept.burftime * 20, 5, false, false, false) + ) + + + val player = esper.player + val location = player.location + val world = location.world + + world.spawnParticle(Particle.LAVA, particleloc(), 20) + + } + } + + +} \ No newline at end of file diff --git a/psychics-abilities/ability-mirror/src/main/resources/ability.yml b/psychics-abilities/ability-mirror/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-mirror/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-satellite/gradle.properties b/psychics-abilities/ability-satellite/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-satellite/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-satellite/src/main/kotlin/io/github/sincostan1122/psychics/ability/satellite/AbilitySatellite.kt b/psychics-abilities/ability-satellite/src/main/kotlin/io/github/sincostan1122/psychics/ability/satellite/AbilitySatellite.kt new file mode 100644 index 00000000..e4a68862 --- /dev/null +++ b/psychics-abilities/ability-satellite/src/main/kotlin/io/github/sincostan1122/psychics/ability/satellite/AbilitySatellite.kt @@ -0,0 +1,150 @@ +package io.github.sincostan1122.psychics.ability.satellite + + +import io.github.monun.psychics.Ability +import io.github.monun.psychics.AbilityConcept +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.psychics.damage.Damage +import io.github.monun.psychics.damage.DamageType +import io.github.monun.psychics.tooltip.TooltipBuilder +import io.github.monun.psychics.util.hostileFilter +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import io.github.monun.tap.fake.FakeEntity +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.TextDecoration +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.entity.* +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.player.PlayerEvent +import org.bukkit.event.player.PlayerVelocityEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType +import org.bukkit.util.BoundingBox + + +@Name("satellite") +class AbilityConceptSatellite : AbilityConcept() { + + + init { + + damage = Damage.of(DamageType.RANGED, EsperStatistic.of(EsperAttribute.ATTACK_DAMAGE to 2.0)) + displayName = "위성" + + description = listOf( + text("한개의 위성이 주변을 돕니다."), + text("위성에 닿은 적은 원거리 피해를 입습니다."), + + ) + } + +} +class AbilitySatellite : Ability(), Listener { + var stloc = 1 + var locx = 0.0 + var locz = 0.0 + var firstst: FakeEntity? = null + + override fun onEnable() { + psychic.registerEvents(this) + firstst = psychic.spawnFakeEntity(esper.player.location, Shulker::class.java).apply { + updateMetadata { + isVisible = true + } + } + psychic.runTaskTimer({ + if (stloc == 12) { + stloc = 1 + } + else{ + stloc++ + } + movest() + damagef() + + },0L, 1L) + } + fun damagef() { + val loc = firstst?.location + val box = loc?.let { BoundingBox.of(it, 1.0, 1.5, 1.0) } + val hostiles = box?.let { loc?.world.getNearbyEntities(it, esper.player.hostileFilter()) } + + if (hostiles != null) { + for (entity in hostiles) { + (entity as LivingEntity).psychicDamage() + } + } + } + fun movest() { + if(stloc == 1) { + locx = 0.0 + locz = 5.0 + } + else if(stloc == 2) { + locx = 2.5 + locz = 4.33 + } + else if(stloc == 3) { + locx = 4.33 + locz = 2.5 + } + else if(stloc == 4) { + locx = 5.0 + locz = 0.0 + } + else if(stloc == 5) { + locx = 4.33 + locz = -2.5 + } + else if(stloc == 6) { + locx = 2.5 + locz = -4.33 + } + else if(stloc == 7) { + locx = 0.0 + locz = -5.0 + } + else if(stloc == 8) { + locx = -2.5 + locz = -4.33 + } + else if(stloc == 9) { + locx = -4.33 + locz = -2.5 + } + else if(stloc == 10) { + locx = -5.0 + locz = 0.0 + } + else if(stloc == 11) { + locx = -4.33 + locz = 2.5 + } + else if(stloc == 12) { + locx = -2.5 + locz = 4.33 + } + + firstst?.moveTo(stlocz(locx, locz).apply{y += 0.5}) + } + private fun stlocx(vx : Double) = esper.player.location.apply{x += vx} + private fun stlocz(vx : Double, vz : Double) = stlocx(vx).apply{z += vz} + + override fun onDisable() { + // 제거 + firstst?.let { fakeEntity -> + fakeEntity.remove() + this.firstst = null + } + } + + +} \ No newline at end of file diff --git a/psychics-abilities/ability-satellite/src/main/resources/ability.yml b/psychics-abilities/ability-satellite/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-satellite/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-telekinesis/gradle.properties b/psychics-abilities/ability-telekinesis/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-telekinesis/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-telekinesis/src/main/kotlin/io/github/sincostan1122/psychics/ability/telekinesis/AbilityTelekinesis.kt b/psychics-abilities/ability-telekinesis/src/main/kotlin/io/github/sincostan1122/psychics/ability/telekinesis/AbilityTelekinesis.kt new file mode 100644 index 00000000..3aec59da --- /dev/null +++ b/psychics-abilities/ability-telekinesis/src/main/kotlin/io/github/sincostan1122/psychics/ability/telekinesis/AbilityTelekinesis.kt @@ -0,0 +1,244 @@ +package io.github.sincostan1122.psychics.ability.telekinesis + + +import io.github.monun.psychics.ActiveAbility +import io.github.monun.psychics.AbilityConcept +import io.github.monun.psychics.TestResult +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.psychics.damage.Damage +import io.github.monun.psychics.damage.DamageType +import io.github.monun.psychics.damage.psychicDamage +import io.github.monun.psychics.util.TargetFilter +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import io.github.monun.tap.fake.FakeEntity +import net.kyori.adventure.text.Component.text +import org.bukkit.Location +import org.bukkit.Material +import org.bukkit.Particle +import org.bukkit.Sound +import org.bukkit.entity.* +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.player.PlayerEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType +import org.bukkit.util.BoundingBox +import kotlin.math.max + + +@Name("Telekinesis") +class AbilityConceptTelekinesis : AbilityConcept() { + + @Config + var cancelcooltime = 10 + + init { + range = 6.0 + cost = 50.0 + durationTime = 5000L + cooldownTime = 1000L + wand = ItemStack(Material.EMERALD) + damage = Damage.of(DamageType.BLAST, EsperStatistic.of(EsperAttribute.ATTACK_DAMAGE to 5.0)) + displayName = "염력" + + description = listOf( + text("화약을 담은 구체를 소환하고 최대 ${durationTime / 1000.0}초동안 정신 집중을 합니다."), + text("정신 집중 동안 구체는 자동으로 바라보는 방향으로 날아갑니다."), + text("재사용하거나 지속시간이 끝날 시 구체가 폭팔을 일으킵니다."), + text("만약 정신 집중 동안 피격당할 시 ${cancelcooltime}초 동안 염력이 봉인됩니다.") + ) + } +} +class AbilityTelekinesis : ActiveAbility(), Listener { + private var tnt: TNT? = null + var playerdt = 0.0 + var fakeEntity: FakeEntity? = null + var isskillon = 0 + var manafifty = 0 + + + override fun onEnable() { + psychic.registerEvents(this) + fakeEntity = psychic.spawnFakeEntity(esper.player.location, ShulkerBullet::class.java).apply { + updateMetadata { + isVisible = false + } + } + val world = esper.player.world + psychic.runTaskTimer({ + fakeEntity?.moveTo(tntloc()) + if (isskillon == 1) { + + fakeEntity!!.isVisible = true + playerdt += 1 + esper.player.sendActionBar("정신 집중...") + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SLOW_FALLING, 10, 255, false, false, false) + ) + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.SLOW, 10, 5, false, false, false) + ) + } + + if (durationTime == 0L) { + if (isskillon == 1) { + esper.player.sendActionBar("펑!") + fakeEntity!!.isVisible = false + cooldownTime = concept.cooldownTime + isskillon = 0 + tnt = TNT(tntloc()) + destroy() + if (manafifty == 1){ + psychic.consumeMana(concept.cost) + manafifty = 0 + } + + + } + + + } + }, 0L, 1L) + } + override fun onDisable() { + // 제거 + fakeEntity?.let { fakeEntity -> + fakeEntity.remove() + this.fakeEntity = null + } + } + private fun destroy() { + tnt?.run { + + + remove() + tnt = null + + val location = tntloc() + val world = location.world + + val r = max(1.0, concept.range - 2.0) + world.spawnParticle(Particle.EXPLOSION_HUGE, location, (r * r).toInt(), r, r, r, 0.0, null, true) + world.playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 2.0F, 1.0F) + + val damage = concept.damage!! + var amount = esper.getStatistic(damage.stats) + + + val knockback = concept.knockback + + val box = BoundingBox.of(location, r, r, r) + world.getNearbyEntities(box, TargetFilter(esper.player)).forEach { enemy -> + if (enemy is LivingEntity) { + enemy.psychicDamage(this@AbilityTelekinesis, damage.type, amount, esper.player, location, knockback) + } + } + + + + } + } + private fun removetnt() { + tnt?.run { + + remove() + tnt = null + } + } + override fun onCast(event: PlayerEvent, action: WandAction, target: Any?) { + val concept = concept + val result = test() + + + if(isskillon == 0) { + playerdt = 0.0 + psychic.consumeMana(concept.cost) + durationTime = concept.durationTime + isskillon = 1 + fakeEntity!!.isVisible = true + if (esper.getAttribute(EsperAttribute.MANA) < 50) { + psychic.consumeMana(-(concept.cost)) + manafifty = 1 + } + } + else if(isskillon == 1) { + esper.player.sendActionBar("펑!") + tnt = TNT(tntloc()) + destroy() + cooldownTime = concept.cooldownTime + fakeEntity!!.isVisible = false + isskillon = 0 + if (manafifty == 1){ + psychic.consumeMana(concept.cost) + manafifty = 0 + } + } + + + } + + + + private fun tntloc(): Location { + return esper.player.eyeLocation.apply { + add(direction.multiply(playerdt)) + } + } + + + inner class TNT(location: Location) { + private val stand: FakeEntity + private val tnt: FakeEntity + + init { + val psychic = psychic + stand = psychic.spawnFakeEntity(location, ArmorStand::class.java).apply { + updateMetadata { + isMarker = true + isInvisible = true + } + } + tnt = psychic.spawnFakeEntity(location, TNTPrimed::class.java).apply { + updateMetadata { + fuseTicks = 1 + } + } + stand.addPassenger(tnt) + } + + fun onUpdate(location: Location) { + stand.moveTo(location) + location.y += 0.9 + + val maxFuseDistance = 5.0 + val durationTime = 1L + val maxDurationTime = 1L + val r = (durationTime.toDouble() / maxDurationTime.toDouble()) + + location.y += r * maxFuseDistance + location.world.spawnParticle(Particle.FLAME, location, 1, 0.0, 0.0, 0.0, 0.025, null, true) + } + + fun remove() { + tnt.remove() + stand.remove() + } + } + @EventHandler(ignoreCancelled = true) + fun onEntityDamage(event: EntityDamageEvent) { + if (durationTime > 0L) { + esper.player.sendActionBar("피격당했습니다!") + cooldownTime = concept.cancelcooltime * 1000L + tnt = TNT(tntloc()) + removetnt() + fakeEntity!!.isVisible = false + isskillon = 0 + } + } + + +} diff --git a/psychics-abilities/ability-telekinesis/src/main/resources/ability.yml b/psychics-abilities/ability-telekinesis/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-telekinesis/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-abilities/ability-withertransform/gradle.properties b/psychics-abilities/ability-withertransform/gradle.properties new file mode 100644 index 00000000..27668fde --- /dev/null +++ b/psychics-abilities/ability-withertransform/gradle.properties @@ -0,0 +1,2 @@ +group=io.github.sincostan1122 +author=sincostan1122 diff --git a/psychics-abilities/ability-withertransform/src/main/kotlin/io/github/sincostan1122/psychics/ability/withertransform/AbilityWithertransform.kt b/psychics-abilities/ability-withertransform/src/main/kotlin/io/github/sincostan1122/psychics/ability/withertransform/AbilityWithertransform.kt new file mode 100644 index 00000000..eac88ca6 --- /dev/null +++ b/psychics-abilities/ability-withertransform/src/main/kotlin/io/github/sincostan1122/psychics/ability/withertransform/AbilityWithertransform.kt @@ -0,0 +1,463 @@ +package io.github.sincostan1122.psychics.ability.withertransform + +import io.github.monun.psychics.* +import io.github.monun.psychics.attribute.EsperAttribute +import io.github.monun.psychics.attribute.EsperStatistic +import io.github.monun.psychics.damage.Damage +import io.github.monun.psychics.damage.DamageType +import io.github.monun.psychics.damage.psychicDamage +import io.github.monun.psychics.tooltip.TooltipBuilder +import io.github.monun.psychics.util.TargetFilter +import io.github.monun.tap.config.Config +import io.github.monun.tap.config.Name +import io.github.monun.tap.event.EntityProvider +import io.github.monun.tap.event.TargetEntity +import io.github.monun.tap.fake.FakeEntity +import io.github.monun.tap.fake.Movement +import io.github.monun.tap.fake.Trail +import io.github.monun.tap.math.normalizeAndLength +import net.kyori.adventure.text.Component.text +import net.kyori.adventure.text.format.NamedTextColor +import net.kyori.adventure.text.format.TextDecoration +import org.bukkit.* +import org.bukkit.entity.* +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.block.Action +import org.bukkit.event.entity.EntityDamageEvent +import org.bukkit.event.entity.EntityDeathEvent +import org.bukkit.event.player.PlayerEvent +import org.bukkit.event.player.PlayerInteractEvent +import org.bukkit.event.player.PlayerVelocityEvent +import org.bukkit.inventory.ItemStack +import org.bukkit.potion.PotionEffect +import org.bukkit.potion.PotionEffectType +import org.bukkit.util.BoundingBox +import kotlin.math.max + + +@Name("Withertransform") +class AbilityConceptWithertransform : AbilityConcept() { + + @Config + var skullSpeed = 5.0 + + @Config + var skullSize = 2.0 + + @Config + var witherAm = 1 + + @Config + var witherDuration = 5.0 + + @Config + var transformDuration = 5.0 + + @Config + var explosionDamage = 4.0 + + @Config + var explosionRange = 7.0 + + @Config + var explosionRange2 = 3.0 + + @Config + var healthPlusAM = 25 + + @Config + var requireSoul = 10 + + @Config + var durationPlus = 3000 + + init { + type = AbilityType.ACTIVE + range = 128.0 + durationTime = 15000L + cooldownTime = 1500L + wand = ItemStack(Material.WITHER_ROSE) + damage = Damage.of(DamageType.BLAST, EsperStatistic.of(EsperAttribute.ATTACK_DAMAGE to 5.0)) + displayName = "위더 강림" + + description = listOf( + text("${ChatColor.GOLD}인간 형상일때:"), + text("시전하기 위해 위더 해골 3개, 소울샌드 4개,"), + text("그리고 영혼 ${requireSoul}개를 제물로 바쳐야 합니다."), + text("웅크린 채로 우클릭하여 바칠 수 있습니다."), + text("시전 시 주변에 폭팔을 일으키며 추가 체력을 얻고."), + text("위더로 변신합니다."), + text(""), + text("${ChatColor.GRAY}위더 형상일때:"), + text("낙하 피해를 받지 않고 비행이 가능해집니다."), + text("위더 장미를 우클릭할 시 위더 해골을 발사합니다."), + text("위더 해골은 폭팔을 일으키고 시듦 효과를 부여합니다."), + text("생명체를 처치할 시 지속시간이 늘어납니다.") + ) + } + override fun onRenderTooltip(tooltip: TooltipBuilder, stats: (EsperStatistic) -> Double) { + tooltip.header( + text().content("폭팔 피해량 ").color(NamedTextColor.RED).decoration(TextDecoration.ITALIC, false) + .append(text().content((explosionDamage * 100.0).toInt().toString())).append(text().content("%")).build() + ) + tooltip.header( + text().content("시듦 LV.").color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, false) + .append(text().content(witherAm.toString())).build() + ) + tooltip.header( + text().content("처치 시 지속시간 증가량 ").color(NamedTextColor.GRAY).decoration(TextDecoration.ITALIC, false) + .append(text().content((durationPlus / 1000).toString())).append(text().content("초")).build() + ) + } +} +class AbilityWithertransform : Ability(), Listener { + private var wither : FakeEntity? = null + private var tnt: TNT? = null + private var withertnt: TNT? = null + private var transformLevel = 0 + private var skull = 0 + private var soulsand = 0 + private var soul = 0 + lateinit var anchoredLoc : Location + override fun onEnable() { + psychic.registerEvents(this) + + val world = esper.player.world + psychic.runTaskTimer({ + var location = esper.player.location + scanCreative() + if(transformLevel == 0) { + esper.player.sendActionBar(text().content("바친 위더 해골:").append(text().content(skull.toString())) + .append(text().content(" ")) + .append(text().content("바친 영혼 모래:").append(text().content(soulsand.toString()))) + .append(text().content(" ")) + .append(text().content("모은 영혼:").append(text().content(soul.toString())))) + if(soulsand == 4 && skull == 3 && soul == concept.requireSoul) { + transformLevel = 1 + } + } + if(transformLevel == 1) { + + esper.player.sendActionBar("당신의 신체에 위더가 강림하려 합니다...") + world.spawnParticle(Particle.SMOKE_NORMAL, location.x, location.y, location.z, 5, 1.0, 1.0, 1.0, 0.0, null, true) + } + if(transformLevel == 2) { + giveEffect() + esper.player.addPotionEffect( + PotionEffect(PotionEffectType.ABSORPTION, 999999999, concept.healthPlusAM, false, false) + ) + + esper.player.teleport(anchoredLoc) + esper.player.sendActionBar("당신의 신체에 위더가 강림하고 있습니다...") + world.spawnParticle(Particle.SMOKE_NORMAL, location.x, location.y, location.z, 20, 1.0, 1.0, 1.0, 0.0, null, true) + wither?.moveTo(esper.player.location) + if(durationTime == 0L) { + tnt = TNT(esper.player.location) + destroy() + durationTime = concept.durationTime + transformLevel = 3 + } + } + if(transformLevel == 3) { + giveEffect() + esper.player.sendActionBar(text().content("본래 모습으로 돌아오기까지 ").append(text().content((durationTime / 1000L).toString())) + .append(text().content("초"))) + world.spawnParticle(Particle.SMOKE_NORMAL, location.x, location.y, location.z, 10, 0.5, 0.5, 0.5, 0.0, null, true) + esper.player.allowFlight = true + esper.player.isFlying = true + wither?.moveTo(esper.player.location) + if(durationTime == 0L) { + wither?.remove() + wither = null + esper.player.allowFlight = false + esper.player.isFlying = false + scanCreative() + transformLevel = 0 + esper.player.removePotionEffect(PotionEffectType.ABSORPTION) + } + } + + }, 0L, 1L) + } + override fun onDisable() { + transformLevel = 0 + skull = 0 + soulsand = 0 + soul = 0 + val player = esper.player + + player.allowFlight = false + player.isFlying = false + scanCreative() + wither?.remove() + wither = null + } + + fun scanCreative() { + if(esper.player.gameMode == GameMode.CREATIVE) { + esper.player.allowFlight = true + } + } + fun giveEffect() { + esper.player.addPotionEffects( + listOf( + PotionEffect( + PotionEffectType.INVISIBILITY, + 10, + 1, + false, + false + ), + PotionEffect( + PotionEffectType.WEAKNESS, + 10, + 255, + false, + false + ) + ) + + ) + } + + @EventHandler + fun onPlayerInteract(event: PlayerInteractEvent) { + val action = event.action + + if (action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) { + if(transformLevel == 0 && esper.player.isSneaking) { + event.item?.let { item -> + if (item.type == Material.SOUL_SAND) { + if(soulsand < 4) { + val player = esper.player + if(cooldownTime > 0L) return + cooldownTime = 80L + + if (player.gameMode != GameMode.CREATIVE) item.amount-- + + soulsand++ + var location = player.location + esper.player.world.spawnParticle(Particle.CLOUD, location.x, location.y, location.z, 5, 1.0, 1.0, 1.0, 0.0, null, true) + esper.player.eyeLocation.world.playSound(esper.player.eyeLocation, Sound.ENTITY_BLAZE_AMBIENT , 1.0F, 0.1F) + } + + } + if (item.type == Material.WITHER_SKELETON_SKULL) { + if(skull < 3) { + if(cooldownTime > 0L) return + cooldownTime = 80L + val player = esper.player + + + if (player.gameMode != GameMode.CREATIVE) item.amount-- + + skull++ + var location = player.location + esper.player.world.spawnParticle(Particle.CLOUD, location.x, location.y, location.z, 5, 1.0, 1.0, 1.0, 0.0, null, true) + esper.player.eyeLocation.world.playSound(esper.player.eyeLocation, Sound.ENTITY_BLAZE_AMBIENT , 1.0F, 0.1F) + } + + } + } + } + + + event.item?.let { item -> + if (item.type == Material.WITHER_ROSE) { + val player = esper.player + if(transformLevel == 1) { + soulsand = 0 + skull = 0 + soul = 0 + wither = this.psychic.spawnFakeEntity(player.location, Wither::class.java).apply { + updateMetadata { + setAI(false) + + } + } + anchoredLoc = esper.player.location + durationTime = (concept.transformDuration * 1000).toLong() + transformLevel = 2 + esper.player.eyeLocation.world.playSound(esper.player.eyeLocation, Sound.ENTITY_WITHER_SPAWN , 1.0F, 0.1F) + } + if(transformLevel == 3) { + if(cooldownTime > 0L) return + cooldownTime = concept.cooldownTime + val location = player.eyeLocation + val projectile = SkullProjectile().apply { + skull = + this@AbilityWithertransform.psychic.spawnFakeEntity(location, ArmorStand::class.java).apply { + updateMetadata { + isVisible = false + } + updateEquipment { + helmet = ItemStack(Material.WITHER_SKELETON_SKULL) + } + } + } + cooldownTime = concept.cooldownTime + psychic.launchProjectile(location, projectile) + projectile.velocity = location.direction.multiply(concept.skullSpeed) + + val loc = player.location + loc.world.playSound(loc, Sound.ENTITY_WITHER_SHOOT, 1.0F, 0.1F) + } + } + } + + + } + } + + @EventHandler + @TargetEntity(EntityProvider.EntityDeath.Killer::class) + fun onKill(event: EntityDeathEvent) { + if(transformLevel == 0) { + if(soul < concept.requireSoul) { + esper.player.location.world.spawnParticle(Particle.SOUL, event.entity.location, 5, 0.5, 0.5, 0.5, 0.0, null, true) + soul++ + } + } + if (transformLevel == 3) { + esper.player.location.world.spawnParticle(Particle.SOUL, event.entity.location, 5, 0.5, 0.5, 0.5, 0.0, null, true) + durationTime += concept.durationPlus + } + } + + @EventHandler(ignoreCancelled = true) + fun onVelocity(event: PlayerVelocityEvent) { + if (transformLevel >= 2) { + event.isCancelled = true + } + + } + private fun destroy() { + tnt?.run { + remove() + tnt = null + + val location = esper.player.location + val world = location.world + + val r = max(1.0, concept.explosionRange- 2.0) + world.spawnParticle(Particle.EXPLOSION_HUGE, location, (r * r).toInt(), r, r, r, 0.0, null, true) + world.playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 2.0F, 1.0F) + + val damage = concept.damage!! + var amount = esper.getStatistic(damage.stats) + + + val knockback = concept.knockback + + val box = BoundingBox.of(location, r, r, r) + world.getNearbyEntities(box, TargetFilter(esper.player)).forEach { enemy -> + if (enemy is LivingEntity) { + enemy.psychicDamage(this@AbilityWithertransform, damage.type, amount * concept.explosionDamage, esper.player, location, knockback) + } + } + + + + } + } + + private fun witherdestroy(location : Location) { + withertnt?.run { + remove() + withertnt = null + + val world = location.world + + val r = max(1.0, concept.explosionRange2- 2.0) + world.spawnParticle(Particle.EXPLOSION_HUGE, location, (r * r).toInt(), r, r, r, 0.0, null, true) + world.playSound(location, Sound.ENTITY_GENERIC_EXPLODE, 2.0F, 1.0F) + + val damage = concept.damage!! + var amount = esper.getStatistic(damage.stats) + + + val knockback = concept.knockback + + val box = BoundingBox.of(location, r, r, r) + world.getNearbyEntities(box, TargetFilter(esper.player)).forEach { enemy -> + if (enemy is LivingEntity) { + enemy.psychicDamage(this@AbilityWithertransform, damage.type, amount, esper.player, location, knockback) + enemy.addPotionEffect( + PotionEffect(PotionEffectType.WITHER, + concept.witherDuration.toInt() * 20, concept.witherAm, false, false) + ) + + } + } + + + + } + } + + inner class TNT(location: Location) { + private val stand: FakeEntity + private val tnt: FakeEntity + + init { + val psychic = psychic + stand = psychic.spawnFakeEntity(location, ArmorStand::class.java).apply { + updateMetadata { + isMarker = true + isInvisible = true + } + } + tnt = psychic.spawnFakeEntity(location, TNTPrimed::class.java).apply { + updateMetadata { + fuseTicks = 1 + } + } + stand.addPassenger(tnt) + } + + fun remove() { + tnt.remove() + stand.remove() + } + } + inner class SkullProjectile : PsychicProjectile(1200, concept.range) { + lateinit var skull: FakeEntity + + override fun onMove(movement: Movement) { + skull.moveTo(movement.to.clone().apply { y -= 1.62 }) + } + + override fun onTrail(trail: Trail) { + trail.velocity?.let { v -> + val length = v.normalizeAndLength() + + if (length > 0.0) { + val start = trail.from + val world = start.world + + world.rayTrace( + start, v, length, FluidCollisionMode.NEVER, true, concept.skullSize / 2.0, + TargetFilter(esper.player) + )?.let { result -> + remove() + + val hitLocation = result.hitPosition.toLocation(world) + + result.hitEntity?.let { entity -> + if (entity is LivingEntity) { + entity.psychicDamage() + } + } + withertnt = TNT(hitLocation) + witherdestroy(hitLocation) + } + } + } + } + + override fun onRemove() { + skull.remove() + } + } +} diff --git a/psychics-abilities/ability-withertransform/src/main/resources/ability.yml b/psychics-abilities/ability-withertransform/src/main/resources/ability.yml new file mode 100644 index 00000000..4a3bc10a --- /dev/null +++ b/psychics-abilities/ability-withertransform/src/main/resources/ability.yml @@ -0,0 +1,5 @@ +group: ${group} +name: ${projectName} +version: ${version} +main: ${group}.psychics.ability.${packageName}.Ability${abilityName.capitalize()} +author: $author \ No newline at end of file diff --git a/psychics-core/build.gradle.kts b/psychics-core/build.gradle.kts index 271aebd0..87fd05af 100644 --- a/psychics-core/build.gradle.kts +++ b/psychics-core/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } dependencies { - implementation("io.github.monun:kommand-api:2.6.6") + implementation("io.github.monun:kommand-api:2.8.0") implementation("io.github.monun:invfx-api:3.0.1") }