Alchemy transmutation support.

Need to implement transmute skills.
I have added skill 17928 as example.
This commit is contained in:
MobiusDev
2015-05-18 01:56:28 +00:00
parent ddc3ef9037
commit 6a2082a86f
10 changed files with 505 additions and 3 deletions

View File

@ -1303,6 +1303,16 @@ public abstract class DocumentBase
set.set("capsuled_items_skill", value);
}
protected void setAlchemyTransmuteIngredientData(StatsSet set, String value)
{
set.set("alchemyTransmuteIngredients", value);
}
protected void setAlchemyTransmuteProductData(StatsSet set, String value)
{
set.set("alchemyTransmuteProduction", value);
}
protected String getValue(String value, Object template)
{
// is it a table?

View File

@ -235,6 +235,40 @@ public class DocumentSkill extends DocumentBase
}
}
}
for (int i = 1; i <= lastLvl; i++)
{
for (n = first; n != null; n = n.getNextSibling())
{
if ("set".equalsIgnoreCase(n.getNodeName()))
{
if ("alchemyTransmuteIngredients".equalsIgnoreCase(n.getAttributes().getNamedItem("name").getNodeValue()))
{
setAlchemyTransmuteIngredientData(_currentSkill.sets[i - 1], getTableValue("#alchemyTransmuteIngredients", i));
}
else
{
parseBeanSet(n, _currentSkill.sets[i - 1], i);
}
}
}
}
for (int i = 1; i <= lastLvl; i++)
{
for (n = first; n != null; n = n.getNextSibling())
{
if ("set".equalsIgnoreCase(n.getNodeName()))
{
if ("alchemyTransmuteProduction".equalsIgnoreCase(n.getAttributes().getNamedItem("name").getNodeValue()))
{
setAlchemyTransmuteProductData(_currentSkill.sets[i - 1], getTableValue("#alchemyTransmuteProduction", i));
}
else
{
parseBeanSet(n, _currentSkill.sets[i - 1], i);
}
}
}
}
for (int i = 0; i < enchantLevels1; i++)
{
_currentSkill.enchsets1[i] = new StatsSet();

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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 com.l2jserver.gameserver.model;
import java.util.List;
import com.l2jserver.gameserver.model.holders.ItemHolder;
/**
* Alchemy transmute skill DTO.
* @author Mobius
*/
public class L2AlchemySkill
{
private final List<ItemHolder> _ingredients;
private final ItemHolder _product;
public L2AlchemySkill(List<ItemHolder> ingredients, ItemHolder product)
{
_ingredients = ingredients;
_product = product;
}
public List<ItemHolder> getIngridientItems()
{
return _ingredients;
}
public ItemHolder getTransmutedItem()
{
return _product;
}
}

View File

@ -39,6 +39,7 @@ import com.l2jserver.gameserver.handler.ITargetTypeHandler;
import com.l2jserver.gameserver.handler.TargetHandler;
import com.l2jserver.gameserver.instancemanager.HandysBlockCheckerManager;
import com.l2jserver.gameserver.model.ArenaParticipantsHolder;
import com.l2jserver.gameserver.model.L2AlchemySkill;
import com.l2jserver.gameserver.model.L2ExtractableProductItem;
import com.l2jserver.gameserver.model.L2ExtractableSkill;
import com.l2jserver.gameserver.model.L2Object;
@ -208,6 +209,7 @@ public final class Skill implements IIdentifiable
private final boolean _simultaneousCast;
private L2ExtractableSkill _extractableItems = null;
private L2AlchemySkill _transmutedItems = null;
private final String _icon;
@ -385,6 +387,13 @@ public final class Skill implements IIdentifiable
_extractableItems = parseExtractableSkill(_id, _level, capsuled_items);
}
String alchemyTransmuteIngredients = set.getString("alchemyTransmuteIngredients", null);
String alchemyTransmuteProducts = set.getString("alchemyTransmuteProduction", null);
if ((alchemyTransmuteIngredients != null) && (alchemyTransmuteProducts != null))
{
_transmutedItems = parseAlchemySkill(_id, _level, alchemyTransmuteIngredients, alchemyTransmuteProducts);
}
_icon = set.getString("icon", "icon.skill0000");
_channelingSkillId = set.getInt("channelingSkillId", 0);
@ -1706,6 +1715,46 @@ public final class Skill implements IIdentifiable
return new L2ExtractableSkill(SkillData.getSkillHashCode(skillId, skillLvl), products);
}
/**
* Parse an Alchemy transmute skill.
* @param skillId the skill Id
* @param skillLvl the skill level
* @param alchemyTransmuteIngredients the values to parse
* @param alchemyTransmuteProducts the values to parse
* @return the parsed transmute skill
*/
private L2AlchemySkill parseAlchemySkill(int skillId, int skillLvl, String alchemyTransmuteIngredients, String alchemyTransmuteProducts)
{
final String[] ingrLists = alchemyTransmuteIngredients.split(";");
final String[] prodLists = alchemyTransmuteProducts.split(";");
List<ItemHolder> ingridients = new ArrayList<>();
ItemHolder product = null;
String[] ingrData;
for (String ingrList : ingrLists)
{
ingrData = ingrList.split(",");
if (ingrData.length < 2)
{
_log.warning("Alchemy skills data: Error in Skill Id: " + skillId + " Level: " + skillLvl + " -> wrong seperator!");
}
ingridients.add(new ItemHolder(Integer.parseInt(ingrData[0]), Integer.parseInt(ingrData[1])));
}
String[] prodData;
for (String prodList : prodLists)
{
prodData = prodList.split(",");
if (prodData.length < 2)
{
_log.warning("Alchemy skills data: Error in Skill Id: " + skillId + " Level: " + skillLvl + " -> wrong seperator!");
}
product = new ItemHolder(Integer.parseInt(prodData[0]), Integer.parseInt(prodData[1]));
}
return new L2AlchemySkill(ingridients, product);
}
/**
* Parses all the abnormal visual effects.
* @param abnormalVisualEffects the abnormal visual effects list
@ -1741,6 +1790,11 @@ public final class Skill implements IIdentifiable
return _extractableItems;
}
public L2AlchemySkill getAlchemySkill()
{
return _transmutedItems;
}
/**
* @param effectType Effect type to check if its present on this skill effects.
* @param effectTypes Effect types to check if are present on this skill effects.

View File

@ -1651,10 +1651,10 @@ public final class L2GamePacketHandler implements IPacketHandler<L2GameClient>,
msg = new RequestAlchemySkillList();
break;
case 0x100:
// msg = new RequestAlchemyTryMixCube();
msg = new RequestAlchemyTryMixCube();
break;
case 0x101:
// msg = new RequestAlchemyConversion();
msg = new RequestAlchemyConversion();
break;
case 0x102:
// msg = new SendExecutedUIEventsCount();

View File

@ -0,0 +1,131 @@
/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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 com.l2jserver.gameserver.network.clientpackets;
import com.l2jserver.Config;
import com.l2jserver.gameserver.datatables.SkillData;
import com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.model.holders.ItemHolder;
import com.l2jserver.gameserver.model.items.instance.L2ItemInstance;
import com.l2jserver.gameserver.model.skills.Skill;
import com.l2jserver.gameserver.network.SystemMessageId;
import com.l2jserver.gameserver.network.serverpackets.ExAlchemyConversion;
import com.l2jserver.gameserver.network.serverpackets.InventoryUpdate;
import com.l2jserver.gameserver.network.serverpackets.ItemList;
import com.l2jserver.util.Rnd;
/**
* @author GenCloud, Mobius
*/
public class RequestAlchemyConversion extends L2GameClientPacket
{
@SuppressWarnings("unused")
private int _unk;
private int _skillId;
private int _skillLevel;
private int _skillUseCount;
private long _resultItemCount = 0;
private long _resultFailCount = 0;
@Override
protected void readImpl()
{
_skillUseCount = readD();
_unk = readH(); // Unk = 10; xs is
_skillId = readD();
_skillLevel = readD();
readB(new byte[28]);
}
@Override
protected void runImpl()
{
L2PcInstance activeChar = getClient().getActiveChar();
Skill skill = SkillData.getInstance().getSkill(_skillId, _skillLevel);
L2ItemInstance invitem = null;
if ((activeChar == null) || (activeChar.getRace() != Race.ERTHEIA))
{
return;
}
double chance = 100; // 100% ?
boolean hasIngidients = true;
for (ItemHolder item : skill.getAlchemySkill().getIngridientItems())
{
if ((activeChar.getInventory().getInventoryItemCount(item.getId(), -1) * _skillUseCount) < (item.getCount() * _skillUseCount))
{
hasIngidients = false;
break;
}
}
if (!hasIngidients)
{
activeChar.sendPacket(SystemMessageId.PLEASE_ENTER_THE_COMBINATION_INGREDIENTS);
return;
}
for (int i = 0; i < _skillUseCount; i++)
{
boolean ok = Rnd.get(1, 100) < chance;
skill.getAlchemySkill().getIngridientItems().forEach(holder -> activeChar.getInventory().destroyItemByItemId("Alchemy", holder.getId(), holder.getCount(), activeChar, null));
if (ok)
{
_resultItemCount = skill.getAlchemySkill().getTransmutedItem().getCount() * _skillUseCount;
}
else
{
_resultFailCount++; // ?
}
}
if (_resultItemCount > 0)
{
invitem = activeChar.getInventory().addItem("Alchemy", skill.getAlchemySkill().getTransmutedItem().getId(), _resultItemCount, activeChar, null);
}
if (_resultFailCount > 0) // ?
{
invitem = activeChar.getInventory().destroyItemByItemId("Alchemy", skill.getAlchemySkill().getTransmutedItem().getId(), _resultFailCount, activeChar, null);
activeChar.sendPacket(SystemMessageId.FAILURE_TO_TRANSMUTE_WILL_DESTROY_SOME_INGREDIENTS);
}
activeChar.sendPacket(new ExAlchemyConversion((int) _resultItemCount, (int) _resultFailCount));
if (Config.FORCE_INVENTORY_UPDATE)
{
activeChar.sendPacket(new ItemList(activeChar, false));
}
else
{
InventoryUpdate playerIU = new InventoryUpdate();
playerIU.addItem(invitem);
sendPacket(playerIU);
}
}
@Override
public String getType()
{
return getClass().getSimpleName();
}
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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 com.l2jserver.gameserver.network.clientpackets;
import com.l2jserver.gameserver.enums.Race;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.gameserver.network.serverpackets.ExTryMixCube;
import com.l2jserver.gameserver.network.serverpackets.ItemList;
/**
* @author GenCloud
*/
public class RequestAlchemyTryMixCube extends L2GameClientPacket
{
private int _activeItems;
private int[] _objId;
private long[] _itemCounts;
private long _allPrice = 0;
private long _stoneCount;
private final int _stoneID = 39461;
@SuppressWarnings("unused")
private final boolean _isActiveMegaStone = false;
@Override
protected void readImpl()
{
_activeItems = readD();
_objId = new int[5];
_itemCounts = new long[5];
switch (_activeItems)
{
case 1:
{
_objId[1] = readD();
_itemCounts[1] = readQ();
break;
}
case 2:
{
_objId[1] = readD();
_itemCounts[1] = readQ();
_objId[2] = readD();
_itemCounts[2] = readQ();
break;
}
case 3:
{
_objId[1] = readD();
_itemCounts[1] = readQ();
_objId[2] = readD();
_itemCounts[2] = readQ();
_objId[3] = readD();
_itemCounts[3] = readQ();
break;
}
case 4:
{
_objId[1] = readD();
_itemCounts[1] = readQ();
_objId[2] = readD();
_itemCounts[2] = readQ();
_objId[3] = readD();
_itemCounts[3] = readQ();
_objId[4] = readD();
_itemCounts[4] = readQ();
break;
}
}
}
@Override
protected void runImpl()
{
final L2PcInstance activeChar = getClient().getActiveChar();
if ((activeChar == null) || (activeChar.getRace() != Race.ERTHEIA))
{
return;
}
for (int i = 1; i <= _activeItems; i++)
{
_allPrice = _allPrice + (_itemCounts[i] * activeChar.getInventory().getItemByObjectId(_objId[i]).getReferencePrice());
activeChar.getInventory().destroyItem("Alchemy", _objId[i], _itemCounts[i], activeChar, null);
}
_stoneCount = _allPrice / 10000; // TODO: formula is not the correct ratio
activeChar.getInventory().addItem("Alchemy", _stoneID, _stoneCount, activeChar, null);
activeChar.sendPacket(new ExTryMixCube(_stoneCount, _stoneID, 0));
activeChar.sendPacket(new ItemList(activeChar, false));
}
@Override
public String getType()
{
return getClass().getSimpleName();
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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 com.l2jserver.gameserver.network.serverpackets;
/**
* @author GenCloud
*/
public class ExAlchemyConversion extends L2GameServerPacket
{
private final int _itemCount;
private final int _failCount;
public ExAlchemyConversion(int _resultItemCount, int failCount)
{
_itemCount = _resultItemCount;
_failCount = failCount;
}
@Override
protected void writeImpl()
{
writeC(0x00); // Unk
writeD(_itemCount);
writeD(_failCount);
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server 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.
*
* L2J Server 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 com.l2jserver.gameserver.network.serverpackets;
/**
* @author GenCloud
*/
public class ExTryMixCube extends L2GameServerPacket
{
private final int _stoneID;
private final long _count;
@SuppressWarnings("unused")
private final int _typePacket;
public ExTryMixCube(long count, int stoneId, int type)
{
_count = count;
_typePacket = type;
_stoneID = stoneId;
}
@Override
protected void writeImpl()
{
writeC(0x00); // Unk
writeC(0x01); // Type
writeD(0x00); // Unk
writeD(_stoneID); // StoneID
writeQ(_count); // Count
}
}