Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Помогите Убийство игрока при нулевом уровне (каждую минуту уровень уменьшается)

Bars

Старожил
Девелопер
Пользователь
Баллы
173
Есть плагин, который превращает уровень опыта игрока в уровень жажды. Изначально у игрока 20-й уровень. Затем каждую минуту уровень становится на единицу меньше.

Сразу же при достижении нулевого уровня у игрока должно быстро уменьшаться здоровье (2/20 сердца в секунду). Мгновенная смерть тут не подходит, игроку нужно дать время попить. Одним из примеров такой медленной смерти является удушье под водой (когда заканчивается "воздух в лёгких").

Уменьшение уровня каждую минуту:
Код:
getServer().getScheduler().runTaskTimer(this, new ThirstTask(this), 1L, getConfig().getLong("player.water-decay-delay"));
Код:
getServer().getScheduler().runTaskTimer(this, new ThirstTask(this), 1L, getConfig().getLong("player.water-decay-delay"));

Код:
    @Override
    public void run() {
        for (Player p : Bukkit.getOnlinePlayers()) {
            if (p.getGameMode() != GameMode.CREATIVE && omz.isSpawned(p.getLocation())) {
                int lvl = p.getLevel();
                if (lvl > 1) {
                    p.setLevel(lvl - 1);
                    PlayerThirstChangeEvent ptce = new PlayerThirstChangeEvent(p, lvl + 1, lvl);
                    plugin.getServer().getPluginManager().callEvent(ptce);
                } else {
                    p.setLevel(0);
                    p.damage(2);
                    PlayerThirstChangeEvent ptce = new PlayerThirstChangeEvent(p, lvl, lvl);
                    plugin.getServer().getPluginManager().callEvent(ptce);
                }
            }
        }
    }
 
Даже циклом пробовал (типа такого):
Код:
while (здоровье_игрока > 0) {
    try {
        p.damage(2);
        wait(1000);
    } catch (...) {  }
}
 
Ах, да :)
Дело в том, что у игрока снимается только одно сердце и всё. Даже такой цикл не работает (игрок не получает урон дальше, через секунду). У него только один раз снимается сердце, а надо, чтобы они снимались постоянно (одно сердце в секунду), пока игрок не умрёт.
 
Что за интересный метод isSpawned()
 
Что за интересный метод isSpawned()
Это мой :)
Проверяет, не в бункере ли игрок (т.е. заспавнен ли в мире).
Код:
    public boolean isSpawned(Location loc) {
        Plugin worldGuard = getServer().getPluginManager().getPlugin("WorldGuard");
        WorldGuardPlugin wg = (WorldGuardPlugin) worldGuard;
        RegionManager manager = wg.getRegionManager(loc.getWorld());
        Vector v = toVector(loc);
        ApplicableRegionSet set = manager.getApplicableRegions(v);
        for (ProtectedRegion each : set){
            if (each.getId().equals("spawn")) return false;
        }
        return true;
    }
 
В чем проблема отдебагать плагин? Подключиться отладчиком к серверу, поставить точки останова и контролировать метод, где отнимается здоровье.

То, что написано в шапке - на первый взгляд нормально и должно работать.

Т.е. банально нужно убедиться, что ThirstTask выполняется каждую секунду.
 
В чем проблема отдебагать плагин? Подключиться отладчиком к серверу, поставить точки останова и контролировать метод, где отнимается здоровье.

То, что написано в шапке - на первый взгляд нормально и должно работать.

Т.е. банально нужно убедиться, что ThirstTask выполняется каждую секунду.
Да нет же, он выполняется каждую минуту, иначе через 20 секунд игрок умер бы от жажды. При выпивании воды жажда становится 20. Сейчас перепробую это:
Код:
                int lvl = p.getLevel();
                if (lvl > 1) {
                    p.setLevel(lvl - 1);
                } else {
                    p.setLevel(0);
                    try {
                        while (p.getHealth() > 0) {
                            p.damage(2);
                            wait(1000);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
Если у игрока жажда 2, то отнимаем и становится один. Через минуту условие ложно, мы ставим ему нулевую жажду и сразу же начинаем медленно убивать (по сердцу в секунду). Циклом снимаем сердце и ждём секунду, покуда у игрока здоровье больше нуля.
Даже так снялось сердце только один раз. Цикл работать не хочет.
 
Нужно было указывать, что твой цикл выполняется раз в минут.
"player.water-decay-delay" - я не нашел, что там у тебя за значение стоит.
Все очень просто - тебе нужен отдельные шедуллер, который бы каждую секунду отнимал бы у игрока сердечков, а сейчас - с тем кодом, которые наверху - отниматься будет каждую минуту.
Код:
 while (p.getHealth() > 0) {
                            p.damage(2);
                            wait(1000);
                        }

С подобной ерундой вообще не должно ничего выходить, никаких конструкций wait быть не должно. Здесь должен быть запуск другого шедуллера, который бы каждую секунду отнимал бы у данного игрока здоровья, как только игрок умирает или уровень меняется - этот шедуллер должен прекратить свою работу.
 
Какой запускать шедулер и какой функцией его остановить? Для вычитания опыта runTaskTimer(arg1, arg2, arg3, arg4).
Нужно было указывать, что твой цикл выполняется раз в минут.
"player.water-decay-delay" - я не нашел, что там у тебя за значение стоит.
Да, извиняюсь (стоит 1200).
 
Какой запускать шедулер и какой функцией его остановить? Для вычитания опыта runTaskTimer(arg1, arg2, arg3, arg4).

Да, извиняюсь (стоит 1200).
При создании получаешь id поток, его можно установить cancelSheduller что-то такое. Читай документацию, там есть эти методы.
 
При создании получаешь id поток, его можно установить cancelSheduller что-то такое. Читай документацию, там есть эти методы.
Что-то я не совсем понимаю. Как, например, остановить шедулер из события EntityDeathEvent?
 
Что-то я не совсем понимаю. Как, например, остановить шедулер из события EntityDeathEvent?
Записываешь куда нибудь ид шедулера и при событии делаешь Bukkit.getScheduler().cancelTask(id)
 
HashMap подойдёт? И чем отличается асинхронный шедулер от синхронного?
Синхронный выполняется в главном потоке, асинхронный в отдельном. Хешмап подойдёт
 

Поделиться этой страницей

Назад
Верх