잡다한 개발/마크플러그인

마크 플러그인 만들기 (#2)

오잎 클로버 2021. 8. 31. 17:00
728x90

RPG 직업들은 현재 기획한 것으로는 파이터, 머스킷티어, 버서커, 마법사, 암살자로 

직업들은 각각 액티브형 능력 하나와 패시브형 능력 하나를 구현할 것입니다.

현재 버서커의 광전사 능력(패시브)과 암살자의 도주 능력(패시브)는 krapoi의 티스토리를 확인하여 코드와 더불어

어떤 형식으로 작동하는 지를 확인할 수 있습니다.

 

제가 구현한 기능들은 마법사의 라이트닝(액티브)능력과 머스킷티어의 헤드샷(패시브)를 구현하였습니다.

먼저 마법사의 라이트닝입니다.

Wizard라는 클래스를 만들고 플러그인에 사용될 클래스들은 대부분은 Listener를 사용하여 이벤트를 받습니다.

implements Listener를 하고, 

받을 이벤트를 @EventHandler를 합니다.

마법사는 현재 개발해나가는 과정이기에 막대기를 사용하여 능력을 발동시킬 것입니다.

마법사의 패시브 능력 역시, 막대기를 사용할 것이기에 이벤트를 하나로 묶습니다.

 

이벤트는 PlayerInteractEvent으로 플레이어(유저)가 상호작용을 할 때 발생하는 이벤트입니다.

public class Wizard implements Listener {
  
    @EventHandler
    public void ability(PlayerInteractEvent e) {
        
    }
}

그런다음 변수를 지정합니다.

Player player = e.getPlayer();
Action action = e.getAction();

e.getPlayer메소드는 이벤트가 발생하였을 때, 어떤 플레이어에 의해 발생했는 지를 확인하는 메소드이고,

e.getAction메소드는 이벤트가 발생하였을 때, 어떤 액션(상호작용)이 발생하였는 지 확인하는 메소드입니다.

 

마법사의 라이트닝은 막대기를 든 상태에서 좌클릭을 하면 번개가 치도록 하였습니다.

또, 사거리가 최대이어서는 안되기에 최대 사거리를 10으로 정하였습니다.

if ((action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK) && player.getInventory().getItemInMainHand().getType() == Material.STICK) {
    player.getWorld().strikeLightning(player.getTargetBlock(null, 10).getLocation());
}

좌클릭의 액션 종류는 2가지가 있습니다.

블럭을 좌클릭하였을 때와 허공에 좌클릭 하였을 때가 있는 데, 그냥 통합적으로 좌클릭으로 만들고자 둘 중 하나만 행동하더라도 작동하도록 하였습니다.

또, 플레이어의 현재 손에 어떤 타입이 있는 지를 확인하기위해

player.getInventory().getItemInMainHand().getType() == Material.STICK

를 사용하였습니다.

번개는 strikeLightning과 spawnEntity를 통해 사용이 가능하나 비교적 코드 길이를 줄이고 인자값을 최대한으로 줄일 수 있는 strikeLightning을 사용하였습니다.

 

player.getTargetBlock

메소드는 특정 범위를 설정하여 해당 조건에 맞는 블럭까지만 타겟으로 설정하는 메소드입니다.

null값은 HashSet<Block>으로 인자값을 보내는 것이 보통이지만, 따로 지정하지않고 모든 블럭을 전부 인식하고자 null값으로 지정하였습니다.

※단, null값으로 할 시, log창에서 수 많은 에러를 볼 수 있습니다.

2번째 인자값은 플레이어를 기준으로 x,y,z 정사면체로 할 길이입니다.

예) null, 10 → 모든 블럭으로 타겟으로 하되, 길이가 10인 정사면체 내에서만 선택가능하도록 함

해당 블럭 위치에 번개를 떨어뜨리도록 하였습니다.

마법사 라이트닝 이벤트의 전체 코드는 아래와 같습니다.

@EventHandler
public void ability(PlayerInteractEvent e) {
    Player player = e.getPlayer();
    Action action = e.getAction();

    if ((action == Action.LEFT_CLICK_AIR || action == Action.LEFT_CLICK_BLOCK) && player.getInventory().getItemInMainHand().getType() == Material.STICK) {
        player.getWorld().strikeLightning(player.getTargetBlock(null, 10).getLocation());
    }
}

막대기를 들고 좌클릭을 하면 범위 내에서 바라보는 방향으로 번개를 떨어뜨림

 

그다음은 머스킷티어의 헤드샷 기능입니다.

헤드샷 기능은 적을 4번 공격할 때마다 기본 공격력 * 2 피해를 주는 기능입니다.

해당 기능을 테스트하기위해 스스로에게 4번 화살을 맞춰서 공격력이 2배 들어오는 지를 테스트하였습니다.

반칸에서 한칸 가량으로 피해를 입지만 4번째 화살에서는 한 칸의 피해를 입음

RPG 플러그인 특성상 많은 유저들이 같은 직업을 가질 수 있기때문에 능력을 만일 사용한다면 각각의 쿨타임등 계산하여줄 변수가 필요하기에 HashMap을 사용하였습니다.

public static HashMap<UUID, Integer> shotCount = new HashMap<>();

UUID는 고유 코드를 키값으로 하였습니다.

Integer는 4번째마다 피해량을 2배로 하여야하기에 밸류값으로 하였습니다.

 

이벤트는 EntityDamageByEntityEvent 이벤트로 하였습니다.

어떠한 엔티티로 공격을 하였는 지, 피격당한 엔티티는 무엇인지등을 변수로 사용하였습니다.

먼저 화살은 엔티티입니다.

그렇기때문에 위 이벤트로 인해 화살로 공격당한다면 화살에게 공격받은 것입니다.

Entity tool = e.getDamager();

그리고 화살로 피격받은 엔티티는 플레이어(유저)일때에만 적용하였습니다.

if (e.getEntity() instanceof Player)

하지만 화살의 고유한 코드로 저장을 한다면 랜덤하게 해당 고유한 코드를 가진 화살을 발사하였을 때에만 저장되므로

화살을 발사하여 맞춘 공격자가 누군지를 알아야합니다.

((Arrow) tool).getShooter() instanceof Player

위 조건을 사용하여 플레이어만 인식하도록 합니다.

그런다음 shotCount라는 HashMap에 공격자의 고유 코드가 있고, 해당 키를 한 밸류값이 3미만일때에만 작동합니다.

if (shotCount.containsKey(shooter.getUniqueId()) && shotCount.get(shooter.getUniqueId()) < 3) {
    shotCount.put(shooter.getUniqueId(), shotCount.get(shooter.getUniqueId()) + 1);
}

그렇지않다면 초기화 및 피해량을 2배로 지정합니다.

하지만 초기화 (즉, 첫 발)째에는 4번째가 아닌데에도 불구하고 피해량이 2배로 적용되기에 

조건을 추가합니다.

if (shotCount.get(shooter.getUniqueId()) > 3)

위 조건이 true라면 피해자에게 피해량 2배를 입힙니다.

위 조건과는 별개로 shotCount를 초기화합니다.

 

헤드샷의 전체 이벤트 코드는 아래와 같습니다.

public static HashMap<UUID, Integer> shotCount = new HashMap<>();

@EventHandler
public void headShot(EntityDamageByEntityEvent e) {
    Entity tool = e.getDamager();
    if (tool instanceof Arrow) {
        if (e.getEntity() instanceof Player) {
            if (((Arrow) tool).getShooter() instanceof Player) {
                Player shooter = (Player) ((Arrow) tool).getShooter();
                if (shooter != null) {
                    if (shotCount.containsKey(shooter.getUniqueId()) && shotCount.get(shooter.getUniqueId()) < 3) {
                        shotCount.put(shooter.getUniqueId(), shotCount.get(shooter.getUniqueId()) + 1);
                    }
                    else {
                        if (shotCount.get(shooter.getUniqueId()) > 3)
                            e.setDamage(e.getDamage() * 2);
                        shotCount.put(shooter.getUniqueId(), 0);
                    }
                }
            }
        }
    }
}

 

'잡다한 개발 > 마크플러그인' 카테고리의 다른 글

마크 가챠 1편  (0) 2021.11.20
마크 가챠 0편  (0) 2021.11.19
마크 플러그인 만들기 (#3)  (0) 2021.09.01
마크 플러그인 만들기 (#1)  (0) 2021.08.30
마크 플러그인 만들기 (#0)  (0) 2021.08.26