1. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

Тема в разделе "Разработка плагинов для новичков", создана пользователем Bars, 7 дек 2013.

  1. Автор темы
    Bars

    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);
                    }
                }
            }
        }
     
  2. Автор темы
    Bars

    Bars Старожил Девелопер Пользователь

    Баллы:
    173
    Даже циклом пробовал (типа такого):
    Код:
    while (здоровье_игрока > 0) {
        try {
            p.damage(2);
            wait(1000);
        } catch (...) {  }
    }
     
  3. Den_Abr

    Den_Abr Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    Den_Abr
    Имя в Minecraft:
    Den_Abr
    А в чем вопрос?
     
  4. Автор темы
    Bars

    Bars Старожил Девелопер Пользователь

    Баллы:
    173
    Ах, да :)
    Дело в том, что у игрока снимается только одно сердце и всё. Даже такой цикл не работает (игрок не получает урон дальше, через секунду). У него только один раз снимается сердце, а надо, чтобы они снимались постоянно (одно сердце в секунду), пока игрок не умрёт.
     
  5. Den_Abr

    Den_Abr Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    Den_Abr
    Имя в Minecraft:
    Den_Abr
    Что за интересный метод isSpawned()
     
  6. Автор темы
    Bars

    Bars Старожил Девелопер Пользователь

    Баллы:
    173
    Это мой :)
    Проверяет, не в бункере ли игрок (т.е. заспавнен ли в мире).
    Код:
        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;
        }
     
  7. ptnk

    ptnk Старожил Пользователь

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

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

    Т.е. банально нужно убедиться, что ThirstTask выполняется каждую секунду.
     
  8. Автор темы
    Bars

    Bars Старожил Девелопер Пользователь

    Баллы:
    173
    Да нет же, он выполняется каждую минуту, иначе через 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, то отнимаем и становится один. Через минуту условие ложно, мы ставим ему нулевую жажду и сразу же начинаем медленно убивать (по сердцу в секунду). Циклом снимаем сердце и ждём секунду, покуда у игрока здоровье больше нуля.
    Даже так снялось сердце только один раз. Цикл работать не хочет.
     
  9. ptnk

    ptnk Старожил Пользователь

    Баллы:
    173
    Нужно было указывать, что твой цикл выполняется раз в минут.
    "player.water-decay-delay" - я не нашел, что там у тебя за значение стоит.
    Все очень просто - тебе нужен отдельные шедуллер, который бы каждую секунду отнимал бы у игрока сердечков, а сейчас - с тем кодом, которые наверху - отниматься будет каждую минуту.
    Код:
     while (p.getHealth() > 0) {
                                p.damage(2);
                                wait(1000);
                            }
    С подобной ерундой вообще не должно ничего выходить, никаких конструкций wait быть не должно. Здесь должен быть запуск другого шедуллера, который бы каждую секунду отнимал бы у данного игрока здоровья, как только игрок умирает или уровень меняется - этот шедуллер должен прекратить свою работу.
     
    Bars нравится это.
  10. Автор темы
    Bars

    Bars Старожил Девелопер Пользователь

    Баллы:
    173
    Какой запускать шедулер и какой функцией его остановить? Для вычитания опыта runTaskTimer(arg1, arg2, arg3, arg4).
    Да, извиняюсь (стоит 1200).
     
    GJEvolution и Сникерсни нравится это.
  11. ptnk

    ptnk Старожил Пользователь

    Баллы:
    173
    При создании получаешь id поток, его можно установить cancelSheduller что-то такое. Читай документацию, там есть эти методы.
     
    Bars нравится это.
  12. Автор темы
    Bars

    Bars Старожил Девелопер Пользователь

    Баллы:
    173
    Что-то я не совсем понимаю. Как, например, остановить шедулер из события EntityDeathEvent?
     
  13. Den_Abr

    Den_Abr Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    Den_Abr
    Имя в Minecraft:
    Den_Abr
    Записываешь куда нибудь ид шедулера и при событии делаешь Bukkit.getScheduler().cancelTask(id)
     
    ВремяПриключений и Bars нравится это.
  14. Автор темы
    Bars

    Bars Старожил Девелопер Пользователь

    Баллы:
    173
    HashMap подойдёт? И чем отличается асинхронный шедулер от синхронного?
     
  15. Den_Abr

    Den_Abr Старожил Девелопер Пользователь

    Баллы:
    173
    Skype:
    Den_Abr
    Имя в Minecraft:
    Den_Abr
    Синхронный выполняется в главном потоке, асинхронный в отдельном. Хешмап подойдёт
     

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