ArrowSpeed - скорость полета стрелы.

Hitcher

Знаменитый
Местный
Сообщения
206
Розыгрыши
0
Репутация
1
Реакции
21
Баллы
1 280
Хроники
  1. Interlude
Исходники
Присутствуют
Сборка
acis 409
Здравствуйте!)


добиться идеальной визуальной синхронизации между анимацией стрелы (ее "появлением" и "попаданием" в цель на клиенте) и моментом нанесения урона на сервере.
Опытным путем, методом научного тыка, удалось произвести калибровку-синхронизацию момента попадания стрелы в цель и списания урона на сервере. Выявив закономерности в которых *расстояние до цели* ровняется = *итоговой задержке полета стрелы в мс.* но только в среднем диапазоне расстояний.
Общее расстояние было разделено на три диапазона.
Включил соски. Добился визуальной синхронизации. Соски должны загораться идентично синхронно: Мгновение попадания стрелы в цель равно = Мгновению наполнения оружия новой силой души.
Я не знаю есть ли некий ресив пакет визуального клатча от клиента при попадании стрелы, может можно было сделать проще?)
Я не знаю не засамонит ли моя очередная ии разработка новых оверхедов с дедпулами, дредпулями или как там эти матюки называются у разработчиков!?)
Следует ли проверять условия после задержки ThreadPool: цель может умереть, выйти из радиуса, исчезнуть, критануть.
Обработка ошибок? Обернуть логику в try catch чтобы сервер не падал из-за исключений?

Но чисто такую математику я люблю, не подходит 1 нажал 2 не 3 так 4 и так далее) чуть ошибся, не страшно, ии подровняет. Если нет, - покажите фотографию идеального безошибочного человека!) ну ладно, Aristo не считается, на такую икону - грех не помолиться!

Видосик:

Прошу Вас:
Java:
CreatureAttack.java

private HitHolder[] doAttackHitByBow(Creature target, Weapon weapon, int sAtk, boolean isSoulshot)
    {
        _actor.reduceArrowCount();
        _actor.getStatus().reduceMp(_actor.getActiveWeaponItem().getMpConsume());

        final HitHolder[] hits = new HitHolder[]
                {
                        getHitHolder(target, isSoulshot, false)
                };

        // Расчет задержки перезарядки лука
        int reuse = weapon.getReuseDelay();
        if (reuse != 0)
            reuse = (reuse * 345) / _actor.getStatus().getPAtkSpd();

        // Расчет расстояния до цели
        final double distance = _actor.distance3D(target);
        final double maxAttackRange = _actor.getStatus().getPhysicalAttackRange();

        // Распределение дистанции:
        // Короткая: до 130.0
        // Средняя: от 130.0 до 542.37
        // Дальняя: от 542.37 до максимума
        final double MEDIUM_RANGE_START = 130.0;
        final double FAR_RANGE_START = 542.37;

        // Базовые скорости полета стрелы
        // Скорость измеряется в (игровых_единицах / миллисекунду). Чем выше значение, тем быстрее стрела.
        double baseArrowSpeed;

        String rangeDescription; // Для логгирования

        if (distance < MEDIUM_RANGE_START) // Расстояние до 130.0 (короткая)
        {
            // Цель вблизи. Стрела должна попадать очень быстро.
            baseArrowSpeed = 20.0; // 20 единиц/мс.
            rangeDescription = "короткой (до 130.0)";
        }
        else if (distance < FAR_RANGE_START) // Расстояние от 130.0 до 542.37 (средняя)
        {
            // Цель на средней дистанции.
            baseArrowSpeed = 1.0; // единиц/мс.
            rangeDescription = "средней (от 130.0 до 542.37)";
        }
        else // Расстояние от 542.37 до maxAttackRange (дальняя)
        {
            // Цель на дальней дистанции.
            baseArrowSpeed = 2.5; // единиц/мс.
            rangeDescription = "дальней (от 542.37 до максимума)";
        }

        // Расчет текущей скорости стрелы (базовая скорость)
        double currentArrowSpeed = baseArrowSpeed;

        // Расчет задержки полета стрелы на основе дистанции и текущей скорости
        int flightDelay = (int) (distance / currentArrowSpeed);

        // Убедимся, что задержка не опускается ниже минимального значения (например, 1 мс).
        flightDelay = Math.max(1, flightDelay);


        System.out.println(String.format("\uD83C\uDFAFЦель %s на %s дистанции \uD83C\uDFAF(%.2f / %.2f). \uD83C\uDFF9Базовая скорость: %.2f ед/мс. Итоговая скорость: %.2f ед/мс. ⏳Итоговая задержка полета: %d мс (PAtkSpd: %d).",
                target.getName(), rangeDescription, distance, maxAttackRange, baseArrowSpeed, currentArrowSpeed, flightDelay, _actor.getStatus().getPAtkSpd()));


        setAttackTask(hits, weapon, reuse, isSoulshot);

        // Запуск таймера для нанесения урона с учетом задержки полета стрелы
        _attackTask = ThreadPool.schedule(this::onHitTimer, sAtk + flightDelay);

        if (_actor instanceof Player)
        {
            _actor.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.GETTING_READY_TO_SHOOT_AN_ARROW));
            // Для отображения полосы подготовки (setup gauge) также нужно учитывать общую задержку
            _actor.sendPacket(new SetupGauge(GaugeColor.RED, sAtk + reuse + flightDelay));
        }
        return hits;
    }
 
дедпулами, дредпулями или как там эти матюки называются у разработчиков!?)
дедлоки.
и нет - не засамонит если на сервере будет только не будет луков, которые будут стрелять каждую. Даже самый быстрый лук - имеет откат 1 секунду, так что - все норм.
Следует ли проверять условия после задержки ThreadPool: цель может умереть, выйти из радиуса, исчезнуть, критануть.
Обработка ошибок? Обернуть логику в try catch чтобы сервер не падал из-за исключений?
если хотите учесть вообще все - то нужно учитывать пинг игрока, условно ускорять стрелу / отправку пакета о попадании быстрее, чем это есть на самом деле. Но смысла большого в этом наверное нет, ибо сама стрела летит несколько мс, чего точно не обработать нормально с учетом пинга.
В ПТС есть такой прикол, как докаст. Когда на 70% каста - запускается проверка на возможность видеть цель / effective range от тебя и до цели (не путать с cast range). Могу предположить - тут может быть такая же зависимость. Её реализовать достаточно просто.

Запускаем 2 таска
- первый на 70% натягивания тетевы;
- второй на момент выстрела;
Так мы сможем проверить стоит ли цель все еще в радиусе выстрела или уже убажала достаточно далеко.
Так же нужно бы сделать проверки на общую доступность цели, а то вдруг она в промежутке между 70% и фактическим выстрелом успеет сделать БСОЕ.

Ну если проверки на 70% не подверждаются - отменять вторую таску и говорить "цель убежаль :("
Опытным путем, методом научного тыка, удалось произвести калибровку-синхронизацию момента попадания стрелы в цель и списания урона на сервере. Выявив закономерности в которых *расстояние до цели* ровняется = *итоговой задержке полета стрелы в мс.* но только в среднем диапазоне расстояний.
вообще на ПТС есть такой параметр (как минимум у призываемых самонов) - hit_time_factor и hit_time_factor_skill которые откладывают/ускоряют фактический бродкаст пакета "attack" и "systemmessage" до момента, пока не произойдет анимация у НПС-а.
То-есть кнопка "атака" - сразу же отправить информацию о том что был нанесен урон, а учет первого значения - момент нанесения удара на клиенте отложит/ускорит на Н мс, чтобы соответсвовать анимации.
 
енергия космоса на оперативку и это подтверждено :)
Подтверждаю) Спасибо за интересную статью:
Разработчики иногда думают, что всё в этом мире работает абсолютно предсказуемо. Но тестировщикам и специалистам по QA приходится учитывать физическую реальность. Они знают, что абсолютной предсказуемости не существует.
Более того, за 20 лет жизни моего компьютера, уже второй раз покупаю pci планку для Lan. По причине второго удара молнии.) Главное все остается целым, но горит именно Lan.) Ну почти все целое, так же возник баг который все время перезапускает систему вместо выключения. Хотя баг замечен только на операционных системах выше win 7. На семерке все стабильно)
------------------------------------------------------------
Хорошая практика:
В ПТС есть такой прикол, как докаст. Когда на 70% каста - запускается проверка на возможность видеть цель / effective range от тебя и до цели (не путать с cast range). Могу предположить - тут может быть такая же зависимость. Её реализовать достаточно просто.

Запускаем 2 таска
- первый на 70% натягивания тетевы;
- второй на момент выстрела;
Так мы сможем проверить стоит ли цель все еще в радиусе выстрела или уже убажала достаточно далеко.
Так же нужно бы сделать проверки на общую доступность цели, а то вдруг она в промежутке между 70% и фактическим выстрелом успеет сделать БСОЕ.

Ну если проверки на 70% не подверждаются - отменять вторую таску и говорить "цель убежаль :("


Еще думаю о реализации динамического отслеживания позиции, т.к цель может подойти ближе/дальше во время атаки и точность синхронизации упадет.
 
Еще думаю о реализации динамического отслеживания позиции, т.к цель может подойти ближе/дальше во время атаки и точность синхронизации упадет.
почему не делать расчеты типо "крит атака" / "базовый урон" / "скорость полета" и прочие перед началом удара, а расчеты "дальность" / "бонус позиции" / "время полета" уже по факту успешности выстрела?
 
Еще думаю о реализации динамического отслеживания позиции, т.к цель может подойти ближе/дальше во время атаки и точность синхронизации упадет.
А какая может быть разница между тем будет цель ближе или нет? С точки времени и полета стрелы это конечно зависит от скорости стреллы. Но как сам факт о том что стрелла прийдет на десятую секунды раньше или позже повлияет на повидение различной логики на сервере? Я так понимаю что тут вопрос именно о том когда сервер будет отсылать пакеты о уроне. Да, возможно что сервер отошлет пакеты раньше чем надо, но ведь это еще и увидить надо в клиенте. А что еще?
 
Назад
Сверху