На сколько я помню на старой версии CCP, от лыжи там мало чего есть. Даже если и на лыже то механика передвижений почти полностью совпадает с фениксо-подобными. А основа для геодвижка бралась (судя по копирайтам в GeoEngine) та же что и на большинстве l2p-подобных исходниках.Сегодня проверю на l2gw. L2GW основан на лыже вроде, нет?
Нет.Сегодня проверю на l2gw. L2GW основан на лыже вроде, нет?
У себя на лыже проверил... Такой фигни нету)
Пока решения нет. Для интересующихся - копать следует в таск передвижения.Т.е предположение верно и в массив координат при передвижении передаются "левые" точки?
Ок, попробую переписать функции связанные с передвижением
donedist += (now - _startMoveTime) * _previousSpeed / 1000.;
if(done >= 1)
{
moveNext(false);
return;
}
int index = (int) (moveList.size() * done);
if(index >= moveList.size())
index = moveList.size() - 1;
if(index < 0)
index = 0;
Соответственно бежать можно бесконечно и по итогу персонаж все равно окажется на "левых" координатах. При этом после окончания бега сработает пакет validatePosition и переместит/портанет персонажа в зависимости от diff между клиентом и сервером.
public void setLocFly(Location loc)
{
if(loc == null)
{
return;
}
setXYZ(loc.x, loc.y, loc.z);
if(isPlayer())
{
getPlayer().setLastServerPosition(loc);
}
}
Пробовал, дело не в этом.Попробуйте точку полета выставлять в lastServerPosition
что-то вроде такого.
Код:public void setLocFly(Location loc) { if(loc == null) { return; } setXYZ(loc.x, loc.y, loc.z); if(isPlayer()) { getPlayer().setLastServerPosition(loc); } }
Странно, на оффе примерно такой же отброс есть. Только там практически сразу телепортит назад.Пробовал, дело не в этом.
А что глянуть декомпил L2Server, религия не позволяет ?Добрый вечер, решил переписать flytype-скилы (Rush Impact, Shadow Step, Warp и тд) и на последнем этапе столкнулся с проблемой некорректной обработки движения после использования Charge-скилов.
Баг актуален для всех сборок на базе l2p (Так же актуально для l2gw) даже если не трогать изначальный код.
В чем суть:
Если после окончания каста (после срабатывания clearCastVars() и finishFly()) начать отбегать то подключается nextAction.MOVE (обрабатывается в PlayableAI). По окончанию бега если персонаж на стороне клиента не добегает до точки то его возвращает в последние координаты после каста (в координаты, что находится в переменной _flyLoc и возвращается функцией getFlyLoc()).
Соответственно бежать можно бесконечно и по итогу персонаж все равно окажется на "левых" координатах. При этом после окончания бега сработает пакет validatePosition и переместит/портанет персонажа в зависимости от diff между клиентом и сервером.
Данного бага не было на лайве лостворлда (в шарных сурсах он остался)
Подробней как это проявляется:
Собственно вопрос - кто-то фиксил этот момент? Такое чувство что он зарыт где-то в мув-листе
Похоже на Костыль/заглушку, от того что автор не вкурсе как оно должно обрабатываться на самом деле.int index = (int) (moveList.size() * done);
if(index >= moveList.size())
index = moveList.size() - 1;
if(index < 0)
index = 0;
На офе отброса нет. На любой птс сборке персонаж просто останавливается на пол пути не доходя до курсора, т.е со стороны сервера он дошел, а со стороны клиента нет, т.е там есть допуск рассинхрона.Странно, на оффе примерно такой же отброс есть. Только там практически сразу телепортит назад.
А что глянуть декомпил L2Server, религия не позволяет ?
И вот это
Похоже на Костыль/заглушку, от того что автор не вкурсе как оно должно обрабатываться на самом деле.
И вообще хорошо былоб предоставить дебаг от сервера, а то так без информации, пальцем в небо !
Каждую часть вот этого, желательно увидеть полностью в коде, и в эклипсе !clearCastVars() и finishFly()) начать отбегать то подключается nextAction.MOVE
Я имел ввиду более подробный дебаг( в эклипске), нужно пройтись по каждому классу который отвечает за передвижение во время каста, так с этими XYZ мало что поймешь.
И вообще правильнее будет смотреть в L2Server.exe, и разбирать что там указанно, а так можно вечно гадать не видя всего кода - мало кто сможет помочь, либо скинь полностью весь код который отвечает за все.
Каждую часть вот этого, желательно увидеть полностью в коде, и в эклипсе !
_flyLoc = null; // Обнуляем переменную _flyLoc
switch(skill.getFlyType())
{
case CHARGE:
_flyLoc = getFlyLocation(target, skill); // Получаем координату к которой рашим
if(_flyLoc != null) {
setPrevLoc(getLoc()); // Устанавливаем изначальную позицию (нужно позднее для SkillType.TARGET_TUNNEL)
broadcastPacket(new FlyToLocation(this, _flyLoc, skill.getFlyType())); // Броадкаст пакета полета
}
else
{
sendPacket(SystemMsg.CANNOT_SEE_TARGET);
return;
}
default:
break;
}
if(skill.getFlyType() == FlyType.CHARGE){
// Получаем ближайшую точку к цели
loc = applyOffset(target.getLoc(), (int) target.getColRadius()+40);
// loc.correctGeoZ; Нет смысла корректировать координату Z тк это делает applyOffset
// Коррекировки если скилл используется в полете
if(isFlying())
{
if(isPlayer() && ((Player) this).isInFlyingTransform() && (loc.z <= 0 || loc.z >= 6000))
return null;
if(GeoEngine.moveCheckInAir(getX(), getY(), getZ(), loc.x, loc.y, loc.z, 45, getGeoIndex()) == null)
return null;
}
// Проверка на возможность перемещения
if(!GeoEngine.canMoveToCoord(getX(), getY(), getZ(), loc.x, loc.y, loc.z, getGeoIndex()))
{
loc = target.getLoc(); // Если не получается встать рядом с объектом, пробуем встать прямо в него
if(!GeoEngine.canMoveToCoord(getX(), getY(), getZ(), loc.x, loc.y, loc.z, getGeoIndex()))
return null;
}
return loc;
}
switch(skill.getFlyType())
{
case CHARGE:
setLocOnFly(_flyLoc); // Перемещаем персонажа к позиции полученной из getFlyLocation
// stopMove(false, true); Тестовый стоп мув для предотвращения бага с использованием валидации, не помогает
finishFly(false); // Вызов finishFly
break;
}
setPrevLoc(null); // Обнуляем _prevLocation что бы избежать багов в SkillType.TARGET_TUNNEL
private void finishFly(boolean aborted)
{
Skill skill = _castingSkill; // Получаем кастуемый скилл
Location flyLoc = _flyLoc; // Сохраняем локацию
_flyLoc = null; // Обнуляем на всякий случай (По факту так же обнуляется при начале каста)
if(flyLoc != null)
{
// TODO: DS: уточнить пакет при обрыве каста
if (aborted && skill != null && skill.getFlyType() != FlyType.CHARGE)
broadcastPacket(new FlyToLocation(this, getLoc(), FlyType.NONE));
else
if(skill.getFlyType() != FlyType.CHARGE)
setLocOnFly(flyLoc); // Используется для альтернативного юза по типу Wrap, Blink, Shadow Step и тд тк локация для них не выставляется в onMagicUseTimer
}
}
public void setLocOnFly(Location loc)
{
/* Тестовая установка Клиент-серверных координат, никак не влияет
if(isPlayer()) {
getPlayer().setLastClientPosition(loc);
getPlayer().setLastServerPosition(loc);
}*/
setXYZ(loc.x, loc.y, loc.z);
}
public void setXYZ(int x, int y, int z, boolean MoveTask)
{
if(!MoveTask)
stopMove();
moveLock.lock();
try
{
super.setXYZ(x, y, z);
}
finally
{
moveLock.unlock();
}
updateZones(); // Zones Listener
}
Я имел ввиду более подробный дебаг( в эклипске), нужно пройтись по каждому классу который отвечает за передвижение во время каста, так с этими XYZ мало что поймешь.
И вообще правильнее будет смотреть в L2Server.exe, и разбирать что там указанно, а так можно вечно гадать не видя всего кода - мало кто сможет помочь, либо скинь полностью весь код который отвечает за все.
Каждую часть вот этого, желательно увидеть полностью в коде, и в эклипсе !
public boolean isMovementDisabled()
{
return isBlocked() || isRooted() || isImmobilized() || isAlikeDead() || isStunned() || isSleeping() || isParalyzed() || isAttackingNow() || (isCastingNow() && !canMoveOnCurCast()) || isFrozen();
}
Зачем +40, Colradius всегда равен 0 ?loc = applyOffset(target.getLoc(), (int) target.getColRadius()+40);
Вот тут лучше поставить брекпойнт и output, чтобы точно видеть что он делает.loc = target.getLoc();
if(!GeoEngine.canMoveToCoord(getX(), getY(), getZ(), loc.x, loc.y, loc.z, getGeoIndex()))
return null;
Желательно поставить breakpoint с Output,if (aborted && skill != null && skill.getFlyType() != FlyType.CHARGE)
broadcastPacket(new FlyToLocation(this, getLoc(), FlyType.NONE));
else
if(skill.getFlyType() != FlyType.CHARGE)
setLocOnFly(flyLoc);
Ну вот теперь немного понятнее
Зачем +40, Colradius всегда равен 0 ?
Вот тут лучше поставить брекпойнт и output, чтобы точно видеть что он делает.
Но выглядит оно не правильно, 3 раза просчитывается Loc , еще не понятно что делает canMoveToCoord(он двигает самого персонажа ? )
И что из себя представляет setXYZ ? Отправляется ли там пакет ?
Ну и суда
Желательно поставить breakpoint с Output,
ибо не понятно что за значение, имеет getLoc(), до того как был задействован метод FinishFly, и зачем вызывать setXYZ() еще раз(при завершении), если предыдущее движение(до FinishFly) должно завершится .
P.S.
На лицо вся суть java Разработок, один написал не правильно и все за ним скопировали, а работает оно как надо или нет, особо не волнует!
Советую все-таки глянуть декомпил L2server, выдумывать велосипед не всегда того стоит.
А зачем в начале темы ты пишешь что используешь Finish flyColRadius может быть грубо говоря до 8 до 20 если нпц большой, иногда этого мало и мы влетает в лицо, 40 оптимальное значение что бы получить точку не в мобе и при этом оставаться на дистанции атаки
canMoveToCoord - определяет может ли персонаж добежать до точки (В функцию передается соотв координата начала и конца). Возращается булево значение.
Впринципе выглядит годно т.к там идет просчет изначальной координаты, потом идет пересчет координаты если персонаж в флай-трансформе и соотв идет проверка на возможность передвижения.
finishFly я поставил просто для понимания. Если посмотреть внимательней он не задействуется для раш скилов из за условия skill.getFlyType() != FlyType.CHARGE
SetXYZ - соотв. перемещает персонажа в нужную локацию. Если в функцию передается булева переменная move как true то идет бродкаст пакет MoveToLocation
Единственное что я бы проработал в алгоритме - лишние обнуления переменной _flyLoc.
P.S: Занимался декомпилом только AI.obj, есть ли в шаре пригодный для разбора декомпил серверной части птс того же финала?
Если по сути этот метод не как не обрабатывает скилы с багом ?Если после окончания каста (после срабатывания clearCastVars() и finishFly())
как по мне это та самая проблема, и она возможно глубжке( в самом canMoveToCoord) .if(!GeoEngine.canMoveToCoord(getX(), getY(), getZ(), loc.x, loc.y, loc.z, getGeoIndex()))
{
loc = target.getLoc(); // Если не получается встать рядом с объектом, пробуем встать прямо в него
if(!GeoEngine.canMoveToCoord(getX(), getY(), getZ(), loc.x, loc.y, loc.z, getGeoIndex()))
return null;
}
Если перс в ФлайТрансформе/виверне, то getFlyLocation всегда будет возвращать Null, смысл с метода который возвращает null ?if(isFlying())
{
if(isPlayer() && ((Player) this).isInFlyingTransform() && (loc.z <= 0 || loc.z >= 6000))
return null;
if(GeoEngine.moveCheckInAir(getX(), getY(), getZ(), loc.x, loc.y, loc.z, 45, getGeoIndex()) == null)
return null;
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?