123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889 |
- /*
- * 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 net.sf.l2j.gameserver.model;
- import java.util.Collection;
- import net.sf.l2j.Config;
- import net.sf.l2j.gameserver.GeoData;
- import net.sf.l2j.gameserver.ai.CtrlIntention;
- import net.sf.l2j.gameserver.ai.L2CharacterAI;
- import net.sf.l2j.gameserver.ai.L2SummonAI;
- import net.sf.l2j.gameserver.datatables.SkillTable;
- import net.sf.l2j.gameserver.model.L2Attackable.AggroInfo;
- import net.sf.l2j.gameserver.model.L2Skill.SkillTargetType;
- import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
- import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
- import net.sf.l2j.gameserver.model.actor.instance.L2PetInstance;
- import net.sf.l2j.gameserver.model.actor.instance.L2PlayableInstance;
- import net.sf.l2j.gameserver.model.actor.instance.L2SummonInstance;
- import net.sf.l2j.gameserver.model.actor.knownlist.SummonKnownList;
- import net.sf.l2j.gameserver.model.actor.stat.SummonStat;
- import net.sf.l2j.gameserver.model.actor.status.SummonStatus;
- import net.sf.l2j.gameserver.model.base.Experience;
- import net.sf.l2j.gameserver.model.itemcontainer.PetInventory;
- import net.sf.l2j.gameserver.model.olympiad.Olympiad;
- import net.sf.l2j.gameserver.network.SystemMessageId;
- import net.sf.l2j.gameserver.network.serverpackets.ActionFailed;
- import net.sf.l2j.gameserver.network.serverpackets.ExPartyPetWindowAdd;
- import net.sf.l2j.gameserver.network.serverpackets.ExPartyPetWindowDelete;
- import net.sf.l2j.gameserver.network.serverpackets.ExPartyPetWindowUpdate;
- import net.sf.l2j.gameserver.network.serverpackets.MyTargetSelected;
- import net.sf.l2j.gameserver.network.serverpackets.NpcInfo;
- import net.sf.l2j.gameserver.network.serverpackets.PartySpelled;
- import net.sf.l2j.gameserver.network.serverpackets.PetDelete;
- import net.sf.l2j.gameserver.network.serverpackets.PetInfo;
- import net.sf.l2j.gameserver.network.serverpackets.PetStatusShow;
- import net.sf.l2j.gameserver.network.serverpackets.PetStatusUpdate;
- import net.sf.l2j.gameserver.network.serverpackets.RelationChanged;
- import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
- import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
- import net.sf.l2j.gameserver.taskmanager.DecayTaskManager;
- import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
- import net.sf.l2j.gameserver.templates.item.L2Weapon;
- public abstract class L2Summon extends L2PlayableInstance
- {
- //private static Logger _log = Logger.getLogger(L2Summon.class.getName());
- protected int _pkKills;
- private byte _pvpFlag;
- private L2PcInstance _owner;
- private int _karma = 0;
- private int _attackRange = 36; //Melee range
- private boolean _follow = true;
- private boolean _previousFollowStatus = true;
- private int _maxLoad;
- private int _chargedSoulShot;
- private int _chargedSpiritShot;
- // TODO: currently, all servitors use 1 shot. However, this value
- // should vary depending on the servitor template (id and level)!
- private int _soulShotsPerHit = 1;
- private int _spiritShotsPerHit = 1;
- public class AIAccessor extends L2Character.AIAccessor
- {
- protected AIAccessor() {}
- public L2Summon getSummon() { return L2Summon.this; }
- public boolean isAutoFollow() {
- return L2Summon.this.getFollowStatus();
- }
- public void doPickupItem(L2Object object) {
- L2Summon.this.doPickupItem(object);
- }
- }
- public L2Summon(int objectId, L2NpcTemplate template, L2PcInstance owner)
- {
- super(objectId, template);
- getKnownList(); // init knownlist
- getStat(); // init stats
- getStatus(); // init status
- setInstanceId(owner.getInstanceId()); // set instance to same as owner
-
- _showSummonAnimation = true;
- _owner = owner;
- _ai = new L2SummonAI(new L2Summon.AIAccessor());
- setXYZInvisible(owner.getX()+50, owner.getY()+100, owner.getZ()+100);
- }
- @Override
- public void onSpawn()
- {
- super.onSpawn();
- this.setFollowStatus(true);
- setShowSummonAnimation(false); // addVisibleObject created the info packets with summon animation
- // if someone comes into range now, the animation shouldnt show any more
- this.getOwner().sendPacket(new PetInfo(this));
- getOwner().sendPacket(new RelationChanged(this, getOwner().getRelation(getOwner()), false));
- for (L2PcInstance player : getOwner().getKnownList().getKnownPlayersInRadius(800))
- player.sendPacket(new RelationChanged(this, getOwner().getRelation(player), isAutoAttackable(player)));
- L2Party party = this.getOwner().getParty();
- if (party != null)
- {
- party.broadcastToPartyMembers(this.getOwner(), new ExPartyPetWindowAdd(this));
- }
- }
- @Override
- public final SummonKnownList getKnownList()
- {
- if(!(super.getKnownList() instanceof SummonKnownList))
- setKnownList(new SummonKnownList(this));
- return (SummonKnownList)super.getKnownList();
- }
- @Override
- public SummonStat getStat()
- {
- if(!(super.getStat() instanceof SummonStat))
- setStat(new SummonStat(this));
- return (SummonStat)super.getStat();
- }
- @Override
- public SummonStatus getStatus()
- {
- if(!(super.getStatus() instanceof SummonStatus))
- setStatus(new SummonStatus(this));
- return (SummonStatus)super.getStatus();
- }
- @Override
- public L2CharacterAI getAI()
- {
- L2CharacterAI ai = _ai; // copy handle
- if (ai == null)
- {
- synchronized(this)
- {
- if (_ai == null) _ai = new L2SummonAI(new L2Summon.AIAccessor());
- return _ai;
- }
- }
- return ai;
- }
- @Override
- public L2NpcTemplate getTemplate()
- {
- return (L2NpcTemplate)super.getTemplate();
- }
- // this defines the action buttons, 1 for Summon, 2 for Pets
- public abstract int getSummonType();
- @Override
- public void updateAbnormalEffect()
- {
- Collection<L2PcInstance> plrs = getKnownList().getKnownPlayers().values();
- //synchronized (getKnownList().getKnownPlayers())
- {
- for (L2PcInstance player : plrs)
- player.sendPacket(new NpcInfo(this, player));
- }
- }
- /**
- * @return Returns the mountable.
- */
- public boolean isMountable()
- {
- return false;
- }
-
- public boolean isMountableOverTime()
- {
- return false;
- }
- @Override
- public void onAction(L2PcInstance player)
- {
- if (player == _owner && player.getTarget() == this)
- {
- player.sendPacket(new PetStatusShow(this));
- player.sendPacket(ActionFailed.STATIC_PACKET);
- }
- else if (player.getTarget() != this)
- {
- if (Config.DEBUG) _log.fine("new target selected:"+getObjectId());
- player.setTarget(this);
- MyTargetSelected my = new MyTargetSelected(getObjectId(), player.getLevel() - getLevel());
- player.sendPacket(my);
- //sends HP/MP status of the summon to other characters
- StatusUpdate su = new StatusUpdate(getObjectId());
- su.addAttribute(StatusUpdate.CUR_HP, (int) getCurrentHp());
- su.addAttribute(StatusUpdate.MAX_HP, getMaxHp());
- player.sendPacket(su);
- }
- else if (player.getTarget() == this)
- {
- if (isAutoAttackable(player))
- {
- if (Config.GEODATA > 0)
- {
- if (GeoData.getInstance().canSeeTarget(player, this))
- {
- player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
- player.onActionRequest();
- }
- }
- else
- {
- player.getAI().setIntention(CtrlIntention.AI_INTENTION_ATTACK, this);
- player.onActionRequest();
- }
- }
- else
- {
- // This Action Failed packet avoids player getting stuck when clicking three or more times
- player.sendPacket(ActionFailed.STATIC_PACKET);
- if (Config.GEODATA > 0)
- {
- if (GeoData.getInstance().canSeeTarget(player, this))
- player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this);
- }
- else
- player.getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, this);
- }
- }
- }
- public long getExpForThisLevel()
- {
- if(getLevel() >= Experience.LEVEL.length)
- {
- return 0;
- }
- return Experience.LEVEL[getLevel()];
- }
- public long getExpForNextLevel()
- {
- if(getLevel() >= Experience.LEVEL.length - 1)
- {
- return 0;
- }
- return Experience.LEVEL[getLevel()+1];
- }
- public final int getKarma()
- {
- return _karma;
- }
- public void setKarma(int karma)
- {
- _karma = karma;
- }
- public final L2PcInstance getOwner()
- {
- return _owner;
- }
- public final int getNpcId()
- {
- return getTemplate().npcId;
- }
- public void setPvpFlag(byte pvpFlag)
- {
- _pvpFlag = pvpFlag;
- }
- public byte getPvpFlag()
- {
- return _pvpFlag;
- }
- public void setPkKills(int pkKills)
- {
- _pkKills = pkKills;
- }
- public final int getPkKills()
- {
- return _pkKills;
- }
- public final int getMaxLoad()
- {
- return _maxLoad;
- }
- public final int getSoulShotsPerHit()
- {
- return _soulShotsPerHit;
- }
- public final int getSpiritShotsPerHit()
- {
- return _spiritShotsPerHit;
- }
- public void setMaxLoad(int maxLoad)
- {
- _maxLoad = maxLoad;
- }
- public void setChargedSoulShot(int shotType)
- {
- _chargedSoulShot = shotType;
- }
- public void setChargedSpiritShot(int shotType)
- {
- _chargedSpiritShot = shotType;
- }
- public void followOwner()
- {
- setFollowStatus(true);
- }
- @Override
- public boolean doDie(L2Character killer)
- {
- if (!super.doDie(killer))
- return false;
-
- L2PcInstance owner = getOwner();
-
- if (owner != null)
- {
- Collection<L2Character> KnownTarget = this.getKnownList().getKnownCharacters();
- for (L2Character TgMob : KnownTarget)
- {
- // get the mobs which have aggro on the this instance
- if (TgMob instanceof L2Attackable)
- {
- if (((L2Attackable) TgMob).isDead())
- continue;
-
- AggroInfo info = ((L2Attackable) TgMob).getAggroListRP().get(this);
- if (info != null)
- ((L2Attackable) TgMob).addDamageHate(owner, info._damage, info._hate);
- }
- }
- }
-
- if (isPhoenixBlessed() && (getOwner() != null))
- getOwner().reviveRequest(getOwner(), null, true);
-
- DecayTaskManager.getInstance().addDecayTask(this);
- return true;
- }
- public boolean doDie(L2Character killer, boolean decayed)
- {
- if (!super.doDie(killer))
- return false;
- if (!decayed)
- {
- DecayTaskManager.getInstance().addDecayTask(this);
- }
- return true;
- }
- public void stopDecay()
- {
- DecayTaskManager.getInstance().cancelDecayTask(this);
- }
- @Override
- public void onDecay()
- {
- deleteMe(_owner);
- }
- @Override
- public void broadcastStatusUpdate()
- {
- super.broadcastStatusUpdate();
- if (isVisible())
- {
- getOwner().sendPacket(new PetStatusUpdate(this));
-
- L2Party party = this.getOwner().getParty();
- if (party != null)
- {
- party.broadcastToPartyMembers(this.getOwner(), new ExPartyPetWindowUpdate(this));
- }
- }
-
- }
-
- @Override
- public void updateEffectIcons(boolean partyOnly)
- {
- PartySpelled ps = new PartySpelled(this);
-
- // Go through all effects if any
- L2Effect[] effects = getAllEffects();
- if (effects != null && effects.length > 0)
- {
- for (L2Effect effect: effects)
- {
- if (effect == null)
- continue;
-
- if (effect.getInUse())
- {
- effect.addPartySpelledIcon(ps);
- }
- }
- }
-
- L2Party party = this.getOwner().getParty();
- if (party != null)
- {
- // tell everyone about the summon effect
- party.broadcastToPartyMembers(ps);
- }
- else
- {
- // tell only the owner
- this.getOwner().sendPacket(ps);
- }
- }
- public void deleteMe(L2PcInstance owner)
- {
- getAI().stopFollow();
- owner.sendPacket(new PetDelete(getObjectId(), 2));
- //FIXME: I think it should really drop items to ground and only owner can take for a while
- giveAllToOwner();
- decayMe();
- getKnownList().removeAllKnownObjects();
- owner.setPet(null);
- }
-
- public void onSummon()
- {
-
- }
- public void unSummon(L2PcInstance owner)
- {
- if (isVisible() && !isDead())
- {
- getAI().stopFollow();
- owner.sendPacket(new PetDelete(getObjectId(), 2));
- L2Party party;
- if ((party = owner.getParty()) != null)
- {
- party.broadcastToPartyMembers(owner, new ExPartyPetWindowDelete(this));
- }
-
- store();
- giveAllToOwner();
-
- L2WorldRegion oldRegion = getWorldRegion();
- decayMe();
- if (oldRegion != null) oldRegion.removeFromZones(this);
- getKnownList().removeAllKnownObjects();
- owner.setPet(null);
- setTarget(null);
-
- if (this instanceof L2PetInstance)
- ((L2PetInstance)this).setIsMountableOverTime(false);
- }
- }
- public int getAttackRange()
- {
- return _attackRange;
- }
- public void setAttackRange(int range)
- {
- if (range < 36)
- range = 36;
- _attackRange = range;
- }
- public void setFollowStatus(boolean state)
- {
- _follow = state;
- if (_follow)
- getAI().setIntention(CtrlIntention.AI_INTENTION_FOLLOW, getOwner());
- else
- getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE, null);
- }
- public boolean getFollowStatus()
- {
- return _follow;
- }
- @Override
- public boolean isAutoAttackable(L2Character attacker)
- {
- return _owner.isAutoAttackable(attacker);
- }
- public int getChargedSoulShot()
- {
- return _chargedSoulShot;
- }
- public int getChargedSpiritShot()
- {
- return _chargedSpiritShot;
- }
- public int getControlItemId()
- {
- return 0;
- }
- public L2Weapon getActiveWeapon()
- {
- return null;
- }
- @Override
- public PetInventory getInventory()
- {
- return null;
- }
- protected void doPickupItem(L2Object object)
- {
- return;
- }
- public void giveAllToOwner()
- {
- return;
- }
- public void store()
- {
- return;
- }
- @Override
- public L2ItemInstance getActiveWeaponInstance()
- {
- return null;
- }
- @Override
- public L2Weapon getActiveWeaponItem()
- {
- return null;
- }
- @Override
- public L2ItemInstance getSecondaryWeaponInstance()
- {
- return null;
- }
- @Override
- public L2Weapon getSecondaryWeaponItem()
- {
- return null;
- }
- /**
- * Return True if the L2Summon is invulnerable or if the summoner is in spawn protection.<BR><BR>
- */
- @Override
- public boolean isInvul()
- {
- return _isInvul || _isTeleporting || getOwner().isSpawnProtected();
- }
- /**
- * Return the L2Party object of its L2PcInstance owner or null.<BR><BR>
- */
- @Override
- public L2Party getParty()
- {
- if (_owner == null)
- return null;
- else
- return _owner.getParty();
- }
- /**
- * Return True if the L2Character has a Party in progress.<BR><BR>
- */
- @Override
- public boolean isInParty()
- {
- if (_owner == null)
- return false;
- else
- return _owner.getParty() != null;
- }
- /**
- * Check if the active L2Skill can be casted.<BR><BR>
- *
- * <B><U> Actions</U> :</B><BR><BR>
- * <li>Check if the target is correct </li>
- * <li>Check if the target is in the skill cast range </li>
- * <li>Check if the summon owns enough HP and MP to cast the skill </li>
- * <li>Check if all skills are enabled and this skill is enabled </li><BR><BR>
- * <li>Check if the skill is active </li><BR><BR>
- * <li>Notify the AI with AI_INTENTION_CAST and target</li><BR><BR>
- *
- * @param skill The L2Skill to use
- * @param forceUse used to force ATTACK on players
- * @param dontMove used to prevent movement, if not in range
- *
- */
- public void useMagic(L2Skill skill, boolean forceUse, boolean dontMove)
- {
- if (skill == null || isDead())
- return;
- // Check if the skill is active
- if (skill.isPassive())
- {
- // just ignore the passive skill request. why does the client send it anyway ??
- return;
- }
- //************************************* Check Casting in Progress *******************************************
- // If a skill is currently being used
- if (isCastingNow())
- {
- return;
- }
- //************************************* Check Target *******************************************
- // Get the target for the skill
- L2Object target = null;
- switch (skill.getTargetType())
- {
- // OWNER_PET should be cast even if no target has been found
- case TARGET_OWNER_PET:
- target = getOwner();
- break;
- // PARTY, AURA, SELF should be cast even if no target has been found
- case TARGET_PARTY:
- case TARGET_AURA:
- case TARGET_FRONT_AURA:
- case TARGET_BEHIND_AURA:
- case TARGET_SELF:
- target = this;
- break;
- default:
- // Get the first target of the list
- target = skill.getFirstOfTargetList(this);
- break;
- }
- // Check the validity of the target
- if (target == null)
- {
- if (getOwner() != null)
- getOwner().sendPacket(new SystemMessage(SystemMessageId.TARGET_CANT_FOUND));
- return;
- }
- //************************************* Check skill availability *******************************************
- // Check if this skill is enabled (e.g. reuse time)
- if (isSkillDisabled(skill.getId()))
- {
- if (getOwner() != null)
- {
- SystemMessage sm = new SystemMessage(SystemMessageId.S1_PREPARED_FOR_REUSE);
- sm.addSkillName(skill);
- getOwner().sendPacket(sm);
- }
- return;
- }
- //************************************* Check Consumables *******************************************
- // Check if the summon has enough MP
- if (getCurrentMp() < getStat().getMpConsume(skill) + getStat().getMpInitialConsume(skill))
- {
- // Send a System Message to the caster
- if (getOwner() != null)
- getOwner().sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_MP));
- return;
- }
- // Check if the summon has enough HP
- if (getCurrentHp() <= skill.getHpConsume())
- {
- // Send a System Message to the caster
- if (getOwner() != null)
- getOwner().sendPacket(new SystemMessage(SystemMessageId.NOT_ENOUGH_HP));
- return;
- }
- //************************************* Check Summon State *******************************************
- // Check if this is offensive magic skill
- if (skill.isOffensive())
- {
- if (isInsidePeaceZone(this, target)
- && getOwner() != null
- && (!getOwner().getAccessLevel().allowPeaceAttack()))
- {
- // If summon or target is in a peace zone, send a system message TARGET_IN_PEACEZONE
- sendPacket(new SystemMessage(SystemMessageId.TARGET_IN_PEACEZONE));
- return;
- }
- if (getOwner() != null && getOwner().isInOlympiadMode() && !getOwner().isOlympiadStart()){
- // if L2PcInstance is in Olympia and the match isn't already start, send a Server->Client packet ActionFailed
- sendPacket(ActionFailed.STATIC_PACKET);
- return;
- }
- // Check if the target is attackable
- if (target instanceof L2DoorInstance)
- {
- if(!((L2DoorInstance)target).isAttackable(getOwner()))
- return;
- }
- else
- {
- if (!target.isAttackable()
- && getOwner() != null
- && (!getOwner().getAccessLevel().allowPeaceAttack()))
- {
- return;
- }
- // Check if a Forced ATTACK is in progress on non-attackable target
- if (!target.isAutoAttackable(this) && !forceUse &&
- skill.getTargetType() != SkillTargetType.TARGET_AURA &&
- skill.getTargetType() != SkillTargetType.TARGET_FRONT_AURA &&
- skill.getTargetType() != SkillTargetType.TARGET_BEHIND_AURA &&
- skill.getTargetType() != SkillTargetType.TARGET_CLAN &&
- skill.getTargetType() != SkillTargetType.TARGET_ALLY &&
- skill.getTargetType() != SkillTargetType.TARGET_PARTY &&
- skill.getTargetType() != SkillTargetType.TARGET_SELF)
- {
- return;
- }
- }
- }
- // Notify the AI with AI_INTENTION_CAST and target
- getAI().setIntention(CtrlIntention.AI_INTENTION_CAST, skill, target);
- }
- @Override
- public void setIsImmobilized(boolean value)
- {
- super.setIsImmobilized(value);
- if (value)
- {
- _previousFollowStatus = getFollowStatus();
- // if immobilized temporarly disable follow mode
- if (_previousFollowStatus)
- setFollowStatus(false);
- }
- else
- {
- // if not more immobilized restore previous follow mode
- setFollowStatus(_previousFollowStatus);
- }
- }
- public void setOwner(L2PcInstance newOwner)
- {
- _owner = newOwner;
- }
- @Override
- public final void sendDamageMessage(L2Character target, int damage, boolean mcrit, boolean pcrit, boolean miss)
- {
- if (miss) return;
- // Prevents the double spam of system messages, if the target is the owning player.
- if (target.getObjectId() != getOwner().getObjectId())
- {
- if (pcrit || mcrit)
- if (this instanceof L2SummonInstance)
- getOwner().sendPacket(new SystemMessage(SystemMessageId.CRITICAL_HIT_BY_SUMMONED_MOB));
- else
- getOwner().sendPacket(new SystemMessage(SystemMessageId.CRITICAL_HIT_BY_PET));
- if (getOwner().isInOlympiadMode() &&
- target instanceof L2PcInstance &&
- ((L2PcInstance)target).isInOlympiadMode() &&
- ((L2PcInstance)target).getOlympiadGameId() == getOwner().getOlympiadGameId())
- {
- Olympiad.getInstance().notifyCompetitorDamage(getOwner(), damage, getOwner().getOlympiadGameId());
- }
- SystemMessage sm;
- if (this instanceof L2SummonInstance)
- sm = new SystemMessage(SystemMessageId.SUMMON_GAVE_DAMAGE_S1);
- else
- sm = new SystemMessage(SystemMessageId.PET_HIT_FOR_S1_DAMAGE);
- sm.addNumber(damage);
- getOwner().sendPacket(sm);
- }
- }
- public void reduceCurrentHp(int damage, L2Character attacker, L2Skill skill)
- {
- super.reduceCurrentHp(damage, attacker, skill);
- SystemMessage sm;
- if (this instanceof L2SummonInstance)
- sm = new SystemMessage(SystemMessageId.SUMMON_RECEIVED_DAMAGE_S2_BY_S1);
- else
- sm = new SystemMessage(SystemMessageId.PET_RECEIVED_S2_DAMAGE_BY_S1);
- sm.addCharName(attacker);
- sm.addNumber(damage);
- getOwner().sendPacket(sm);
- }
- /**
- * Servitors' skills automatically change their level based on the servitor's level.
- * Until level 70, the servitor gets 1 lv of skill per 10 levels. After that, it is 1
- * skill level per 5 servitor levels. If the resulting skill level doesn't exist use
- * the max that does exist!
- *
- * @see net.sf.l2j.gameserver.model.L2Character#doCast(net.sf.l2j.gameserver.model.L2Skill)
- */
- @Override
- public void doCast(L2Skill skill)
- {
- int petLevel = getLevel();
- int skillLevel = petLevel/10;
- if(petLevel >= 70)
- skillLevel += (petLevel-65)/10;
- // adjust the level for servitors less than lv 10
- if (skillLevel < 1)
- skillLevel = 1;
- L2Skill skillToCast = SkillTable.getInstance().getInfo(skill.getId(),skillLevel);
- if (skillToCast != null)
- super.doCast(skillToCast);
- else
- super.doCast(skill);
- }
- @Override
- public L2PcInstance getActingPlayer()
- {
- return getOwner();
- }
- }
|