L2Npc.java 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package com.l2jserver.gameserver.model.actor;
  16. import static com.l2jserver.gameserver.ai.CtrlIntention.AI_INTENTION_ACTIVE;
  17. import java.util.Collection;
  18. import java.util.logging.Level;
  19. import javolution.util.FastList;
  20. import com.l2jserver.Config;
  21. import com.l2jserver.gameserver.SevenSigns;
  22. import com.l2jserver.gameserver.SevenSignsFestival;
  23. import com.l2jserver.gameserver.ThreadPoolManager;
  24. import com.l2jserver.gameserver.cache.HtmCache;
  25. import com.l2jserver.gameserver.datatables.ItemTable;
  26. import com.l2jserver.gameserver.handler.BypassHandler;
  27. import com.l2jserver.gameserver.handler.IBypassHandler;
  28. import com.l2jserver.gameserver.instancemanager.CastleManager;
  29. import com.l2jserver.gameserver.instancemanager.FortManager;
  30. import com.l2jserver.gameserver.instancemanager.TownManager;
  31. import com.l2jserver.gameserver.model.L2ItemInstance;
  32. import com.l2jserver.gameserver.model.L2NpcAIData;
  33. import com.l2jserver.gameserver.model.L2Object;
  34. import com.l2jserver.gameserver.model.L2Skill;
  35. import com.l2jserver.gameserver.model.L2Spawn;
  36. import com.l2jserver.gameserver.model.L2World;
  37. import com.l2jserver.gameserver.model.L2WorldRegion;
  38. import com.l2jserver.gameserver.model.actor.instance.L2ClanHallManagerInstance;
  39. import com.l2jserver.gameserver.model.actor.instance.L2DoormenInstance;
  40. import com.l2jserver.gameserver.model.actor.instance.L2FestivalGuideInstance;
  41. import com.l2jserver.gameserver.model.actor.instance.L2FishermanInstance;
  42. import com.l2jserver.gameserver.model.actor.instance.L2MerchantInstance;
  43. import com.l2jserver.gameserver.model.actor.instance.L2NpcInstance;
  44. import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
  45. import com.l2jserver.gameserver.model.actor.instance.L2TeleporterInstance;
  46. import com.l2jserver.gameserver.model.actor.instance.L2TrainerInstance;
  47. import com.l2jserver.gameserver.model.actor.instance.L2WarehouseInstance;
  48. import com.l2jserver.gameserver.model.actor.knownlist.NpcKnownList;
  49. import com.l2jserver.gameserver.model.actor.stat.NpcStat;
  50. import com.l2jserver.gameserver.model.actor.status.NpcStatus;
  51. import com.l2jserver.gameserver.model.entity.Castle;
  52. import com.l2jserver.gameserver.model.entity.Fort;
  53. import com.l2jserver.gameserver.model.olympiad.Olympiad;
  54. import com.l2jserver.gameserver.model.quest.Quest;
  55. import com.l2jserver.gameserver.model.zone.type.L2TownZone;
  56. import com.l2jserver.gameserver.network.SystemMessageId;
  57. import com.l2jserver.gameserver.network.serverpackets.AbstractNpcInfo;
  58. import com.l2jserver.gameserver.network.serverpackets.ActionFailed;
  59. import com.l2jserver.gameserver.network.serverpackets.ExChangeNpcState;
  60. import com.l2jserver.gameserver.network.serverpackets.MagicSkillUse;
  61. import com.l2jserver.gameserver.network.serverpackets.NpcHtmlMessage;
  62. import com.l2jserver.gameserver.network.serverpackets.ServerObjectInfo;
  63. import com.l2jserver.gameserver.network.serverpackets.SocialAction;
  64. import com.l2jserver.gameserver.network.serverpackets.SystemMessage;
  65. import com.l2jserver.gameserver.taskmanager.DecayTaskManager;
  66. import com.l2jserver.gameserver.templates.chars.L2NpcTemplate;
  67. import com.l2jserver.gameserver.templates.chars.L2NpcTemplate.AIType;
  68. import com.l2jserver.gameserver.templates.item.L2Item;
  69. import com.l2jserver.gameserver.templates.item.L2Weapon;
  70. import com.l2jserver.gameserver.util.Broadcast;
  71. import com.l2jserver.util.Rnd;
  72. import com.l2jserver.util.StringUtil;
  73. /**
  74. * This class represents a Non-Player-Character in the world. It can be a monster or a friendly character.
  75. * It also uses a template to fetch some static values. The templates are hardcoded in the client, so we can rely on them.<BR><BR>
  76. *
  77. * L2Character :<BR><BR>
  78. * <li>L2Attackable</li>
  79. * <li>L2BoxInstance</li>
  80. * <li>L2FolkInstance</li>
  81. *
  82. * @version $Revision: 1.32.2.7.2.24 $ $Date: 2005/04/11 10:06:09 $
  83. */
  84. public class L2Npc extends L2Character
  85. {
  86. //private static Logger _log = Logger.getLogger(L2NpcInstance.class.getName());
  87. /** The interaction distance of the L2NpcInstance(is used as offset in MovetoLocation method) */
  88. public static final int INTERACTION_DISTANCE = 150;
  89. /** The L2Spawn object that manage this L2NpcInstance */
  90. private L2Spawn _spawn;
  91. /** The flag to specify if this L2NpcInstance is busy */
  92. private boolean _isBusy = false;
  93. /** The busy message for this L2NpcInstance */
  94. private String _busyMessage = "";
  95. /** True if endDecayTask has already been called */
  96. volatile boolean _isDecayed = false;
  97. /** The castle index in the array of L2Castle this L2NpcInstance belongs to */
  98. private int _castleIndex = -2;
  99. /** The fortress index in the array of L2Fort this L2NpcInstance belongs to */
  100. private int _fortIndex = -2;
  101. public boolean isEventMob = false;
  102. private boolean _isInTown = false;
  103. /** True if this L2Npc is autoattackable **/
  104. private boolean _isAutoAttackable = false;
  105. /** Time of last social packet broadcast*/
  106. private long _lastSocialBroadcast = 0;
  107. /** Minimum interval between social packets*/
  108. private int _minimalSocialInterval = 6000;
  109. protected RandomAnimationTask _rAniTask = null;
  110. private int _currentLHandId; // normally this shouldn't change from the template, but there exist exceptions
  111. private int _currentRHandId; // normally this shouldn't change from the template, but there exist exceptions
  112. private int _currentEnchant; // normally this shouldn't change from the template, but there exist exceptions
  113. private double _currentCollisionHeight; // used for npc grow effect skills
  114. private double _currentCollisionRadius; // used for npc grow effect skills
  115. public boolean _soulshotcharged = false;
  116. public boolean _spiritshotcharged = false;
  117. private int _soulshotamount = 0;
  118. private int _spiritshotamount = 0;
  119. public boolean _ssrecharged = true;
  120. public boolean _spsrecharged = true;
  121. protected boolean _isHideName = false;
  122. private int _displayEffect = 0;
  123. //AI Recall
  124. public int getSoulShot()
  125. {
  126. L2NpcAIData AI = getTemplate().getAIDataStatic();
  127. return AI.getSoulShot();
  128. }
  129. public int getSpiritShot()
  130. {
  131. L2NpcAIData AI = getTemplate().getAIDataStatic();
  132. return AI.getSpiritShot();
  133. }
  134. public int getSoulShotChance()
  135. {
  136. L2NpcAIData AI = getTemplate().getAIDataStatic();
  137. return AI.getSoulShotChance();
  138. }
  139. public int getSpiritShotChance()
  140. {
  141. L2NpcAIData AI = getTemplate().getAIDataStatic();
  142. return AI.getSpiritShotChance();
  143. }
  144. public boolean useSoulShot()
  145. {
  146. if(_soulshotcharged)
  147. return true;
  148. if(_ssrecharged)
  149. {
  150. _soulshotamount = getSoulShot();
  151. _ssrecharged = false;
  152. }
  153. else if (_soulshotamount>0)
  154. {
  155. if (Rnd.get(100) <= getSoulShotChance())
  156. {
  157. _soulshotamount = _soulshotamount - 1;
  158. Broadcast.toSelfAndKnownPlayersInRadius(this, new MagicSkillUse(this, this, 2154, 1, 0, 0), 360000);
  159. _soulshotcharged = true;
  160. }
  161. }
  162. else return false;
  163. return _soulshotcharged;
  164. }
  165. public boolean useSpiritShot()
  166. {
  167. if(_spiritshotcharged)
  168. return true;
  169. else
  170. {
  171. //_spiritshotcharged = false;
  172. if(_spsrecharged)
  173. {
  174. _spiritshotamount = getSpiritShot();
  175. _spsrecharged = false;
  176. }
  177. else if (_spiritshotamount>0)
  178. {
  179. if (Rnd.get(100) <= getSpiritShotChance())
  180. {
  181. _spiritshotamount = _spiritshotamount - 1;
  182. Broadcast.toSelfAndKnownPlayersInRadius(this, new MagicSkillUse(this, this, 2061, 1, 0, 0), 360000);
  183. _spiritshotcharged = true;
  184. }
  185. }
  186. else return false;
  187. }
  188. return _spiritshotcharged;
  189. }
  190. public int getEnemyRange()
  191. {
  192. L2NpcAIData AI = getTemplate().getAIDataStatic();
  193. return AI.getEnemyRange();
  194. }
  195. public String getEnemyClan()
  196. {
  197. L2NpcAIData AI = getTemplate().getAIDataStatic();
  198. return AI.getEnemyClan();
  199. }
  200. public int getClanRange()
  201. {
  202. L2NpcAIData AI = getTemplate().getAIDataStatic();
  203. return AI.getClanRange();
  204. }
  205. public String getClan()
  206. {
  207. L2NpcAIData AI = getTemplate().getAIDataStatic();
  208. return AI.getClan();
  209. }
  210. // GET THE PRIMARY ATTACK
  211. public int getPrimaryAttack()
  212. {
  213. L2NpcAIData AI = getTemplate().getAIDataStatic();
  214. return AI.getPrimaryAttack();
  215. }
  216. public int getSkillChance()
  217. {
  218. L2NpcAIData AI = getTemplate().getAIDataStatic();
  219. return AI.getSkillChance();
  220. }
  221. public int getCanMove()
  222. {
  223. L2NpcAIData AI = getTemplate().getAIDataStatic();
  224. return AI.getCanMove();
  225. }
  226. public int getIsChaos()
  227. {
  228. L2NpcAIData AI = getTemplate().getAIDataStatic();
  229. return AI.getIsChaos();
  230. }
  231. public int getCanDodge()
  232. {
  233. L2NpcAIData AI = getTemplate().getAIDataStatic();
  234. return AI.getDodge();
  235. }
  236. public int getSSkillChance()
  237. {
  238. L2NpcAIData AI = getTemplate().getAIDataStatic();
  239. return AI.getShortRangeChance();
  240. }
  241. public int getLSkillChance()
  242. {
  243. L2NpcAIData AI = getTemplate().getAIDataStatic();
  244. return AI.getLongRangeChance();
  245. }
  246. public int getSwitchRangeChance()
  247. {
  248. L2NpcAIData AI = getTemplate().getAIDataStatic();
  249. return AI.getSwitchRangeChance();
  250. }
  251. public boolean hasLSkill()
  252. {
  253. L2NpcAIData AI = getTemplate().getAIDataStatic();
  254. if (AI.getLongRangeSkill() == 0)
  255. return false;
  256. else
  257. return true;
  258. }
  259. public boolean hasSSkill()
  260. {
  261. L2NpcAIData AI = getTemplate().getAIDataStatic();
  262. if (AI.getShortRangeSkill() == 0)
  263. return false;
  264. else
  265. return true;
  266. }
  267. public FastList<L2Skill> getLrangeSkill()
  268. {
  269. FastList<L2Skill> skilldata = new FastList <L2Skill>();
  270. boolean hasLrange = false;
  271. L2NpcAIData AI = getTemplate().getAIDataStatic();
  272. if (AI == null || AI.getLongRangeSkill() == 0)
  273. return null;
  274. switch (AI.getLongRangeSkill())
  275. {
  276. case -1:
  277. {
  278. L2Skill[] skills = null;
  279. skills = getAllSkills();
  280. if (skills != null)
  281. {
  282. for (L2Skill sk: skills)
  283. {
  284. if (sk == null || sk.isPassive()
  285. || sk.getTargetType() == L2Skill.SkillTargetType.TARGET_SELF)
  286. continue;
  287. if (sk.getCastRange() >= 200)
  288. {
  289. skilldata.add(sk);
  290. hasLrange = true;
  291. }
  292. }
  293. }
  294. break;
  295. }
  296. case 1:
  297. {
  298. if (getTemplate()._universalskills != null)
  299. {
  300. for (L2Skill sk: getTemplate()._universalskills)
  301. {
  302. if (sk.getCastRange() >= 200)
  303. {
  304. skilldata.add(sk);
  305. hasLrange = true;
  306. }
  307. }
  308. }
  309. break;
  310. }
  311. default:
  312. {
  313. for (L2Skill sk: getAllSkills())
  314. {
  315. if (sk.getId() == AI.getLongRangeSkill())
  316. {
  317. skilldata.add(sk);
  318. hasLrange = true;
  319. }
  320. }
  321. }
  322. }
  323. return (hasLrange ? skilldata : null);
  324. }
  325. public FastList<L2Skill> getSrangeSkill()
  326. {
  327. FastList<L2Skill> skilldata = new FastList <L2Skill>();
  328. boolean hasSrange = false;
  329. L2NpcAIData AI = getTemplate().getAIDataStatic();
  330. if (AI == null || AI.getShortRangeSkill() == 0)
  331. return null;
  332. switch (AI.getShortRangeSkill())
  333. {
  334. case -1:
  335. {
  336. L2Skill[] skills = null;
  337. skills = getAllSkills();
  338. if (skills != null)
  339. {
  340. for (L2Skill sk: skills)
  341. {
  342. if (sk == null || sk.isPassive()
  343. || sk.getTargetType() == L2Skill.SkillTargetType.TARGET_SELF)
  344. continue;
  345. if (sk.getCastRange() <= 200)
  346. {
  347. skilldata.add(sk);
  348. hasSrange = true;
  349. }
  350. }
  351. }
  352. break;
  353. }
  354. case 1:
  355. {
  356. if (getTemplate()._universalskills != null)
  357. {
  358. for (L2Skill sk: getTemplate()._universalskills)
  359. {
  360. if (sk.getCastRange() <= 200)
  361. {
  362. skilldata.add(sk);
  363. hasSrange = true;
  364. }
  365. }
  366. }
  367. break;
  368. }
  369. default:
  370. {
  371. for (L2Skill sk: getAllSkills())
  372. {
  373. if (sk.getId() == AI.getShortRangeSkill())
  374. {
  375. skilldata.add(sk);
  376. hasSrange = true;
  377. }
  378. }
  379. }
  380. }
  381. return (hasSrange ? skilldata : null);
  382. }
  383. /** Task launching the function onRandomAnimation() */
  384. protected class RandomAnimationTask implements Runnable
  385. {
  386. public void run()
  387. {
  388. try
  389. {
  390. if (this != _rAniTask)
  391. return; // Shouldn't happen, but who knows... just to make sure every active npc has only one timer.
  392. if (isMob())
  393. {
  394. // Cancel further animation timers until intention is changed to ACTIVE again.
  395. if (getAI().getIntention() != AI_INTENTION_ACTIVE)
  396. return;
  397. }
  398. else
  399. {
  400. if (!isInActiveRegion()) // NPCs in inactive region don't run this task
  401. return;
  402. }
  403. if (!(isDead() || isStunned() || isSleeping() || isParalyzed()))
  404. onRandomAnimation(Rnd.get(2, 3));
  405. startRandomAnimationTimer();
  406. }
  407. catch (Exception e)
  408. {
  409. _log.log(Level.SEVERE, "", e);
  410. }
  411. }
  412. }
  413. /**
  414. * Send a packet SocialAction to all L2PcInstance in the _KnownPlayers of the L2NpcInstance and create a new RandomAnimation Task.<BR><BR>
  415. */
  416. public void onRandomAnimation(int animationId)
  417. {
  418. // Send a packet SocialAction to all L2PcInstance in the _KnownPlayers of the L2NpcInstance
  419. long now = System.currentTimeMillis();
  420. if (now - _lastSocialBroadcast > _minimalSocialInterval)
  421. {
  422. _lastSocialBroadcast = now;
  423. broadcastPacket(new SocialAction(getObjectId(), animationId));
  424. }
  425. }
  426. /**
  427. * Create a RandomAnimation Task that will be launched after the calculated delay.<BR><BR>
  428. */
  429. public void startRandomAnimationTimer()
  430. {
  431. if (!hasRandomAnimation())
  432. return;
  433. int minWait = isMob() ? Config.MIN_MONSTER_ANIMATION : Config.MIN_NPC_ANIMATION;
  434. int maxWait = isMob() ? Config.MAX_MONSTER_ANIMATION : Config.MAX_NPC_ANIMATION;
  435. // Calculate the delay before the next animation
  436. int interval = Rnd.get(minWait, maxWait) * 1000;
  437. // Create a RandomAnimation Task that will be launched after the calculated delay
  438. _rAniTask = new RandomAnimationTask();
  439. ThreadPoolManager.getInstance().scheduleGeneral(_rAniTask, interval);
  440. }
  441. /**
  442. * Check if the server allows Random Animation.<BR><BR>
  443. */
  444. public boolean hasRandomAnimation()
  445. {
  446. return (Config.MAX_NPC_ANIMATION > 0 && !getAiType().equals(AIType.CORPSE));
  447. }
  448. /**
  449. * Constructor of L2NpcInstance (use L2Character constructor).<BR><BR>
  450. *
  451. * <B><U> Actions</U> :</B><BR><BR>
  452. * <li>Call the L2Character constructor to set the _template of the L2Character (copy skills from template to object and link _calculators to NPC_STD_CALCULATOR) </li>
  453. * <li>Set the name of the L2Character</li>
  454. * <li>Create a RandomAnimation Task that will be launched after the calculated delay if the server allow it </li><BR><BR>
  455. *
  456. * @param objectId Identifier of the object to initialized
  457. * @param template The L2NpcTemplate to apply to the NPC
  458. *
  459. */
  460. public L2Npc(int objectId, L2NpcTemplate template)
  461. {
  462. // Call the L2Character constructor to set the _template of the L2Character, copy skills from template to object
  463. // and link _calculators to NPC_STD_CALCULATOR
  464. super(objectId, template);
  465. setInstanceType(InstanceType.L2Npc);
  466. initCharStatusUpdateValues();
  467. // initialize the "current" equipment
  468. _currentLHandId = getTemplate().lhand;
  469. _currentRHandId = getTemplate().rhand;
  470. _currentEnchant = Config.ENABLE_RANDOM_ENCHANT_EFFECT ? Rnd.get(4,21) : getTemplate().enchantEffect;
  471. // initialize the "current" collisions
  472. _currentCollisionHeight = getTemplate().fCollisionHeight;
  473. _currentCollisionRadius = getTemplate().fCollisionRadius;
  474. if (template == null)
  475. {
  476. _log.severe("No template for Npc. Please check your datapack is setup correctly.");
  477. return;
  478. }
  479. // Set the name of the L2Character
  480. setName(template.name);
  481. }
  482. @Override
  483. public NpcKnownList getKnownList()
  484. {
  485. return (NpcKnownList) super.getKnownList();
  486. }
  487. @Override
  488. public void initKnownList()
  489. {
  490. setKnownList(new NpcKnownList(this));
  491. }
  492. @Override
  493. public NpcStat getStat()
  494. {
  495. return (NpcStat) super.getStat();
  496. }
  497. @Override
  498. public void initCharStat()
  499. {
  500. setStat(new NpcStat(this));
  501. }
  502. @Override
  503. public NpcStatus getStatus()
  504. {
  505. return (NpcStatus) super.getStatus();
  506. }
  507. @Override
  508. public void initCharStatus()
  509. {
  510. setStatus(new NpcStatus(this));
  511. }
  512. /** Return the L2NpcTemplate of the L2NpcInstance. */
  513. @Override
  514. public final L2NpcTemplate getTemplate()
  515. {
  516. return (L2NpcTemplate) super.getTemplate();
  517. }
  518. /**
  519. * Return the generic Identifier of this L2NpcInstance contained in the L2NpcTemplate.<BR><BR>
  520. */
  521. public int getNpcId()
  522. {
  523. return getTemplate().npcId;
  524. }
  525. @Override
  526. public boolean isAttackable()
  527. {
  528. return Config.ALT_ATTACKABLE_NPCS;
  529. }
  530. /**
  531. * Return the faction Identifier of this L2NpcInstance contained in the L2NpcTemplate.<BR><BR>
  532. *
  533. * <B><U> Concept</U> :</B><BR><BR>
  534. * If a NPC belows to a Faction, other NPC of the faction inside the Faction range will help it if it's attacked<BR><BR>
  535. *
  536. */
  537. //@Deprecated
  538. public final String getFactionId()
  539. {
  540. return getClan();
  541. }
  542. /**
  543. * Return the Level of this L2NpcInstance contained in the L2NpcTemplate.<BR><BR>
  544. */
  545. @Override
  546. public final int getLevel()
  547. {
  548. return getTemplate().level;
  549. }
  550. /**
  551. * Return True if the L2NpcInstance is agressive (ex : L2MonsterInstance in function of aggroRange).<BR><BR>
  552. */
  553. public boolean isAggressive()
  554. {
  555. return false;
  556. }
  557. /**
  558. * Return the Aggro Range of this L2NpcInstance contained in the L2NpcTemplate.<BR><BR>
  559. */
  560. public int getAggroRange()
  561. {
  562. return getTemplate().aggroRange;
  563. }
  564. /**
  565. * Return the Faction Range of this L2NpcInstance contained in the L2NpcTemplate.<BR><BR>
  566. */
  567. //@Deprecated
  568. public int getFactionRange()
  569. {
  570. return getClanRange();
  571. }
  572. /**
  573. * Return True if this L2NpcInstance is undead in function of the L2NpcTemplate.<BR><BR>
  574. */
  575. @Override
  576. public boolean isUndead()
  577. {
  578. return getTemplate().isUndead();
  579. }
  580. /**
  581. * Send a packet NpcInfo with state of abnormal effect to all L2PcInstance in the _KnownPlayers of the L2NpcInstance.<BR><BR>
  582. */
  583. @Override
  584. public void updateAbnormalEffect()
  585. {
  586. // Send a Server->Client packet NpcInfo with state of abnormal effect to all L2PcInstance in the _KnownPlayers of the L2NpcInstance
  587. Collection<L2PcInstance> plrs = getKnownList().getKnownPlayers().values();
  588. //synchronized (getKnownList().getKnownPlayers())
  589. {
  590. for (L2PcInstance player : plrs)
  591. {
  592. if (player == null)
  593. continue;
  594. if (getRunSpeed() == 0)
  595. player.sendPacket(new ServerObjectInfo(this, player));
  596. else
  597. player.sendPacket(new AbstractNpcInfo.NpcInfo(this, player));
  598. }
  599. }
  600. }
  601. /**
  602. * Return the distance under which the object must be add to _knownObject in
  603. * function of the object type.<BR>
  604. * <BR>
  605. *
  606. * <B><U> Values </U> :</B><BR>
  607. * <BR>
  608. * <li> object is a L2FolkInstance : 0 (don't remember it) </li>
  609. * <li> object is a L2Character : 0 (don't remember it) </li>
  610. * <li> object is a L2PlayableInstance : 1500 </li>
  611. * <li> others : 500 </li>
  612. * <BR>
  613. * <BR>
  614. *
  615. * <B><U> Override in </U> :</B><BR>
  616. * <BR>
  617. * <li> L2Attackable</li>
  618. * <BR>
  619. * <BR>
  620. *
  621. * @param object
  622. * The Object to add to _knownObject
  623. *
  624. */
  625. public int getDistanceToWatchObject(L2Object object)
  626. {
  627. if (object instanceof L2FestivalGuideInstance)
  628. return 10000;
  629. if (object instanceof L2NpcInstance || !(object instanceof L2Character))
  630. return 0;
  631. if (object instanceof L2Playable)
  632. return 1500;
  633. return 500;
  634. }
  635. /**
  636. * Return the distance after which the object must be remove from _knownObject in function of the object type.<BR><BR>
  637. *
  638. * <B><U> Values </U> :</B><BR><BR>
  639. * <li> object is not a L2Character : 0 (don't remember it) </li>
  640. * <li> object is a L2FolkInstance : 0 (don't remember it)</li>
  641. * <li> object is a L2PlayableInstance : 3000 </li>
  642. * <li> others : 1000 </li><BR><BR>
  643. *
  644. * <B><U> Overridden in </U> :</B><BR><BR>
  645. * <li> L2Attackable</li><BR><BR>
  646. *
  647. * @param object The Object to remove from _knownObject
  648. *
  649. */
  650. public int getDistanceToForgetObject(L2Object object)
  651. {
  652. return 2 * getDistanceToWatchObject(object);
  653. }
  654. /**
  655. * Return False.<BR><BR>
  656. *
  657. * <B><U> Overridden in </U> :</B><BR><BR>
  658. * <li> L2MonsterInstance : Check if the attacker is not another L2MonsterInstance</li>
  659. * <li> L2PcInstance</li><BR><BR>
  660. */
  661. @Override
  662. public boolean isAutoAttackable(L2Character attacker)
  663. {
  664. return _isAutoAttackable;
  665. }
  666. public void setAutoAttackable(boolean flag)
  667. {
  668. _isAutoAttackable = flag;
  669. }
  670. /**
  671. * Return the Identifier of the item in the left hand of this L2NpcInstance contained in the L2NpcTemplate.<BR><BR>
  672. */
  673. public int getLeftHandItem()
  674. {
  675. return _currentLHandId;
  676. }
  677. /**
  678. * Return the Identifier of the item in the right hand of this L2NpcInstance contained in the L2NpcTemplate.<BR><BR>
  679. */
  680. public int getRightHandItem()
  681. {
  682. return _currentRHandId;
  683. }
  684. public int getEnchantEffect()
  685. {
  686. return _currentEnchant;
  687. }
  688. /**
  689. * Return the busy status of this L2NpcInstance.<BR><BR>
  690. */
  691. public final boolean isBusy()
  692. {
  693. return _isBusy;
  694. }
  695. /**
  696. * Set the busy status of this L2NpcInstance.<BR><BR>
  697. */
  698. public void setBusy(boolean isBusy)
  699. {
  700. _isBusy = isBusy;
  701. }
  702. /**
  703. * Return the busy message of this L2NpcInstance.<BR><BR>
  704. */
  705. public final String getBusyMessage()
  706. {
  707. return _busyMessage;
  708. }
  709. /**
  710. * Set the busy message of this L2NpcInstance.<BR><BR>
  711. */
  712. public void setBusyMessage(String message)
  713. {
  714. _busyMessage = message;
  715. }
  716. /**
  717. * Return true if this L2Npc instance can be warehouse manager.<BR><BR>
  718. */
  719. public boolean isWarehouse()
  720. {
  721. return false;
  722. }
  723. public boolean canTarget(L2PcInstance player)
  724. {
  725. if (player.isOutOfControl())
  726. {
  727. player.sendPacket(ActionFailed.STATIC_PACKET);
  728. return false;
  729. }
  730. if (player.isLockedTarget() && player.getLockedTarget() != this)
  731. {
  732. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.FAILED_CHANGE_TARGET));
  733. player.sendPacket(ActionFailed.STATIC_PACKET);
  734. return false;
  735. }
  736. // TODO: More checks...
  737. return true;
  738. }
  739. public boolean canInteract(L2PcInstance player)
  740. {
  741. // TODO: NPC busy check etc...
  742. if (player.isCastingNow() || player.isCastingSimultaneouslyNow())
  743. return false;
  744. if (player.isDead() || player.isFakeDeath())
  745. return false;
  746. if (player.isSitting())
  747. return false;
  748. if (player.getPrivateStoreType() != 0)
  749. return false;
  750. if (!isInsideRadius(player, INTERACTION_DISTANCE, true, false))
  751. return false;
  752. if (player.getInstanceId() != getInstanceId()
  753. && player.getInstanceId() != -1)
  754. return false;
  755. return true;
  756. }
  757. /** Return the L2Castle this L2NpcInstance belongs to. */
  758. public final Castle getCastle()
  759. {
  760. // Get castle this NPC belongs to (excluding L2Attackable)
  761. if (_castleIndex < 0)
  762. {
  763. L2TownZone town = TownManager.getTown(getX(), getY(), getZ());
  764. if (town != null)
  765. _castleIndex = CastleManager.getInstance().getCastleIndex(town.getTaxById());
  766. if (_castleIndex < 0)
  767. {
  768. _castleIndex = CastleManager.getInstance().findNearestCastleIndex(this);
  769. }
  770. else
  771. _isInTown = true; // Npc was spawned in town
  772. }
  773. if (_castleIndex < 0)
  774. return null;
  775. return CastleManager.getInstance().getCastles().get(_castleIndex);
  776. }
  777. /**
  778. * Return closest castle in defined distance
  779. * @param maxDistance long
  780. * @return Castle
  781. */
  782. public final Castle getCastle(long maxDistance)
  783. {
  784. int index = CastleManager.getInstance().findNearestCastleIndex(this, maxDistance);
  785. if (index < 0)
  786. return null;
  787. return CastleManager.getInstance().getCastles().get(index);
  788. }
  789. /** Return the L2Fort this L2NpcInstance belongs to. */
  790. public final Fort getFort()
  791. {
  792. // Get Fort this NPC belongs to (excluding L2Attackable)
  793. if (_fortIndex < 0)
  794. {
  795. Fort fort = FortManager.getInstance().getFort(getX(), getY(), getZ());
  796. if (fort != null)
  797. _fortIndex = FortManager.getInstance().getFortIndex(fort.getFortId());
  798. if (_fortIndex < 0)
  799. _fortIndex = FortManager.getInstance().findNearestFortIndex(this);
  800. }
  801. if (_fortIndex < 0)
  802. return null;
  803. return FortManager.getInstance().getForts().get(_fortIndex);
  804. }
  805. /**
  806. * Return closest Fort in defined distance
  807. * @param maxDistance long
  808. * @return Fort
  809. */
  810. public final Fort getFort(long maxDistance)
  811. {
  812. int index = FortManager.getInstance().findNearestFortIndex(this, maxDistance);
  813. if (index < 0)
  814. return null;
  815. return FortManager.getInstance().getForts().get(index);
  816. }
  817. public final boolean getIsInTown()
  818. {
  819. if (_castleIndex < 0)
  820. getCastle();
  821. return _isInTown;
  822. }
  823. /**
  824. * Open a quest or chat window on client with the text of the L2NpcInstance in function of the command.<BR><BR>
  825. *
  826. * <B><U> Example of use </U> :</B><BR><BR>
  827. * <li> Client packet : RequestBypassToServer</li><BR><BR>
  828. *
  829. * @param command The command string received from client
  830. *
  831. */
  832. public void onBypassFeedback(L2PcInstance player, String command)
  833. {
  834. //if (canInteract(player))
  835. {
  836. if (isBusy() && getBusyMessage().length() > 0)
  837. {
  838. player.sendPacket(ActionFailed.STATIC_PACKET);
  839. NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  840. html.setFile(player.getHtmlPrefix(), "data/html/npcbusy.htm");
  841. html.replace("%busymessage%", getBusyMessage());
  842. html.replace("%npcname%", getName());
  843. html.replace("%playername%", player.getName());
  844. player.sendPacket(html);
  845. }
  846. else
  847. {
  848. IBypassHandler handler = BypassHandler.getInstance().getBypassHandler(command);
  849. if (handler != null)
  850. handler.useBypass(command, player, this);
  851. else
  852. _log.info(getClass().getSimpleName()+": Unknown NPC bypass: \""+command+"\" NpcId: "+getNpcId());
  853. }
  854. }
  855. }
  856. /**
  857. * Return null (regular NPCs don't have weapons instancies).<BR><BR>
  858. */
  859. @Override
  860. public L2ItemInstance getActiveWeaponInstance()
  861. {
  862. // regular NPCs dont have weapons instancies
  863. return null;
  864. }
  865. /**
  866. * Return the weapon item equiped in the right hand of the L2NpcInstance or null.<BR><BR>
  867. */
  868. @Override
  869. public L2Weapon getActiveWeaponItem()
  870. {
  871. // Get the weapon identifier equiped in the right hand of the L2NpcInstance
  872. int weaponId = getTemplate().rhand;
  873. if (weaponId < 1)
  874. return null;
  875. // Get the weapon item equiped in the right hand of the L2NpcInstance
  876. L2Item item = ItemTable.getInstance().getTemplate(getTemplate().rhand);
  877. if (!(item instanceof L2Weapon))
  878. return null;
  879. return (L2Weapon) item;
  880. }
  881. /**
  882. * Return null (regular NPCs don't have weapons instancies).<BR><BR>
  883. */
  884. @Override
  885. public L2ItemInstance getSecondaryWeaponInstance()
  886. {
  887. // regular NPCs dont have weapons instancies
  888. return null;
  889. }
  890. /**
  891. * Return the weapon item equiped in the left hand of the L2NpcInstance or null.<BR><BR>
  892. */
  893. @Override
  894. public L2Weapon getSecondaryWeaponItem()
  895. {
  896. // Get the weapon identifier equiped in the right hand of the L2NpcInstance
  897. int weaponId = getTemplate().lhand;
  898. if (weaponId < 1)
  899. return null;
  900. // Get the weapon item equiped in the right hand of the L2NpcInstance
  901. L2Item item = ItemTable.getInstance().getTemplate(getTemplate().lhand);
  902. if (!(item instanceof L2Weapon))
  903. return null;
  904. return (L2Weapon) item;
  905. }
  906. /**
  907. * Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in order to display the message of the L2NpcInstance.<BR><BR>
  908. *
  909. * @param player The L2PcInstance who talks with the L2NpcInstance
  910. * @param content The text of the L2NpcMessage
  911. *
  912. */
  913. public void insertObjectIdAndShowChatWindow(L2PcInstance player, String content)
  914. {
  915. // Send a Server->Client packet NpcHtmlMessage to the L2PcInstance in order to display the message of the L2NpcInstance
  916. content = content.replaceAll("%objectId%", String.valueOf(getObjectId()));
  917. NpcHtmlMessage npcReply = new NpcHtmlMessage(getObjectId());
  918. npcReply.setHtml(content);
  919. player.sendPacket(npcReply);
  920. }
  921. /**
  922. * Return the pathfile of the selected HTML file in function of the npcId and of the page number.<BR><BR>
  923. *
  924. * <B><U> Format of the pathfile </U> :</B><BR><BR>
  925. * <li> if the file exists on the server (page number = 0) : <B>data/html/default/12006.htm</B> (npcId-page number)</li>
  926. * <li> if the file exists on the server (page number > 0) : <B>data/html/default/12006-1.htm</B> (npcId-page number)</li>
  927. * <li> if the file doesn't exist on the server : <B>data/html/npcdefault.htm</B> (message : "I have nothing to say to you")</li><BR><BR>
  928. *
  929. * <B><U> Overridden in </U> :</B><BR><BR>
  930. * <li> L2GuardInstance : Set the pathfile to data/html/guard/12006-1.htm (npcId-page number)</li><BR><BR>
  931. *
  932. * @param npcId The Identifier of the L2NpcInstance whose text must be display
  933. * @param val The number of the page to display
  934. *
  935. */
  936. public String getHtmlPath(int npcId, int val)
  937. {
  938. String pom = "";
  939. if (val == 0)
  940. pom = "" + npcId;
  941. else
  942. pom = npcId + "-" + val;
  943. String temp = "data/html/default/" + pom + ".htm";
  944. if (!Config.LAZY_CACHE)
  945. {
  946. // If not running lazy cache the file must be in the cache or it doesnt exist
  947. if (HtmCache.getInstance().contains(temp))
  948. return temp;
  949. }
  950. else
  951. {
  952. if (HtmCache.getInstance().isLoadable(temp))
  953. return temp;
  954. }
  955. // If the file is not found, the standard message "I have nothing to say to you" is returned
  956. return "data/html/npcdefault.htm";
  957. }
  958. public void showChatWindow(L2PcInstance player)
  959. {
  960. showChatWindow(player, 0);
  961. }
  962. /**
  963. * Returns true if html exists
  964. * @param player
  965. * @param type
  966. * @return boolean
  967. */
  968. private boolean showPkDenyChatWindow(L2PcInstance player, String type)
  969. {
  970. String html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/" + type + "/" + getNpcId() + "-pk.htm");
  971. if (html != null)
  972. {
  973. NpcHtmlMessage pkDenyMsg = new NpcHtmlMessage(getObjectId());
  974. pkDenyMsg.setHtml(html);
  975. player.sendPacket(pkDenyMsg);
  976. player.sendPacket(ActionFailed.STATIC_PACKET);
  977. return true;
  978. }
  979. return false;
  980. }
  981. /**
  982. * Open a chat window on client with the text of the L2NpcInstance.<BR><BR>
  983. *
  984. * <B><U> Actions</U> :</B><BR><BR>
  985. * <li>Get the text of the selected HTML file in function of the npcId and of the page number </li>
  986. * <li>Send a Server->Client NpcHtmlMessage containing the text of the L2NpcInstance to the L2PcInstance </li>
  987. * <li>Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet </li><BR>
  988. *
  989. * @param player The L2PcInstance that talk with the L2NpcInstance
  990. * @param val The number of the page of the L2NpcInstance to display
  991. *
  992. */
  993. public void showChatWindow(L2PcInstance player, int val)
  994. {
  995. if (player.isCursedWeaponEquipped() && (!(player.getTarget() instanceof L2ClanHallManagerInstance) || !(player.getTarget() instanceof L2DoormenInstance)))
  996. {
  997. player.setTarget(player);
  998. return;
  999. }
  1000. if (player.getKarma() > 0)
  1001. {
  1002. if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && this instanceof L2MerchantInstance)
  1003. {
  1004. if (showPkDenyChatWindow(player, "merchant"))
  1005. return;
  1006. }
  1007. else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_GK && this instanceof L2TeleporterInstance)
  1008. {
  1009. if (showPkDenyChatWindow(player, "teleporter"))
  1010. return;
  1011. }
  1012. else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_USE_WAREHOUSE && this instanceof L2WarehouseInstance)
  1013. {
  1014. if (showPkDenyChatWindow(player, "warehouse"))
  1015. return;
  1016. }
  1017. else if (!Config.ALT_GAME_KARMA_PLAYER_CAN_SHOP && this instanceof L2FishermanInstance)
  1018. {
  1019. if (showPkDenyChatWindow(player, "fisherman"))
  1020. return;
  1021. }
  1022. }
  1023. if ("L2Auctioneer".equals(getTemplate().type) && val == 0)
  1024. return;
  1025. int npcId = getTemplate().npcId;
  1026. /* For use with Seven Signs implementation */
  1027. String filename = SevenSigns.SEVEN_SIGNS_HTML_PATH;
  1028. int sealAvariceOwner = SevenSigns.getInstance().getSealOwner(SevenSigns.SEAL_AVARICE);
  1029. int sealGnosisOwner = SevenSigns.getInstance().getSealOwner(SevenSigns.SEAL_GNOSIS);
  1030. int playerCabal = SevenSigns.getInstance().getPlayerCabal(player.getObjectId());
  1031. int compWinner = SevenSigns.getInstance().getCabalHighestScore();
  1032. switch (npcId)
  1033. {
  1034. case 31127: //
  1035. case 31128: //
  1036. case 31129: // Dawn Festival Guides
  1037. case 31130: //
  1038. case 31131: //
  1039. filename += "festival/dawn_guide.htm";
  1040. break;
  1041. case 31137: //
  1042. case 31138: //
  1043. case 31139: // Dusk Festival Guides
  1044. case 31140: //
  1045. case 31141: //
  1046. filename += "festival/dusk_guide.htm";
  1047. break;
  1048. case 31092: // Black Marketeer of Mammon
  1049. filename += "blkmrkt_1.htm";
  1050. break;
  1051. case 31113: // Merchant of Mammon
  1052. if (Config.ALT_STRICT_SEVENSIGNS)
  1053. {
  1054. switch (compWinner)
  1055. {
  1056. case SevenSigns.CABAL_DAWN:
  1057. if (playerCabal != compWinner || playerCabal != sealAvariceOwner)
  1058. {
  1059. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));
  1060. player.sendPacket(ActionFailed.STATIC_PACKET);
  1061. return;
  1062. }
  1063. break;
  1064. case SevenSigns.CABAL_DUSK:
  1065. if (playerCabal != compWinner || playerCabal != sealAvariceOwner)
  1066. {
  1067. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));
  1068. player.sendPacket(ActionFailed.STATIC_PACKET);
  1069. return;
  1070. }
  1071. break;
  1072. default:
  1073. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.QUEST_EVENT_PERIOD));
  1074. return;
  1075. }
  1076. }
  1077. filename += "mammmerch_1.htm";
  1078. break;
  1079. case 31126: // Blacksmith of Mammon
  1080. if (Config.ALT_STRICT_SEVENSIGNS)
  1081. {
  1082. switch (compWinner)
  1083. {
  1084. case SevenSigns.CABAL_DAWN:
  1085. if (playerCabal != compWinner || playerCabal != sealGnosisOwner)
  1086. {
  1087. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CAN_BE_USED_BY_DAWN));
  1088. player.sendPacket(ActionFailed.STATIC_PACKET);
  1089. return;
  1090. }
  1091. break;
  1092. case SevenSigns.CABAL_DUSK:
  1093. if (playerCabal != compWinner || playerCabal != sealGnosisOwner)
  1094. {
  1095. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.CAN_BE_USED_BY_DUSK));
  1096. player.sendPacket(ActionFailed.STATIC_PACKET);
  1097. return;
  1098. }
  1099. break;
  1100. default:
  1101. player.sendPacket(SystemMessage.getSystemMessage(SystemMessageId.QUEST_EVENT_PERIOD));
  1102. return;
  1103. }
  1104. }
  1105. filename += "mammblack_1.htm";
  1106. break;
  1107. case 31132:
  1108. case 31133:
  1109. case 31134:
  1110. case 31135:
  1111. case 31136: // Festival Witches
  1112. case 31142:
  1113. case 31143:
  1114. case 31144:
  1115. case 31145:
  1116. case 31146:
  1117. filename += "festival/festival_witch.htm";
  1118. break;
  1119. case 31688:
  1120. if (player.isNoble())
  1121. filename = Olympiad.OLYMPIAD_HTML_PATH + "noble_main.htm";
  1122. else
  1123. filename = (getHtmlPath(npcId, val));
  1124. break;
  1125. case 31690:
  1126. case 31769:
  1127. case 31770:
  1128. case 31771:
  1129. case 31772:
  1130. if (player.isHero() || player.isNoble())
  1131. filename = Olympiad.OLYMPIAD_HTML_PATH + "hero_main.htm";
  1132. else
  1133. filename = (getHtmlPath(npcId, val));
  1134. break;
  1135. case 36402:
  1136. if (player.olyBuff > 0)
  1137. filename = (player.olyBuff == 5 ? Olympiad.OLYMPIAD_HTML_PATH + "olympiad_buffs.htm" : Olympiad.OLYMPIAD_HTML_PATH + "olympiad_5buffs.htm");
  1138. else
  1139. filename = Olympiad.OLYMPIAD_HTML_PATH + "olympiad_nobuffs.htm";
  1140. break;
  1141. case 30298: // Blacksmith Pinter
  1142. if(player.isAcademyMember())
  1143. filename = (getHtmlPath(npcId, 1));
  1144. else
  1145. filename = (getHtmlPath(npcId, 0));
  1146. break;
  1147. default:
  1148. if (npcId >= 31865 && npcId <= 31918)
  1149. {
  1150. if (val == 0 )
  1151. filename += "rift/GuardianOfBorder.htm";
  1152. else
  1153. filename += "rift/GuardianOfBorder-" + val + ".htm";
  1154. break;
  1155. }
  1156. if ((npcId >= 31093 && npcId <= 31094) || (npcId >= 31172 && npcId <= 31201) || (npcId >= 31239 && npcId <= 31254))
  1157. return;
  1158. // Get the text of the selected HTML file in function of the npcId and of the page number
  1159. filename = (getHtmlPath(npcId, val));
  1160. break;
  1161. }
  1162. // Send a Server->Client NpcHtmlMessage containing the text of the L2NpcInstance to the L2PcInstance
  1163. NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1164. html.setFile(player.getHtmlPrefix(), filename);
  1165. if (this instanceof L2MerchantInstance)
  1166. {
  1167. if (Config.LIST_PET_RENT_NPC.contains(npcId))
  1168. html.replace("_Quest", "_RentPet\">Rent Pet</a><br><a action=\"bypass -h npc_%objectId%_Quest");
  1169. }
  1170. html.replace("%objectId%", String.valueOf(getObjectId()));
  1171. html.replace("%festivalMins%", SevenSignsFestival.getInstance().getTimeToNextFestivalStr());
  1172. player.sendPacket(html);
  1173. // Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
  1174. player.sendPacket(ActionFailed.STATIC_PACKET);
  1175. }
  1176. /**
  1177. * Open a chat window on client with the text specified by the given file name and path,<BR>
  1178. * relative to the datapack root.
  1179. * <BR><BR>
  1180. * Added by Tempy
  1181. * @param player The L2PcInstance that talk with the L2NpcInstance
  1182. * @param filename The filename that contains the text to send
  1183. *
  1184. */
  1185. public void showChatWindow(L2PcInstance player, String filename)
  1186. {
  1187. // Send a Server->Client NpcHtmlMessage containing the text of the L2NpcInstance to the L2PcInstance
  1188. NpcHtmlMessage html = new NpcHtmlMessage(getObjectId());
  1189. html.setFile(player.getHtmlPrefix(), filename);
  1190. html.replace("%objectId%", String.valueOf(getObjectId()));
  1191. player.sendPacket(html);
  1192. // Send a Server->Client ActionFailed to the L2PcInstance in order to avoid that the client wait another packet
  1193. player.sendPacket(ActionFailed.STATIC_PACKET);
  1194. }
  1195. /**
  1196. * Return the Exp Reward of this L2NpcInstance contained in the L2NpcTemplate (modified by RATE_XP).<BR><BR>
  1197. */
  1198. public int getExpReward()
  1199. {
  1200. return (int) (getTemplate().rewardExp * Config.RATE_XP);
  1201. }
  1202. /**
  1203. * Return the SP Reward of this L2NpcInstance contained in the L2NpcTemplate (modified by RATE_SP).<BR><BR>
  1204. */
  1205. public int getSpReward()
  1206. {
  1207. return (int) (getTemplate().rewardSp * Config.RATE_SP);
  1208. }
  1209. /**
  1210. * Kill the L2NpcInstance (the corpse disappeared after 7 seconds).<BR><BR>
  1211. *
  1212. * <B><U> Actions</U> :</B><BR><BR>
  1213. * <li>Create a DecayTask to remove the corpse of the L2NpcInstance after 7 seconds </li>
  1214. * <li>Set target to null and cancel Attack or Cast </li>
  1215. * <li>Stop movement </li>
  1216. * <li>Stop HP/MP/CP Regeneration task </li>
  1217. * <li>Stop all active skills effects in progress on the L2Character </li>
  1218. * <li>Send the Server->Client packet StatusUpdate with current HP and MP to all other L2PcInstance to inform </li>
  1219. * <li>Notify L2Character AI </li><BR><BR>
  1220. *
  1221. * <B><U> Overridden in </U> :</B><BR><BR>
  1222. * <li> L2Attackable </li><BR><BR>
  1223. *
  1224. * @param killer The L2Character who killed it
  1225. *
  1226. */
  1227. @Override
  1228. public boolean doDie(L2Character killer)
  1229. {
  1230. if (!super.doDie(killer))
  1231. return false;
  1232. // normally this wouldn't really be needed, but for those few exceptions,
  1233. // we do need to reset the weapons back to the initial templated weapon.
  1234. _currentLHandId = getTemplate().lhand;
  1235. _currentRHandId = getTemplate().rhand;
  1236. _currentCollisionHeight = getTemplate().fCollisionHeight;
  1237. _currentCollisionRadius = getTemplate().fCollisionRadius;
  1238. DecayTaskManager.getInstance().addDecayTask(this);
  1239. return true;
  1240. }
  1241. /**
  1242. * Set the spawn of the L2NpcInstance.<BR><BR>
  1243. *
  1244. * @param spawn The L2Spawn that manage the L2NpcInstance
  1245. *
  1246. */
  1247. public void setSpawn(L2Spawn spawn)
  1248. {
  1249. _spawn = spawn;
  1250. }
  1251. @Override
  1252. public void onSpawn()
  1253. {
  1254. super.onSpawn();
  1255. if (getTemplate().getEventQuests(Quest.QuestEventType.ON_SPAWN) != null)
  1256. for (Quest quest : getTemplate().getEventQuests(Quest.QuestEventType.ON_SPAWN))
  1257. quest.notifySpawn(this);
  1258. }
  1259. /**
  1260. * Remove the L2NpcInstance from the world and update its spawn object (for a complete removal use the deleteMe method).<BR><BR>
  1261. *
  1262. * <B><U> Actions</U> :</B><BR><BR>
  1263. * <li>Remove the L2NpcInstance from the world when the decay task is launched </li>
  1264. * <li>Decrease its spawn counter </li>
  1265. * <li>Manage Siege task (killFlag, killCT) </li><BR><BR>
  1266. *
  1267. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T REMOVE the object from _allObjects of L2World </B></FONT><BR>
  1268. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND Server->Client packets to players</B></FONT><BR><BR>
  1269. *
  1270. */
  1271. @Override
  1272. public void onDecay()
  1273. {
  1274. if (isDecayed())
  1275. return;
  1276. setDecayed(true);
  1277. // Remove the L2NpcInstance from the world when the decay task is launched
  1278. super.onDecay();
  1279. // Decrease its spawn counter
  1280. if (_spawn != null)
  1281. _spawn.decreaseCount(this);
  1282. }
  1283. /**
  1284. * Remove PROPERLY the L2NpcInstance from the world.<BR><BR>
  1285. *
  1286. * <B><U> Actions</U> :</B><BR><BR>
  1287. * <li>Remove the L2NpcInstance from the world and update its spawn object </li>
  1288. * <li>Remove all L2Object from _knownObjects and _knownPlayer of the L2NpcInstance then cancel Attack or Cast and notify AI </li>
  1289. * <li>Remove L2Object object from _allObjects of L2World </li><BR><BR>
  1290. *
  1291. * <FONT COLOR=#FF0000><B> <U>Caution</U> : This method DOESN'T SEND Server->Client packets to players</B></FONT><BR><BR>
  1292. *
  1293. */
  1294. @Override
  1295. public void deleteMe()
  1296. {
  1297. L2WorldRegion oldRegion = getWorldRegion();
  1298. try
  1299. {
  1300. onDecay();
  1301. }
  1302. catch (Exception e)
  1303. {
  1304. _log.log(Level.SEVERE, "Failed decayMe().", e);
  1305. }
  1306. try
  1307. {
  1308. if (_fusionSkill != null)
  1309. abortCast();
  1310. for (L2Character character : getKnownList().getKnownCharacters())
  1311. if (character.getFusionSkill() != null && character.getFusionSkill().getTarget() == this)
  1312. character.abortCast();
  1313. }
  1314. catch (Exception e)
  1315. {
  1316. _log.log(Level.SEVERE, "deleteMe()", e);
  1317. }
  1318. if (oldRegion != null)
  1319. oldRegion.removeFromZones(this);
  1320. // Remove all L2Object from _knownObjects and _knownPlayer of the L2Character then cancel Attak or Cast and notify AI
  1321. try
  1322. {
  1323. getKnownList().removeAllKnownObjects();
  1324. }
  1325. catch (Exception e)
  1326. {
  1327. _log.log(Level.SEVERE, "Failed removing cleaning knownlist.", e);
  1328. }
  1329. // Remove L2Object object from _allObjects of L2World
  1330. L2World.getInstance().removeObject(this);
  1331. super.deleteMe();
  1332. }
  1333. /**
  1334. * Return the L2Spawn object that manage this L2NpcInstance.<BR><BR>
  1335. */
  1336. public L2Spawn getSpawn()
  1337. {
  1338. return _spawn;
  1339. }
  1340. @Override
  1341. public String toString()
  1342. {
  1343. return getClass().getSimpleName()+":"+getTemplate().name+"("+getNpcId()+")"+"["+getObjectId()+"]";
  1344. }
  1345. public boolean isDecayed()
  1346. {
  1347. return _isDecayed;
  1348. }
  1349. public void setDecayed(boolean decayed)
  1350. {
  1351. _isDecayed = decayed;
  1352. }
  1353. public void endDecayTask()
  1354. {
  1355. if (!isDecayed())
  1356. {
  1357. DecayTaskManager.getInstance().cancelDecayTask(this);
  1358. onDecay();
  1359. }
  1360. }
  1361. public boolean isMob() // rather delete this check
  1362. {
  1363. return false; // This means we use MAX_NPC_ANIMATION instead of MAX_MONSTER_ANIMATION
  1364. }
  1365. // Two functions to change the appearance of the equipped weapons on the NPC
  1366. // This is only useful for a few NPCs and is most likely going to be called from AI
  1367. public void setLHandId(int newWeaponId)
  1368. {
  1369. _currentLHandId = newWeaponId;
  1370. updateAbnormalEffect();
  1371. }
  1372. public void setRHandId(int newWeaponId)
  1373. {
  1374. _currentRHandId = newWeaponId;
  1375. updateAbnormalEffect();
  1376. }
  1377. public void setLRHandId(int newLWeaponId, int newRWeaponId)
  1378. {
  1379. _currentRHandId = newRWeaponId;
  1380. _currentLHandId = newLWeaponId;
  1381. updateAbnormalEffect();
  1382. }
  1383. public void setEnchant(int newEnchantValue)
  1384. {
  1385. _currentEnchant = newEnchantValue;
  1386. updateAbnormalEffect();
  1387. }
  1388. public void setHideName(boolean val)
  1389. {
  1390. _isHideName = val;
  1391. }
  1392. public boolean isHideName()
  1393. {
  1394. return _isHideName;
  1395. }
  1396. public void setCollisionHeight(double height)
  1397. {
  1398. _currentCollisionHeight = height;
  1399. }
  1400. public void setCollisionRadius(double radius)
  1401. {
  1402. _currentCollisionRadius = radius;
  1403. }
  1404. public double getCollisionHeight()
  1405. {
  1406. return _currentCollisionHeight;
  1407. }
  1408. public double getCollisionRadius()
  1409. {
  1410. return _currentCollisionRadius;
  1411. }
  1412. @Override
  1413. public void sendInfo(L2PcInstance activeChar)
  1414. {
  1415. if (Config.CHECK_KNOWN && activeChar.isGM())
  1416. activeChar.sendMessage("Added NPC: "+getName());
  1417. if (getRunSpeed() == 0)
  1418. activeChar.sendPacket(new ServerObjectInfo(this, activeChar));
  1419. else
  1420. activeChar.sendPacket(new AbstractNpcInfo.NpcInfo(this, activeChar));
  1421. }
  1422. public void showNoTeachHtml(L2PcInstance player)
  1423. {
  1424. int npcId = getNpcId();
  1425. String html = "";
  1426. if (this instanceof L2WarehouseInstance)
  1427. html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/warehouse/" + npcId + "-noteach.htm");
  1428. else if (this instanceof L2TrainerInstance)
  1429. html = HtmCache.getInstance().getHtm(player.getHtmlPrefix(), "data/html/trainer/" + npcId + "-noteach.htm");
  1430. if (html == null)
  1431. {
  1432. _log.warning("Npc " + npcId + " missing noTeach html!");
  1433. NpcHtmlMessage msg = new NpcHtmlMessage(getObjectId());
  1434. final String sb = StringUtil.concat(
  1435. "<html><body>" +
  1436. "I cannot teach you any skills.<br>You must find your current class teachers.",
  1437. "</body></html>"
  1438. );
  1439. msg.setHtml(sb);
  1440. player.sendPacket(msg);
  1441. return;
  1442. }
  1443. else
  1444. {
  1445. NpcHtmlMessage noTeachMsg = new NpcHtmlMessage(getObjectId());
  1446. noTeachMsg.setHtml(html);
  1447. noTeachMsg.replace("%objectId%", String.valueOf(getObjectId()));
  1448. player.sendPacket(noTeachMsg);
  1449. }
  1450. }
  1451. public L2Npc scheduleDespawn(long delay)
  1452. {
  1453. ThreadPoolManager.getInstance().scheduleGeneral(this.new DespawnTask(), delay);
  1454. return this;
  1455. }
  1456. private class DespawnTask implements Runnable
  1457. {
  1458. @Override
  1459. public void run()
  1460. {
  1461. if (!L2Npc.this.isDecayed())
  1462. L2Npc.this.deleteMe();
  1463. }
  1464. }
  1465. @Override
  1466. protected final void notifyQuestEventSkillFinished(L2Skill skill, L2Object target)
  1467. {
  1468. try
  1469. {
  1470. if (getTemplate().getEventQuests(Quest.QuestEventType.ON_SPELL_FINISHED) != null)
  1471. {
  1472. L2PcInstance player = null;
  1473. if (target != null)
  1474. player = target.getActingPlayer();
  1475. for (Quest quest : getTemplate().getEventQuests(Quest.QuestEventType.ON_SPELL_FINISHED))
  1476. {
  1477. quest.notifySpellFinished(this, player, skill);
  1478. }
  1479. }
  1480. }
  1481. catch (Exception e)
  1482. {
  1483. _log.log(Level.SEVERE, "", e);
  1484. }
  1485. }
  1486. /* (non-Javadoc)
  1487. * @see com.l2jserver.gameserver.model.actor.L2Character#isMovementDisabled()
  1488. */
  1489. @Override
  1490. public boolean isMovementDisabled()
  1491. {
  1492. return super.isMovementDisabled() || getCanMove() == 0 || getAiType().equals(AIType.CORPSE);
  1493. }
  1494. public AIType getAiType()
  1495. {
  1496. return getTemplate().getAIDataStatic().getAiType();
  1497. }
  1498. public void setDisplayEffect(int val)
  1499. {
  1500. if (val != _displayEffect)
  1501. {
  1502. _displayEffect = val;
  1503. broadcastPacket(new ExChangeNpcState(getObjectId(), val));
  1504. }
  1505. }
  1506. public int getDisplayEffect()
  1507. {
  1508. return _displayEffect;
  1509. }
  1510. public int getColorEffect()
  1511. {
  1512. return 0;
  1513. }
  1514. }