L2Npc.java 47 KB

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