Support for henna duration and skills.
This commit is contained in:
parent
c777a4609a
commit
9894a46ce7
@ -26,20 +26,19 @@
|
|||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:attribute name="count" type="xs:positiveInteger" use="required" />
|
<xs:attribute name="count" type="xs:integer" use="required" />
|
||||||
<xs:attribute name="fee" type="xs:integer" use="required" />
|
<xs:attribute name="fee" type="xs:integer" use="required" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="skills" minOccurs="0">
|
<xs:element name="duration" minOccurs="0" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:attribute name="time" type="xs:positiveInteger" use="required" />
|
||||||
<xs:element name="skill">
|
</xs:complexType>
|
||||||
<xs:complexType>
|
</xs:element>
|
||||||
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
<xs:element name="skill" minOccurs="0" maxOccurs="unbounded">
|
||||||
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
<xs:complexType>
|
||||||
</xs:complexType>
|
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
||||||
</xs:element>
|
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
||||||
</xs:sequence>
|
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
@ -31,13 +31,14 @@ import com.l2jmobius.commons.util.IGameXmlReader;
|
|||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
import com.l2jmobius.gameserver.model.items.L2Henna;
|
import com.l2jmobius.gameserver.model.items.L2Henna;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds the henna related information.<br>
|
* This class holds the henna related information.<br>
|
||||||
* Cost and required amount to add the henna to the player.<br>
|
* Cost and required amount to add the henna to the player.<br>
|
||||||
* Cost and retrieved amount for removing the henna from the player.<br>
|
* Cost and retrieved amount for removing the henna from the player.<br>
|
||||||
* Allowed classes to wear each henna.
|
* Allowed classes to wear each henna.
|
||||||
* @author Zoey76
|
* @author Zoey76, Mobius
|
||||||
*/
|
*/
|
||||||
public final class HennaData implements IGameXmlReader
|
public final class HennaData implements IGameXmlReader
|
||||||
{
|
{
|
||||||
@ -87,6 +88,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
{
|
{
|
||||||
final StatsSet set = new StatsSet();
|
final StatsSet set = new StatsSet();
|
||||||
final List<ClassId> wearClassIds = new ArrayList<>();
|
final List<ClassId> wearClassIds = new ArrayList<>();
|
||||||
|
final List<Skill> skills = new ArrayList<>();
|
||||||
NamedNodeMap attrs = d.getAttributes();
|
NamedNodeMap attrs = d.getAttributes();
|
||||||
Node attr;
|
Node attr;
|
||||||
for (int i = 0; i < attrs.getLength(); i++)
|
for (int i = 0; i < attrs.getLength(); i++)
|
||||||
@ -126,6 +128,17 @@ public final class HennaData implements IGameXmlReader
|
|||||||
set.set("cancel_fee", attr.getNodeValue());
|
set.set("cancel_fee", attr.getNodeValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "duration":
|
||||||
|
{
|
||||||
|
attr = attrs.getNamedItem("time"); // in minutes
|
||||||
|
set.set("duration", attr.getNodeValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "skill":
|
||||||
|
{
|
||||||
|
skills.add(SkillData.getInstance().getSkill(parseInteger(attrs, "id"), parseInteger(attrs, "level")));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "classId":
|
case "classId":
|
||||||
{
|
{
|
||||||
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
||||||
@ -134,6 +147,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final L2Henna henna = new L2Henna(set);
|
final L2Henna henna = new L2Henna(set);
|
||||||
|
henna.setSkills(skills);
|
||||||
henna.setWearClassIds(wearClassIds);
|
henna.setWearClassIds(wearClassIds);
|
||||||
_hennaList.put(henna.getDyeId(), henna);
|
_hennaList.put(henna.getDyeId(), henna);
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,7 @@ import com.l2jmobius.gameserver.model.actor.status.PcStatus;
|
|||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
||||||
|
import com.l2jmobius.gameserver.model.actor.tasks.player.HennaDurationTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
||||||
@ -595,9 +596,10 @@ public final class L2PcInstance extends L2Playable
|
|||||||
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
||||||
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
// hennas
|
/** Hennas */
|
||||||
private final L2Henna[] _henna = new L2Henna[3];
|
private final L2Henna[] _henna = new L2Henna[3];
|
||||||
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
||||||
|
private final Map<Integer, ScheduledFuture<?>> _hennaRemoveSchedules = new ConcurrentHashMap<>(3);
|
||||||
|
|
||||||
/** The Pet of the L2PcInstance */
|
/** The Pet of the L2PcInstance */
|
||||||
private L2PetInstance _pet = null;
|
private L2PetInstance _pet = null;
|
||||||
@ -7752,9 +7754,9 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
private void restoreHenna()
|
private void restoreHenna()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
_henna[i] = null;
|
_henna[i - 1] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
@ -7779,7 +7781,28 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_henna[slot - 1] = HennaData.getInstance().getHenna(symbolId);
|
|
||||||
|
final L2Henna henna = HennaData.getInstance().getHenna(symbolId);
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
|
if (remainingTime < 0)
|
||||||
|
{
|
||||||
|
removeHenna(slot);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_hennaRemoveSchedules.put(slot, ThreadPoolManager.schedule(new HennaDurationTask(this, slot), System.currentTimeMillis() + remainingTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
_henna[slot - 1] = henna;
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7835,27 +7858,25 @@ public final class L2PcInstance extends L2Playable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot--;
|
final L2Henna henna = _henna[slot - 1];
|
||||||
|
|
||||||
final L2Henna henna = _henna[slot];
|
|
||||||
if (henna == null)
|
if (henna == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_henna[slot] = null;
|
_henna[slot - 1] = null;
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, slot + 1);
|
statement.setInt(2, slot);
|
||||||
statement.setInt(3, getClassIndex());
|
statement.setInt(3, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.log(Level.SEVERE, "Failed remocing character henna.", e);
|
_log.log(Level.SEVERE, "Failed removing character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
@ -7868,16 +7889,43 @@ public final class L2PcInstance extends L2Playable
|
|||||||
final UserInfo ui = new UserInfo(this, false);
|
final UserInfo ui = new UserInfo(this, false);
|
||||||
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
||||||
sendPacket(ui);
|
sendPacket(ui);
|
||||||
// Add the recovered dyes to the player's inventory and notify them.
|
|
||||||
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
|
||||||
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
|
||||||
|
|
||||||
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
sm.addItemName(henna.getDyeItemId());
|
if ((henna.getDuration() < 0) || (remainingTime > 0))
|
||||||
sm.addLong(henna.getCancelCount());
|
{
|
||||||
sendPacket(sm);
|
// Add the recovered dyes to the player's inventory and notify them.
|
||||||
|
if (henna.getCancelFee() > 0)
|
||||||
|
{
|
||||||
|
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
||||||
|
}
|
||||||
|
if (henna.getCancelCount() > 0)
|
||||||
|
{
|
||||||
|
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
||||||
|
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
||||||
|
sm.addItemName(henna.getDyeItemId());
|
||||||
|
sm.addLong(henna.getCancelCount());
|
||||||
|
sendPacket(sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
||||||
|
|
||||||
|
// Remove henna duration task
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().remove("HennaDuration" + slot);
|
||||||
|
if (_hennaRemoveSchedules.get(slot) != null)
|
||||||
|
{
|
||||||
|
_hennaRemoveSchedules.get(slot).cancel(false);
|
||||||
|
_hennaRemoveSchedules.remove(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
removeSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify to scripts
|
// Notify to scripts
|
||||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
||||||
return true;
|
return true;
|
||||||
@ -7890,11 +7938,11 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
public boolean addHenna(L2Henna henna)
|
public boolean addHenna(L2Henna henna)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (_henna[i] == null)
|
if (_henna[i - 1] == null)
|
||||||
{
|
{
|
||||||
_henna[i] = henna;
|
_henna[i - 1] = henna;
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
recalcHennaStats();
|
recalcHennaStats();
|
||||||
@ -7904,7 +7952,7 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, henna.getDyeId());
|
statement.setInt(2, henna.getDyeId());
|
||||||
statement.setInt(3, i + 1);
|
statement.setInt(3, i);
|
||||||
statement.setInt(4, getClassIndex());
|
statement.setInt(4, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
@ -7913,6 +7961,19 @@ public final class L2PcInstance extends L2Playable
|
|||||||
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().set("HennaDuration" + i, System.currentTimeMillis() + (henna.getDuration() * 60000));
|
||||||
|
_hennaRemoveSchedules.put(i, ThreadPoolManager.schedule(new HennaDurationTask(this, i), System.currentTimeMillis() + (henna.getDuration() * 60000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Send Server->Client HennaInfo packet to this L2PcInstance
|
// Send Server->Client HennaInfo packet to this L2PcInstance
|
||||||
sendPacket(new HennaInfo(this));
|
sendPacket(new HennaInfo(this));
|
||||||
|
|
||||||
|
@ -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 com.l2jmobius.gameserver.model.actor.tasks.player;
|
||||||
|
|
||||||
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class HennaDurationTask implements Runnable
|
||||||
|
{
|
||||||
|
private final L2PcInstance _player;
|
||||||
|
private final int _slot;
|
||||||
|
|
||||||
|
public HennaDurationTask(L2PcInstance player, int slot)
|
||||||
|
{
|
||||||
|
_player = player;
|
||||||
|
_slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.removeHenna(_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
||||||
import com.l2jmobius.gameserver.model.stats.Stats;
|
import com.l2jmobius.gameserver.model.stats.Stats;
|
||||||
|
|
||||||
@ -40,6 +41,8 @@ public class L2Henna
|
|||||||
private final int _wear_count;
|
private final int _wear_count;
|
||||||
private final int _cancel_fee;
|
private final int _cancel_fee;
|
||||||
private final int _cancel_count;
|
private final int _cancel_count;
|
||||||
|
private final int _duration;
|
||||||
|
private final List<Skill> _skills;
|
||||||
private final List<ClassId> _wear_class;
|
private final List<ClassId> _wear_class;
|
||||||
|
|
||||||
public L2Henna(StatsSet set)
|
public L2Henna(StatsSet set)
|
||||||
@ -59,6 +62,8 @@ public class L2Henna
|
|||||||
_wear_count = set.getInt("wear_count");
|
_wear_count = set.getInt("wear_count");
|
||||||
_cancel_fee = set.getInt("cancel_fee");
|
_cancel_fee = set.getInt("cancel_fee");
|
||||||
_cancel_count = set.getInt("cancel_count");
|
_cancel_count = set.getInt("cancel_count");
|
||||||
|
_duration = set.getInt("duration", -1);
|
||||||
|
_skills = new ArrayList<>();
|
||||||
_wear_class = new ArrayList<>();
|
_wear_class = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +133,30 @@ public class L2Henna
|
|||||||
return _cancel_count;
|
return _cancel_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the duration of this dye.
|
||||||
|
*/
|
||||||
|
public int getDuration()
|
||||||
|
{
|
||||||
|
return _duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param skillList the list of skills related to this dye.
|
||||||
|
*/
|
||||||
|
public void setSkills(List<Skill> skillList)
|
||||||
|
{
|
||||||
|
_skills.addAll(skillList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the skills related to this dye.
|
||||||
|
*/
|
||||||
|
public List<Skill> getSkills()
|
||||||
|
{
|
||||||
|
return _skills;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list with the allowed classes to wear this dye.
|
* @return the list with the allowed classes to wear this dye.
|
||||||
*/
|
*/
|
||||||
|
@ -26,20 +26,19 @@
|
|||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:attribute name="count" type="xs:positiveInteger" use="required" />
|
<xs:attribute name="count" type="xs:integer" use="required" />
|
||||||
<xs:attribute name="fee" type="xs:integer" use="required" />
|
<xs:attribute name="fee" type="xs:integer" use="required" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="skills" minOccurs="0">
|
<xs:element name="duration" minOccurs="0" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:attribute name="time" type="xs:positiveInteger" use="required" />
|
||||||
<xs:element name="skill">
|
</xs:complexType>
|
||||||
<xs:complexType>
|
</xs:element>
|
||||||
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
<xs:element name="skill" minOccurs="0" maxOccurs="unbounded">
|
||||||
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
<xs:complexType>
|
||||||
</xs:complexType>
|
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
||||||
</xs:element>
|
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
||||||
</xs:sequence>
|
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
@ -31,13 +31,14 @@ import com.l2jmobius.commons.util.IGameXmlReader;
|
|||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
import com.l2jmobius.gameserver.model.items.L2Henna;
|
import com.l2jmobius.gameserver.model.items.L2Henna;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds the henna related information.<br>
|
* This class holds the henna related information.<br>
|
||||||
* Cost and required amount to add the henna to the player.<br>
|
* Cost and required amount to add the henna to the player.<br>
|
||||||
* Cost and retrieved amount for removing the henna from the player.<br>
|
* Cost and retrieved amount for removing the henna from the player.<br>
|
||||||
* Allowed classes to wear each henna.
|
* Allowed classes to wear each henna.
|
||||||
* @author Zoey76
|
* @author Zoey76, Mobius
|
||||||
*/
|
*/
|
||||||
public final class HennaData implements IGameXmlReader
|
public final class HennaData implements IGameXmlReader
|
||||||
{
|
{
|
||||||
@ -87,6 +88,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
{
|
{
|
||||||
final StatsSet set = new StatsSet();
|
final StatsSet set = new StatsSet();
|
||||||
final List<ClassId> wearClassIds = new ArrayList<>();
|
final List<ClassId> wearClassIds = new ArrayList<>();
|
||||||
|
final List<Skill> skills = new ArrayList<>();
|
||||||
NamedNodeMap attrs = d.getAttributes();
|
NamedNodeMap attrs = d.getAttributes();
|
||||||
Node attr;
|
Node attr;
|
||||||
for (int i = 0; i < attrs.getLength(); i++)
|
for (int i = 0; i < attrs.getLength(); i++)
|
||||||
@ -126,6 +128,17 @@ public final class HennaData implements IGameXmlReader
|
|||||||
set.set("cancel_fee", attr.getNodeValue());
|
set.set("cancel_fee", attr.getNodeValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "duration":
|
||||||
|
{
|
||||||
|
attr = attrs.getNamedItem("time"); // in minutes
|
||||||
|
set.set("duration", attr.getNodeValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "skill":
|
||||||
|
{
|
||||||
|
skills.add(SkillData.getInstance().getSkill(parseInteger(attrs, "id"), parseInteger(attrs, "level")));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "classId":
|
case "classId":
|
||||||
{
|
{
|
||||||
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
||||||
@ -134,6 +147,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final L2Henna henna = new L2Henna(set);
|
final L2Henna henna = new L2Henna(set);
|
||||||
|
henna.setSkills(skills);
|
||||||
henna.setWearClassIds(wearClassIds);
|
henna.setWearClassIds(wearClassIds);
|
||||||
_hennaList.put(henna.getDyeId(), henna);
|
_hennaList.put(henna.getDyeId(), henna);
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,7 @@ import com.l2jmobius.gameserver.model.actor.status.PcStatus;
|
|||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
||||||
|
import com.l2jmobius.gameserver.model.actor.tasks.player.HennaDurationTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
||||||
@ -594,9 +595,10 @@ public final class L2PcInstance extends L2Playable
|
|||||||
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
||||||
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
// hennas
|
/** Hennas */
|
||||||
private final L2Henna[] _henna = new L2Henna[3];
|
private final L2Henna[] _henna = new L2Henna[3];
|
||||||
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
||||||
|
private final Map<Integer, ScheduledFuture<?>> _hennaRemoveSchedules = new ConcurrentHashMap<>(3);
|
||||||
|
|
||||||
/** The Pet of the L2PcInstance */
|
/** The Pet of the L2PcInstance */
|
||||||
private L2PetInstance _pet = null;
|
private L2PetInstance _pet = null;
|
||||||
@ -7752,9 +7754,9 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
private void restoreHenna()
|
private void restoreHenna()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
_henna[i] = null;
|
_henna[i - 1] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
@ -7779,7 +7781,28 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_henna[slot - 1] = HennaData.getInstance().getHenna(symbolId);
|
|
||||||
|
final L2Henna henna = HennaData.getInstance().getHenna(symbolId);
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
|
if (remainingTime < 0)
|
||||||
|
{
|
||||||
|
removeHenna(slot);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_hennaRemoveSchedules.put(slot, ThreadPoolManager.schedule(new HennaDurationTask(this, slot), System.currentTimeMillis() + remainingTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
_henna[slot - 1] = henna;
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7835,27 +7858,25 @@ public final class L2PcInstance extends L2Playable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot--;
|
final L2Henna henna = _henna[slot - 1];
|
||||||
|
|
||||||
final L2Henna henna = _henna[slot];
|
|
||||||
if (henna == null)
|
if (henna == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_henna[slot] = null;
|
_henna[slot - 1] = null;
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, slot + 1);
|
statement.setInt(2, slot);
|
||||||
statement.setInt(3, getClassIndex());
|
statement.setInt(3, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.log(Level.SEVERE, "Failed remocing character henna.", e);
|
_log.log(Level.SEVERE, "Failed removing character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
@ -7868,16 +7889,43 @@ public final class L2PcInstance extends L2Playable
|
|||||||
final UserInfo ui = new UserInfo(this, false);
|
final UserInfo ui = new UserInfo(this, false);
|
||||||
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
||||||
sendPacket(ui);
|
sendPacket(ui);
|
||||||
// Add the recovered dyes to the player's inventory and notify them.
|
|
||||||
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
|
||||||
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
|
||||||
|
|
||||||
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
sm.addItemName(henna.getDyeItemId());
|
if ((henna.getDuration() < 0) || (remainingTime > 0))
|
||||||
sm.addLong(henna.getCancelCount());
|
{
|
||||||
sendPacket(sm);
|
// Add the recovered dyes to the player's inventory and notify them.
|
||||||
|
if (henna.getCancelFee() > 0)
|
||||||
|
{
|
||||||
|
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
||||||
|
}
|
||||||
|
if (henna.getCancelCount() > 0)
|
||||||
|
{
|
||||||
|
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
||||||
|
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
||||||
|
sm.addItemName(henna.getDyeItemId());
|
||||||
|
sm.addLong(henna.getCancelCount());
|
||||||
|
sendPacket(sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
||||||
|
|
||||||
|
// Remove henna duration task
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().remove("HennaDuration" + slot);
|
||||||
|
if (_hennaRemoveSchedules.get(slot) != null)
|
||||||
|
{
|
||||||
|
_hennaRemoveSchedules.get(slot).cancel(false);
|
||||||
|
_hennaRemoveSchedules.remove(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
removeSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify to scripts
|
// Notify to scripts
|
||||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
||||||
return true;
|
return true;
|
||||||
@ -7890,11 +7938,11 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
public boolean addHenna(L2Henna henna)
|
public boolean addHenna(L2Henna henna)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (_henna[i] == null)
|
if (_henna[i - 1] == null)
|
||||||
{
|
{
|
||||||
_henna[i] = henna;
|
_henna[i - 1] = henna;
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
recalcHennaStats();
|
recalcHennaStats();
|
||||||
@ -7904,7 +7952,7 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, henna.getDyeId());
|
statement.setInt(2, henna.getDyeId());
|
||||||
statement.setInt(3, i + 1);
|
statement.setInt(3, i);
|
||||||
statement.setInt(4, getClassIndex());
|
statement.setInt(4, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
@ -7913,6 +7961,19 @@ public final class L2PcInstance extends L2Playable
|
|||||||
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().set("HennaDuration" + i, System.currentTimeMillis() + (henna.getDuration() * 60000));
|
||||||
|
_hennaRemoveSchedules.put(i, ThreadPoolManager.schedule(new HennaDurationTask(this, i), System.currentTimeMillis() + (henna.getDuration() * 60000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Send Server->Client HennaInfo packet to this L2PcInstance
|
// Send Server->Client HennaInfo packet to this L2PcInstance
|
||||||
sendPacket(new HennaInfo(this));
|
sendPacket(new HennaInfo(this));
|
||||||
|
|
||||||
|
@ -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 com.l2jmobius.gameserver.model.actor.tasks.player;
|
||||||
|
|
||||||
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class HennaDurationTask implements Runnable
|
||||||
|
{
|
||||||
|
private final L2PcInstance _player;
|
||||||
|
private final int _slot;
|
||||||
|
|
||||||
|
public HennaDurationTask(L2PcInstance player, int slot)
|
||||||
|
{
|
||||||
|
_player = player;
|
||||||
|
_slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.removeHenna(_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
||||||
import com.l2jmobius.gameserver.model.stats.Stats;
|
import com.l2jmobius.gameserver.model.stats.Stats;
|
||||||
|
|
||||||
@ -40,6 +41,8 @@ public class L2Henna
|
|||||||
private final int _wear_count;
|
private final int _wear_count;
|
||||||
private final int _cancel_fee;
|
private final int _cancel_fee;
|
||||||
private final int _cancel_count;
|
private final int _cancel_count;
|
||||||
|
private final int _duration;
|
||||||
|
private final List<Skill> _skills;
|
||||||
private final List<ClassId> _wear_class;
|
private final List<ClassId> _wear_class;
|
||||||
|
|
||||||
public L2Henna(StatsSet set)
|
public L2Henna(StatsSet set)
|
||||||
@ -59,6 +62,8 @@ public class L2Henna
|
|||||||
_wear_count = set.getInt("wear_count");
|
_wear_count = set.getInt("wear_count");
|
||||||
_cancel_fee = set.getInt("cancel_fee");
|
_cancel_fee = set.getInt("cancel_fee");
|
||||||
_cancel_count = set.getInt("cancel_count");
|
_cancel_count = set.getInt("cancel_count");
|
||||||
|
_duration = set.getInt("duration", -1);
|
||||||
|
_skills = new ArrayList<>();
|
||||||
_wear_class = new ArrayList<>();
|
_wear_class = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +133,30 @@ public class L2Henna
|
|||||||
return _cancel_count;
|
return _cancel_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the duration of this dye.
|
||||||
|
*/
|
||||||
|
public int getDuration()
|
||||||
|
{
|
||||||
|
return _duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param skillList the list of skills related to this dye.
|
||||||
|
*/
|
||||||
|
public void setSkills(List<Skill> skillList)
|
||||||
|
{
|
||||||
|
_skills.addAll(skillList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the skills related to this dye.
|
||||||
|
*/
|
||||||
|
public List<Skill> getSkills()
|
||||||
|
{
|
||||||
|
return _skills;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list with the allowed classes to wear this dye.
|
* @return the list with the allowed classes to wear this dye.
|
||||||
*/
|
*/
|
||||||
|
@ -26,20 +26,19 @@
|
|||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:attribute name="count" type="xs:positiveInteger" use="required" />
|
<xs:attribute name="count" type="xs:integer" use="required" />
|
||||||
<xs:attribute name="fee" type="xs:integer" use="required" />
|
<xs:attribute name="fee" type="xs:integer" use="required" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="skills" minOccurs="0">
|
<xs:element name="duration" minOccurs="0" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:attribute name="time" type="xs:positiveInteger" use="required" />
|
||||||
<xs:element name="skill">
|
</xs:complexType>
|
||||||
<xs:complexType>
|
</xs:element>
|
||||||
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
<xs:element name="skill" minOccurs="0" maxOccurs="unbounded">
|
||||||
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
<xs:complexType>
|
||||||
</xs:complexType>
|
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
||||||
</xs:element>
|
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
||||||
</xs:sequence>
|
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
@ -31,13 +31,14 @@ import com.l2jmobius.commons.util.IGameXmlReader;
|
|||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
import com.l2jmobius.gameserver.model.items.L2Henna;
|
import com.l2jmobius.gameserver.model.items.L2Henna;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds the henna related information.<br>
|
* This class holds the henna related information.<br>
|
||||||
* Cost and required amount to add the henna to the player.<br>
|
* Cost and required amount to add the henna to the player.<br>
|
||||||
* Cost and retrieved amount for removing the henna from the player.<br>
|
* Cost and retrieved amount for removing the henna from the player.<br>
|
||||||
* Allowed classes to wear each henna.
|
* Allowed classes to wear each henna.
|
||||||
* @author Zoey76
|
* @author Zoey76, Mobius
|
||||||
*/
|
*/
|
||||||
public final class HennaData implements IGameXmlReader
|
public final class HennaData implements IGameXmlReader
|
||||||
{
|
{
|
||||||
@ -87,6 +88,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
{
|
{
|
||||||
final StatsSet set = new StatsSet();
|
final StatsSet set = new StatsSet();
|
||||||
final List<ClassId> wearClassIds = new ArrayList<>();
|
final List<ClassId> wearClassIds = new ArrayList<>();
|
||||||
|
final List<Skill> skills = new ArrayList<>();
|
||||||
NamedNodeMap attrs = d.getAttributes();
|
NamedNodeMap attrs = d.getAttributes();
|
||||||
Node attr;
|
Node attr;
|
||||||
for (int i = 0; i < attrs.getLength(); i++)
|
for (int i = 0; i < attrs.getLength(); i++)
|
||||||
@ -126,6 +128,17 @@ public final class HennaData implements IGameXmlReader
|
|||||||
set.set("cancel_fee", attr.getNodeValue());
|
set.set("cancel_fee", attr.getNodeValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "duration":
|
||||||
|
{
|
||||||
|
attr = attrs.getNamedItem("time"); // in minutes
|
||||||
|
set.set("duration", attr.getNodeValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "skill":
|
||||||
|
{
|
||||||
|
skills.add(SkillData.getInstance().getSkill(parseInteger(attrs, "id"), parseInteger(attrs, "level")));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "classId":
|
case "classId":
|
||||||
{
|
{
|
||||||
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
||||||
@ -134,6 +147,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final L2Henna henna = new L2Henna(set);
|
final L2Henna henna = new L2Henna(set);
|
||||||
|
henna.setSkills(skills);
|
||||||
henna.setWearClassIds(wearClassIds);
|
henna.setWearClassIds(wearClassIds);
|
||||||
_hennaList.put(henna.getDyeId(), henna);
|
_hennaList.put(henna.getDyeId(), henna);
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,7 @@ import com.l2jmobius.gameserver.model.actor.status.PcStatus;
|
|||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
||||||
|
import com.l2jmobius.gameserver.model.actor.tasks.player.HennaDurationTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
||||||
@ -596,9 +597,10 @@ public final class L2PcInstance extends L2Playable
|
|||||||
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
||||||
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
// hennas
|
/** Hennas */
|
||||||
private final L2Henna[] _henna = new L2Henna[3];
|
private final L2Henna[] _henna = new L2Henna[3];
|
||||||
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
||||||
|
private final Map<Integer, ScheduledFuture<?>> _hennaRemoveSchedules = new ConcurrentHashMap<>(3);
|
||||||
|
|
||||||
/** The Pet of the L2PcInstance */
|
/** The Pet of the L2PcInstance */
|
||||||
private L2PetInstance _pet = null;
|
private L2PetInstance _pet = null;
|
||||||
@ -7754,9 +7756,9 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
private void restoreHenna()
|
private void restoreHenna()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
_henna[i] = null;
|
_henna[i - 1] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
@ -7781,7 +7783,28 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_henna[slot - 1] = HennaData.getInstance().getHenna(symbolId);
|
|
||||||
|
final L2Henna henna = HennaData.getInstance().getHenna(symbolId);
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
|
if (remainingTime < 0)
|
||||||
|
{
|
||||||
|
removeHenna(slot);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_hennaRemoveSchedules.put(slot, ThreadPoolManager.schedule(new HennaDurationTask(this, slot), System.currentTimeMillis() + remainingTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
_henna[slot - 1] = henna;
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7837,27 +7860,25 @@ public final class L2PcInstance extends L2Playable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot--;
|
final L2Henna henna = _henna[slot - 1];
|
||||||
|
|
||||||
final L2Henna henna = _henna[slot];
|
|
||||||
if (henna == null)
|
if (henna == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_henna[slot] = null;
|
_henna[slot - 1] = null;
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, slot + 1);
|
statement.setInt(2, slot);
|
||||||
statement.setInt(3, getClassIndex());
|
statement.setInt(3, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.log(Level.SEVERE, "Failed remocing character henna.", e);
|
_log.log(Level.SEVERE, "Failed removing character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
@ -7870,16 +7891,43 @@ public final class L2PcInstance extends L2Playable
|
|||||||
final UserInfo ui = new UserInfo(this, false);
|
final UserInfo ui = new UserInfo(this, false);
|
||||||
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
||||||
sendPacket(ui);
|
sendPacket(ui);
|
||||||
// Add the recovered dyes to the player's inventory and notify them.
|
|
||||||
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
|
||||||
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
|
||||||
|
|
||||||
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
sm.addItemName(henna.getDyeItemId());
|
if ((henna.getDuration() < 0) || (remainingTime > 0))
|
||||||
sm.addLong(henna.getCancelCount());
|
{
|
||||||
sendPacket(sm);
|
// Add the recovered dyes to the player's inventory and notify them.
|
||||||
|
if (henna.getCancelFee() > 0)
|
||||||
|
{
|
||||||
|
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
||||||
|
}
|
||||||
|
if (henna.getCancelCount() > 0)
|
||||||
|
{
|
||||||
|
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
||||||
|
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
||||||
|
sm.addItemName(henna.getDyeItemId());
|
||||||
|
sm.addLong(henna.getCancelCount());
|
||||||
|
sendPacket(sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
||||||
|
|
||||||
|
// Remove henna duration task
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().remove("HennaDuration" + slot);
|
||||||
|
if (_hennaRemoveSchedules.get(slot) != null)
|
||||||
|
{
|
||||||
|
_hennaRemoveSchedules.get(slot).cancel(false);
|
||||||
|
_hennaRemoveSchedules.remove(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
removeSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify to scripts
|
// Notify to scripts
|
||||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
||||||
return true;
|
return true;
|
||||||
@ -7892,11 +7940,11 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
public boolean addHenna(L2Henna henna)
|
public boolean addHenna(L2Henna henna)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (_henna[i] == null)
|
if (_henna[i - 1] == null)
|
||||||
{
|
{
|
||||||
_henna[i] = henna;
|
_henna[i - 1] = henna;
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
recalcHennaStats();
|
recalcHennaStats();
|
||||||
@ -7906,7 +7954,7 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, henna.getDyeId());
|
statement.setInt(2, henna.getDyeId());
|
||||||
statement.setInt(3, i + 1);
|
statement.setInt(3, i);
|
||||||
statement.setInt(4, getClassIndex());
|
statement.setInt(4, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
@ -7915,6 +7963,19 @@ public final class L2PcInstance extends L2Playable
|
|||||||
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().set("HennaDuration" + i, System.currentTimeMillis() + (henna.getDuration() * 60000));
|
||||||
|
_hennaRemoveSchedules.put(i, ThreadPoolManager.schedule(new HennaDurationTask(this, i), System.currentTimeMillis() + (henna.getDuration() * 60000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Send Server->Client HennaInfo packet to this L2PcInstance
|
// Send Server->Client HennaInfo packet to this L2PcInstance
|
||||||
sendPacket(new HennaInfo(this));
|
sendPacket(new HennaInfo(this));
|
||||||
|
|
||||||
|
@ -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 com.l2jmobius.gameserver.model.actor.tasks.player;
|
||||||
|
|
||||||
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class HennaDurationTask implements Runnable
|
||||||
|
{
|
||||||
|
private final L2PcInstance _player;
|
||||||
|
private final int _slot;
|
||||||
|
|
||||||
|
public HennaDurationTask(L2PcInstance player, int slot)
|
||||||
|
{
|
||||||
|
_player = player;
|
||||||
|
_slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.removeHenna(_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
||||||
import com.l2jmobius.gameserver.model.stats.Stats;
|
import com.l2jmobius.gameserver.model.stats.Stats;
|
||||||
|
|
||||||
@ -40,6 +41,8 @@ public class L2Henna
|
|||||||
private final int _wear_count;
|
private final int _wear_count;
|
||||||
private final int _cancel_fee;
|
private final int _cancel_fee;
|
||||||
private final int _cancel_count;
|
private final int _cancel_count;
|
||||||
|
private final int _duration;
|
||||||
|
private final List<Skill> _skills;
|
||||||
private final List<ClassId> _wear_class;
|
private final List<ClassId> _wear_class;
|
||||||
|
|
||||||
public L2Henna(StatsSet set)
|
public L2Henna(StatsSet set)
|
||||||
@ -59,6 +62,8 @@ public class L2Henna
|
|||||||
_wear_count = set.getInt("wear_count");
|
_wear_count = set.getInt("wear_count");
|
||||||
_cancel_fee = set.getInt("cancel_fee");
|
_cancel_fee = set.getInt("cancel_fee");
|
||||||
_cancel_count = set.getInt("cancel_count");
|
_cancel_count = set.getInt("cancel_count");
|
||||||
|
_duration = set.getInt("duration", -1);
|
||||||
|
_skills = new ArrayList<>();
|
||||||
_wear_class = new ArrayList<>();
|
_wear_class = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +133,30 @@ public class L2Henna
|
|||||||
return _cancel_count;
|
return _cancel_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the duration of this dye.
|
||||||
|
*/
|
||||||
|
public int getDuration()
|
||||||
|
{
|
||||||
|
return _duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param skillList the list of skills related to this dye.
|
||||||
|
*/
|
||||||
|
public void setSkills(List<Skill> skillList)
|
||||||
|
{
|
||||||
|
_skills.addAll(skillList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the skills related to this dye.
|
||||||
|
*/
|
||||||
|
public List<Skill> getSkills()
|
||||||
|
{
|
||||||
|
return _skills;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list with the allowed classes to wear this dye.
|
* @return the list with the allowed classes to wear this dye.
|
||||||
*/
|
*/
|
||||||
|
@ -26,20 +26,19 @@
|
|||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
<xs:element name="cancel" minOccurs="1" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:attribute name="count" type="xs:positiveInteger" use="required" />
|
<xs:attribute name="count" type="xs:integer" use="required" />
|
||||||
<xs:attribute name="fee" type="xs:integer" use="required" />
|
<xs:attribute name="fee" type="xs:integer" use="required" />
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="skills" minOccurs="0">
|
<xs:element name="duration" minOccurs="0" maxOccurs="1">
|
||||||
<xs:complexType>
|
<xs:complexType>
|
||||||
<xs:sequence>
|
<xs:attribute name="time" type="xs:positiveInteger" use="required" />
|
||||||
<xs:element name="skill">
|
</xs:complexType>
|
||||||
<xs:complexType>
|
</xs:element>
|
||||||
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
<xs:element name="skill" minOccurs="0" maxOccurs="unbounded">
|
||||||
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
<xs:complexType>
|
||||||
</xs:complexType>
|
<xs:attribute type="xs:positiveInteger" name="id" use="required"/>
|
||||||
</xs:element>
|
<xs:attribute type="xs:positiveInteger" name="level" use="required"/>
|
||||||
</xs:sequence>
|
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
</xs:element>
|
</xs:element>
|
||||||
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
<xs:element name="classId" minOccurs="0" maxOccurs="unbounded">
|
||||||
|
@ -31,13 +31,14 @@ import com.l2jmobius.commons.util.IGameXmlReader;
|
|||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
import com.l2jmobius.gameserver.model.items.L2Henna;
|
import com.l2jmobius.gameserver.model.items.L2Henna;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class holds the henna related information.<br>
|
* This class holds the henna related information.<br>
|
||||||
* Cost and required amount to add the henna to the player.<br>
|
* Cost and required amount to add the henna to the player.<br>
|
||||||
* Cost and retrieved amount for removing the henna from the player.<br>
|
* Cost and retrieved amount for removing the henna from the player.<br>
|
||||||
* Allowed classes to wear each henna.
|
* Allowed classes to wear each henna.
|
||||||
* @author Zoey76
|
* @author Zoey76, Mobius
|
||||||
*/
|
*/
|
||||||
public final class HennaData implements IGameXmlReader
|
public final class HennaData implements IGameXmlReader
|
||||||
{
|
{
|
||||||
@ -87,6 +88,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
{
|
{
|
||||||
final StatsSet set = new StatsSet();
|
final StatsSet set = new StatsSet();
|
||||||
final List<ClassId> wearClassIds = new ArrayList<>();
|
final List<ClassId> wearClassIds = new ArrayList<>();
|
||||||
|
final List<Skill> skills = new ArrayList<>();
|
||||||
NamedNodeMap attrs = d.getAttributes();
|
NamedNodeMap attrs = d.getAttributes();
|
||||||
Node attr;
|
Node attr;
|
||||||
for (int i = 0; i < attrs.getLength(); i++)
|
for (int i = 0; i < attrs.getLength(); i++)
|
||||||
@ -126,6 +128,17 @@ public final class HennaData implements IGameXmlReader
|
|||||||
set.set("cancel_fee", attr.getNodeValue());
|
set.set("cancel_fee", attr.getNodeValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "duration":
|
||||||
|
{
|
||||||
|
attr = attrs.getNamedItem("time"); // in minutes
|
||||||
|
set.set("duration", attr.getNodeValue());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "skill":
|
||||||
|
{
|
||||||
|
skills.add(SkillData.getInstance().getSkill(parseInteger(attrs, "id"), parseInteger(attrs, "level")));
|
||||||
|
break;
|
||||||
|
}
|
||||||
case "classId":
|
case "classId":
|
||||||
{
|
{
|
||||||
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
wearClassIds.add(ClassId.getClassId(Integer.parseInt(c.getTextContent())));
|
||||||
@ -134,6 +147,7 @@ public final class HennaData implements IGameXmlReader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
final L2Henna henna = new L2Henna(set);
|
final L2Henna henna = new L2Henna(set);
|
||||||
|
henna.setSkills(skills);
|
||||||
henna.setWearClassIds(wearClassIds);
|
henna.setWearClassIds(wearClassIds);
|
||||||
_hennaList.put(henna.getDyeId(), henna);
|
_hennaList.put(henna.getDyeId(), henna);
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,7 @@ import com.l2jmobius.gameserver.model.actor.status.PcStatus;
|
|||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.DismountTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.FameTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.GameGuardCheckTask;
|
||||||
|
import com.l2jmobius.gameserver.model.actor.tasks.player.HennaDurationTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.InventoryEnableTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PetFeedTask;
|
||||||
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
import com.l2jmobius.gameserver.model.actor.tasks.player.PvPFlagTask;
|
||||||
@ -593,9 +594,10 @@ public final class L2PcInstance extends L2Playable
|
|||||||
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopListener = ConcurrentHashMap.newKeySet();
|
||||||
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
private final Set<L2PcInstance> _snoopedPlayer = ConcurrentHashMap.newKeySet();
|
||||||
|
|
||||||
// hennas
|
/** Hennas */
|
||||||
private final L2Henna[] _henna = new L2Henna[3];
|
private final L2Henna[] _henna = new L2Henna[3];
|
||||||
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
private final Map<BaseStats, Integer> _hennaBaseStats = new ConcurrentHashMap<>();
|
||||||
|
private final Map<Integer, ScheduledFuture<?>> _hennaRemoveSchedules = new ConcurrentHashMap<>(3);
|
||||||
|
|
||||||
/** The Pet of the L2PcInstance */
|
/** The Pet of the L2PcInstance */
|
||||||
private L2PetInstance _pet = null;
|
private L2PetInstance _pet = null;
|
||||||
@ -7724,9 +7726,9 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
private void restoreHenna()
|
private void restoreHenna()
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
_henna[i] = null;
|
_henna[i - 1] = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
@ -7751,7 +7753,28 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
_henna[slot - 1] = HennaData.getInstance().getHenna(symbolId);
|
|
||||||
|
final L2Henna henna = HennaData.getInstance().getHenna(symbolId);
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
|
if (remainingTime < 0)
|
||||||
|
{
|
||||||
|
removeHenna(slot);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_hennaRemoveSchedules.put(slot, ThreadPoolManager.schedule(new HennaDurationTask(this, slot), System.currentTimeMillis() + remainingTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
_henna[slot - 1] = henna;
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7807,27 +7830,25 @@ public final class L2PcInstance extends L2Playable
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot--;
|
final L2Henna henna = _henna[slot - 1];
|
||||||
|
|
||||||
final L2Henna henna = _henna[slot];
|
|
||||||
if (henna == null)
|
if (henna == null)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_henna[slot] = null;
|
_henna[slot - 1] = null;
|
||||||
|
|
||||||
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
try (Connection con = DatabaseFactory.getInstance().getConnection();
|
||||||
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
PreparedStatement statement = con.prepareStatement(DELETE_CHAR_HENNA))
|
||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, slot + 1);
|
statement.setInt(2, slot);
|
||||||
statement.setInt(3, getClassIndex());
|
statement.setInt(3, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_log.log(Level.SEVERE, "Failed remocing character henna.", e);
|
_log.log(Level.SEVERE, "Failed removing character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
@ -7840,16 +7861,43 @@ public final class L2PcInstance extends L2Playable
|
|||||||
final UserInfo ui = new UserInfo(this, false);
|
final UserInfo ui = new UserInfo(this, false);
|
||||||
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
ui.addComponentType(UserInfoType.BASE_STATS, UserInfoType.MAX_HPCPMP, UserInfoType.STATS, UserInfoType.SPEED);
|
||||||
sendPacket(ui);
|
sendPacket(ui);
|
||||||
// Add the recovered dyes to the player's inventory and notify them.
|
|
||||||
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
|
||||||
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
|
||||||
|
|
||||||
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
final long remainingTime = getVariables().getLong("HennaDuration" + slot, 0) - System.currentTimeMillis();
|
||||||
sm.addItemName(henna.getDyeItemId());
|
if ((henna.getDuration() < 0) || (remainingTime > 0))
|
||||||
sm.addLong(henna.getCancelCount());
|
{
|
||||||
sendPacket(sm);
|
// Add the recovered dyes to the player's inventory and notify them.
|
||||||
|
if (henna.getCancelFee() > 0)
|
||||||
|
{
|
||||||
|
reduceAdena("Henna", henna.getCancelFee(), this, false);
|
||||||
|
}
|
||||||
|
if (henna.getCancelCount() > 0)
|
||||||
|
{
|
||||||
|
getInventory().addItem("Henna", henna.getDyeItemId(), henna.getCancelCount(), this, null);
|
||||||
|
final SystemMessage sm = SystemMessage.getSystemMessage(SystemMessageId.YOU_HAVE_EARNED_S2_S1_S);
|
||||||
|
sm.addItemName(henna.getDyeItemId());
|
||||||
|
sm.addLong(henna.getCancelCount());
|
||||||
|
sendPacket(sm);
|
||||||
|
}
|
||||||
|
}
|
||||||
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
sendPacket(SystemMessageId.THE_SYMBOL_HAS_BEEN_DELETED);
|
||||||
|
|
||||||
|
// Remove henna duration task
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().remove("HennaDuration" + slot);
|
||||||
|
if (_hennaRemoveSchedules.get(slot) != null)
|
||||||
|
{
|
||||||
|
_hennaRemoveSchedules.get(slot).cancel(false);
|
||||||
|
_hennaRemoveSchedules.remove(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
removeSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify to scripts
|
// Notify to scripts
|
||||||
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
EventDispatcher.getInstance().notifyEventAsync(new OnPlayerHennaRemove(this, henna), this);
|
||||||
return true;
|
return true;
|
||||||
@ -7862,11 +7910,11 @@ public final class L2PcInstance extends L2Playable
|
|||||||
*/
|
*/
|
||||||
public boolean addHenna(L2Henna henna)
|
public boolean addHenna(L2Henna henna)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
if (_henna[i] == null)
|
if (_henna[i - 1] == null)
|
||||||
{
|
{
|
||||||
_henna[i] = henna;
|
_henna[i - 1] = henna;
|
||||||
|
|
||||||
// Calculate Henna modifiers of this L2PcInstance
|
// Calculate Henna modifiers of this L2PcInstance
|
||||||
recalcHennaStats();
|
recalcHennaStats();
|
||||||
@ -7876,7 +7924,7 @@ public final class L2PcInstance extends L2Playable
|
|||||||
{
|
{
|
||||||
statement.setInt(1, getObjectId());
|
statement.setInt(1, getObjectId());
|
||||||
statement.setInt(2, henna.getDyeId());
|
statement.setInt(2, henna.getDyeId());
|
||||||
statement.setInt(3, i + 1);
|
statement.setInt(3, i);
|
||||||
statement.setInt(4, getClassIndex());
|
statement.setInt(4, getClassIndex());
|
||||||
statement.execute();
|
statement.execute();
|
||||||
}
|
}
|
||||||
@ -7885,6 +7933,19 @@ public final class L2PcInstance extends L2Playable
|
|||||||
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
_log.log(Level.SEVERE, "Failed saving character henna.", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Task for henna duration
|
||||||
|
if (henna.getDuration() > 0)
|
||||||
|
{
|
||||||
|
getVariables().set("HennaDuration" + i, System.currentTimeMillis() + (henna.getDuration() * 60000));
|
||||||
|
_hennaRemoveSchedules.put(i, ThreadPoolManager.schedule(new HennaDurationTask(this, i), System.currentTimeMillis() + (henna.getDuration() * 60000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reward henna skills
|
||||||
|
for (Skill skill : henna.getSkills())
|
||||||
|
{
|
||||||
|
addSkill(skill, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Send Server->Client HennaInfo packet to this L2PcInstance
|
// Send Server->Client HennaInfo packet to this L2PcInstance
|
||||||
sendPacket(new HennaInfo(this));
|
sendPacket(new HennaInfo(this));
|
||||||
|
|
||||||
|
@ -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 com.l2jmobius.gameserver.model.actor.tasks.player;
|
||||||
|
|
||||||
|
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Mobius
|
||||||
|
*/
|
||||||
|
public class HennaDurationTask implements Runnable
|
||||||
|
{
|
||||||
|
private final L2PcInstance _player;
|
||||||
|
private final int _slot;
|
||||||
|
|
||||||
|
public HennaDurationTask(L2PcInstance player, int slot)
|
||||||
|
{
|
||||||
|
_player = player;
|
||||||
|
_slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run()
|
||||||
|
{
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.removeHenna(_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import com.l2jmobius.gameserver.model.StatsSet;
|
import com.l2jmobius.gameserver.model.StatsSet;
|
||||||
import com.l2jmobius.gameserver.model.base.ClassId;
|
import com.l2jmobius.gameserver.model.base.ClassId;
|
||||||
|
import com.l2jmobius.gameserver.model.skills.Skill;
|
||||||
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
import com.l2jmobius.gameserver.model.stats.BaseStats;
|
||||||
import com.l2jmobius.gameserver.model.stats.Stats;
|
import com.l2jmobius.gameserver.model.stats.Stats;
|
||||||
|
|
||||||
@ -40,6 +41,8 @@ public class L2Henna
|
|||||||
private final int _wear_count;
|
private final int _wear_count;
|
||||||
private final int _cancel_fee;
|
private final int _cancel_fee;
|
||||||
private final int _cancel_count;
|
private final int _cancel_count;
|
||||||
|
private final int _duration;
|
||||||
|
private final List<Skill> _skills;
|
||||||
private final List<ClassId> _wear_class;
|
private final List<ClassId> _wear_class;
|
||||||
|
|
||||||
public L2Henna(StatsSet set)
|
public L2Henna(StatsSet set)
|
||||||
@ -59,6 +62,8 @@ public class L2Henna
|
|||||||
_wear_count = set.getInt("wear_count");
|
_wear_count = set.getInt("wear_count");
|
||||||
_cancel_fee = set.getInt("cancel_fee");
|
_cancel_fee = set.getInt("cancel_fee");
|
||||||
_cancel_count = set.getInt("cancel_count");
|
_cancel_count = set.getInt("cancel_count");
|
||||||
|
_duration = set.getInt("duration", -1);
|
||||||
|
_skills = new ArrayList<>();
|
||||||
_wear_class = new ArrayList<>();
|
_wear_class = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +133,30 @@ public class L2Henna
|
|||||||
return _cancel_count;
|
return _cancel_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the duration of this dye.
|
||||||
|
*/
|
||||||
|
public int getDuration()
|
||||||
|
{
|
||||||
|
return _duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param skillList the list of skills related to this dye.
|
||||||
|
*/
|
||||||
|
public void setSkills(List<Skill> skillList)
|
||||||
|
{
|
||||||
|
_skills.addAll(skillList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the skills related to this dye.
|
||||||
|
*/
|
||||||
|
public List<Skill> getSkills()
|
||||||
|
{
|
||||||
|
return _skills;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the list with the allowed classes to wear this dye.
|
* @return the list with the allowed classes to wear this dye.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user