Addition of SoulType enum.

This commit is contained in:
MobiusDevelopment 2021-01-25 23:08:37 +00:00
parent a8e1ab0ba6
commit 15183e84b6
34 changed files with 510 additions and 152 deletions

View File

@ -16,6 +16,7 @@
*/
package handlers.effecthandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
@ -32,10 +33,12 @@ import org.l2jmobius.gameserver.network.SystemMessageId;
public class FocusSouls extends AbstractEffect
{
private final int _charge;
private final SoulType _type;
public FocusSouls(StatSet params)
{
_charge = params.getInt("charge", 0);
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
}
@Override
@ -57,10 +60,10 @@ public class FocusSouls extends AbstractEffect
if (maxSouls > 0)
{
final int amount = _charge;
if ((target.getChargedSouls() < maxSouls))
if ((target.getChargedSouls(_type) < maxSouls))
{
final int count = ((target.getChargedSouls() + amount) <= maxSouls) ? amount : (maxSouls - target.getChargedSouls());
target.increaseSouls(count);
final int count = ((target.getChargedSouls(_type) + amount) <= maxSouls) ? amount : (maxSouls - target.getChargedSouls(_type));
target.increaseSouls(count, _type);
}
else
{

View File

@ -66,8 +66,26 @@ public class MagicalSoulAttack extends AbstractEffect
effected.stopFakeDeath(true);
}
final int chargedSouls = Math.min(skill.getMaxSoulConsumeCount(), effector.getActingPlayer().getCharges());
if (!effector.getActingPlayer().decreaseCharges(chargedSouls))
final int chargedLightSouls = Math.min(skill.getMaxLightSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedLightSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedLightSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedShadowSouls = Math.min(skill.getMaxShadowSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedShadowSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedShadowSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedSouls = chargedLightSouls + chargedShadowSouls;
if (chargedSouls < 1)
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);

View File

@ -86,8 +86,26 @@ public class PhysicalSoulAttack extends AbstractEffect
effected.stopFakeDeath(true);
}
final int souls = Math.min(skill.getMaxSoulConsumeCount(), effector.getActingPlayer().getCharges());
if (!effector.getActingPlayer().decreaseCharges(souls))
final int chargedLightSouls = Math.min(skill.getMaxLightSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedLightSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedLightSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedShadowSouls = Math.min(skill.getMaxShadowSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedShadowSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedShadowSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedSouls = chargedLightSouls + chargedShadowSouls;
if (chargedSouls < 1)
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
@ -150,7 +168,7 @@ public class PhysicalSoulAttack extends AbstractEffect
ssmod = 4 * effector.getStat().getValue(Stat.SHOTS_BONUS);
}
}
final double soulsMod = 1 + (souls * 0.04); // Souls Formula (each soul increase +4%)
final double soulsMod = 1 + (chargedSouls * 0.04); // Souls Formula (each soul increase +4%)
// ...................____________Melee Damage_____________......................................___________________Ranged Damage____________________
// ATTACK CALCULATION 77 * ((pAtk * lvlMod) + power) / pdef            RANGED ATTACK CALCULATION 70 * ((pAtk * lvlMod) + power + patk + power) / pdef

View File

@ -17,6 +17,7 @@
package handlers.effecthandlers;
import org.l2jmobius.gameserver.enums.ShotType;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Creature;
@ -83,12 +84,22 @@ public class SoulBlow extends AbstractEffect
final boolean ss = skill.useSoulShot() && (effector.isChargedShot(ShotType.SOULSHOTS) || effector.isChargedShot(ShotType.BLESSED_SOULSHOTS));
final byte shld = Formulas.calcShldUse(effector, effected);
double damage = Formulas.calcBlowDamage(effector, effected, skill, false, _power, shld, ss);
if ((skill.getMaxSoulConsumeCount() > 0) && effector.isPlayer())
if (effector.isPlayer())
{
if (skill.getMaxLightSoulConsumeCount() > 0)
{
// Souls Formula (each soul increase +4%)
final int chargedSouls = (effector.getActingPlayer().getChargedSouls() <= skill.getMaxSoulConsumeCount()) ? effector.getActingPlayer().getChargedSouls() : skill.getMaxSoulConsumeCount();
final int chargedSouls = (effector.getActingPlayer().getChargedSouls(SoulType.LIGHT) <= skill.getMaxLightSoulConsumeCount()) ? effector.getActingPlayer().getChargedSouls(SoulType.LIGHT) : skill.getMaxLightSoulConsumeCount();
damage *= 1 + (chargedSouls * 0.04);
}
if (skill.getMaxShadowSoulConsumeCount() > 0)
{
// Souls Formula (each soul increase +4%)
final int chargedSouls = (effector.getActingPlayer().getChargedSouls(SoulType.SHADOW) <= skill.getMaxShadowSoulConsumeCount()) ? effector.getActingPlayer().getChargedSouls(SoulType.SHADOW) : skill.getMaxShadowSoulConsumeCount();
damage *= 1 + (chargedSouls * 0.04);
}
}
effector.doAttack(damage, effected, skill, false, false, true, false);
}

View File

@ -16,6 +16,7 @@
*/
package handlers.effecthandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
@ -37,11 +38,13 @@ import org.l2jmobius.gameserver.network.serverpackets.ExSpawnEmitter;
*/
public class SoulEating extends AbstractEffect
{
private final SoulType _type;
private final int _expNeeded;
private final int _maxSouls;
public SoulEating(StatSet params)
{
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
_expNeeded = params.getInt("expNeeded");
_maxSouls = params.getInt("maxSouls");
}
@ -77,13 +80,13 @@ public class SoulEating extends AbstractEffect
{
final PlayerInstance player = playable.getActingPlayer();
final int maxSouls = (int) player.getStat().getValue(Stat.MAX_SOULS, 0);
if (player.getChargedSouls() >= maxSouls)
if (player.getChargedSouls(_type) >= maxSouls)
{
playable.sendPacket(SystemMessageId.SOUL_CANNOT_BE_ABSORBED_ANYMORE);
return;
}
player.increaseSouls(1);
player.increaseSouls(1, _type);
if ((player.getTarget() != null) && player.getTarget().isNpc())
{

View File

@ -16,6 +16,7 @@
*/
package handlers.skillconditionhandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature;
@ -28,14 +29,17 @@ import org.l2jmobius.gameserver.model.stats.Stat;
*/
public class OpSoulMaxSkillCondition implements ISkillCondition
{
private final SoulType _type;
public OpSoulMaxSkillCondition(StatSet params)
{
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
}
@Override
public boolean canUse(Creature caster, Skill skill, WorldObject target)
{
final int maxSouls = (int) caster.getStat().getValue(Stat.MAX_SOULS);
return caster.isPlayable() && (caster.getActingPlayer().getChargedSouls() < maxSouls);
return caster.isPlayable() && (caster.getActingPlayer().getChargedSouls(_type) < maxSouls);
}
}

View File

@ -16,6 +16,7 @@
*/
package handlers.skillconditionhandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature;
@ -27,16 +28,18 @@ import org.l2jmobius.gameserver.model.skills.Skill;
*/
public class SoulSavedSkillCondition implements ISkillCondition
{
private final SoulType _type;
private final int _amount;
public SoulSavedSkillCondition(StatSet params)
{
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
_amount = params.getInt("amount");
}
@Override
public boolean canUse(Creature caster, Skill skill, WorldObject target)
{
return caster.isPlayer() && (caster.getActingPlayer().getChargedSouls() >= _amount);
return caster.isPlayer() && (caster.getActingPlayer().getChargedSouls(_type) >= _amount);
}
}

View File

@ -3652,19 +3652,40 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="LIGHT" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>LIGHT</type>
<charge>2</charge>
</effect>
</effects>
</skill>
<skill id="394" toLevel="1" name="Shadow Soul Finding">
<!-- TODO: Shadow Souls Implementation -->
<magicLevel>1</magicLevel>
<effectPoint>150</effectPoint>
<hitTime>500</hitTime>
<hpConsume>30</hpConsume>
<magicLevel>
<value level="1">40</value>
<value level="2">49</value>
<value level="3">58</value>
<value level="4">66</value>
<value level="5">72</value>
</magicLevel>
<operateType>A1</operateType>
<reuseDelay>2000</reuseDelay>
<magicCriticalRate>5</magicCriticalRate>
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" type="SHADOW" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>SHADOW</type>
<charge>2</charge>
</effect>
</effects>
</skill>
<skill id="395" toLevel="1" name="Heroic Miracle">
<!-- For 30 sec., P. Def. +5400, M. Def. +4050, Buff-canceling Attack Resistance +80, and Speed +5. Consumes 40 Soulstone(s). -->
@ -3780,7 +3801,8 @@
<skill id="397" toLevel="2" name="Shine Side">
<!-- Enough Shine Souls have been gathered to be in the Shine Side state. <Acceleration Stage 1>. P. Atk. +130, Atk. Spd. +30, Casting Spd. +40, Speed +10. P./M. Def. +5%. Has a chance to recover MP when attacking. -->
<abnormalLevel>1</abnormalLevel>
<abnormalTime>30</abnormalTime>
<abnormalTime>60</abnormalTime>
<abnormalType>BR_EVENT_BUF1</abnormalType>
<isMagic>4</isMagic>
<magicLevel>
<value level="1">20</value>
@ -3858,7 +3880,8 @@
<skill id="398" toLevel="2" name="Shadow Side">
<!-- Enough Shadow Souls have been gathered to be in the Shadow Side state. <Acceleration Stage 2>. P. Atk. +280, Atk. Spd. +80, Casting Spd. +120, Speed +15. Has a chance to activate powerful attack skills. -->
<abnormalLevel>1</abnormalLevel>
<abnormalTime>30</abnormalTime>
<abnormalTime>60</abnormalTime>
<abnormalType>BR_EVENT_BUF1</abnormalType>
<isMagic>4</isMagic>
<magicLevel>
<value level="1">20</value>

View File

@ -390,10 +390,11 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="SHADOW" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>SHADOW</type>
<charge>
<value level="1">70</value>
<value level="2">100</value>
@ -415,10 +416,11 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="LIGHT" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>LIGHT</type>
<charge>
<value level="1">70</value>
<value level="2">100</value>
@ -1700,6 +1702,7 @@
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="SoulEating">
<type>LIGHT</type>
<maxSouls>
<value level="1">100</value>
<value level="2">100</value>
@ -1734,8 +1737,45 @@
<skill id="45179" toLevel="2" name="Shadow Master">
<!-- Allows to absorb the power of shadows.\n\nCollect 100 Shadow Souls to assume the Shadow Veil.\n\n<Shadow Veil>\nGrants Evolved Wings Lv. 2 that allows to make powerful attacks. -->
<icon>icon.skill_jinkama_black1</icon>
<magicLevel>
<value level="1">20</value>
<value level="2">60</value>
</magicLevel>
<operateType>P</operateType>
<isMagic>4</isMagic>
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="SoulEating">
<type>SHADOW</type>
<maxSouls>
<value level="1">100</value>
<value level="2">100</value>
</maxSouls>
<expNeeded>
<value level="1">294</value>
<value level="2">2160</value>
</expNeeded>
</effect>
<effect name="TriggerSkillByAttack">
<isCritical>true</isCritical>
<skillId>45181</skillId> <!-- Shadow Soul Absorption -->
<skillLevel>1</skillLevel>
<allowWeapons>ALL</allowWeapons>
<attackerType>Creature</attackerType>
<targetType>SELF</targetType>
<minDamage>1</minDamage>
<chance>30</chance>
</effect>
<effect name="TriggerSkillByAttack">
<isCritical>false</isCritical>
<skillId>45181</skillId> <!-- Shadow Soul Absorption -->
<skillLevel>1</skillLevel>
<allowWeapons>ALL</allowWeapons>
<attackerType>Creature</attackerType>
<targetType>SELF</targetType>
<minDamage>1</minDamage>
<chance>15</chance>
</effect>
</effects>
</skill>
<skill id="45180" toLevel="4" name="Light Soul Absorption">
<!-- Activates when attacking. -->
@ -1748,17 +1788,33 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="LIGHT" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>LIGHT</type>
<charge>1</charge>
</effect>
</effects>
</skill>
<skill id="45181" toLevel="4" name="Shadow Soul Absorption">
<!-- Activates when attacking. -->
<isTriggeredSkill>true</isTriggeredSkill>
<magicLevel>20</magicLevel>
<operateType>A1</operateType>
<reuseDelay>10000</reuseDelay>
<magicCriticalRate>-5</magicCriticalRate>
<hitCancelTime>0</hitCancelTime>
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" type="SHADOW" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>SHADOW</type>
<charge>1</charge>
</effect>
</effects>
</skill>
<skill id="45182" toLevel="8" name="Soul Thrust">
<!-- M. Def. -$s1. -->

View File

@ -461,6 +461,7 @@
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="type" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>

View File

@ -0,0 +1,26 @@
/*
* 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.enums;
/**
* @author Mobius
*/
public enum SoulType
{
LIGHT,
SHADOW
}

View File

@ -101,6 +101,7 @@ import org.l2jmobius.gameserver.enums.PrivateStoreType;
import org.l2jmobius.gameserver.enums.Race;
import org.l2jmobius.gameserver.enums.Sex;
import org.l2jmobius.gameserver.enums.ShortcutType;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.enums.StatusUpdateType;
import org.l2jmobius.gameserver.enums.SubclassInfoType;
import org.l2jmobius.gameserver.enums.Team;
@ -669,7 +670,7 @@ public class PlayerInstance extends Playable
private final static int KAMAEL_SHADOW_MASTER = 45179;
private final static int KAMAEL_LIGHT_TRANSFORMATION = 397;
private final static int KAMAEL_SHADOW_TRANSFORMATION = 398;
private int _souls = 0;
private final Map<SoulType, Integer> _souls = new ConcurrentHashMap<>(2);
private ScheduledFuture<?> _soulTask = null;
// WorldPosition used by TARGET_SIGNET_GROUND
@ -11226,48 +11227,53 @@ public class PlayerInstance extends Playable
}
/**
* Returns the Number of Souls this PlayerInstance got.
* Returns the Number of souls.
* @param type the type of souls.
* @return
*/
public int getChargedSouls()
public int getChargedSouls(SoulType type)
{
return _souls;
return _souls.getOrDefault(type, 0).intValue();
}
/**
* Increase Souls
* @param count
* @param type
*/
public void increaseSouls(int count)
public void increaseSouls(int count, SoulType type)
{
_souls += count;
final int newCount = getChargedSouls(type) + count;
_souls.put(type, newCount);
final SystemMessage sm = new SystemMessage(SystemMessageId.YOUR_SOUL_COUNT_HAS_INCREASED_BY_S1_IT_IS_NOW_AT_S2);
sm.addInt(count);
sm.addInt(_souls);
sm.addInt(newCount);
sendPacket(sm);
restartSoulTask();
sendPacket(new EtcStatusUpdate(this));
// TODO: Unhardcode?
if ((getRace() == Race.KAMAEL) && (_souls >= 100))
if ((getRace() == Race.KAMAEL) && (newCount >= 100) && !isTransformed())
{
int skillLevel = getShadowMasterLevel();
if (type == SoulType.LIGHT)
{
final int skillLevel = getLightMasterLevel();
if (skillLevel > 0)
{
abortCast();
decreaseSouls(100);
SkillData.getInstance().getSkill(KAMAEL_SHADOW_TRANSFORMATION, skillLevel).applyEffects(this, this);
}
else
{
skillLevel = getLightMasterLevel();
if (skillLevel > 0)
{
abortCast();
decreaseSouls(100);
decreaseSouls(100, type);
SkillData.getInstance().getSkill(KAMAEL_LIGHT_TRANSFORMATION, skillLevel).applyEffects(this, this);
}
}
else // Shadow.
{
final int skillLevel = getShadowMasterLevel();
if (skillLevel > 0)
{
abortCast();
decreaseSouls(100, type);
SkillData.getInstance().getSkill(KAMAEL_SHADOW_TRANSFORMATION, skillLevel).applyEffects(this, this);
}
}
}
}
@ -11284,17 +11290,19 @@ public class PlayerInstance extends Playable
/**
* Decreases existing Souls.
* @param count
* @param type
* @return
*/
public boolean decreaseSouls(int count)
public boolean decreaseSouls(int count, SoulType type)
{
_souls -= count;
if (_souls < 0)
int newCount = getChargedSouls(type) - count;
if (newCount < 0)
{
_souls = 0;
newCount = 0;
}
_souls.put(type, newCount);
if (_souls == 0)
if (newCount == 0)
{
stopSoulTask();
}
@ -11312,7 +11320,7 @@ public class PlayerInstance extends Playable
*/
public void clearSouls()
{
_souls = 0;
_souls.clear();
stopSoulTask();
sendPacket(new EtcStatusUpdate(this));
}

View File

@ -16,6 +16,7 @@
*/
package org.l2jmobius.gameserver.model.conditions;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
@ -26,19 +27,22 @@ import org.l2jmobius.gameserver.model.skills.Skill;
public class ConditionPlayerSouls extends Condition
{
private final int _souls;
private final SoulType _type;
/**
* Instantiates a new condition player souls.
* @param souls the souls
* @param type the soul type
*/
public ConditionPlayerSouls(int souls)
public ConditionPlayerSouls(int souls, SoulType type)
{
_souls = souls;
_type = type;
}
@Override
public boolean testImpl(Creature effector, Creature effected, Skill skill, Item item)
{
return (effector.getActingPlayer() != null) && (effector.getActingPlayer().getChargedSouls() >= _souls);
return (effector.getActingPlayer() != null) && (effector.getActingPlayer().getChargedSouls(_type) >= _souls);
}
}

View File

@ -161,7 +161,8 @@ public class Skill implements IIdentifiable
private final BasicProperty _basicProperty;
private final int _minPledgeClass;
private final int _soulMaxConsume;
private final int _lightSoulMaxConsume;
private final int _shadowSoulMaxConsume;
private final int _chargeConsume;
private final boolean _isTriggeredSkill; // If true the skill will take activation buff slot instead of a normal buff slot
@ -345,7 +346,8 @@ public class Skill implements IIdentifiable
_basicProperty = set.getEnum("basicProperty", BasicProperty.class, BasicProperty.NONE);
_isSuicideAttack = set.getBoolean("isSuicideAttack", false);
_minPledgeClass = set.getInt("minPledgeClass", 0);
_soulMaxConsume = set.getInt("soulMaxConsumeCount", 0);
_lightSoulMaxConsume = set.getInt("lightSoulMaxConsume", 0);
_shadowSoulMaxConsume = set.getInt("shadowSoulMaxConsume", 0);
_chargeConsume = set.getInt("chargeConsume", 0);
_isTriggeredSkill = set.getBoolean("isTriggeredSkill", false);
_effectPoint = set.getInt("effectPoint", 0);
@ -1022,9 +1024,14 @@ public class Skill implements IIdentifiable
return _abnormalType == AbnormalType.HP_RECOVER;
}
public int getMaxSoulConsumeCount()
public int getMaxLightSoulConsumeCount()
{
return _soulMaxConsume;
return _lightSoulMaxConsume;
}
public int getMaxShadowSoulConsumeCount()
{
return _shadowSoulMaxConsume;
}
public int getChargeConsumeCount()

View File

@ -36,6 +36,7 @@ import org.l2jmobius.gameserver.data.ItemTable;
import org.l2jmobius.gameserver.data.xml.ActionData;
import org.l2jmobius.gameserver.enums.ItemSkillType;
import org.l2jmobius.gameserver.enums.NextActionType;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.enums.StatusUpdateType;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.instancemanager.QuestManager;
@ -490,7 +491,11 @@ public class SkillCaster implements Runnable
if (caster.isPlayer())
{
// Consume Souls if necessary.
if ((_skill.getMaxSoulConsumeCount() > 0) && !caster.getActingPlayer().decreaseSouls(_skill.getMaxSoulConsumeCount()))
if ((_skill.getMaxLightSoulConsumeCount() > 0) && !caster.getActingPlayer().decreaseSouls(_skill.getMaxLightSoulConsumeCount(), SoulType.LIGHT))
{
return false;
}
if ((_skill.getMaxShadowSoulConsumeCount() > 0) && !caster.getActingPlayer().decreaseSouls(_skill.getMaxShadowSoulConsumeCount(), SoulType.SHADOW))
{
return false;
}

View File

@ -17,7 +17,7 @@
package org.l2jmobius.gameserver.network.serverpackets;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.enums.Race;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.OutgoingPackets;
@ -28,8 +28,6 @@ import org.l2jmobius.gameserver.network.OutgoingPackets;
public class EtcStatusUpdate implements IClientOutgoingPacket
{
private final PlayerInstance _player;
private final boolean _isLight;
private final boolean _isShadow;
private int _mask;
public EtcStatusUpdate(PlayerInstance player)
@ -38,17 +36,6 @@ public class EtcStatusUpdate implements IClientOutgoingPacket
_mask = _player.getMessageRefusal() || _player.isChatBanned() || _player.isSilenceMode() ? 1 : 0;
_mask |= _player.isInsideZone(ZoneId.DANGER_AREA) ? 2 : 0;
_mask |= _player.hasCharmOfCourage() ? 4 : 0;
if (_player.getRace() == Race.KAMAEL)
{
_isShadow = _player.getShadowMasterLevel() > 0;
_isLight = !_isShadow && (_player.getLightMasterLevel() > 0);
}
else
{
_isLight = false;
_isShadow = false;
}
}
@Override
@ -61,10 +48,10 @@ public class EtcStatusUpdate implements IClientOutgoingPacket
packet.writeC(0); // Weapon Grade Penalty [1-4]
packet.writeC(0); // Armor Grade Penalty [1-4]
packet.writeC(0); // Death Penalty [1-15, 0 = disabled)], not used anymore in Ertheia
packet.writeC(!_isShadow && !_isLight ? _player.getChargedSouls() : 0);
packet.writeC(0); // Old count for charged souls.
packet.writeC(_mask);
packet.writeC(_isShadow ? _player.getChargedSouls() : 0); // Shadow souls
packet.writeC(_isLight ? _player.getChargedSouls() : 0); // Light souls
packet.writeC(_player.getChargedSouls(SoulType.SHADOW)); // Shadow souls
packet.writeC(_player.getChargedSouls(SoulType.LIGHT)); // Light souls
return true;
}
}

View File

@ -39,6 +39,7 @@ import org.l2jmobius.gameserver.enums.CategoryType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.PlayerState;
import org.l2jmobius.gameserver.enums.Race;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.conditions.Condition;
import org.l2jmobius.gameserver.model.conditions.ConditionCategoryType;
@ -537,7 +538,8 @@ public abstract class DocumentBase
case "souls":
{
final int value = Integer.decode(getValue(a.getNodeValue(), template));
cond = joinAnd(cond, new ConditionPlayerSouls(value));
final SoulType type = Enum.valueOf(SoulType.class, a.getNodeValue());
cond = joinAnd(cond, new ConditionPlayerSouls(value, type));
break;
}
case "weight":

View File

@ -16,6 +16,7 @@
*/
package handlers.effecthandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
@ -32,10 +33,12 @@ import org.l2jmobius.gameserver.network.SystemMessageId;
public class FocusSouls extends AbstractEffect
{
private final int _charge;
private final SoulType _type;
public FocusSouls(StatSet params)
{
_charge = params.getInt("charge", 0);
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
}
@Override
@ -57,10 +60,10 @@ public class FocusSouls extends AbstractEffect
if (maxSouls > 0)
{
final int amount = _charge;
if ((target.getChargedSouls() < maxSouls))
if ((target.getChargedSouls(_type) < maxSouls))
{
final int count = ((target.getChargedSouls() + amount) <= maxSouls) ? amount : (maxSouls - target.getChargedSouls());
target.increaseSouls(count);
final int count = ((target.getChargedSouls(_type) + amount) <= maxSouls) ? amount : (maxSouls - target.getChargedSouls(_type));
target.increaseSouls(count, _type);
}
else
{

View File

@ -66,8 +66,26 @@ public class MagicalSoulAttack extends AbstractEffect
effected.stopFakeDeath(true);
}
final int chargedSouls = Math.min(skill.getMaxSoulConsumeCount(), effector.getActingPlayer().getCharges());
if (!effector.getActingPlayer().decreaseCharges(chargedSouls))
final int chargedLightSouls = Math.min(skill.getMaxLightSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedLightSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedLightSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedShadowSouls = Math.min(skill.getMaxShadowSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedShadowSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedShadowSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedSouls = chargedLightSouls + chargedShadowSouls;
if (chargedSouls < 1)
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);

View File

@ -86,8 +86,26 @@ public class PhysicalSoulAttack extends AbstractEffect
effected.stopFakeDeath(true);
}
final int souls = Math.min(skill.getMaxSoulConsumeCount(), effector.getActingPlayer().getCharges());
if (!effector.getActingPlayer().decreaseCharges(souls))
final int chargedLightSouls = Math.min(skill.getMaxLightSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedLightSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedLightSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedShadowSouls = Math.min(skill.getMaxShadowSoulConsumeCount(), effector.getActingPlayer().getCharges());
if ((chargedShadowSouls > 0) && !effector.getActingPlayer().decreaseCharges(chargedShadowSouls))
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
effector.sendPacket(sm);
return;
}
final int chargedSouls = chargedLightSouls + chargedShadowSouls;
if (chargedSouls < 1)
{
final SystemMessage sm = new SystemMessage(SystemMessageId.S1_CANNOT_BE_USED_DUE_TO_UNSUITABLE_TERMS);
sm.addSkillName(skill);
@ -150,7 +168,7 @@ public class PhysicalSoulAttack extends AbstractEffect
ssmod = 4 * effector.getStat().getValue(Stat.SHOTS_BONUS);
}
}
final double soulsMod = 1 + (souls * 0.04); // Souls Formula (each soul increase +4%)
final double soulsMod = 1 + (chargedSouls * 0.04); // Souls Formula (each soul increase +4%)
// ...................____________Melee Damage_____________......................................___________________Ranged Damage____________________
// ATTACK CALCULATION 77 * ((pAtk * lvlMod) + power) / pdef            RANGED ATTACK CALCULATION 70 * ((pAtk * lvlMod) + power + patk + power) / pdef

View File

@ -17,6 +17,7 @@
package handlers.effecthandlers;
import org.l2jmobius.gameserver.enums.ShotType;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.actor.Attackable;
import org.l2jmobius.gameserver.model.actor.Creature;
@ -83,12 +84,22 @@ public class SoulBlow extends AbstractEffect
final boolean ss = skill.useSoulShot() && (effector.isChargedShot(ShotType.SOULSHOTS) || effector.isChargedShot(ShotType.BLESSED_SOULSHOTS));
final byte shld = Formulas.calcShldUse(effector, effected);
double damage = Formulas.calcBlowDamage(effector, effected, skill, false, _power, shld, ss);
if ((skill.getMaxSoulConsumeCount() > 0) && effector.isPlayer())
if (effector.isPlayer())
{
if (skill.getMaxLightSoulConsumeCount() > 0)
{
// Souls Formula (each soul increase +4%)
final int chargedSouls = (effector.getActingPlayer().getChargedSouls() <= skill.getMaxSoulConsumeCount()) ? effector.getActingPlayer().getChargedSouls() : skill.getMaxSoulConsumeCount();
final int chargedSouls = (effector.getActingPlayer().getChargedSouls(SoulType.LIGHT) <= skill.getMaxLightSoulConsumeCount()) ? effector.getActingPlayer().getChargedSouls(SoulType.LIGHT) : skill.getMaxLightSoulConsumeCount();
damage *= 1 + (chargedSouls * 0.04);
}
if (skill.getMaxShadowSoulConsumeCount() > 0)
{
// Souls Formula (each soul increase +4%)
final int chargedSouls = (effector.getActingPlayer().getChargedSouls(SoulType.SHADOW) <= skill.getMaxShadowSoulConsumeCount()) ? effector.getActingPlayer().getChargedSouls(SoulType.SHADOW) : skill.getMaxShadowSoulConsumeCount();
damage *= 1 + (chargedSouls * 0.04);
}
}
effector.doAttack(damage, effected, skill, false, false, true, false);
}

View File

@ -16,6 +16,7 @@
*/
package handlers.effecthandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.actor.Npc;
@ -37,11 +38,13 @@ import org.l2jmobius.gameserver.network.serverpackets.ExSpawnEmitter;
*/
public class SoulEating extends AbstractEffect
{
private final SoulType _type;
private final int _expNeeded;
private final int _maxSouls;
public SoulEating(StatSet params)
{
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
_expNeeded = params.getInt("expNeeded");
_maxSouls = params.getInt("maxSouls");
}
@ -77,13 +80,13 @@ public class SoulEating extends AbstractEffect
{
final PlayerInstance player = playable.getActingPlayer();
final int maxSouls = (int) player.getStat().getValue(Stat.MAX_SOULS, 0);
if (player.getChargedSouls() >= maxSouls)
if (player.getChargedSouls(_type) >= maxSouls)
{
playable.sendPacket(SystemMessageId.YOU_CAN_T_ABSORB_MORE_SOULS);
return;
}
player.increaseSouls(1);
player.increaseSouls(1, _type);
if ((player.getTarget() != null) && player.getTarget().isNpc())
{

View File

@ -16,6 +16,7 @@
*/
package handlers.skillconditionhandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature;
@ -28,14 +29,17 @@ import org.l2jmobius.gameserver.model.stats.Stat;
*/
public class OpSoulMaxSkillCondition implements ISkillCondition
{
private final SoulType _type;
public OpSoulMaxSkillCondition(StatSet params)
{
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
}
@Override
public boolean canUse(Creature caster, Skill skill, WorldObject target)
{
final int maxSouls = (int) caster.getStat().getValue(Stat.MAX_SOULS);
return caster.isPlayable() && (caster.getActingPlayer().getChargedSouls() < maxSouls);
return caster.isPlayable() && (caster.getActingPlayer().getChargedSouls(_type) < maxSouls);
}
}

View File

@ -16,6 +16,7 @@
*/
package handlers.skillconditionhandlers;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.WorldObject;
import org.l2jmobius.gameserver.model.actor.Creature;
@ -27,16 +28,18 @@ import org.l2jmobius.gameserver.model.skills.Skill;
*/
public class SoulSavedSkillCondition implements ISkillCondition
{
private final SoulType _type;
private final int _amount;
public SoulSavedSkillCondition(StatSet params)
{
_type = params.getEnum("type", SoulType.class, SoulType.LIGHT);
_amount = params.getInt("amount");
}
@Override
public boolean canUse(Creature caster, Skill skill, WorldObject target)
{
return caster.isPlayer() && (caster.getActingPlayer().getChargedSouls() >= _amount);
return caster.isPlayer() && (caster.getActingPlayer().getChargedSouls(_type) >= _amount);
}
}

View File

@ -3678,19 +3678,40 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="LIGHT" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>LIGHT</type>
<charge>2</charge>
</effect>
</effects>
</skill>
<skill id="394" toLevel="1" name="Absorb Shadow Souls">
<!-- TODO: Shadow Souls Implementation -->
<magicLevel>1</magicLevel>
<effectPoint>150</effectPoint>
<hitTime>500</hitTime>
<hpConsume>30</hpConsume>
<magicLevel>
<value level="1">40</value>
<value level="2">49</value>
<value level="3">58</value>
<value level="4">66</value>
<value level="5">72</value>
</magicLevel>
<operateType>A1</operateType>
<reuseDelay>2000</reuseDelay>
<magicCriticalRate>5</magicCriticalRate>
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" type="SHADOW" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>SHADOW</type>
<charge>2</charge>
</effect>
</effects>
</skill>
<skill id="395" toLevel="1" name="Heroic Miracle">
<!-- For 30 sec., P. Def. +5400, M. Def. +4050, Buff-canceling Attack Resistance +80, and Speed +5. Consumes 40 Soulstone(s). -->
@ -3806,7 +3827,8 @@
<skill id="397" toLevel="2" name="Light Veil">
<!-- Enough Shine Souls have been gathered to be in the Shine Side state. <Acceleration Stage 1>. P. Atk. +130, Atk. Spd. +30, Casting Spd. +40, Speed +10. P./M. Def. +5%. Has a chance to recover MP when attacking. -->
<abnormalLevel>1</abnormalLevel>
<abnormalTime>30</abnormalTime>
<abnormalTime>60</abnormalTime>
<abnormalType>BR_EVENT_BUF1</abnormalType>
<isMagic>4</isMagic>
<magicLevel>
<value level="1">20</value>
@ -3884,7 +3906,8 @@
<skill id="398" toLevel="2" name="Shadow Veil">
<!-- Enough Shadow Souls have been gathered to be in the Shadow Side state. <Acceleration Stage 2>. P. Atk. +280, Atk. Spd. +80, Casting Spd. +120, Speed +15. Has a chance to activate powerful attack skills. -->
<abnormalLevel>1</abnormalLevel>
<abnormalTime>30</abnormalTime>
<abnormalTime>60</abnormalTime>
<abnormalType>BR_EVENT_BUF1</abnormalType>
<isMagic>4</isMagic>
<magicLevel>
<value level="1">20</value>

View File

@ -2235,10 +2235,11 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="LIGHT" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>LIGHT</type>
<charge>
<value level="1">70</value>
<value level="2">100</value>
@ -2260,10 +2261,11 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="SHADOW" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>SHADOW</type>
<charge>
<value level="1">70</value>
<value level="2">100</value>
@ -3595,6 +3597,7 @@
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="SoulEating">
<type>LIGHT</type>
<maxSouls>
<value level="1">100</value>
<value level="2">100</value>
@ -3629,8 +3632,45 @@
<skill id="45179" toLevel="2" name="Shadow Master">
<!-- Allows to absorb the power of shadows.\n\nCollect 100 Shadow Souls to assume the Shadow Veil.\n\n<Shadow Veil>\nGrants Evolved Wings Lv. 2 that allows to make powerful attacks. -->
<icon>icon.skill_jinkama_black1</icon>
<magicLevel>
<value level="1">20</value>
<value level="2">60</value>
</magicLevel>
<operateType>P</operateType>
<isMagic>4</isMagic>
<magicCriticalRate>5</magicCriticalRate>
<effects>
<effect name="SoulEating">
<type>SHADOW</type>
<maxSouls>
<value level="1">100</value>
<value level="2">100</value>
</maxSouls>
<expNeeded>
<value level="1">294</value>
<value level="2">2160</value>
</expNeeded>
</effect>
<effect name="TriggerSkillByAttack">
<isCritical>true</isCritical>
<skillId>45181</skillId> <!-- Shadow Soul Absorption -->
<skillLevel>1</skillLevel>
<allowWeapons>ALL</allowWeapons>
<attackerType>Creature</attackerType>
<targetType>SELF</targetType>
<minDamage>1</minDamage>
<chance>30</chance>
</effect>
<effect name="TriggerSkillByAttack">
<isCritical>false</isCritical>
<skillId>45181</skillId> <!-- Shadow Soul Absorption -->
<skillLevel>1</skillLevel>
<allowWeapons>ALL</allowWeapons>
<attackerType>Creature</attackerType>
<targetType>SELF</targetType>
<minDamage>1</minDamage>
<chance>15</chance>
</effect>
</effects>
</skill>
<skill id="45180" toLevel="4" name="Light Soul Absorption">
<!-- Activates when attacking. -->
@ -3643,17 +3683,33 @@
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" />
<condition name="OpSoulMax" type="LIGHT" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>LIGHT</type>
<charge>1</charge>
</effect>
</effects>
</skill>
<skill id="45181" toLevel="4" name="Shadow Soul Absorption">
<!-- Activates when attacking. -->
<isTriggeredSkill>true</isTriggeredSkill>
<magicLevel>20</magicLevel>
<operateType>A1</operateType>
<reuseDelay>10000</reuseDelay>
<magicCriticalRate>-5</magicCriticalRate>
<hitCancelTime>0</hitCancelTime>
<targetType>SELF</targetType>
<affectScope>SINGLE</affectScope>
<conditions>
<condition name="OpSoulMax" type="SHADOW" />
</conditions>
<effects>
<effect name="FocusSouls">
<type>SHADOW</type>
<charge>1</charge>
</effect>
</effects>
</skill>
<skill id="45182" toLevel="8" name="Soul Thrust">
<!-- M. Def. -$s1. -->

View File

@ -462,6 +462,7 @@
</xs:element>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="type" type="xs:string" use="optional" />
</xs:complexType>
</xs:element>
</xs:sequence>

View File

@ -0,0 +1,26 @@
/*
* 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.enums;
/**
* @author Mobius
*/
public enum SoulType
{
LIGHT,
SHADOW
}

View File

@ -101,6 +101,7 @@ import org.l2jmobius.gameserver.enums.PrivateStoreType;
import org.l2jmobius.gameserver.enums.Race;
import org.l2jmobius.gameserver.enums.Sex;
import org.l2jmobius.gameserver.enums.ShortcutType;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.enums.StatusUpdateType;
import org.l2jmobius.gameserver.enums.SubclassInfoType;
import org.l2jmobius.gameserver.enums.Team;
@ -675,7 +676,7 @@ public class PlayerInstance extends Playable
private final static int KAMAEL_SHADOW_MASTER = 45179;
private final static int KAMAEL_LIGHT_TRANSFORMATION = 397;
private final static int KAMAEL_SHADOW_TRANSFORMATION = 398;
private int _souls = 0;
private final Map<SoulType, Integer> _souls = new ConcurrentHashMap<>(2);
private ScheduledFuture<?> _soulTask = null;
// Death Points
@ -11317,48 +11318,53 @@ public class PlayerInstance extends Playable
}
/**
* Returns the Number of Souls this PlayerInstance got.
* Returns the Number of souls.
* @param type the type of souls.
* @return
*/
public int getChargedSouls()
public int getChargedSouls(SoulType type)
{
return _souls;
return _souls.getOrDefault(type, 0).intValue();
}
/**
* Increase Souls
* @param count
* @param type
*/
public void increaseSouls(int count)
public void increaseSouls(int count, SoulType type)
{
_souls += count;
final int newCount = getChargedSouls(type) + count;
_souls.put(type, newCount);
final SystemMessage sm = new SystemMessage(SystemMessageId.YOUR_SOUL_COUNT_HAS_INCREASED_BY_S1_IT_IS_NOW_AT_S2);
sm.addInt(count);
sm.addInt(_souls);
sm.addInt(newCount);
sendPacket(sm);
restartSoulTask();
sendPacket(new EtcStatusUpdate(this));
// TODO: Unhardcode?
if ((getRace() == Race.KAMAEL) && (_souls >= 100))
if ((getRace() == Race.KAMAEL) && (newCount >= 100) && !isTransformed())
{
int skillLevel = getShadowMasterLevel();
if (type == SoulType.LIGHT)
{
final int skillLevel = getLightMasterLevel();
if (skillLevel > 0)
{
abortCast();
decreaseSouls(100);
SkillData.getInstance().getSkill(KAMAEL_SHADOW_TRANSFORMATION, skillLevel).applyEffects(this, this);
}
else
{
skillLevel = getLightMasterLevel();
if (skillLevel > 0)
{
abortCast();
decreaseSouls(100);
decreaseSouls(100, type);
SkillData.getInstance().getSkill(KAMAEL_LIGHT_TRANSFORMATION, skillLevel).applyEffects(this, this);
}
}
else // Shadow.
{
final int skillLevel = getShadowMasterLevel();
if (skillLevel > 0)
{
abortCast();
decreaseSouls(100, type);
SkillData.getInstance().getSkill(KAMAEL_SHADOW_TRANSFORMATION, skillLevel).applyEffects(this, this);
}
}
}
}
@ -11375,17 +11381,19 @@ public class PlayerInstance extends Playable
/**
* Decreases existing Souls.
* @param count
* @param type
* @return
*/
public boolean decreaseSouls(int count)
public boolean decreaseSouls(int count, SoulType type)
{
_souls -= count;
if (_souls < 0)
int newCount = getChargedSouls(type) - count;
if (newCount < 0)
{
_souls = 0;
newCount = 0;
}
_souls.put(type, newCount);
if (_souls == 0)
if (newCount == 0)
{
stopSoulTask();
}
@ -11403,7 +11411,7 @@ public class PlayerInstance extends Playable
*/
public void clearSouls()
{
_souls = 0;
_souls.clear();
stopSoulTask();
sendPacket(new EtcStatusUpdate(this));
}

View File

@ -16,6 +16,7 @@
*/
package org.l2jmobius.gameserver.model.conditions;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.actor.Creature;
import org.l2jmobius.gameserver.model.items.Item;
import org.l2jmobius.gameserver.model.skills.Skill;
@ -26,19 +27,22 @@ import org.l2jmobius.gameserver.model.skills.Skill;
public class ConditionPlayerSouls extends Condition
{
private final int _souls;
private final SoulType _type;
/**
* Instantiates a new condition player souls.
* @param souls the souls
* @param type the soul type
*/
public ConditionPlayerSouls(int souls)
public ConditionPlayerSouls(int souls, SoulType type)
{
_souls = souls;
_type = type;
}
@Override
public boolean testImpl(Creature effector, Creature effected, Skill skill, Item item)
{
return (effector.getActingPlayer() != null) && (effector.getActingPlayer().getChargedSouls() >= _souls);
return (effector.getActingPlayer() != null) && (effector.getActingPlayer().getChargedSouls(_type) >= _souls);
}
}

View File

@ -161,7 +161,8 @@ public class Skill implements IIdentifiable
private final BasicProperty _basicProperty;
private final int _minPledgeClass;
private final int _soulMaxConsume;
private final int _lightSoulMaxConsume;
private final int _shadowSoulMaxConsume;
private final int _chargeConsume;
private final boolean _isTriggeredSkill; // If true the skill will take activation buff slot instead of a normal buff slot
@ -345,7 +346,8 @@ public class Skill implements IIdentifiable
_basicProperty = set.getEnum("basicProperty", BasicProperty.class, BasicProperty.NONE);
_isSuicideAttack = set.getBoolean("isSuicideAttack", false);
_minPledgeClass = set.getInt("minPledgeClass", 0);
_soulMaxConsume = set.getInt("soulMaxConsumeCount", 0);
_lightSoulMaxConsume = set.getInt("lightSoulMaxConsume", 0);
_shadowSoulMaxConsume = set.getInt("shadowSoulMaxConsume", 0);
_chargeConsume = set.getInt("chargeConsume", 0);
_isTriggeredSkill = set.getBoolean("isTriggeredSkill", false);
_effectPoint = set.getInt("effectPoint", 0);
@ -1022,9 +1024,14 @@ public class Skill implements IIdentifiable
return _abnormalType == AbnormalType.HP_RECOVER;
}
public int getMaxSoulConsumeCount()
public int getMaxLightSoulConsumeCount()
{
return _soulMaxConsume;
return _lightSoulMaxConsume;
}
public int getMaxShadowSoulConsumeCount()
{
return _shadowSoulMaxConsume;
}
public int getChargeConsumeCount()

View File

@ -36,6 +36,7 @@ import org.l2jmobius.gameserver.data.ItemTable;
import org.l2jmobius.gameserver.data.xml.ActionData;
import org.l2jmobius.gameserver.enums.ItemSkillType;
import org.l2jmobius.gameserver.enums.NextActionType;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.enums.StatusUpdateType;
import org.l2jmobius.gameserver.geoengine.GeoEngine;
import org.l2jmobius.gameserver.instancemanager.QuestManager;
@ -490,7 +491,11 @@ public class SkillCaster implements Runnable
if (caster.isPlayer())
{
// Consume Souls if necessary.
if ((_skill.getMaxSoulConsumeCount() > 0) && !caster.getActingPlayer().decreaseSouls(_skill.getMaxSoulConsumeCount()))
if ((_skill.getMaxLightSoulConsumeCount() > 0) && !caster.getActingPlayer().decreaseSouls(_skill.getMaxLightSoulConsumeCount(), SoulType.LIGHT))
{
return false;
}
if ((_skill.getMaxShadowSoulConsumeCount() > 0) && !caster.getActingPlayer().decreaseSouls(_skill.getMaxShadowSoulConsumeCount(), SoulType.SHADOW))
{
return false;
}

View File

@ -17,7 +17,7 @@
package org.l2jmobius.gameserver.network.serverpackets;
import org.l2jmobius.commons.network.PacketWriter;
import org.l2jmobius.gameserver.enums.Race;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.actor.instance.PlayerInstance;
import org.l2jmobius.gameserver.model.zone.ZoneId;
import org.l2jmobius.gameserver.network.OutgoingPackets;
@ -28,8 +28,6 @@ import org.l2jmobius.gameserver.network.OutgoingPackets;
public class EtcStatusUpdate implements IClientOutgoingPacket
{
private final PlayerInstance _player;
private final boolean _isLight;
private final boolean _isShadow;
private int _mask;
public EtcStatusUpdate(PlayerInstance player)
@ -38,17 +36,6 @@ public class EtcStatusUpdate implements IClientOutgoingPacket
_mask = _player.getMessageRefusal() || _player.isChatBanned() || _player.isSilenceMode() ? 1 : 0;
_mask |= _player.isInsideZone(ZoneId.DANGER_AREA) ? 2 : 0;
_mask |= _player.hasCharmOfCourage() ? 4 : 0;
if (_player.getRace() == Race.KAMAEL)
{
_isShadow = _player.getShadowMasterLevel() > 0;
_isLight = !_isShadow && (_player.getLightMasterLevel() > 0);
}
else
{
_isLight = false;
_isShadow = false;
}
}
@Override
@ -61,10 +48,10 @@ public class EtcStatusUpdate implements IClientOutgoingPacket
packet.writeC(0); // Weapon Grade Penalty [1-4]
packet.writeC(0); // Armor Grade Penalty [1-4]
packet.writeC(0); // Death Penalty [1-15, 0 = disabled)], not used anymore in Ertheia
packet.writeC(!_isShadow && !_isLight ? _player.getChargedSouls() : 0);
packet.writeC(0); // Old count for charged souls.
packet.writeC(_mask);
packet.writeC(_isShadow ? _player.getChargedSouls() : 0); // Shadow souls
packet.writeC(_isLight ? _player.getChargedSouls() : 0); // Light souls
packet.writeC(_player.getChargedSouls(SoulType.SHADOW)); // Shadow souls
packet.writeC(_player.getChargedSouls(SoulType.LIGHT)); // Light souls
return true;
}
}

View File

@ -39,6 +39,7 @@ import org.l2jmobius.gameserver.enums.CategoryType;
import org.l2jmobius.gameserver.enums.InstanceType;
import org.l2jmobius.gameserver.enums.PlayerState;
import org.l2jmobius.gameserver.enums.Race;
import org.l2jmobius.gameserver.enums.SoulType;
import org.l2jmobius.gameserver.model.StatSet;
import org.l2jmobius.gameserver.model.conditions.Condition;
import org.l2jmobius.gameserver.model.conditions.ConditionCategoryType;
@ -537,7 +538,8 @@ public abstract class DocumentBase
case "souls":
{
final int value = Integer.decode(getValue(a.getNodeValue(), template));
cond = joinAnd(cond, new ConditionPlayerSouls(value));
final SoulType type = Enum.valueOf(SoulType.class, a.getNodeValue());
cond = joinAnd(cond, new ConditionPlayerSouls(value, type));
break;
}
case "weight":