TvTEvent.java 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072
  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 net.sf.l2j.gameserver.model.entity;
  16. import java.util.List;
  17. import java.util.Map;
  18. import java.util.logging.Logger;
  19. import javolution.util.FastMap;
  20. import net.sf.l2j.Config;
  21. import net.sf.l2j.gameserver.datatables.DoorTable;
  22. import net.sf.l2j.gameserver.datatables.ItemTable;
  23. import net.sf.l2j.gameserver.datatables.NpcTable;
  24. import net.sf.l2j.gameserver.datatables.SpawnTable;
  25. import net.sf.l2j.gameserver.model.L2Spawn;
  26. import net.sf.l2j.gameserver.model.actor.L2Character;
  27. import net.sf.l2j.gameserver.model.actor.L2Npc;
  28. import net.sf.l2j.gameserver.model.actor.L2Summon;
  29. import net.sf.l2j.gameserver.model.actor.instance.L2DoorInstance;
  30. import net.sf.l2j.gameserver.model.actor.instance.L2PcInstance;
  31. import net.sf.l2j.gameserver.model.actor.instance.L2PetInstance;
  32. import net.sf.l2j.gameserver.model.actor.instance.L2SummonInstance;
  33. import net.sf.l2j.gameserver.model.itemcontainer.PcInventory;
  34. import net.sf.l2j.gameserver.model.olympiad.Olympiad;
  35. import net.sf.l2j.gameserver.network.SystemMessageId;
  36. import net.sf.l2j.gameserver.network.clientpackets.Say2;
  37. import net.sf.l2j.gameserver.network.serverpackets.CreatureSay;
  38. import net.sf.l2j.gameserver.network.serverpackets.MagicSkillUse;
  39. import net.sf.l2j.gameserver.network.serverpackets.NpcHtmlMessage;
  40. import net.sf.l2j.gameserver.network.serverpackets.StatusUpdate;
  41. import net.sf.l2j.gameserver.network.serverpackets.SystemMessage;
  42. import net.sf.l2j.gameserver.templates.chars.L2NpcTemplate;
  43. import net.sf.l2j.util.Rnd;
  44. /**
  45. * @author FBIagent
  46. */
  47. public class TvTEvent
  48. {
  49. enum EventState
  50. {
  51. INACTIVE,
  52. INACTIVATING,
  53. PARTICIPATING,
  54. STARTING,
  55. STARTED,
  56. REWARDING
  57. }
  58. protected static final Logger _log = Logger.getLogger(TvTEvent.class.getName());
  59. /** The teams of the TvTEvent<br> */
  60. private static TvTEventTeam[] _teams = new TvTEventTeam[2];
  61. /** The state of the TvTEvent<br> */
  62. private static EventState _state = EventState.INACTIVE;
  63. /** The spawn of the participation npc<br> */
  64. private static L2Spawn _npcSpawn = null;
  65. /** the npc instance of the participation npc<br> */
  66. private static L2Npc _lastNpcSpawn = null;
  67. /**
  68. * No instance of this class!<br>
  69. */
  70. private TvTEvent()
  71. {
  72. }
  73. /**
  74. * Teams initializing<br>
  75. */
  76. public static void init()
  77. {
  78. _teams[0] = new TvTEventTeam(Config.TVT_EVENT_TEAM_1_NAME, Config.TVT_EVENT_TEAM_1_COORDINATES);
  79. _teams[1] = new TvTEventTeam(Config.TVT_EVENT_TEAM_2_NAME, Config.TVT_EVENT_TEAM_2_COORDINATES);
  80. }
  81. /**
  82. * Starts the participation of the TvTEvent<br>
  83. * 1. Get L2NpcTemplate by Config.TVT_EVENT_PARTICIPATION_NPC_ID<br>
  84. * 2. Try to spawn a new npc of it<br><br>
  85. *
  86. * @return boolean: true if success, otherwise false<br>
  87. */
  88. public static boolean startParticipation()
  89. {
  90. L2NpcTemplate tmpl = NpcTable.getInstance().getTemplate(Config.TVT_EVENT_PARTICIPATION_NPC_ID);
  91. if (tmpl == null)
  92. {
  93. _log.warning("TvTEventEngine[TvTEvent.startParticipation()]: L2NpcTemplate is a NullPointer -> Invalid npc id in configs?");
  94. return false;
  95. }
  96. try
  97. {
  98. _npcSpawn = new L2Spawn(tmpl);
  99. _npcSpawn.setLocx(Config.TVT_EVENT_PARTICIPATION_NPC_COORDINATES[0]);
  100. _npcSpawn.setLocy(Config.TVT_EVENT_PARTICIPATION_NPC_COORDINATES[1]);
  101. _npcSpawn.setLocz(Config.TVT_EVENT_PARTICIPATION_NPC_COORDINATES[2]);
  102. _npcSpawn.setAmount(1);
  103. _npcSpawn.setHeading(0);
  104. _npcSpawn.setRespawnDelay(1);
  105. // later no need to delete spawn from db, we don't store it (false)
  106. SpawnTable.getInstance().addNewSpawn(_npcSpawn, false);
  107. _npcSpawn.init();
  108. _lastNpcSpawn = _npcSpawn.getLastSpawn();
  109. _lastNpcSpawn.setCurrentHp(_lastNpcSpawn.getMaxHp());
  110. _lastNpcSpawn.setTitle("TvT Event Participation");
  111. _lastNpcSpawn.isAggressive();
  112. _lastNpcSpawn.decayMe();
  113. _lastNpcSpawn.spawnMe(_npcSpawn.getLastSpawn().getX(), _npcSpawn.getLastSpawn().getY(), _npcSpawn.getLastSpawn().getZ());
  114. _lastNpcSpawn.broadcastPacket(new MagicSkillUse(_lastNpcSpawn, _lastNpcSpawn, 1034, 1, 1, 1));
  115. }
  116. catch (Exception e)
  117. {
  118. _log.warning("TvTEventEngine[TvTEvent.startParticipation()]: exception: " + e);
  119. return false;
  120. }
  121. setState(EventState.PARTICIPATING);
  122. return true;
  123. }
  124. private static int highestLevelPcInstanceOf(Map< Integer, L2PcInstance > players)
  125. {
  126. int maxLevel = Integer.MIN_VALUE, maxLevelId = -1;
  127. for (L2PcInstance player : players.values())
  128. {
  129. if (player.getLevel() >= maxLevel)
  130. {
  131. maxLevel = player.getLevel();
  132. maxLevelId = player.getObjectId();
  133. }
  134. }
  135. return maxLevelId;
  136. }
  137. /**
  138. * Starts the TvTEvent fight<br>
  139. * 1. Set state EventState.STARTING<br>
  140. * 2. Close doors specified in configs<br>
  141. * 3. Abort if not enought participants(return false)<br>
  142. * 4. Set state EventState.STARTED<br>
  143. * 5. Teleport all participants to team spot<br><br>
  144. *
  145. * @return boolean: true if success, otherwise false<br>
  146. */
  147. public static boolean startFight()
  148. {
  149. // Set state to STARTING
  150. setState(EventState.STARTING);
  151. // Randomize and balance team distribution
  152. Map< Integer, L2PcInstance > allParticipants = new FastMap< Integer, L2PcInstance >();
  153. allParticipants.putAll(_teams[0].getParticipatedPlayers());
  154. allParticipants.putAll(_teams[1].getParticipatedPlayers());
  155. _teams[0].cleanMe();
  156. _teams[1].cleanMe();
  157. int balance[] = { 0, 0 }, priority = 0, highestLevelPlayerId;
  158. L2PcInstance highestLevelPlayer;
  159. // XXX: allParticipants should be sorted by level instead of using highestLevelPcInstanceOf for every fetch
  160. while (!allParticipants.isEmpty())
  161. {
  162. // Priority team gets one player
  163. highestLevelPlayerId = highestLevelPcInstanceOf(allParticipants);
  164. highestLevelPlayer = allParticipants.get(highestLevelPlayerId);
  165. allParticipants.remove(highestLevelPlayerId);
  166. _teams[priority].addPlayer(highestLevelPlayer);
  167. balance[priority] += highestLevelPlayer.getLevel();
  168. // Exiting if no more players
  169. if (allParticipants.isEmpty()) break;
  170. // The other team gets one player
  171. // XXX: Code not dry
  172. priority = 1-priority;
  173. highestLevelPlayerId = highestLevelPcInstanceOf(allParticipants);
  174. highestLevelPlayer = allParticipants.get(highestLevelPlayerId);
  175. allParticipants.remove(highestLevelPlayerId);
  176. _teams[priority].addPlayer(highestLevelPlayer);
  177. balance[priority] += highestLevelPlayer.getLevel();
  178. // Recalculating priority
  179. priority = balance[0] > balance[1] ? 1 : 0;
  180. }
  181. // Check for enought participants
  182. if (_teams[0].getParticipatedPlayerCount() < Config.TVT_EVENT_MIN_PLAYERS_IN_TEAMS || _teams[1].getParticipatedPlayerCount() < Config.TVT_EVENT_MIN_PLAYERS_IN_TEAMS)
  183. {
  184. // Set state INACTIVE
  185. setState(EventState.INACTIVE);
  186. // Cleanup of teams
  187. _teams[0].cleanMe();
  188. _teams[1].cleanMe();
  189. // Unspawn the event NPC
  190. unSpawnNpc();
  191. return false;
  192. }
  193. // Opens all doors specified in configs for tvt
  194. openDoors(Config.TVT_DOORS_IDS_TO_OPEN);
  195. // Closes all doors specified in configs for tvt
  196. closeDoors(Config.TVT_DOORS_IDS_TO_CLOSE);
  197. // Set state STARTED
  198. setState(EventState.STARTED);
  199. // Iterate over all teams
  200. for (TvTEventTeam team : _teams)
  201. {
  202. // Iterate over all participated player instances in this team
  203. for (L2PcInstance playerInstance : team.getParticipatedPlayers().values())
  204. {
  205. if (playerInstance != null)
  206. {
  207. // Teleporter implements Runnable and starts itself
  208. new TvTEventTeleporter(playerInstance, team.getCoordinates(), false, false);
  209. }
  210. }
  211. }
  212. return true;
  213. }
  214. /**
  215. * Calculates the TvTEvent reward<br>
  216. * 1. If both teams are at a tie(points equals), send it as system message to all participants, if one of the teams have 0 participants left online abort rewarding<br>
  217. * 2. Wait till teams are not at a tie anymore<br>
  218. * 3. Set state EvcentState.REWARDING<br>
  219. * 4. Reward team with more points<br>
  220. * 5. Show win html to wining team participants<br><br>
  221. *
  222. * @return String: winning team name<br>
  223. */
  224. public static String calculateRewards()
  225. {
  226. if (_teams[0].getPoints() == _teams[1].getPoints())
  227. {
  228. // Check if one of the teams have no more players left
  229. if (_teams[0].getParticipatedPlayerCount() == 0 || _teams[1].getParticipatedPlayerCount() == 0)
  230. {
  231. // set state to rewarding
  232. setState(EventState.REWARDING);
  233. // return here, the fight can't be completed
  234. return "TvT Event: Event has ended. No team won due to inactivity!";
  235. }
  236. // Both teams have equals points
  237. sysMsgToAllParticipants("TvT Event: Event has ended, both teams have tied.");
  238. if (Config.TVT_REWARD_TEAM_TIE)
  239. {
  240. rewardTeamOne();
  241. rewardTeamTwo();
  242. return "TvT Event: Event has ended with both teams tying.";
  243. }
  244. else
  245. return "TvT Event: Event has ended with both teams tying.";
  246. }
  247. // Set state REWARDING so nobody can point anymore
  248. setState(EventState.REWARDING);
  249. // Get team which has more points
  250. TvTEventTeam team = _teams[_teams[0].getPoints() > _teams[1].getPoints() ? 0 : 1];
  251. if (team == _teams[0])
  252. rewardTeamOne();
  253. else
  254. rewardTeamTwo();
  255. return "TvT Event: Event finish. Team " + team.getName() + " won with " + team.getPoints() + " kills.";
  256. }
  257. private static void rewardTeamOne()
  258. {
  259. TvTEventTeam team = _teams[0];
  260. // Iterate over all participated player instances of the winning team
  261. for (L2PcInstance playerInstance : team.getParticipatedPlayers().values())
  262. {
  263. // Check for nullpointer
  264. if (playerInstance == null)
  265. {
  266. continue;
  267. }
  268. SystemMessage systemMessage = null;
  269. // Iterate over all tvt event rewards
  270. for (int[] reward : Config.TVT_EVENT_REWARDS)
  271. {
  272. PcInventory inv = playerInstance.getInventory();
  273. // Check for stackable item, non stackabe items need to be added one by one
  274. if (ItemTable.getInstance().createDummyItem(reward[0]).isStackable())
  275. {
  276. inv.addItem("TvT Event", reward[0], reward[1], playerInstance, playerInstance);
  277. if (reward[1] > 1)
  278. {
  279. systemMessage = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
  280. systemMessage.addItemName(reward[0]);
  281. systemMessage.addItemNumber(reward[1]);
  282. }
  283. else
  284. {
  285. systemMessage = new SystemMessage(SystemMessageId.EARNED_ITEM);
  286. systemMessage.addItemName(reward[0]);
  287. }
  288. playerInstance.sendPacket(systemMessage);
  289. }
  290. else
  291. {
  292. for (int i = 0; i < reward[1]; ++i)
  293. {
  294. inv.addItem("TvT Event", reward[0], 1, playerInstance, playerInstance);
  295. systemMessage = new SystemMessage(SystemMessageId.EARNED_ITEM);
  296. systemMessage.addItemName(reward[0]);
  297. playerInstance.sendPacket(systemMessage);
  298. }
  299. }
  300. }
  301. StatusUpdate statusUpdate = new StatusUpdate(playerInstance.getObjectId());
  302. NpcHtmlMessage npcHtmlMessage = new NpcHtmlMessage(0);
  303. statusUpdate.addAttribute(StatusUpdate.CUR_LOAD, playerInstance.getCurrentLoad());
  304. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>Your team won the event. Look in your inventory, there should be your reward.</body></html>");
  305. playerInstance.sendPacket(statusUpdate);
  306. playerInstance.sendPacket(npcHtmlMessage);
  307. }
  308. }
  309. private static void rewardTeamTwo()
  310. {
  311. TvTEventTeam team = _teams[1];
  312. // Iterate over all participated player instances of the winning team
  313. for (L2PcInstance playerInstance : team.getParticipatedPlayers().values())
  314. {
  315. // Check for nullpointer
  316. if (playerInstance == null)
  317. {
  318. continue;
  319. }
  320. SystemMessage systemMessage = null;
  321. // Iterate over all tvt event rewards
  322. for (int[] reward : Config.TVT_EVENT_REWARDS)
  323. {
  324. PcInventory inv = playerInstance.getInventory();
  325. // Check for stackable item, non stackabe items need to be added one by one
  326. if (ItemTable.getInstance().createDummyItem(reward[0]).isStackable())
  327. {
  328. inv.addItem("TvT Event", reward[0], reward[1], playerInstance, playerInstance);
  329. if (reward[1] > 1)
  330. {
  331. systemMessage = new SystemMessage(SystemMessageId.EARNED_S2_S1_S);
  332. systemMessage.addItemName(reward[0]);
  333. systemMessage.addItemNumber(reward[1]);
  334. }
  335. else
  336. {
  337. systemMessage = new SystemMessage(SystemMessageId.EARNED_ITEM);
  338. systemMessage.addItemName(reward[0]);
  339. }
  340. playerInstance.sendPacket(systemMessage);
  341. }
  342. else
  343. {
  344. for (int i = 0; i < reward[1]; ++i)
  345. {
  346. inv.addItem("TvT Event", reward[0], 1, playerInstance, playerInstance);
  347. systemMessage = new SystemMessage(SystemMessageId.EARNED_ITEM);
  348. systemMessage.addItemName(reward[0]);
  349. playerInstance.sendPacket(systemMessage);
  350. }
  351. }
  352. }
  353. StatusUpdate statusUpdate = new StatusUpdate(playerInstance.getObjectId());
  354. NpcHtmlMessage npcHtmlMessage = new NpcHtmlMessage(0);
  355. statusUpdate.addAttribute(StatusUpdate.CUR_LOAD, playerInstance.getCurrentLoad());
  356. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>Your team won the event. Look in your inventory, there should be your reward.</body></html>");
  357. playerInstance.sendPacket(statusUpdate);
  358. playerInstance.sendPacket(npcHtmlMessage);
  359. }
  360. }
  361. /**
  362. * Stops the TvTEvent fight<br>
  363. * 1. Set state EventState.INACTIVATING<br>
  364. * 2. Remove tvt npc from world<br>
  365. * 3. Open doors specified in configs<br>
  366. * 4. Teleport all participants back to participation npc location<br>
  367. * 5. Teams cleaning<br>
  368. * 6. Set state EventState.INACTIVE<br>
  369. */
  370. public static void stopFight()
  371. {
  372. // Set state INACTIVATING
  373. setState(EventState.INACTIVATING);
  374. //Unspawn event npc
  375. unSpawnNpc();
  376. // Opens all doors specified in configs for tvt
  377. openDoors(Config.TVT_DOORS_IDS_TO_CLOSE);
  378. // Closes all doors specified in Configs for tvt
  379. closeDoors(Config.TVT_DOORS_IDS_TO_OPEN);
  380. // Iterate over all teams
  381. for (TvTEventTeam team : _teams)
  382. {
  383. for (L2PcInstance playerInstance : team.getParticipatedPlayers().values())
  384. {
  385. // Check for nullpointer
  386. if (playerInstance != null)
  387. {
  388. new TvTEventTeleporter(playerInstance, Config.TVT_EVENT_PARTICIPATION_NPC_COORDINATES, false, false);
  389. }
  390. }
  391. }
  392. // Cleanup of teams
  393. _teams[0].cleanMe();
  394. _teams[1].cleanMe();
  395. // Set state INACTIVE
  396. setState(EventState.INACTIVE);
  397. }
  398. /**
  399. * Adds a player to a TvTEvent team<br>
  400. * 1. Calculate the id of the team in which the player should be added<br>
  401. * 2. Add the player to the calculated team<br><br>
  402. *
  403. * @param playerInstance as L2PcInstance<br>
  404. * @return boolean: true if success, otherwise false<br>
  405. */
  406. public static synchronized boolean addParticipant(L2PcInstance playerInstance)
  407. {
  408. // Check for nullpoitner
  409. if (playerInstance == null)
  410. {
  411. return false;
  412. }
  413. byte teamId = 0;
  414. // Check to which team the player should be added
  415. if (_teams[0].getParticipatedPlayerCount() == _teams[1].getParticipatedPlayerCount())
  416. {
  417. teamId = (byte) (Rnd.get(2));
  418. }
  419. else
  420. {
  421. teamId = (byte) (_teams[0].getParticipatedPlayerCount() > _teams[1].getParticipatedPlayerCount() ? 1 : 0);
  422. }
  423. return _teams[teamId].addPlayer(playerInstance);
  424. }
  425. /**
  426. * Removes a TvTEvent player from it's team<br>
  427. * 1. Get team id of the player<br>
  428. * 2. Remove player from it's team<br><br>
  429. *
  430. * @param playerName as String<br>
  431. * @return boolean: true if success, otherwise false<br>
  432. */
  433. public static boolean removeParticipant(int playerObjectId)
  434. {
  435. // Get the teamId of the player
  436. byte teamId = getParticipantTeamId(playerObjectId);
  437. // Check if the player is participant
  438. if (teamId != -1)
  439. {
  440. // Remove the player from team
  441. _teams[teamId].removePlayer(playerObjectId);
  442. return true;
  443. }
  444. return false;
  445. }
  446. /**
  447. * Send a SystemMessage to all participated players<br>
  448. * 1. Send the message to all players of team number one<br>
  449. * 2. Send the message to all players of team number two<br><br>
  450. *
  451. * @param message as String<br>
  452. */
  453. public static void sysMsgToAllParticipants(String message)
  454. {
  455. for (L2PcInstance playerInstance : _teams[0].getParticipatedPlayers().values())
  456. {
  457. if (playerInstance != null)
  458. {
  459. playerInstance.sendMessage(message);
  460. }
  461. }
  462. for (L2PcInstance playerInstance : _teams[1].getParticipatedPlayers().values())
  463. {
  464. if (playerInstance != null)
  465. {
  466. playerInstance.sendMessage(message);
  467. }
  468. }
  469. }
  470. /**
  471. * Close doors specified in configs
  472. */
  473. private static void closeDoors(List<Integer> doors)
  474. {
  475. for (int doorId : doors)
  476. {
  477. L2DoorInstance doorInstance = DoorTable.getInstance().getDoor(doorId);
  478. if (doorInstance != null)
  479. {
  480. doorInstance.closeMe();
  481. }
  482. }
  483. }
  484. /**
  485. * Open doors specified in configs
  486. */
  487. private static void openDoors(List<Integer> doors)
  488. {
  489. for (int doorId : doors)
  490. {
  491. L2DoorInstance doorInstance = DoorTable.getInstance().getDoor(doorId);
  492. if (doorInstance != null)
  493. {
  494. doorInstance.openMe();
  495. }
  496. }
  497. }
  498. /**
  499. * UnSpawns the TvTEvent npc
  500. */
  501. private static void unSpawnNpc()
  502. {
  503. // Delete the npc
  504. _lastNpcSpawn.deleteMe();
  505. // Stop respawningof the npc
  506. _npcSpawn.stopRespawn();
  507. _npcSpawn = null;
  508. _lastNpcSpawn = null;
  509. }
  510. /**
  511. * Called when a player logs in<br><br>
  512. *
  513. * @param playerInstance as L2PcInstance<br>
  514. */
  515. public static void onLogin(L2PcInstance playerInstance)
  516. {
  517. if (playerInstance == null || (!isStarting() && !isStarted()))
  518. {
  519. return;
  520. }
  521. byte teamId = getParticipantTeamId(playerInstance.getObjectId());
  522. if (teamId == -1)
  523. {
  524. return;
  525. }
  526. _teams[teamId].addPlayer(playerInstance);
  527. new TvTEventTeleporter(playerInstance, _teams[teamId].getCoordinates(), true, false);
  528. }
  529. /**
  530. * Called when a player logs out<br><br>
  531. *
  532. * @param playerInstance as L2PcInstance<br>
  533. */
  534. public static void onLogout(L2PcInstance playerInstance)
  535. {
  536. if (playerInstance != null && (isStarting() || isStarted() || isParticipating()))
  537. {
  538. removeParticipant(playerInstance.getObjectId());
  539. }
  540. }
  541. /**
  542. * Called on every bypass by npc of type L2TvTEventNpc<br>
  543. * Needs synchronization cause of the max player check<br><br>
  544. *
  545. * @param command as String<br>
  546. * @param playerInstance as L2PcInstance<br>
  547. */
  548. public static synchronized void onBypass(String command, L2PcInstance playerInstance)
  549. {
  550. if (playerInstance == null || !isParticipating())
  551. {
  552. return;
  553. }
  554. if (command.equals("tvt_event_participation"))
  555. {
  556. NpcHtmlMessage npcHtmlMessage = new NpcHtmlMessage(0);
  557. int playerLevel = playerInstance.getLevel();
  558. if (playerInstance.isCursedWeaponEquipped())
  559. {
  560. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>Cursed weapon owners are not allowed to participate.</body></html>");
  561. }
  562. else if (Olympiad.getInstance().isRegistered(playerInstance))
  563. {
  564. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>You can not participate when registered for Olympiad.</body></html>");
  565. }
  566. else if (playerInstance.getKarma() > 0)
  567. {
  568. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>Chaotic players are not allowed to participate.</body></html>");
  569. }
  570. else if (playerLevel < Config.TVT_EVENT_MIN_LVL || playerLevel > Config.TVT_EVENT_MAX_LVL)
  571. {
  572. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>Only players from level " + Config.TVT_EVENT_MIN_LVL + " to level " + Config.TVT_EVENT_MAX_LVL + " are allowed tro participate.</body></html>");
  573. }
  574. else if (_teams[0].getParticipatedPlayerCount() == Config.TVT_EVENT_MAX_PLAYERS_IN_TEAMS && _teams[1].getParticipatedPlayerCount() == Config.TVT_EVENT_MAX_PLAYERS_IN_TEAMS)
  575. {
  576. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>The event is full! Only " + Config.TVT_EVENT_MAX_PLAYERS_IN_TEAMS + " players are allowed per team.</body></html>");
  577. }
  578. else if (addParticipant(playerInstance))
  579. {
  580. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>You are on the registration list now.</body></html>");
  581. }
  582. else
  583. {
  584. return;
  585. }
  586. playerInstance.sendPacket(npcHtmlMessage);
  587. }
  588. else if (command.equals("tvt_event_remove_participation"))
  589. {
  590. removeParticipant(playerInstance.getObjectId());
  591. NpcHtmlMessage npcHtmlMessage = new NpcHtmlMessage(0);
  592. npcHtmlMessage.setHtml("<html><head><title>TvT Event</title></head><body>You are not longer on the registration list.</body></html>");
  593. playerInstance.sendPacket(npcHtmlMessage);
  594. }
  595. }
  596. /**
  597. * Called on every onAction in L2PcIstance<br><br>
  598. *
  599. * @param playerName as String<br>
  600. * @param targetPlayerName as String<br>
  601. * @return boolean: true if player is allowed to target, otherwise false<br>
  602. */
  603. public static boolean onAction(L2PcInstance playerInstance, int targetedPlayerObjectId)
  604. {
  605. if (playerInstance == null || !isStarted())
  606. {
  607. return true;
  608. }
  609. if (playerInstance.isGM())
  610. {
  611. return true;
  612. }
  613. byte playerTeamId = getParticipantTeamId(playerInstance.getObjectId());
  614. byte targetedPlayerTeamId = getParticipantTeamId(targetedPlayerObjectId);
  615. if ((playerTeamId != -1 && targetedPlayerTeamId == -1) || (playerTeamId == -1 && targetedPlayerTeamId != -1))
  616. {
  617. return false;
  618. }
  619. if (playerTeamId != -1 && targetedPlayerTeamId != -1 && playerTeamId == targetedPlayerTeamId && playerInstance.getObjectId() != targetedPlayerObjectId && !Config.TVT_EVENT_TARGET_TEAM_MEMBERS_ALLOWED)
  620. {
  621. return false;
  622. }
  623. return true;
  624. }
  625. /**
  626. * Called on every scroll use<br><br>
  627. *
  628. * @param playerName as String<br>
  629. * @return boolean: true if player is allowed to use scroll, otherwise false<br>
  630. */
  631. public static boolean onScrollUse(int playerObjectId)
  632. {
  633. if (!isStarted())
  634. return true;
  635. if (isPlayerParticipant(playerObjectId) && !Config.TVT_EVENT_SCROLL_ALLOWED)
  636. return false;
  637. return true;
  638. }
  639. /**
  640. * Called on every potion use<br><br>
  641. *
  642. * @param playerName as String<br>
  643. * @return boolean: true if player is allowed to use potions, otherwise false<br>
  644. */
  645. public static boolean onPotionUse(int playerObjectId)
  646. {
  647. if (!isStarted())
  648. return true;
  649. if (isPlayerParticipant(playerObjectId) && !Config.TVT_EVENT_POTIONS_ALLOWED)
  650. return false;
  651. return true;
  652. }
  653. /**
  654. * Called on every escape use(thanks to nbd)<br><br>
  655. *
  656. * @param playerName as String<br>
  657. * @return boolean: true if player is not in tvt event, otherwise false<br>
  658. */
  659. public static boolean onEscapeUse(int playerObjectId)
  660. {
  661. if (!isStarted())
  662. {
  663. return true;
  664. }
  665. if (isPlayerParticipant(playerObjectId))
  666. {
  667. return false;
  668. }
  669. return true;
  670. }
  671. /**
  672. * Called on every summon item use<br><br>
  673. *
  674. * @param playerName as String<br>
  675. * @return boolean: true if player is allowed to summon by item, otherwise false<br>
  676. */
  677. public static boolean onItemSummon(int playerObjectId)
  678. {
  679. if (!isStarted())
  680. {
  681. return true;
  682. }
  683. if (isPlayerParticipant(playerObjectId) && !Config.TVT_EVENT_SUMMON_BY_ITEM_ALLOWED)
  684. {
  685. return false;
  686. }
  687. return true;
  688. }
  689. /**
  690. * Is called when a player is killed<br><br>
  691. *
  692. * @param killerCharacter as L2Character<br>
  693. * @param killedPlayerInstance as L2PcInstance<br>
  694. */
  695. public static void onKill(L2Character killerCharacter, L2PcInstance killedPlayerInstance)
  696. {
  697. if (killedPlayerInstance == null || !isStarted())
  698. {
  699. return;
  700. }
  701. byte killedTeamId = getParticipantTeamId(killedPlayerInstance.getObjectId());
  702. if (killedTeamId == -1)
  703. {
  704. return;
  705. }
  706. new TvTEventTeleporter(killedPlayerInstance, _teams[killedTeamId].getCoordinates(), false, false);
  707. if (killerCharacter == null)
  708. {
  709. return;
  710. }
  711. L2PcInstance killerPlayerInstance = null;
  712. if (killerCharacter instanceof L2PetInstance || killerCharacter instanceof L2SummonInstance)
  713. {
  714. killerPlayerInstance = ((L2Summon) killerCharacter).getOwner();
  715. if (killerPlayerInstance == null)
  716. {
  717. return;
  718. }
  719. }
  720. else if (killerCharacter instanceof L2PcInstance)
  721. {
  722. killerPlayerInstance = (L2PcInstance) killerCharacter;
  723. }
  724. else
  725. {
  726. return;
  727. }
  728. byte killerTeamId = getParticipantTeamId(killerPlayerInstance.getObjectId());
  729. if (killerTeamId != -1 && killedTeamId != -1 && killerTeamId != killedTeamId)
  730. {
  731. TvTEventTeam killerTeam = _teams[killerTeamId];
  732. killerTeam.increasePoints();
  733. CreatureSay cs = new CreatureSay(killerPlayerInstance.getObjectId(), Say2.TELL, killerPlayerInstance.getName(), "I have killed " + killedPlayerInstance.getName() + "!");
  734. for (L2PcInstance playerInstance : _teams[killerTeamId].getParticipatedPlayers().values())
  735. {
  736. if (playerInstance != null)
  737. {
  738. playerInstance.sendPacket(cs);
  739. }
  740. }
  741. }
  742. }
  743. /**
  744. * Sets the TvTEvent state<br><br>
  745. *
  746. * @param state as EventState<br>
  747. */
  748. private static void setState(EventState state)
  749. {
  750. synchronized (_state)
  751. {
  752. _state = state;
  753. }
  754. }
  755. /**
  756. * Is TvTEvent inactive?<br><br>
  757. *
  758. * @return boolean: true if event is inactive(waiting for next event cycle), otherwise false<br>
  759. */
  760. public static boolean isInactive()
  761. {
  762. boolean isInactive;
  763. synchronized (_state)
  764. {
  765. isInactive = _state == EventState.INACTIVE;
  766. }
  767. return isInactive;
  768. }
  769. /**
  770. * Is TvTEvent in inactivating?<br><br>
  771. *
  772. * @return boolean: true if event is in inactivating progress, otherwise false<br>
  773. */
  774. public static boolean isInactivating()
  775. {
  776. boolean isInactivating;
  777. synchronized (_state)
  778. {
  779. isInactivating = _state == EventState.INACTIVATING;
  780. }
  781. return isInactivating;
  782. }
  783. /**
  784. * Is TvTEvent in participation?<br><br>
  785. *
  786. * @return boolean: true if event is in participation progress, otherwise false<br>
  787. */
  788. public static boolean isParticipating()
  789. {
  790. boolean isParticipating;
  791. synchronized (_state)
  792. {
  793. isParticipating = _state == EventState.PARTICIPATING;
  794. }
  795. return isParticipating;
  796. }
  797. /**
  798. * Is TvTEvent starting?<br><br>
  799. *
  800. * @return boolean: true if event is starting up(setting up fighting spot, teleport players etc.), otherwise false<br>
  801. */
  802. public static boolean isStarting()
  803. {
  804. boolean isStarting;
  805. synchronized (_state)
  806. {
  807. isStarting = _state == EventState.STARTING;
  808. }
  809. return isStarting;
  810. }
  811. /**
  812. * Is TvTEvent started?<br><br>
  813. *
  814. * @return boolean: true if event is started, otherwise false<br>
  815. */
  816. public static boolean isStarted()
  817. {
  818. boolean isStarted;
  819. synchronized (_state)
  820. {
  821. isStarted = _state == EventState.STARTED;
  822. }
  823. return isStarted;
  824. }
  825. /**
  826. * Is TvTEvent rewadrding?<br><br>
  827. *
  828. * @return boolean: true if event is currently rewarding, otherwise false<br>
  829. */
  830. public static boolean isRewarding()
  831. {
  832. boolean isRewarding;
  833. synchronized (_state)
  834. {
  835. isRewarding = _state == EventState.REWARDING;
  836. }
  837. return isRewarding;
  838. }
  839. /**
  840. * Returns the team id of a player, if player is not participant it returns -1<br><br>
  841. *
  842. * @param playerName as String<br>
  843. * @return byte: team name of the given playerName, if not in event -1<br>
  844. */
  845. public static byte getParticipantTeamId(int playerObjectId)
  846. {
  847. return (byte) (_teams[0].containsPlayer(playerObjectId) ? 0 : (_teams[1].containsPlayer(playerObjectId) ? 1 : -1));
  848. }
  849. /**
  850. * Returns the team of a player, if player is not participant it returns null <br><br>
  851. *
  852. * @param player objectId as Integer<br>
  853. * @return TvTEventTeam: team of the given playerObjectId, if not in event null <br>
  854. */
  855. public static TvTEventTeam getParticipantTeam(int playerObjectId)
  856. {
  857. return (_teams[0].containsPlayer(playerObjectId) ? _teams[0] : (_teams[1].containsPlayer(playerObjectId) ? _teams[1] : null));
  858. }
  859. /**
  860. * Returns the enemy team of a player, if player is not participant it returns null <br><br>
  861. *
  862. * @param player objectId as Integer<br>
  863. * @return TvTEventTeam: enemy team of the given playerObjectId, if not in event null <br>
  864. */
  865. public static TvTEventTeam getParticipantEnemyTeam(int playerObjectId)
  866. {
  867. return (_teams[0].containsPlayer(playerObjectId) ? _teams[1] : (_teams[1].containsPlayer(playerObjectId) ? _teams[0] : null));
  868. }
  869. /**
  870. * Returns the team coordinates in which the player is in, if player is not in a team return null<br><br>
  871. *
  872. * @param playerName as String<br>
  873. * @return int[]: coordinates of teams, 2 elements, index 0 for team 1 and index 1 for team 2<br>
  874. */
  875. public static int[] getParticipantTeamCoordinates(int playerObjectId)
  876. {
  877. return _teams[0].containsPlayer(playerObjectId) ? _teams[0].getCoordinates() : (_teams[1].containsPlayer(playerObjectId) ? _teams[1].getCoordinates() : null);
  878. }
  879. /**
  880. * Is given player participant of the event?<br><br>
  881. *
  882. * @param playerName as String<br>
  883. * @return boolean: true if player is participant, ohterwise false<br>
  884. */
  885. public static boolean isPlayerParticipant(int playerObjectId)
  886. {
  887. if (!isParticipating() && !isStarting() && !isStarted())
  888. {
  889. return false;
  890. }
  891. return _teams[0].containsPlayer(playerObjectId) || _teams[1].containsPlayer(playerObjectId);
  892. }
  893. /**
  894. * Returns participated player count<br><br>
  895. *
  896. * @return int: amount of players registered in the event<br>
  897. */
  898. public static int getParticipatedPlayersCount()
  899. {
  900. if (!isParticipating() && !isStarting() && !isStarted())
  901. {
  902. return 0;
  903. }
  904. return _teams[0].getParticipatedPlayerCount() + _teams[1].getParticipatedPlayerCount();
  905. }
  906. /**
  907. * Returns teams names<br><br>
  908. *
  909. * @return String[]: names of teams, 2 elements, index 0 for team 1 and index 1 for team 2<br>
  910. */
  911. public static String[] getTeamNames()
  912. {
  913. return new String[]
  914. {
  915. _teams[0].getName(), _teams[1].getName()
  916. };
  917. }
  918. /**
  919. * Returns player count of both teams<br><br>
  920. *
  921. * @return int[]: player count of teams, 2 elements, index 0 for team 1 and index 1 for team 2<br>
  922. */
  923. public static int[] getTeamsPlayerCounts()
  924. {
  925. return new int[]
  926. {
  927. _teams[0].getParticipatedPlayerCount(), _teams[1].getParticipatedPlayerCount()
  928. };
  929. }
  930. /**
  931. * Returns points count of both teams
  932. *
  933. * @return int[]: points of teams, 2 elements, index 0 for team 1 and index 1 for team 2<br>
  934. */
  935. public static int[] getTeamsPoints()
  936. {
  937. return new int[]
  938. {
  939. _teams[0].getPoints(), _teams[1].getPoints()
  940. };
  941. }
  942. }