Доброго времени суток, уважаемые форумчане. Работаю с исходниками эпилога от команды L2NextGen rev 7083 из шары. И возникло у меня 3 вопроса, которые уже достаточно долго не могу решить. Видимо, потому что опыта работы с ядром маловато. Чтобы не захламлять форум кучей тем, решил их все изложить в одной теме. За любые подсказки по любому из них буду весьма признателен, да и на спасибки не зажлоблюсь.
1)Наиболее важный из этих вопросов - дуэли. Дело в том, что после окончания дуэли все дебаффы на игроках возвращаются в свое исходное состояние до дуэли. То есть, если в дуэли игрок получил дебафф, то после дуэли он снимется(ну и если до дуэли висел дебафф, а в дуэли его сняли клинсом - после дуэли он вернется). Это правильно, к этому претензий не имею. Но вот с баффами в этой версии сборки такого не предусмотрели, что очень нехорошо. По себе знаю, как неприятно, когда в дуэли кансельнут баффы, а после нее их приходится бафать заново, вот и хотелось бы это исправить, как и сделали на большинстве успешных серверов.
Поискав нужную часть кода, наткнулся на файл l2n\game\model\entity\Duel.java В нем заострил внимание на этой части кода:
// Nested Class
public static class PlayerCondition
{
private long _playerStoreId = 0;
private double _hp, _mp, _cp;
private boolean _paDuel;
private int _x, _y, _z;
private DuelState _duelState;
private GArray<L2Effect> _debuffs;
public PlayerCondition(final L2Player player, final boolean partyDuel)
{
if(player == null)
return;
_playerStoreId = player.getStoredId();
_hp = player.getCurrentHp();
_mp = player.getCurrentMp();
_cp = player.getCurrentCp();
_paDuel = partyDuel;
if(_paDuel)
{
_x = player.getX();
_y = player.getY();
_z = player.getZ();
}
}
public void registerDebuff(final L2Effect debuff)
{
if(_debuffs == null)
_debuffs = new GArray<L2Effect>();
_debuffs.add(debuff);
}
public void RestoreCondition(final boolean abnormalEnd)
{
final L2Player player = getPlayer();
if(player == null)
return;
if(_debuffs != null)
for(final L2Effect e : _debuffs)
if(e != null)
e.exit();
// for(L2Effect e : _player.getAllEffects())
// if(e.getSkill().isOffensive())
// e.exit();
// if it is an abnormal DuelEnd do not restore hp, mp, cp
if(!abnormalEnd && !player.isDead())
{
player.setCurrentHp(_hp, false);
player.setCurrentMp(_mp);
player.setCurrentCp(_cp);
}
if(_paDuel)
TeleportBack();
}
А также в конце файла на этот
public void onBuff(final L2Player player, final L2Effect debuff)
{
if(player == null || debuff == null || _playerConditions == null)
return;
final PlayerCondition pcon = _playerConditions.get(player.getStoredId());
if(pcon != null)
pcon.registerDebuff(debuff);
}
Подумав, что все просто, попробовал добавить аналогичный массив для баффов и аналогичные функции(или как там это правильно назвать), в итоге, получилось вот что:
public static class PlayerCondition
{
private long _playerStoreId = 0;
private double _hp, _mp, _cp;
private boolean _paDuel;
private int _x, _y, _z;
private DuelState _duelState;
private GArray<L2Effect> _debuffs;
private GArray<L2Effect> _buffs;
public PlayerCondition(final L2Player player, final boolean partyDuel)
{
if(player == null)
return;
_playerStoreId = player.getStoredId();
_hp = player.getCurrentHp();
_mp = player.getCurrentMp();
_cp = player.getCurrentCp();
_paDuel = partyDuel;
if(_paDuel)
{
_x = player.getX();
_y = player.getY();
_z = player.getZ();
}
}
public void registerDebuff(final L2Effect debuff)
{
if(_debuffs == null)
_debuffs = new GArray<L2Effect>();
_debuffs.add(debuff);
}
public void registerBuff(final L2Effect buff)
{
if(_buffs == null)
_buffs = new GArray<L2Effect>();
_buffs.add(buff);
}
public void RestoreCondition(final boolean abnormalEnd)
{
final L2Player player = getPlayer();
if(player == null)
return;
if(_debuffs != null)
for(final L2Effect e : _debuffs)
if(e != null)
e.exit();
if(_buffs != null)
for(final L2Effect e : _buffs)
if(e != null)
e.exit();
// for(L2Effect e : _player.getAllEffects())
// if(e.getSkill().isOffensive())
// e.exit();
// if it is an abnormal DuelEnd do not restore hp, mp, cp
if(!abnormalEnd && !player.isDead())
{
player.setCurrentHp(_hp, false);
player.setCurrentMp(_mp);
player.setCurrentCp(_cp);
}
if(_paDuel)
TeleportBack();
}
и в конце файла
public void onBuff(final L2Player player, final L2Effect debuff)
{
if(player == null || debuff == null || _playerConditions == null)
return;
final PlayerCondition pcon = _playerConditions.get(player.getStoredId());
if(pcon != null)
pcon.registerDebuff(debuff);
}
public void onBuff1(final L2Player player, final L2Effect buff)
{
if(player == null || buff == null || _playerConditions == null)
return;
final PlayerCondition pcon = _playerConditions.get(player.getStoredId());
if(pcon != null)
pcon.registerBuff(buff);
}
Но, попробовав это, я увидел, что не изменилось НИЧЕГО. Как возвращались дебаффы и было пофигу на баффы, так и осталось. Пробовал даже в коде этого файла везде, где только можно, менять слово debuff на buff, но даже после этого ничего не менялось при тесте в игре. Создалось впечатление, что сборке будто пофигу на код, описанный в этом файле. Но более похожего на нужный кода я не нашел в файлах исходников этой сборке. Вот и отчаялся со временем. Вся надежда на то, что более шарящие в работе с ядром и яве в целом люди с форума что-нибудь подскажут, натолкнут на истину и укажут на мои ошибки.
2) Вторым нерешенным вопросом остались банки на баффы. Взял за основу добавленные когда-то на руоффе кокткйли(Sweet Fruit Coctail и Fresh Fruit Coctail), изменил даваемые баффы из обычных скромненьких, на точеные резисты, вику, кк и так далее. Все получилось без особых проблем, но тот факт, что эти банки просто безоткатные, не дает мне покоя. И вот, промучившись несколько дней, я так и не смог сделать на них откат, даже идеи толком закончились. И снова надежда на ваши подсказки, господа. Вот получившийся код этих банок(файл в датапаке ItemHandlers.java):
private final int[] sweet_list = {
// Sweet Fruit Cocktail
1191, // Resist Fire
1182, // Resist Aqua
1189, // Resist Wind
1232, // Blazing Skin
1259, // Resist Shock
};
private final int[] sweet_list1 = {
// Sweet Fruit Cocktail
1392, // Holy Resistance
1393, // Unholy Resistance
};
private final int[] sweet_list2 = {
// Sweet Fruit Cocktail
1364, // Eye of Pa'agrio
1542, // Resist Shock
};
private final int[] sweet_list3 = {
// Sweet Fruit Cocktail
1363, // Chant of Victory
};
// Sweet Fruit Cocktail
public void ItemHandler_10178(L2Player player)
{
L2Player p = player;
if(p.isInZone(ZoneType.OlympiadStadia))
{ p.sendMessage("Невозможно использовать на олимпиаде.");
return;
}
if(p.isInCombat())
{ p.sendMessage("Невозможно использовать в бою.");
return;
}
for(int skill : sweet_list)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 300000));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 330));
}
for(int skill : sweet_list1)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 300000));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 130));
}
for(int skill : sweet_list2)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 300000));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 1));
}
for(int skill : sweet_list3)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 300000));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 315));
}
}
private final int[] fresh_list = {
// Fresh Fruit Cocktail
1191, // Resist Fire
1182, // Resist Aqua
1189, // Resist Wind
1238, // Freezing Skin
1259, // Resist Shock
};
private final int[] fresh_list1 = {
// Fresh Fruit Cocktail
1392, // Holy Resistance
1393, // Unholy Resistance
};
private final int[] fresh_list2 = {
// Fresh Fruit Cocktail
1364, // Eye of Pa'agrio
1542, // Resist Shock
};
private final int[] fresh_list3 = {
// Fresh Fruit Cocktail
1357, // Prophecy of Wind
};
// Fresh Fruit Cocktail
public void ItemHandler_10179(L2Player player)
{
L2Player p = player;
if(p.isInZone(ZoneType.OlympiadStadia))
{ p.sendMessage("Невозможно использовать на олимпиаде.");
return;
}
if(p.isInCombat())
{ p.sendMessage("Невозможно использовать в бою.");
return;
}
for(int skill : fresh_list)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 0));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 330));
}
for(int skill : fresh_list1)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 0));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 130));
}
for(int skill : fresh_list2)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 0));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 1));
}
for(int skill : fresh_list3)
{
p.broadcastPacket(new MagicSkillUse(p, p, skill, 1, 0, 0));
p.altOnMagicUseTimer(p, SkillTable.getInstance().getInfo(skill, 315));
}
}
3) Вопрос касается болячек с Хот Спрингс. Сделал их баффом, чтобы не снимались клинсом и занимали бафф-слот, убрал с них эффект стонов персонажа и облака типа как от яда. Клинс их действительно не снимает, бафф-слот, по идее, тоже занимают. Вклиенте отображаются точно так же и там же, в строке дебаффов, как и до этого - это не критично. Но хотелось бы еще сделать возможность игроку снимать их с себя через шифт-клик, но, хоть они и являются бафом, через шифт-клик не снимаются. А теперь вопрос: для того, чтобы они таким образом снимались. нужно менять что-то в клиенте, так как он по-прежнему воспринимает их дебаффом и при попытке даже не шлет серверу пакет, который обычно посылает при шифт-клике на баффе, или в датапаке еще что-то нужно сделась, или же лезть в ядро? Сам я, по сути, сделал совсем немного, просто в датапаке поменял тип скилла, вот пример:
<skill id="4554" levels="10" name="Hot Spring Malaria">
<!-- L2NextGen Team -->
<!--
Need correct: pAtk
Description:
Infected with Hot Springs Malaria. While afflicted, your Casting Spd. is increased and MP consumption is decreased. Effect 1-10
-->
<table name="#mAtkSpd"> 1.04 1.08 1.12 1.16 1.08 1 1 1 1 1 </table>
<table name="#mpConsum"> 1 0.96 0.96 0.96 0.92 0.92 0.92 0.88 0.88 0.84 </table>
<set name="mpInitialConsume" val="14" />
<set name="mpConsume" val="55" />
<set name="isDebuff" val="false" />
<set name="target" val="TARGET_ONE" />
<set name="operateType" val="OP_ACTIVE" />
<set name="reuseDelay" val="4000" />
<set name="skillType" val="BUFF" />
<set name="isMagic" val="true" />
<set name="operateType" val="OP_ACTIVE" />
<set name="castRange" val="600" />
<for>
<effect count="1" name="Buff" time="3600" val="0">
<mul order="0x30" stat="mAtkSpd" val="#mAtkSpd" />
<mul order="0x30" stat="mpConsum" val="#mpConsum" />
</effect>
</for>
</skill>
При этом <set name="isDebuff" val="false" /> там не было изначально, я его добавил в надежде на то, что это поможет, но, как оказалось, его хоть добавляй, хоть не добавляй - ничего не меняет в данной ситуации.
Вот и все вопросы, дорогие друзья. За любую помощь или подсказку по любому из них буду очень признателен. Спасибо за внимание.