Support for blessed items.

Contributed by manax182.
This commit is contained in:
MobiusDevelopment 2021-04-18 21:08:23 +00:00
parent c6a4789f47
commit 6d5a2e7da0
28 changed files with 876 additions and 54 deletions

View File

@ -201,3 +201,11 @@ KarmaRateDropEquipWeapon = 10
PetXpRate = 1
PetFoodRate = 1
SinEaterXpRate = 1
# ---------------------------------------------------------------------------
# Blessed items
# ---------------------------------------------------------------------------
# Chance of blessing weapon.
# Default: 15.0
BlessingChance = 15.0

View File

@ -20,6 +20,14 @@
<enchant id="956" targetGrade="D" maxEnchant="16" safeEnchant="4" scrollGroupId="0" /> <!-- Default scroll groups binding. -->
<enchant id="93411" targetGrade="D" maxEnchant="16" safeEnchant="4" scrollGroupId="0" /> <!-- Default scroll groups binding. -->
<enchant id="94184" targetGrade="C" maxEnchant="1" isBlessed="true"/>
<enchant id="94184" targetGrade="A" maxEnchant="1" isBlessed="true"/>
<enchant id="94208" targetGrade="C" maxEnchant="1" isBlessed="true"/>
<enchant id="94208" targetGrade="A" maxEnchant="1" isBlessed="true"/>
<enchant id="94208" targetGrade="B" maxEnchant="1" isBlessed="true"/>
<enchant id="94208" targetGrade="S" maxEnchant="1" isBlessed="true"/>
<!-- Blessed Scrolls: Enchant Weapon -->
<enchant id="6577" targetGrade="S" maxEnchant="16" />
<enchant id="6569" targetGrade="A" maxEnchant="16" />
@ -230,22 +238,6 @@
<item id="91550" /> <!-- Frintezza's Necklace -->
</enchant>
<!-- Scroll of Blessing -->
<enchant id="94184" maxEnchant="5" safeEnchant="1">
<item id="6660" /> <!-- Queen Ant's Ring -->
<item id="6661" /> <!-- Orfen's Earring -->
<item id="6662" /> <!-- Ring of Core -->
<item id="90763" /> <!-- Zaken's Earring -->
</enchant>
<!-- Scroll of Blessing (Event) -->
<enchant id="94208" maxEnchant="5" safeEnchant="1">
<item id="6660" /> <!-- Queen Ant's Ring -->
<item id="6661" /> <!-- Orfen's Earring -->
<item id="6662" /> <!-- Ring of Core -->
<item id="90763" /> <!-- Zaken's Earring -->
</enchant>
<!-- Enchant Spirit - Zodiac Agathion -->
<enchant id="48046" maxEnchant="10" safeEnchant="3">
<item id="93128" /> <!-- Agathion Ignis -->

View File

@ -191,6 +191,7 @@ import handlers.itemhandlers.BeastSoulShot;
import handlers.itemhandlers.BeastSpiritShot;
import handlers.itemhandlers.BlessedSoulShots;
import handlers.itemhandlers.BlessedSpiritShot;
import handlers.itemhandlers.BlessingScrolls;
import handlers.itemhandlers.Book;
import handlers.itemhandlers.Bypass;
import handlers.itemhandlers.Calculator;
@ -541,6 +542,7 @@ public class MasterHandler
BeastSpiritShot.class,
BlessedSoulShots.class,
BlessedSpiritShot.class,
BlessingScrolls.class,
Book.class,
Bypass.class,
Calculator.class,

View File

@ -0,0 +1,52 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package handlers.itemhandlers;
import org.l2jmobius.gameserver.handler.IItemHandler;
import org.l2jmobius.gameserver.model.actor.Playable;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.serverpackets.blessing.ExOpenBlessOptionScroll;
public class BlessingScrolls implements IItemHandler
{
@Override
public boolean useItem(Playable playable, ItemInstance item, boolean forceUse)
{
if (!playable.isPlayer())
{
playable.sendPacket(SystemMessageId.YOUR_PET_CANNOT_CARRY_THIS_ITEM);
return false;
}
final PlayerInstance player = playable.getActingPlayer();
if (player.isCastingNow())
{
return false;
}
if (player.hasItemRequest())
{
player.sendPacket(SystemMessageId.ANOTHER_ENCHANTMENT_IS_IN_PROGRESS_PLEASE_COMPLETE_THE_PREVIOUS_TASK_THEN_TRY_AGAIN);
return false;
}
player.sendPacket(new ExOpenBlessOptionScroll(item.getId()));
return true;
}
}

View File

@ -1005,7 +1005,7 @@
<set name="is_sellable" val="false" />
<set name="is_stackable" val="true" />
<set name="etcitem_type" val="BLESS_ENCHT_AM" /> <!-- BLESS_ENCHT_AM -->
<set name="handler" val="EnchantScrolls" />
<set name="handler" val="BlessingScrolls" />
<skills>
<skill id="40214" level="1" /> <!-- Scroll of Blessing -->
</skills>

View File

@ -78,6 +78,7 @@
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="isBlessed" type="xs:boolean" use="optional" />
<xs:attribute name="scrollGroupId" type="xs:int" use="optional" />
</xs:complexType>
</xs:element>

View File

@ -738,6 +738,7 @@ public class Config
public static int DROP_ITEM_MIN_LEVEL_DIFFERENCE;
public static int DROP_ITEM_MAX_LEVEL_DIFFERENCE;
public static double DROP_ITEM_MIN_LEVEL_GAP_CHANCE;
public static double BLESSING_CHANCE;
public static float RATE_KARMA_LOST;
public static float RATE_KARMA_EXP_LOST;
public static float RATE_SIEGE_GUARDS_PRICE;
@ -2326,6 +2327,7 @@ public class Config
DROP_ITEM_MIN_LEVEL_DIFFERENCE = RatesSettings.getInt("DropItemMinLevelDifference", 5);
DROP_ITEM_MAX_LEVEL_DIFFERENCE = RatesSettings.getInt("DropItemMaxLevelDifference", 10);
DROP_ITEM_MIN_LEVEL_GAP_CHANCE = RatesSettings.getDouble("DropItemMinLevelGapChance", 10);
BLESSING_CHANCE = RatesSettings.getDouble("BlessingChance", 15.0);
// Load PvP config file (if exists)
final PropertiesParser PVPSettings = new PropertiesParser(PVP_CONFIG_FILE);

View File

@ -17,10 +17,15 @@
package org.l2jmobius.gameserver.data.xml;
import java.io.File;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
@ -42,6 +47,7 @@ public class EnchantItemData implements IXmlReader
private final Map<Integer, EnchantScroll> _scrolls = new HashMap<>();
private final Map<Integer, EnchantSupportItem> _supports = new HashMap<>();
private final List<Entry<Integer, EnchantScroll>> _blessingScrolls = new ArrayList<>();
/**
* Instantiates a new enchant item data.
@ -56,9 +62,11 @@ public class EnchantItemData implements IXmlReader
{
_scrolls.clear();
_supports.clear();
_blessingScrolls.clear();
parseDatapackFile("data/EnchantItemData.xml");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _scrolls.size() + " enchant scrolls.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _supports.size() + " support items.");
LOGGER.info(getClass().getSimpleName() + ": Loaded " + _blessingScrolls.size() + " blessing scrolls.");
}
@Override
@ -93,8 +101,15 @@ public class EnchantItemData implements IXmlReader
item.addItem(parseInteger(cd.getAttributes(), "id"));
}
}
if (set.contains("isBlessed"))
{
_blessingScrolls.add(new AbstractMap.SimpleEntry<>(item.getId(), item));
}
else
{
_scrolls.put(item.getId(), item);
}
}
catch (NullPointerException e)
{
LOGGER.warning(getClass().getSimpleName() + ": Unexistent enchant scroll: " + set.getString("id") + " defined in enchant data!");
@ -158,6 +173,11 @@ public class EnchantItemData implements IXmlReader
return _supports.get(item.getId());
}
public List<Entry<Integer, EnchantScroll>> getBlessingScrolls(int itemId)
{
return _blessingScrolls.stream().filter(it -> it.getKey() == itemId).collect(Collectors.toList());
}
/**
* Gets the single instance of EnchantItemData.
* @return single instance of EnchantItemData

View File

@ -27,7 +27,8 @@ public enum ItemListType implements IUpdateTypeComponent
ELEMENTAL_ATTRIBUTE(0x02),
ENCHANT_EFFECT(0x04),
VISUAL_ID(0x08),
SOUL_CRYSTAL(0x10);
SOUL_CRYSTAL(0x10),
BLESSED(0x100);
private final int _mask;

View File

@ -23,6 +23,7 @@ public enum ItemSkillType
{
NORMAL,
ON_ENCHANT,
ON_BLESSING,
ON_EQUIP,
ON_UNEQUIP,
ON_CRITICAL_SKILL,

View File

@ -64,7 +64,7 @@ public class ItemInfo
/** The mana of this item */
private int _mana;
private int _time;
private boolean _isBlessed = false;
private boolean _available = true;
private int _location;
@ -148,6 +148,7 @@ public class ItemInfo
{
_attributeDefence[type.getClientId()] = item.getDefenceAttribute(type);
}
_isBlessed = item.isBlessed();
_option = item.getEnchantOptions();
_soulCrystalOptions = item.getSpecialAbilities();
_soulCrystalSpecialOptions = item.getAdditionalSpecialAbilities();
@ -212,6 +213,7 @@ public class ItemInfo
_soulCrystalOptions = item.getSoulCrystalOptions();
_soulCrystalSpecialOptions = item.getSoulCrystalSpecialOptions();
_visualId = item.getVisualId();
_isBlessed = item.isBlessed();
}
public ItemInfo(Product item)
@ -296,6 +298,7 @@ public class ItemInfo
_option = item.getEnchantOptions();
_soulCrystalOptions = item.getSoulCrystalOptions();
_soulCrystalSpecialOptions = item.getSoulCrystalSpecialOptions();
_isBlessed = item.isBlessed();
}
public int getObjectId()
@ -408,6 +411,11 @@ public class ItemInfo
return _visualExpiration;
}
public boolean isBlessed()
{
return _isBlessed;
}
@Override
public String toString()
{

View File

@ -53,6 +53,7 @@ public class TradeItem
private int _visualId;
private int _augmentationOption1 = -1;
private int _augmentationOption2 = -1;
private boolean _isBlessed = false;
public TradeItem(ItemInstance item, long count, long price)
{
@ -75,6 +76,7 @@ public class TradeItem
_soulCrystalOptions = item.getSpecialAbilities();
_soulCrystalSpecialOptions = item.getAdditionalSpecialAbilities();
_visualId = item.getVisualId();
_isBlessed = item.isBlessed();
if (item.getAugmentation() != null)
{
_augmentationOption1 = item.getAugmentation().getOption1Id();
@ -123,6 +125,7 @@ public class TradeItem
_soulCrystalOptions = item.getSoulCrystalOptions();
_soulCrystalSpecialOptions = item.getSoulCrystalSpecialOptions();
_visualId = item.getVisualId();
_isBlessed = item.isBlessed();
}
public void setObjectId(int objectId)
@ -270,4 +273,9 @@ public class TradeItem
{
return _visualId;
}
public boolean isBlessed()
{
return _isBlessed;
}
}

View File

@ -0,0 +1,73 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.model.actor.request;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
/**
* @author Horus
*/
public class BlessingItemRequest extends AbstractRequest
{
private volatile int _blessingItemObjectId;
private volatile int _blessingScrollObjectId;
public BlessingItemRequest(PlayerInstance player, int enchantingScrollObjectId)
{
super(player);
_blessingScrollObjectId = enchantingScrollObjectId;
}
public ItemInstance getBlessingItem()
{
return getActiveChar().getInventory().getItemByObjectId(_blessingItemObjectId);
}
public void setBlessingItem(int objectId)
{
_blessingItemObjectId = objectId;
}
public ItemInstance getBlessScroll()
{
return getActiveChar().getInventory().getItemByObjectId(_blessingScrollObjectId);
}
public void setBlessScroll(int objectId)
{
_blessingScrollObjectId = objectId;
}
@Override
public boolean isItemRequest()
{
return true;
}
@Override
public boolean canWorkWith(AbstractRequest request)
{
return !request.isItemRequest();
}
@Override
public boolean isUsing(int objectId)
{
return (objectId > 0) && ((objectId == _blessingItemObjectId) || (objectId == _blessingScrollObjectId));
}
}

View File

@ -359,6 +359,19 @@ public abstract class Inventory extends ItemContainer
}
}
final List<ItemSkillHolder> onBlessingSkills = it.getSkills(ItemSkillType.ON_BLESSING);
if (onBlessingSkills != null)
{
for (ItemSkillHolder holder : onBlessingSkills)
{
if (item.isBlessed())
{
player.removeSkill(holder.getSkill(), false, holder.getSkill().isPassive());
update = true;
}
}
}
// Clear enchant bonus
item.clearEnchantStats();
@ -429,11 +442,31 @@ public abstract class Inventory extends ItemContainer
for (ItemInstance equipped : inventory.getPaperdollItems())
{
final List<ItemSkillHolder> otherEnchantSkills = equipped.getItem().getSkills(ItemSkillType.ON_ENCHANT);
if (otherEnchantSkills == null)
final List<ItemSkillHolder> otherBlessingSkills = equipped.getItem().getSkills(ItemSkillType.ON_BLESSING);
if ((otherEnchantSkills == null) && (otherBlessingSkills == null))
{
continue;
}
if (onBlessingSkills != null)
{
for (ItemSkillHolder holder : otherBlessingSkills)
{
// Add skills bestowed from +4 armor
if (equipped.isBlessed())
{
final Skill skill = holder.getSkill();
// Check passive skill conditions.
if (skill.isPassive() && !skill.checkConditions(SkillConditionScope.PASSIVE, player, player))
{
player.removeSkill(holder.getSkill(), false, holder.getSkill().isPassive());
update = true;
}
}
}
}
if (otherEnchantSkills != null)
{
for (ItemSkillHolder holder : otherEnchantSkills)
{
// Add skills bestowed from +4 armor
@ -449,6 +482,7 @@ public abstract class Inventory extends ItemContainer
}
}
}
}
// Must check for toggle and isRemovedOnUnequipWeapon skill item conditions.
for (Skill skill : player.getAllSkills())
@ -504,6 +538,7 @@ public abstract class Inventory extends ItemContainer
player.getStat().recalculateStats(true);
final List<ItemSkillHolder> onEnchantSkills = item.getItem().getSkills(ItemSkillType.ON_ENCHANT);
final List<ItemSkillHolder> onBlessingSkills = item.getItem().getSkills(ItemSkillType.ON_BLESSING);
if (onEnchantSkills != null)
{
for (ItemSkillHolder holder : onEnchantSkills)
@ -527,6 +562,29 @@ public abstract class Inventory extends ItemContainer
}
}
}
if (onBlessingSkills != null)
{
for (ItemSkillHolder holder : onBlessingSkills)
{
if (player.getSkillLevel(holder.getSkillId()) >= holder.getSkillLevel())
{
continue;
}
// Add skills bestowed from +4 armor
if (item.isBlessed())
{
final Skill skill = holder.getSkill();
// Check passive skill conditions.
if (skill.isPassive() && !skill.checkConditions(SkillConditionScope.PASSIVE, player, player))
{
continue;
}
player.addSkill(skill, false);
update = true;
}
}
}
// Apply enchant stats
item.applyEnchantStats();
@ -576,11 +634,39 @@ public abstract class Inventory extends ItemContainer
for (ItemInstance equipped : inventory.getPaperdollItems())
{
final List<ItemSkillHolder> otherEnchantSkills = equipped.getItem().getSkills(ItemSkillType.ON_ENCHANT);
if (otherEnchantSkills == null)
final List<ItemSkillHolder> otherBlessingSkills = equipped.getItem().getSkills(ItemSkillType.ON_BLESSING);
if ((otherEnchantSkills == null) && (otherBlessingSkills == null))
{
continue;
}
if (otherBlessingSkills != null)
{
for (ItemSkillHolder holder : otherBlessingSkills)
{
if (player.getSkillLevel(holder.getSkillId()) >= holder.getSkillLevel())
{
continue;
}
// Add skills bestowed from +4 armor
if (equipped.isBlessed())
{
final Skill skill = holder.getSkill();
// Check passive skill conditions.
if (skill.isPassive() && !skill.checkConditions(SkillConditionScope.PASSIVE, player, player))
{
continue;
}
player.addSkill(skill, false);
update = true;
}
}
}
if (otherEnchantSkills != null)
{
for (ItemSkillHolder holder : otherEnchantSkills)
{
if (player.getSkillLevel(holder.getSkillId()) >= holder.getSkillLevel())
@ -602,6 +688,7 @@ public abstract class Inventory extends ItemContainer
}
}
}
}
// Apply skill, if item has "skills on equip" and it is not a secondary agathion.
if ((slot < PAPERDOLL_AGATHION2) || (slot > PAPERDOLL_AGATHION5))

View File

@ -68,6 +68,7 @@ public class WarehouseItem
private final Collection<EnsoulOption> _soulCrystalSpecialOptions;
private final int _time;
private final boolean _isBlessed;
public WarehouseItem(ItemInstance item)
{
@ -93,6 +94,7 @@ public class WarehouseItem
_enchantOptions = item.getEnchantOptions();
_soulCrystalOptions = item.getSpecialAbilities();
_soulCrystalSpecialOptions = item.getAdditionalSpecialAbilities();
_isBlessed = item.isBlessed();
}
/**
@ -289,6 +291,11 @@ public class WarehouseItem
return _time;
}
public boolean isBlessed()
{
return _isBlessed;
}
/**
* @return the name of the item
*/

View File

@ -63,6 +63,7 @@ public abstract class AbstractEnchantItem
private final int _maxEnchantLevel;
private final int _safeEnchantLevel;
private final double _bonusRate;
private final boolean _isBlessed;
public AbstractEnchantItem(StatSet set)
{
@ -80,6 +81,7 @@ public abstract class AbstractEnchantItem
_maxEnchantLevel = set.getInt("maxEnchant", 127);
_safeEnchantLevel = set.getInt("safeEnchant", 0);
_bonusRate = set.getDouble("bonusRate", 0);
_isBlessed = set.getBoolean("isBlessed", false);
}
/**
@ -189,4 +191,9 @@ public abstract class AbstractEnchantItem
}
return false;
}
public boolean isActionBlessed()
{
return _isBlessed;
}
}

View File

@ -19,6 +19,7 @@ package org.l2jmobius.gameserver.model.items.enchant;
import java.util.HashSet;
import java.util.Set;
import org.l2jmobius.Config;
import org.l2jmobius.commons.util.Rnd;
import org.l2jmobius.gameserver.data.xml.EnchantItemData;
import org.l2jmobius.gameserver.data.xml.EnchantItemGroupsData;
@ -161,6 +162,10 @@ public class EnchantScroll extends AbstractEnchantItem
}
if (_items == null)
{
if (isActionBlessed() && itemToEnchant.isWeapon() && (itemToEnchant.getItem().getCrystalType() == getGrade()))
{
return true;
}
for (EnchantScroll scroll : EnchantItemData.getInstance().getScrolls())
{
if (scroll.getId() == getId())
@ -233,4 +238,26 @@ public class EnchantScroll extends AbstractEnchantItem
final boolean success = (random < finalChance);
return success ? EnchantResultType.SUCCESS : EnchantResultType.FAILURE;
}
public EnchantResultType calculateSuccess(PlayerInstance player, ItemInstance enchantItem)
{
if (!isActionBlessed() || !enchantItem.isWeapon())
{
return EnchantResultType.ERROR;
}
final double chance = Config.BLESSING_CHANCE;
if (chance == -1)
{
return EnchantResultType.ERROR;
}
final int crystalLevel = enchantItem.getItem().getCrystalType().getLevel();
final double enchantRateStat = (crystalLevel > CrystalType.NONE.getLevel()) && (crystalLevel < CrystalType.EVENT.getLevel()) ? player.getStat().getValue(Stat.ENCHANT_RATE) : 0;
final double bonusRate = getBonusRate();
final double finalChance = Math.min(chance + bonusRate + enchantRateStat, 100);
final double random = 100 * Rnd.nextDouble();
final boolean success = (random < finalChance);
return success ? EnchantResultType.SUCCESS : EnchantResultType.FAILURE;
}
}

View File

@ -182,6 +182,7 @@ public class ItemInstance extends WorldObject
private final List<Options> _enchantOptions = new ArrayList<>();
private final EnsoulOption[] _ensoulOptions = new EnsoulOption[2];
private final EnsoulOption[] _ensoulSpecialOptions = new EnsoulOption[1];
private boolean _isBlessed = false;
/**
* Constructor of the ItemInstance from the objectId and the itemId.
@ -256,6 +257,8 @@ public class ItemInstance extends WorldObject
restoreAttributes();
restoreSpecialAbilities();
}
_isBlessed = getVariables().getBoolean(ItemVariables.BLESSED, false);
}
/**
@ -2546,4 +2549,25 @@ public class ItemInstance extends WorldObject
}
}
}
public boolean isBlessed()
{
return _isBlessed;
}
public void setBlessed(boolean blessed)
{
_isBlessed = blessed;
final ItemVariables vars = getVariables();
if (!blessed)
{
vars.remove(ItemVariables.BLESSED);
}
else
{
vars.set(ItemVariables.BLESSED, true);
}
vars.storeMe();
}
}

View File

@ -45,6 +45,7 @@ public class ItemVariables extends AbstractVariables
public static final String VISUAL_ID = "visualId";
public static final String VISUAL_APPEARANCE_STONE_ID = "visualAppearanceStoneId";
public static final String VISUAL_APPEARANCE_LIFE_TIME = "visualAppearanceLifetime";
public static final String BLESSED = "blessed";
public ItemVariables(int objectId)
{

View File

@ -39,6 +39,9 @@ import org.l2jmobius.gameserver.network.clientpackets.attributechange.RequestCha
import org.l2jmobius.gameserver.network.clientpackets.attributechange.SendChangeAttributeTargetItem;
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExAutoPlaySetting;
import org.l2jmobius.gameserver.network.clientpackets.autoplay.ExRequestActivateAutoShortcut;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionCancel;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionEnchant;
import org.l2jmobius.gameserver.network.clientpackets.blessing.RequestBlessOptionPutItem;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCancelCuriousHouse;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestCuriousHouseHtml;
import org.l2jmobius.gameserver.network.clientpackets.ceremonyofchaos.RequestJoinCuriousHouse;
@ -579,9 +582,9 @@ public enum ExIncomingPackets implements IIncomingPackets<GameClient>
EX_MABLE_GAME_RESET(0x1BC, null, ConnectionState.IN_GAME),
EX_MABLE_GAME_CLOSE(0x1BD, null, ConnectionState.IN_GAME),
EX_RETURN_TO_ORIGIN(0x1BE, null, ConnectionState.IN_GAME),
EX_BLESS_OPTION_PUT_ITEM(0x1BF, null, ConnectionState.IN_GAME),
EX_BLESS_OPTION_ENCHANT(0x1C0, null, ConnectionState.IN_GAME),
EX_BLESS_OPTION_CANCEL(0x1C1, null, ConnectionState.IN_GAME),
EX_BLESS_OPTION_PUT_ITEM(0x1BF, RequestBlessOptionPutItem::new, ConnectionState.IN_GAME),
EX_BLESS_OPTION_ENCHANT(0x1C0, RequestBlessOptionEnchant::new, ConnectionState.IN_GAME),
EX_BLESS_OPTION_CANCEL(0x1C1, RequestBlessOptionCancel::new, ConnectionState.IN_GAME),
EX_PVP_RANKING_MY_INFO(0x1C2, null, ConnectionState.IN_GAME),
EX_PVP_RANKING_LIST(0x1C3, null, ConnectionState.IN_GAME),
EX_ACQUIRE_PET_SKILL(0x1C4, null, ConnectionState.IN_GAME),

View File

@ -0,0 +1,48 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.network.clientpackets.blessing;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.blessing.ExBlessOptionCancel;
/**
* Written by Horus, on 17.04.2021
*/
public class RequestBlessOptionCancel implements IClientIncomingPacket
{
@Override
public boolean read(GameClient client, PacketReader packet)
{
return true;
}
@Override
public void run(GameClient client)
{
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
}
player.sendPacket(new ExBlessOptionCancel(1));
}
}

View File

@ -0,0 +1,205 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.network.clientpackets.blessing;
import java.util.Map;
import java.util.Optional;
import org.l2jmobius.Config;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.data.xml.EnchantItemData;
import org.l2jmobius.gameserver.enums.ItemSkillType;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.actor.request.BlessingItemRequest;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.items.enchant.EnchantResultType;
import org.l2jmobius.gameserver.model.items.enchant.EnchantScroll;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.model.skills.CommonSkill;
import org.l2jmobius.gameserver.model.skills.Skill;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.EnchantResult;
import org.l2jmobius.gameserver.network.serverpackets.ExItemAnnounce;
import org.l2jmobius.gameserver.network.serverpackets.MagicSkillUse;
import org.l2jmobius.gameserver.network.serverpackets.SystemMessage;
import org.l2jmobius.gameserver.network.serverpackets.blessing.ExBlessOptionEnchant;
import org.l2jmobius.gameserver.network.serverpackets.blessing.ExBlessOptionPutItem;
import org.l2jmobius.gameserver.util.Broadcast;
import org.l2jmobius.gameserver.util.Util;
/**
* Written by Horus, on 17.04.2021
*/
public class RequestBlessOptionEnchant implements IClientIncomingPacket
{
private int _itemObjId;
@Override
public boolean read(GameClient client, PacketReader packet)
{
_itemObjId = packet.readD();
return true;
}
@Override
public void run(GameClient client)
{
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
}
final ItemInstance targetInstance = player.getInventory().getItemByObjectId(_itemObjId);
if (targetInstance == null)
{
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
return;
}
final Optional<Map.Entry<Integer, EnchantScroll>> targetScroll = EnchantItemData.getInstance().getBlessingScrolls(targetInstance.getId()).stream().filter(it -> it.getValue().getGrade() == targetInstance.getItem().getCrystalType()).findFirst();
if (targetScroll.isEmpty())
{
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
return;
}
player.addRequest(new BlessingItemRequest(player, targetInstance.getObjectId()));
final BlessingItemRequest request = player.getRequest(BlessingItemRequest.class);
if ((request == null) || request.isProcessing())
{
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
return;
}
request.setBlessingItem(_itemObjId);
request.setProcessing(true);
request.setTimestamp(System.currentTimeMillis());
if (!player.isOnline() || client.isDetached())
{
player.removeRequest(request.getClass());
return;
}
if (player.isInStoreMode())
{
player.sendPacket(SystemMessageId.YOU_CANNOT_ENCHANT_WHILE_OPERATING_A_PRIVATE_STORE_OR_PRIVATE_WORKSHOP);
player.removeRequest(request.getClass());
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
return;
}
final ItemInstance item = request.getBlessingItem();
final ItemInstance scroll = request.getBlessScroll();
if ((item == null) || (scroll == null))
{
player.removeRequest(request.getClass());
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
return;
}
// first validation check - also over enchant check
if (item.isBlessed())
{
client.sendPacket(SystemMessageId.AUGMENTATION_REQUIREMENTS_ARE_NOT_FULFILLED);
player.removeRequest(request.getClass());
player.sendPacket(new ExBlessOptionPutItem(0));
return;
}
// attempting to destroy scroll
if (player.getInventory().destroyItem("Blessing", scroll.getObjectId(), 1, player, item) == null)
{
client.sendPacket(SystemMessageId.INCORRECT_ITEM_COUNT_2);
Util.handleIllegalPlayerAction(player, "Player " + player.getName() + " tried to bless with a scroll he doesn't have", Config.DEFAULT_PUNISH);
player.removeRequest(request.getClass());
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
return;
}
// last validation check
if ((item.getOwnerId() != player.getObjectId()))
{
client.sendPacket(SystemMessageId.AUGMENTATION_REQUIREMENTS_ARE_NOT_FULFILLED);
player.removeRequest(request.getClass());
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
return;
}
final EnchantResultType resultType = targetScroll.get().getValue().calculateSuccess(player, item);
switch (resultType)
{
case ERROR ->
{
player.sendPacket(SystemMessageId.AUGMENTATION_REQUIREMENTS_ARE_NOT_FULFILLED);
player.sendPacket(new ExBlessOptionEnchant(EnchantResult.ERROR));
}
case SUCCESS ->
{
final Item it = item.getItem();
// Increase enchant level only if scroll's base template has chance, some armors can success over +20 but they shouldn't have increased.
item.setBlessed(true);
item.updateDatabase();
player.sendPacket(new ExBlessOptionEnchant(1));
// announce the success
if ((item.getEnchantLevel() >= (item.isArmor() ? Config.MIN_ARMOR_ENCHANT_ANNOUNCE : Config.MIN_WEAPON_ENCHANT_ANNOUNCE)) //
&& (item.getEnchantLevel() <= (item.isArmor() ? Config.MAX_ARMOR_ENCHANT_ANNOUNCE : Config.MAX_WEAPON_ENCHANT_ANNOUNCE)))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.C1_HAS_SUCCESSFULLY_ENCHANTED_A_S2_S3);
sm.addString(player.getName());
sm.addInt(item.getEnchantLevel());
sm.addItemName(item);
player.broadcastPacket(sm);
Broadcast.toAllOnlinePlayers(new ExItemAnnounce(player, item, ExItemAnnounce.ENCHANT));
final Skill skill = CommonSkill.FIREWORK.getSkill();
if (skill != null)
{
player.broadcastPacket(new MagicSkillUse(player, player, skill.getId(), skill.getLevel(), skill.getHitTime(), skill.getReuseDelay()));
}
}
if (item.isEquipped())
{
if (item.isArmor())
{
it.forEachSkill(ItemSkillType.ON_BLESSING, holder ->
{
player.addSkill(holder.getSkill(), false);
player.sendSkillList();
});
}
player.broadcastUserInfo(); // update user info
}
}
case FAILURE ->
{
player.sendPacket(new ExBlessOptionEnchant(0));
}
}
player.sendItemList();
request.setProcessing(false);
player.removeRequest(request.getClass());
player.broadcastUserInfo();
}
}

View File

@ -0,0 +1,72 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.network.clientpackets.blessing;
import org.l2jmobius.commons.network.PacketReader;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.items.instance.ItemInstance;
import org.l2jmobius.gameserver.network.GameClient;
import org.l2jmobius.gameserver.network.SystemMessageId;
import org.l2jmobius.gameserver.network.clientpackets.IClientIncomingPacket;
import org.l2jmobius.gameserver.network.serverpackets.blessing.ExBlessOptionPutItem;
/**
* Written by Horus, on 17.04.2021
*/
public class RequestBlessOptionPutItem implements IClientIncomingPacket
{
private int _objectId;
@Override
public boolean read(GameClient client, PacketReader packet)
{
_objectId = packet.readD();
return true;
}
@Override
public void run(GameClient client)
{
final PlayerInstance player = client.getPlayer();
if (player == null)
{
return;
}
final ItemInstance item = player.getInventory().getItemByObjectId(_objectId);
if (item == null)
{
return;
}
if (player.isProcessingTransaction() || player.isInStoreMode())
{
client.sendPacket(SystemMessageId.YOU_CANNOT_ENCHANT_WHILE_OPERATING_A_PRIVATE_STORE_OR_PRIVATE_WORKSHOP);
return;
}
// first validation check - also over enchant check
if (item.isBlessed())
{
client.sendPacket(SystemMessageId.AUGMENTATION_REQUIREMENTS_ARE_NOT_FULFILLED);
player.sendPacket(new ExBlessOptionPutItem(0));
return;
}
player.sendPacket(new ExBlessOptionPutItem(1));
}
}

View File

@ -72,8 +72,7 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
{
final int mask = calculateMask(item);
packet.writeC(mask);
packet.writeC(item.getItem().isBlessed() ? 0x01 : 0x00); // 286 protocol
packet.writeH(mask);
packet.writeD(item.getObjectId()); // ObjectId
packet.writeD(item.getItem().getDisplayId()); // ItemId
packet.writeC(item.getItem().isQuestItem() || (item.getEquipped() == 1) ? 0xFF : item.getLocation()); // T1
@ -111,9 +110,9 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
{
writeItemEnsoulOptions(packet, item);
}
if (item.getItem().isBlessed())
if (containsMask(mask, ItemListType.BLESSED))
{
packet.writeC(item.getItem().isBlessed() ? 0x01 : 0x00);
packet.writeC(0x01);
}
}
@ -121,8 +120,7 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
{
final int mask = calculateMask(item);
packet.writeC(mask);
packet.writeC(item.getItem().isBlessed() ? 0x01 : 0x00); // 286 protocol
packet.writeH(mask);
packet.writeD(item.getObjectId()); // ObjectId
packet.writeD(item.getItem().getDisplayId()); // ItemId
packet.writeC(item.getItem().isQuestItem() || (item.getEquipped() == 1) ? 0xFF : item.getLocation()); // T1
@ -160,9 +158,9 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
{
writeItemEnsoulOptions(packet, item);
}
if (item.getItem().isBlessed())
if (containsMask(mask, ItemListType.BLESSED))
{
packet.writeC(item.getItem().isBlessed() ? 0x01 : 0x00);
packet.writeC(0x01);
}
}
@ -201,6 +199,11 @@ public abstract class AbstractItemPacket extends AbstractMaskPacket<ItemListType
mask |= ItemListType.SOUL_CRYSTAL.getMask();
}
if (item.isBlessed())
{
mask |= ItemListType.BLESSED.getMask();
}
return mask;
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.network.serverpackets.blessing;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.network.OutgoingPackets;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
/**
* Written by Horus, on 17.04.2021
*/
public class ExBlessOptionCancel implements IClientOutgoingPacket
{
private final int _result;
public ExBlessOptionCancel(int result)
{
_result = result;
}
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.EX_BLESS_OPTION_CANCEL.writeId(packet);
packet.writeC(_result);
return true;
}
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.network.serverpackets.blessing;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.network.OutgoingPackets;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
/**
* Written by Horus, on 17.04.2021
*/
public class ExBlessOptionEnchant implements IClientOutgoingPacket
{
private final int _result;
public ExBlessOptionEnchant(int result)
{
_result = result;
}
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.EX_BLESS_OPTION_ENCHANT.writeId(packet);
packet.writeD(_result);
return true;
}
}

View File

@ -0,0 +1,43 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.network.serverpackets.blessing;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.network.OutgoingPackets;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
/**
* Written by Horus, on 17.04.2021
*/
public class ExBlessOptionPutItem implements IClientOutgoingPacket
{
private final int _result;
public ExBlessOptionPutItem(int result)
{
_result = result;
}
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.EX_BLESS_OPTION_PUT_ITEM.writeId(packet);
packet.writeC(_result);
return true;
}
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.l2jmobius.gameserver.network.serverpackets.blessing;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.network.OutgoingPackets;
import org.l2jmobius.gameserver.network.serverpackets.IClientOutgoingPacket;
/**
* Written by Horus, on 17.04.2021
*/
public class ExOpenBlessOptionScroll implements IClientOutgoingPacket
{
private final int _itemId;
public ExOpenBlessOptionScroll(int itemId)
{
_itemId = itemId;
}
@Override
public boolean write(PacketWriter packet)
{
OutgoingPackets.EX_OPEN_BLESS_OPTION_SCROLL.writeId(packet);
packet.writeD(_itemId);
return true;
}
}