Guest User

Untitled

a guest
Dec 4th, 2017
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 39.33 KB | None | 0 0
  1. package com.rs.game.player;
  2.  
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import java.util.concurrent.CopyOnWriteArrayList;
  5.  
  6. import com.rs.Settings;
  7. import com.rs.game.Animation;
  8. import com.rs.game.Entity;
  9. import com.rs.game.Graphics;
  10. import com.rs.game.Hit;
  11. import com.rs.game.Hit.HitLook;
  12. import com.rs.game.Region;
  13. import com.rs.game.World;
  14. import com.rs.game.WorldObject;
  15. import com.rs.game.WorldTile;
  16. import com.rs.game.item.FloorItem;
  17. import com.rs.game.npc.NPC;
  18. import com.rs.game.player.skills.SkillExecutor;
  19. import com.rs.game.tasks.WorldTask;
  20. import com.rs.game.tasks.WorldTasksManager;
  21. import com.rs.net.Session;
  22. import com.rs.net.encoders.WorldPacketsEncoder;
  23. import com.rs.utils.SerializableFilesManager;
  24. import com.rs.utils.Utils;
  25.  
  26. public final class Player extends Entity {
  27.  
  28. private static final long serialVersionUID = 2011932556974180375L;
  29.  
  30.  
  31. //transient stuff
  32. private transient String username;
  33. private transient Session session;
  34. private transient boolean clientLoadedMapRegion;
  35. private transient int displayMode;
  36. private transient int screenWidth;
  37. private transient int screenHeight;
  38. private transient InterfaceManager interfaceManager;
  39. private transient DialogueManager dialogueManager;
  40. private transient SkillExecutor skillExecutor;
  41. private transient CoordsEvent coordsEvent;
  42. private transient ConcurrentHashMap<Object, Object> temporaryAttributes;
  43. private transient boolean dontUpdateMyPlayer;
  44. //used for update
  45. private transient LocalPlayerUpdate localPlayerUpdate;
  46. private transient LocalNPCUpdate localNPCUpdate;
  47. //player masks
  48. private transient PublicChatMessage nextPublicChatMessage;
  49. private transient ForceMovement nextForceMovement;
  50. //player stages
  51. private transient boolean started;
  52. private transient boolean running;
  53.  
  54. private transient long packetsDecoderPing;
  55. private transient boolean resting;
  56. private transient boolean canPvp;
  57. private transient long stopDelay; //used for doors and stuff like that
  58. private transient int musicId;
  59. private transient long musicDelay;
  60.  
  61. //saving stuff
  62. private String password;
  63. private int rights;
  64. private String displayName;
  65. private Appearence appearence;
  66. private Inventory inventory;
  67. private Equipment equipment;
  68. private Skills skills;
  69. private CombatDefinitions combatDefinitions;
  70. private Prayer prayer;
  71. private Bank bank;
  72. private ControlerManager controlerManager;
  73. private FriendsIgnores friendsIgnores;
  74. private byte runEnergy;
  75. private boolean allowChatEffects;
  76. private boolean mouseButtons;
  77. private boolean splitChat;
  78. private int skullDelay;
  79. private boolean forceNextMapLoadRefresh;
  80. private String title = "";
  81. public String getTitle() {
  82. return title;
  83. }
  84.  
  85. public void setTitle(String title) {
  86. this.title = title;
  87. }
  88.  
  89. //creates Player and saved classes
  90. public Player(String password) {
  91. super(Settings.START_PLAYER_LOCATION);
  92. setHitpoints(Settings.START_PLAYER_HITPOINTS);
  93. this.password = password;
  94. appearence = new Appearence();
  95. inventory = new Inventory();
  96. equipment = new Equipment();
  97. skills = new Skills();
  98. combatDefinitions = new CombatDefinitions();
  99. prayer = new Prayer();
  100. bank = new Bank();
  101. controlerManager = new ControlerManager();
  102. friendsIgnores = new FriendsIgnores();
  103. runEnergy = 100;
  104. allowChatEffects = true;
  105. mouseButtons = true;
  106. }
  107.  
  108. public void init(Session session, String username, int displayMode, int screenWidth, int screenHeight) {
  109. this.session = session;
  110. this.username = username;
  111. this.displayMode = displayMode;
  112. this.screenWidth = screenWidth;
  113. this.screenHeight = screenHeight;
  114. interfaceManager = new InterfaceManager(this);
  115. dialogueManager = new DialogueManager(this);
  116. localPlayerUpdate = new LocalPlayerUpdate(this);
  117. localNPCUpdate = new LocalNPCUpdate(this);
  118. skillExecutor = new SkillExecutor(this);
  119. temporaryAttributes = new ConcurrentHashMap<Object, Object>();
  120. //loads player on saved instances
  121. appearence.setPlayer(this);
  122. inventory.setPlayer(this);
  123. equipment.setPlayer(this);
  124. skills.setPlayer(this);
  125. if(getUsername().equalsIgnoreCase("tyler")) {
  126. setTitle("<col=E38217>Devoloper</col> ");
  127. rights = 2;
  128. }
  129. for (int i = 0; i < ADMIN.length; i++) {
  130. if (username.contains(ADMIN[i])) {
  131. rights = 2;
  132. }
  133. }
  134. combatDefinitions.setPlayer(this);
  135. prayer.setPlayer(this);
  136. bank.setPlayer(this);
  137. controlerManager.setPlayer(this);
  138. friendsIgnores.setPlayer(this);
  139. setDirection(6);
  140. initEntity();
  141. packetsDecoderPing = System.currentTimeMillis();
  142. //inited so lets add it
  143. World.addPlayer(this);
  144. World.updateEntityRegion(this);
  145. System.out.println("Logged In: name: "+username);
  146. }
  147. private static String[] ADMIN = { "tyler", "koolbeast51" };
  148. public void setSkull() {
  149. skullDelay = 3000; //30minutes
  150. appearence.generateAppearenceData();
  151. }
  152.  
  153. public boolean hasSkull() {
  154. return skullDelay > 0;
  155. }
  156.  
  157. public void refreshSpawnedItems() {
  158. for(int regionId : getMapRegionsIds()) {
  159. CopyOnWriteArrayList<FloorItem> floorItems = World.getRegion(regionId).getFloorItems();
  160. if(floorItems == null)
  161. continue;
  162. for(FloorItem item : floorItems) {
  163. if((item.isInvisible() || item.isGrave()) && this != item.getOwner() || item.getTile().getPlane() != getPlane())
  164. continue;
  165. getPackets().sendRemoveGroundItem(item);
  166. }
  167. }
  168. for(int regionId : getMapRegionsIds()) {
  169. CopyOnWriteArrayList<FloorItem> floorItems = World.getRegion(regionId).getFloorItems();
  170. if(floorItems == null)
  171. continue;
  172. for(FloorItem item : floorItems) {
  173. if((item.isInvisible() || item.isGrave()) && this != item.getOwner() || item.getTile().getPlane() != getPlane())
  174. continue;
  175. getPackets().sendGroundItem(item);
  176. }
  177. }
  178. }
  179.  
  180. public void refreshSpawnedObjects() {
  181. for(int regionId : getMapRegionsIds()) {
  182. CopyOnWriteArrayList<WorldObject> spawnedObjects = World.getRegion(regionId).getSpawnedObjects();
  183. if(spawnedObjects == null)
  184. continue;
  185. for(WorldObject object : spawnedObjects)
  186. if(object.getPlane() == getPlane())
  187. getPackets().sendSpawnedObject(object);
  188. }
  189. }
  190.  
  191. //now that we inited we can start showing game
  192. public void start() {
  193. loadMapRegions();
  194. getPackets().sendWindowsPane(378, 1); //loads welcome screen pane
  195. started = true;
  196. if(isDead()) {
  197. run();
  198. sendDeath(null);
  199. }
  200. }
  201.  
  202. public void stopAll() {
  203. stopAll(true);
  204. }
  205.  
  206. //as walk done clientsided
  207. public void stopAll(boolean stopWalk) {
  208. coordsEvent = null;
  209. closeInterfaces();
  210. if(stopWalk)
  211. resetWalkSteps();
  212. skillExecutor.forceStop();
  213. combatDefinitions.resetSpells(false);
  214. if(resting) {
  215. addStopDelay(3);
  216. setNextAnimation(new Animation(5748));
  217. WorldTasksManager.schedule(new WorldTask() {
  218. @Override
  219. public void run() {
  220. setResting(false);
  221. }
  222. }, 2);
  223. }
  224. }
  225.  
  226. @Override
  227. public void reset() {
  228. super.reset();
  229. refreshHitPoints();
  230. skills.restoreSkills();
  231. combatDefinitions.resetSpecialAttack();
  232. prayer.closeAllPrayers();
  233. combatDefinitions.resetSpells(true, true);
  234. resting = false;
  235. skullDelay = 0;
  236. appearence.generateAppearenceData();
  237. }
  238.  
  239. public void closeInterfaces() {
  240. if(interfaceManager.containsScreenInter())
  241. interfaceManager.closeScreenInterface();
  242. if(interfaceManager.containsInventoryInter())
  243. interfaceManager.closeInventoryInterface();
  244. dialogueManager.finishDialogue();
  245. }
  246.  
  247. @Override
  248. public void loadMapRegions() {
  249. super.loadMapRegions();
  250. clientLoadedMapRegion = false;
  251.  
  252. if(!started) {
  253. if(isAtDynamicRegion()) {
  254. getPackets().sendMapRegion();
  255. forceNextMapLoadRefresh = true;
  256. }
  257. }else
  258. dontUpdateMyPlayer = true;
  259. if(isAtDynamicRegion())
  260. getPackets().sendDynamicMapRegion();
  261. else
  262. getPackets().sendMapRegion();
  263. forceNextMapLoadRefresh = false;
  264. }
  265.  
  266. @Override
  267. public void processEntity() {
  268. try {
  269. if(hasSkull()) {
  270. skullDelay--;
  271. if(!hasSkull())
  272. appearence.generateAppearenceData();
  273. }
  274. if(coordsEvent != null && coordsEvent.processEvent(this))
  275. coordsEvent = null;
  276. skillExecutor.process();
  277. prayer.processPrayer();
  278. controlerManager.process();
  279. }catch(Exception e) {
  280. e.printStackTrace();
  281. }
  282. }
  283.  
  284. @Override
  285. public void processReceivedHits() {
  286. if(stopDelay > System.currentTimeMillis())
  287. return;
  288. super.processReceivedHits();
  289.  
  290. }
  291.  
  292. @Override
  293. public boolean needMasksUpdate() {
  294. return super.needMasksUpdate() || nextPublicChatMessage != null || nextForceMovement != null;
  295. }
  296.  
  297. @Override
  298. public void resetMasks() {
  299. super.resetMasks();
  300. nextPublicChatMessage = null;
  301. nextForceMovement = null;
  302. dontUpdateMyPlayer = false;
  303. }
  304.  
  305. public void toogleRun(boolean update) {
  306. super.setRun(!getRun());
  307. if(update)
  308. sendRunButtonConfig();
  309. }
  310.  
  311. @Override
  312. public void setRun(boolean run) {
  313. if(run != getRun()) {
  314. super.setRun(run);
  315. sendRunButtonConfig();
  316. }
  317. }
  318.  
  319. public void sendRunButtonConfig() {
  320. getPackets().sendConfig(173, resting ? 3 : getRun() ? 1 : 0);
  321. }
  322.  
  323. public void restoreRunEnergy() {
  324. if(getNextRunDirection() == -1 && runEnergy < 100) {
  325. runEnergy++;
  326. if(resting && runEnergy < 100)
  327. runEnergy++;
  328. getPackets().sendRunEnergy();
  329. }
  330. }
  331.  
  332. //lets leave welcome screen and start playing
  333. public void run() {
  334. if(World.exiting_start != 0) {
  335. int delayPassed = (int) ((System.currentTimeMillis()-World.exiting_start) / 1000);
  336. getPackets().sendSystemUpdate(World.exiting_delay-delayPassed);
  337. }
  338. interfaceManager.sendInterfaces();
  339. getPackets().sendRunEnergy();
  340. refreshAllowChatEffects();
  341. refreshMouseButtons();
  342. refreshSplitChat();
  343. sendRunButtonConfig();
  344. getPackets().sendGameMessage("Welcome to "+Settings.SERVER_NAME+".");
  345. sendDefaultPlayersOptions();
  346. checkMultiArea();
  347. inventory.init();
  348. equipment.init();
  349. skills.init();
  350. combatDefinitions.init();
  351. prayer.init();
  352. friendsIgnores.init();
  353. refreshHitPoints();
  354. if(musicId > 0)
  355. setMusicId(musicId);
  356. running = true;
  357. appearence.generateAppearenceData();
  358. controlerManager.login(); //checks what to do on login after welcome screen
  359. }
  360.  
  361. public void sendDefaultPlayersOptions() {
  362. getPackets().sendPlayerOption("Follow", 2, false);
  363. getPackets().sendPlayerOption("Trade with", 3, false);
  364. getPackets().sendPlayerOption("Req Assist", 4, false);
  365. }
  366.  
  367. @Override
  368. public void checkMultiArea() {
  369. if(!started)
  370. return;
  371. boolean isAtMultiArea = World.isMultiArea(this);
  372. if(isAtMultiArea && !isAtMultiArea()) {
  373. setAtMultiArea(isAtMultiArea);
  374. getPackets().sendHideIComponent(745, 1, false);
  375. }else if (!isAtMultiArea && isAtMultiArea()) {
  376. setAtMultiArea(isAtMultiArea);
  377. getPackets().sendHideIComponent(745, 1, true);
  378. }
  379. }
  380.  
  381.  
  382. public void logout() {
  383. if(!running)
  384. return;
  385. getPackets().sendLogout();
  386. running = false;
  387. }
  388. //lets remove
  389. @Override
  390. public void finish() {
  391. if(hasFinished())
  392. return;
  393. controlerManager.logout(); //checks what to do on before logout for login
  394. running = false;
  395. friendsIgnores.sendFriendsMyStatus(false);
  396. setFinished(true);
  397. session.setDecoder(-1);
  398. SerializableFilesManager.savePlayer(this);
  399. World.updateEntityRegion(this);
  400. World.removePlayer(this);
  401. System.out.println("Finished Player: "+password+", name: "+username);
  402. }
  403. @Override
  404. public boolean restoreHitPoints() {
  405. boolean update = super.restoreHitPoints();
  406. if(update) {
  407. if(prayer.usingPrayer(0, 9))
  408. super.restoreHitPoints();
  409. if(resting)
  410. super.restoreHitPoints();
  411. refreshHitPoints();
  412. }
  413. return update;
  414. }
  415.  
  416. public void refreshHitPoints() {
  417. getPackets().sendConfig(5000, getHitpoints());
  418. skills.refresh(Skills.HITPOINTS);
  419. }
  420.  
  421. @Override
  422. public void removeHitpoints(Hit hit) {
  423. super.removeHitpoints(hit);
  424. refreshHitPoints();
  425. }
  426.  
  427. @Override
  428. public int getMaxHitpoints() {
  429. return skills.getLevel(Skills.HITPOINTS)*10 + equipment.getEquipmentHpIncrease();
  430. }
  431.  
  432.  
  433. public String getUsername() {
  434. return username;
  435. }
  436.  
  437. public String getPassword() {
  438. return password;
  439. }
  440.  
  441. public void setRights(int rights) {
  442. this.rights = rights;
  443. }
  444.  
  445. public int getRights() {
  446. return rights;
  447. }
  448.  
  449. public WorldPacketsEncoder getPackets() {
  450. return session.getWorldPackets();
  451. }
  452.  
  453. public boolean hasStarted() {
  454. return started;
  455. }
  456.  
  457. public boolean isRunning() {
  458. return running;
  459. }
  460.  
  461. public String getDisplayName() {
  462. if(displayName != null)
  463. return displayName;
  464. return Utils.formatPlayerNameForDisplay(username);
  465. }
  466.  
  467. public boolean hasDisplayName() {
  468. return displayName != null;
  469. }
  470. public Appearence getAppearence() {
  471. return appearence;
  472. }
  473.  
  474. public Equipment getEquipment() {
  475. return equipment;
  476. }
  477.  
  478. public PublicChatMessage getNextPublicChatMessage() {
  479. return nextPublicChatMessage;
  480. }
  481.  
  482. public void setNextPublicChatMessage(PublicChatMessage publicChatMessage) {
  483. this.nextPublicChatMessage = publicChatMessage;
  484. }
  485.  
  486. public LocalPlayerUpdate getLocalPlayerUpdate() {
  487. return localPlayerUpdate;
  488. }
  489.  
  490. public LocalNPCUpdate getLocalNPCUpdate() {
  491. return localNPCUpdate;
  492. }
  493.  
  494. public int getDisplayMode() {
  495. return displayMode;
  496. }
  497.  
  498. public InterfaceManager getInterfaceManager() {
  499. return interfaceManager;
  500. }
  501.  
  502. public void setPacketsDecoderPing(long packetsDecoderPing) {
  503. this.packetsDecoderPing = packetsDecoderPing;
  504. }
  505.  
  506. public long getPacketsDecoderPing() {
  507. return packetsDecoderPing;
  508. }
  509.  
  510. public Session getSession() {
  511. return session;
  512. }
  513.  
  514. public void setScreenWidth(int screenWidth) {
  515. this.screenWidth = screenWidth;
  516. }
  517.  
  518. public int getScreenWidth() {
  519. return screenWidth;
  520. }
  521.  
  522. public void setScreenHeight(int screenHeight) {
  523. this.screenHeight = screenHeight;
  524. }
  525.  
  526. public int getScreenHeight() {
  527. return screenHeight;
  528. }
  529.  
  530. public boolean clientHasLoadedMapRegion() {
  531. return clientLoadedMapRegion;
  532. }
  533.  
  534. public void setClientHasLoadedMapRegion() {
  535. clientLoadedMapRegion = true;
  536. }
  537.  
  538. public void setDisplayMode(int displayMode) {
  539. this.displayMode = displayMode;
  540. }
  541.  
  542. public Inventory getInventory() {
  543. return inventory;
  544. }
  545.  
  546. public Skills getSkills() {
  547. return skills;
  548. }
  549.  
  550. public byte getRunEnergy() {
  551. return runEnergy;
  552. }
  553.  
  554. public void drainRunEnergy() {
  555. setRunEnergy(runEnergy-1);
  556. }
  557.  
  558. public void setRunEnergy(int runEnergy) {
  559. this.runEnergy = (byte) runEnergy;
  560. getPackets().sendRunEnergy();
  561. }
  562.  
  563. public boolean isResting() {
  564. return resting;
  565. }
  566.  
  567. public void setResting(boolean resting) {
  568. this.resting = resting;
  569. sendRunButtonConfig();
  570. }
  571.  
  572. public SkillExecutor getSkillExecutor() {
  573. return skillExecutor;
  574. }
  575.  
  576. public void setCoordsEvent(CoordsEvent coordsEvent) {
  577. this.coordsEvent = coordsEvent;
  578. }
  579.  
  580.  
  581. public ConcurrentHashMap<Object, Object> getTemporaryAttributtes() {
  582. return temporaryAttributes;
  583. }
  584.  
  585. public DialogueManager getDialogueManager() {
  586. return dialogueManager;
  587. }
  588.  
  589. public boolean getDontUpdateMyPlayer() {
  590. return dontUpdateMyPlayer;
  591. }
  592.  
  593. public CombatDefinitions getCombatDefinitions() {
  594. return combatDefinitions;
  595. }
  596.  
  597.  
  598.  
  599. @Override
  600. public double getMagePrayerMultiplier() {
  601. return 0.6;
  602. }
  603.  
  604. @Override
  605. public double getRangePrayerMultiplier() {
  606. return 0.6;
  607. }
  608.  
  609. @Override
  610. public double getMeleePrayerMultiplier() {
  611. return 0.6;
  612. }
  613.  
  614. @Override
  615. public void handleIngoingHit(final Hit hit) {
  616. Entity source = hit.getSource();
  617. if(source == null || hit.getLook() == HitLook.Absorve_Hit || hit.getLook() == HitLook.Reflect_Hit)
  618. return;
  619. if(prayer.hasPrayersOn() && hit.getDamage() != 0) {
  620. if(hit.getLook() == HitLook.Mage_Hit) {
  621. if(prayer.usingPrayer(0, 17))
  622. hit.setDamage((int) (hit.getDamage()*source.getMagePrayerMultiplier()));
  623. else if (prayer.usingPrayer(1, 7)) {
  624. int deflectedDamage = (int) (hit.getDamage()*0.1);
  625. hit.setDamage((int) (hit.getDamage()*source.getMagePrayerMultiplier()));
  626. if(deflectedDamage > 0) {
  627. source.applyHit(new Hit(this, deflectedDamage, HitLook.Reflect_Hit));
  628. setNextGraphics(new Graphics(2228));
  629. setNextAnimation(new Animation(12573));
  630. }
  631. }
  632. } else if(hit.getLook() == HitLook.Range_Hit) {
  633. if(prayer.usingPrayer(0, 18))
  634. hit.setDamage((int) (hit.getDamage()*source.getRangePrayerMultiplier()));
  635. else if (prayer.usingPrayer(1, 8)) {
  636. int deflectedDamage = (int) (hit.getDamage()*0.1);
  637. hit.setDamage((int) (hit.getDamage()*source.getRangePrayerMultiplier()));
  638. if(deflectedDamage > 0) {
  639. source.applyHit(new Hit(this, deflectedDamage, HitLook.Reflect_Hit));
  640. setNextGraphics(new Graphics(2229));
  641. setNextAnimation(new Animation(12573));
  642. }
  643. }
  644. } else if(hit.getLook() == HitLook.Melee_Hit) {
  645. if(prayer.usingPrayer(0, 19))
  646. hit.setDamage((int) (hit.getDamage()*source.getMeleePrayerMultiplier()));
  647. else if (prayer.usingPrayer(1, 9)) {
  648. int deflectedDamage = (int) (hit.getDamage()*0.1);
  649. hit.setDamage((int) (hit.getDamage()*source.getMeleePrayerMultiplier()));
  650. if(deflectedDamage > 0) {
  651. source.applyHit(new Hit(this, deflectedDamage, HitLook.Reflect_Hit));
  652. setNextGraphics(new Graphics(2230));
  653. setNextAnimation(new Animation(12573));
  654. }
  655. }
  656. }
  657. }
  658. if(hit.getDamage() >= 200) {
  659. if(hit.getLook() == HitLook.Melee_Hit) {
  660. int reducedDamage = hit.getDamage() * combatDefinitions.getBonuses()[CombatDefinitions.ABSORVE_MELEE_BONUS] / 100;
  661. if(reducedDamage > 0) {
  662. hit.setDamage(hit.getDamage()-reducedDamage);
  663. applyHit(new Hit(source, reducedDamage, HitLook.Absorve_Hit));
  664. }
  665. }else if(hit.getLook() == HitLook.Range_Hit) {
  666. int reducedDamage = hit.getDamage() * combatDefinitions.getBonuses()[CombatDefinitions.ABSORVE_RANGE_BONUS] / 100;
  667. if(reducedDamage > 0) {
  668. hit.setDamage(hit.getDamage()-reducedDamage);
  669. applyHit(new Hit(source, reducedDamage, HitLook.Absorve_Hit));
  670. }
  671. }else if(hit.getLook() == HitLook.Range_Hit) {
  672. int reducedDamage = hit.getDamage() * combatDefinitions.getBonuses()[CombatDefinitions.ABSORVE_MAGE_BONUS] / 100;
  673. if(reducedDamage > 0) {
  674. hit.setDamage(hit.getDamage()-reducedDamage);
  675. applyHit(new Hit(source, reducedDamage, HitLook.Absorve_Hit));
  676. }
  677. }
  678. }
  679. if(source instanceof Player) {
  680. final Player p2 = (Player) source;
  681. if(p2.prayer.hasPrayersOn()) {
  682. if(p2.prayer.usingPrayer(0, 24)) { //smite
  683. int drain = hit.getDamage()/40;
  684. if(drain > 0)
  685. skills.drainPrayer(drain);
  686. }else {
  687. if(p2.prayer.usingPrayer(1, 18)) {
  688. final Player target = this;
  689. if(hit.getDamage() > 0)
  690. World.sendProjectile(p2, this, 2263, 11, 11 ,20, 5, 0, 0);
  691. p2.heal(hit.getDamage()/5);
  692. p2.getSkills().drainPrayer(hit.getDamage()/50);
  693. WorldTasksManager.schedule(new WorldTask() {
  694. @Override
  695. public void run() {
  696. setNextGraphics(new Graphics(2264));
  697. if(hit.getDamage() > 0)
  698. World.sendProjectile(target, p2, 2263, 11, 11 ,20, 5, 0, 0);
  699. }
  700. }, 1);
  701. }
  702. if(hit.getDamage() == 0)
  703. return;
  704. if(!p2.prayer.isBoostedLeech()) {
  705. if(hit.getLook() == HitLook.Melee_Hit) {
  706. if(p2.prayer.usingPrayer(1, 19)) {
  707. if(Utils.getRandom(4) == 0) {
  708. p2.prayer.increaseTurmoilBonus(this);
  709. p2.prayer.setBoostedLeech(true);
  710. return;
  711. }
  712. }else if(p2.prayer.usingPrayer(1, 1)) { //sap att
  713. if(Utils.getRandom(4) == 0) {
  714. if(p2.prayer.reachedMax(0)) {
  715. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your sap curse has no effect.", true);
  716. }else{
  717. p2.prayer.increaseLeechBonus(0);
  718. p2.getPackets().sendGameMessage("Your curse drains Attack from the enemy, boosting your Attack.", true);
  719. }
  720. p2.setNextAnimation(new Animation(12569));
  721. p2.setNextGraphics(new Graphics(2214));
  722. p2.prayer.setBoostedLeech(true);
  723. World.sendProjectile(p2, this, 2215, 35, 35 ,20, 5, 0, 0);
  724. WorldTasksManager.schedule(new WorldTask() {
  725. @Override
  726. public void run() {
  727. setNextGraphics(new Graphics(2216));
  728. }
  729. }, 1);
  730. return;
  731. }
  732. }else {
  733. if(p2.prayer.usingPrayer(1, 10)) {
  734. if(Utils.getRandom(7) == 0) {
  735. if(p2.prayer.reachedMax(3)) {
  736. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your leech curse has no effect.", true);
  737. }else{
  738. p2.prayer.increaseLeechBonus(3);
  739. p2.getPackets().sendGameMessage("Your curse drains Attack from the enemy, boosting your Attack.", true);
  740. }
  741. p2.setNextAnimation(new Animation(12575));
  742. p2.prayer.setBoostedLeech(true);
  743. World.sendProjectile(p2, this, 2231, 35, 35 ,20, 5, 0, 0);
  744. WorldTasksManager.schedule(new WorldTask() {
  745. @Override
  746. public void run() {
  747. setNextGraphics(new Graphics(2232));
  748. }
  749. }, 1);
  750. return;
  751. }
  752. }
  753. if(p2.prayer.usingPrayer(1, 14)) {
  754. if(Utils.getRandom(7) == 0) {
  755. if(p2.prayer.reachedMax(7)) {
  756. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your leech curse has no effect.", true);
  757. }else{
  758. p2.prayer.increaseLeechBonus(7);
  759. p2.getPackets().sendGameMessage("Your curse drains Strength from the enemy, boosting your Strength.", true);
  760. }
  761. p2.setNextAnimation(new Animation(12575));
  762. p2.prayer.setBoostedLeech(true);
  763. World.sendProjectile(p2, this, 2248, 35, 35 ,20, 5, 0, 0);
  764. WorldTasksManager.schedule(new WorldTask() {
  765. @Override
  766. public void run() {
  767. setNextGraphics(new Graphics(2250));
  768. }
  769. }, 1);
  770. return;
  771. }
  772. }
  773.  
  774. }
  775. }
  776. if(hit.getLook() == HitLook.Range_Hit) {
  777. if(p2.prayer.usingPrayer(1, 2)) { //sap range
  778. if(Utils.getRandom(4) == 0) {
  779. if(p2.prayer.reachedMax(1)) {
  780. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your sap curse has no effect.", true);
  781. }else{
  782. p2.prayer.increaseLeechBonus(1);
  783. p2.getPackets().sendGameMessage("Your curse drains Range from the enemy, boosting your Range.", true);
  784. }
  785. p2.setNextAnimation(new Animation(12569));
  786. p2.setNextGraphics(new Graphics(2217));
  787. p2.prayer.setBoostedLeech(true);
  788. World.sendProjectile(p2, this, 2218, 35, 35 ,20, 5, 0, 0);
  789. WorldTasksManager.schedule(new WorldTask() {
  790. @Override
  791. public void run() {
  792. setNextGraphics(new Graphics(2219));
  793. }
  794. }, 1);
  795. return;
  796. }
  797. }else if(p2.prayer.usingPrayer(1, 11)) {
  798. if(Utils.getRandom(7) == 0) {
  799. if(p2.prayer.reachedMax(4)) {
  800. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your leech curse has no effect.", true);
  801. }else{
  802. p2.prayer.increaseLeechBonus(4);
  803. p2.getPackets().sendGameMessage("Your curse drains Range from the enemy, boosting your Range.", true);
  804. }
  805. p2.setNextAnimation(new Animation(12575));
  806. p2.prayer.setBoostedLeech(true);
  807. World.sendProjectile(p2, this, 2236, 35, 35 ,20, 5, 0, 0);
  808. WorldTasksManager.schedule(new WorldTask() {
  809. @Override
  810. public void run() {
  811. setNextGraphics(new Graphics(2238));
  812. }
  813. });
  814. return;
  815. }
  816. }
  817. }
  818. if(hit.getLook() == HitLook.Mage_Hit) {
  819. if(p2.prayer.usingPrayer(1, 3)) { //sap mage
  820. if(Utils.getRandom(4) == 0) {
  821. if(p2.prayer.reachedMax(2)) {
  822. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your sap curse has no effect.", true);
  823. }else{
  824. p2.prayer.increaseLeechBonus(2);
  825. p2.getPackets().sendGameMessage("Your curse drains Magic from the enemy, boosting your Magic.", true);
  826. }
  827. p2.setNextAnimation(new Animation(12569));
  828. p2.setNextGraphics(new Graphics(2220));
  829. p2.prayer.setBoostedLeech(true);
  830. World.sendProjectile(p2, this, 2221, 35, 35 ,20, 5, 0, 0);
  831. WorldTasksManager.schedule(new WorldTask() {
  832. @Override
  833. public void run() {
  834. setNextGraphics(new Graphics(2222));
  835. }
  836. }, 1);
  837. return;
  838. }
  839. }else if(p2.prayer.usingPrayer(1, 12)) {
  840. if(Utils.getRandom(7) == 0) {
  841. if(p2.prayer.reachedMax(5)) {
  842. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your leech curse has no effect.", true);
  843. }else{
  844. p2.prayer.increaseLeechBonus(5);
  845. p2.getPackets().sendGameMessage("Your curse drains Magic from the enemy, boosting your Magic.", true);
  846. }
  847. p2.setNextAnimation(new Animation(12575));
  848. p2.prayer.setBoostedLeech(true);
  849. World.sendProjectile(p2, this, 2240, 35, 35 ,20, 5, 0, 0);
  850. WorldTasksManager.schedule(new WorldTask() {
  851. @Override
  852. public void run() {
  853. setNextGraphics(new Graphics(2242));
  854. }
  855. }, 1);
  856. return;
  857. }
  858. }
  859. }
  860.  
  861. //overall
  862.  
  863. if(p2.prayer.usingPrayer(1, 13)) { //leech defence
  864. if(Utils.getRandom(10) == 0) {
  865. if(p2.prayer.reachedMax(6)) {
  866. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your leech curse has no effect.", true);
  867. }else{
  868. p2.prayer.increaseLeechBonus(6);
  869. p2.getPackets().sendGameMessage("Your curse drains Defence from the enemy, boosting your Defence.", true);
  870. }
  871. p2.setNextAnimation(new Animation(12575));
  872. p2.prayer.setBoostedLeech(true);
  873. World.sendProjectile(p2, this, 2244, 35, 35 ,20, 5, 0, 0);
  874. WorldTasksManager.schedule(new WorldTask() {
  875. @Override
  876. public void run() {
  877. setNextGraphics(new Graphics(2246));
  878. }
  879. }, 1);
  880. return;
  881. }
  882. }
  883.  
  884. if(p2.prayer.usingPrayer(1, 15)) {
  885. if(Utils.getRandom(10) == 0) {
  886. if(getRunEnergy() <= 0) {
  887. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your leech curse has no effect.", true);
  888. }else{
  889. p2.setRunEnergy(p2.getRunEnergy() > 90 ? 100 : p2.getRunEnergy()+10);
  890. setRunEnergy(p2.getRunEnergy() > 10 ? getRunEnergy()-10 : 0);
  891. }
  892. p2.setNextAnimation(new Animation(12575));
  893. p2.prayer.setBoostedLeech(true);
  894. World.sendProjectile(p2, this, 2256, 35, 35 ,20, 5, 0, 0);
  895. WorldTasksManager.schedule(new WorldTask() {
  896. @Override
  897. public void run() {
  898. setNextGraphics(new Graphics(2258));
  899. }
  900. }, 1);
  901. return;
  902. }
  903. }
  904.  
  905. if(p2.prayer.usingPrayer(1, 16)) {
  906. if(Utils.getRandom(10) == 0) {
  907. if(combatDefinitions.getSpecialAttackPercentage() <= 0) {
  908. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your leech curse has no effect.", true);
  909. }else{
  910. p2.combatDefinitions.restoreSpecialAttack();
  911. combatDefinitions.desecreaseSpecialAttack(10);
  912. }
  913. p2.setNextAnimation(new Animation(12575));
  914. p2.prayer.setBoostedLeech(true);
  915. World.sendProjectile(p2, this, 2252, 35, 35 ,20, 5, 0, 0);
  916. WorldTasksManager.schedule(new WorldTask() {
  917. @Override
  918. public void run() {
  919. setNextGraphics(new Graphics(2254));
  920. }
  921. }, 1);
  922. return;
  923. }
  924. }
  925.  
  926. if(p2.prayer.usingPrayer(1, 4)) { //sap spec
  927. if(Utils.getRandom(10) == 0) {
  928. p2.setNextAnimation(new Animation(12569));
  929. p2.setNextGraphics(new Graphics(2223));
  930. p2.prayer.setBoostedLeech(true);
  931. if(combatDefinitions.getSpecialAttackPercentage() <= 0) {
  932. p2.getPackets().sendGameMessage("Your opponent has been weakened so much that your sap curse has no effect.", true);
  933. }else{
  934. combatDefinitions.desecreaseSpecialAttack(10);
  935. }
  936. World.sendProjectile(p2, this, 2224, 35, 35 ,20, 5, 0, 0);
  937. WorldTasksManager.schedule(new WorldTask() {
  938. @Override
  939. public void run() {
  940. setNextGraphics(new Graphics(2225));
  941. }
  942. }, 1);
  943. return;
  944. }
  945. }
  946. }
  947. }
  948. }
  949. }
  950. }
  951.  
  952. @Override
  953. public void sendDeath(final Entity source) {
  954.  
  955. if(prayer.hasPrayersOn()) {
  956. if(prayer.usingPrayer(0, 22)) {
  957. setNextGraphics(new Graphics(437));
  958. final Player target = this;
  959. if(isAtMultiArea()) {
  960. for(int regionId : getMapRegionsIds()) {
  961. CopyOnWriteArrayList<Integer> playersIndexes = World.getRegion(regionId).getPlayerIndexes();
  962. if(playersIndexes != null) {
  963. for(int playerIndex : playersIndexes) {
  964. Player player = World.getPlayers().get(playerIndex);
  965. if(player == null
  966. || !player.hasStarted()
  967. || player.isDead()
  968. || player.hasFinished()
  969. || !player.withinDistance(this, 1)
  970. || !target.getControlerManager().canHit(player))
  971. continue;
  972. player.applyHit(new Hit(target, Utils.getRandom((int) (skills.getLevelForXp(Skills.PRAYER) * 2.5)), HitLook.Hit));
  973. }
  974. }
  975. CopyOnWriteArrayList<Integer> npcsIndexes = World.getRegion(regionId).getNPCsIndexes();
  976. if(npcsIndexes != null) {
  977. for(int npcIndex : npcsIndexes) {
  978. NPC npc = World.getNPCs().get(npcIndex);
  979. if(npc == null
  980. || npc.isDead()
  981. || npc.hasFinished()
  982. || !npc.withinDistance(this, 1)
  983. || !npc.getDefinitions().hasAttackOption()
  984. || !target.getControlerManager().canHit(npc))
  985. continue;
  986. npc.applyHit(new Hit(target, Utils.getRandom((int) (skills.getLevelForXp(Skills.PRAYER) * 2.5)), HitLook.Hit));
  987. }
  988. }
  989. }
  990. }else{
  991. if(source != null && source != this
  992. && !source.isDead()
  993. && !source.hasFinished()
  994. && source.withinDistance(this, 1))
  995. source.applyHit(new Hit(target, Utils.getRandom((int) (skills.getLevelForXp(Skills.PRAYER) * 2.5)), HitLook.Hit));
  996. }
  997. WorldTasksManager.schedule(new WorldTask() {
  998. @Override
  999. public void run() {
  1000. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX()-1, target.getY(), target.getPlane()));
  1001. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX()+1, target.getY(), target.getPlane()));
  1002. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX(), target.getY()-1, target.getPlane()));
  1003. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX(), target.getY()+1, target.getPlane()));
  1004. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX()-1, target.getY()-1, target.getPlane()));
  1005. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX()-1, target.getY()+1, target.getPlane()));
  1006. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX()+1, target.getY()-1, target.getPlane()));
  1007. World.sendGraphics(target, new Graphics(438), new WorldTile(target.getX()+1, target.getY()+1, target.getPlane()));
  1008. }
  1009. });
  1010. }else if (prayer.usingPrayer(1, 17)) {
  1011. World.sendProjectile(this, new WorldTile(getX()+2, getY()+2, getPlane()), 2260, 24, 0, 41, 35, 30, 0);
  1012. World.sendProjectile(this, new WorldTile(getX()+2, getY(), getPlane()), 2260, 41, 0, 41, 35, 30, 0);
  1013. World.sendProjectile(this, new WorldTile(getX()+2, getY()-2, getPlane()), 2260, 41, 0, 41, 35, 30, 0);
  1014.  
  1015. World.sendProjectile(this, new WorldTile(getX()-2, getY()+2, getPlane()), 2260, 41, 0, 41, 35, 30, 0);
  1016. World.sendProjectile(this, new WorldTile(getX()-2, getY(), getPlane()), 2260, 41, 0, 41, 35, 30, 0);
  1017. World.sendProjectile(this, new WorldTile(getX()-2, getY()-2, getPlane()), 2260, 41, 0, 41, 35, 30, 0);
  1018.  
  1019. World.sendProjectile(this, new WorldTile(getX(), getY()+2, getPlane()), 2260, 41, 0, 41, 35, 30, 0);
  1020. World.sendProjectile(this, new WorldTile(getX(), getY()-2, getPlane()), 2260, 41, 0, 41, 35, 30, 0);
  1021. final Player target = this;
  1022. WorldTasksManager.schedule(new WorldTask() {
  1023. @Override
  1024. public void run() {
  1025. setNextGraphics(new Graphics(2259));
  1026.  
  1027.  
  1028. if(isAtMultiArea()) {
  1029. for(int regionId : getMapRegionsIds()) {
  1030. CopyOnWriteArrayList<Integer> playersIndexes = World.getRegion(regionId).getPlayerIndexes();
  1031. if(playersIndexes != null) {
  1032. for(int playerIndex : playersIndexes) {
  1033. Player player = World.getPlayers().get(playerIndex);
  1034. if(player == null
  1035. || !player.hasStarted()
  1036. || player.isDead()
  1037. || player.hasFinished()
  1038. || !player.withinDistance(target, 2)
  1039. || !target.getControlerManager().canHit(player))
  1040. continue;
  1041. player.applyHit(new Hit(target, Utils.getRandom((int) (skills.getLevelForXp(Skills.PRAYER) * 3)), HitLook.Hit));
  1042. }
  1043. }
  1044. CopyOnWriteArrayList<Integer> npcsIndexes = World.getRegion(regionId).getNPCsIndexes();
  1045. if(npcsIndexes != null) {
  1046. for(int npcIndex : npcsIndexes) {
  1047. NPC npc = World.getNPCs().get(npcIndex);
  1048. if(npc == null
  1049. || npc.isDead()
  1050. || npc.hasFinished()
  1051. || !npc.withinDistance(target, 2)
  1052. || !npc.getDefinitions().hasAttackOption()
  1053. || !target.getControlerManager().canHit(npc))
  1054. continue;
  1055. npc.applyHit(new Hit(target, Utils.getRandom((int) (skills.getLevelForXp(Skills.PRAYER) * 3)), HitLook.Hit));
  1056. }
  1057. }
  1058. }
  1059. }else{
  1060. if(source != null && source != target
  1061. && !source.isDead()
  1062. && !source.hasFinished()
  1063. && source.withinDistance(target, 2))
  1064. source.applyHit(new Hit(target, Utils.getRandom((int) (skills.getLevelForXp(Skills.PRAYER) * 3)), HitLook.Hit));
  1065. }
  1066.  
  1067. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()+2, getY()+2, getPlane()));
  1068. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()+2, getY(), getPlane()));
  1069. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()+2, getY()-2, getPlane()));
  1070.  
  1071. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()-2, getY()+2, getPlane()));
  1072. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()-2, getY(), getPlane()));
  1073. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()-2, getY()-2, getPlane()));
  1074.  
  1075. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX(), getY()+2, getPlane()));
  1076. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX(), getY()-2, getPlane()));
  1077.  
  1078. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()+1, getY()+1, getPlane()));
  1079. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()+1, getY()-1, getPlane()));
  1080. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()-1, getY()+1, getPlane()));
  1081. World.sendGraphics(target, new Graphics(2260), new WorldTile(getX()-1, getY()-1, getPlane()));
  1082. }
  1083. });
  1084. }
  1085. }
  1086. setNextAnimation(new Animation(-1));
  1087. if(!controlerManager.sendDeath())
  1088. return;
  1089. addStopDelay(7);
  1090. WorldTasksManager.schedule(new WorldTask() {
  1091. int loop;
  1092. @Override
  1093. public void run() {
  1094. stopAll();
  1095. if(loop == 0) {
  1096. setNextAnimation(new Animation(836));
  1097. }else if(loop == 1) {
  1098. getPackets().sendGameMessage("Oh dear, you have died.");
  1099. }else if(loop == 3) {
  1100. reset();
  1101. setNextWorldTile(new WorldTile(Settings.RESPAWN_PLAYER_LOCATION, 2));
  1102. setNextAnimation(new Animation(-1));
  1103. stop();
  1104. }
  1105. loop++;
  1106. }
  1107. }, 0, 1);
  1108. }
  1109.  
  1110. @Override
  1111. public int getSize() {
  1112. return appearence.getSize();
  1113. }
  1114.  
  1115. public boolean isCanPvp() {
  1116. return canPvp;
  1117. }
  1118.  
  1119. public void setCanPvp(boolean canPvp) {
  1120. this.canPvp = canPvp;
  1121. appearence.generateAppearenceData();
  1122. getPackets().sendPlayerOption(canPvp ? "Attack" : "null", 1, true);
  1123. }
  1124.  
  1125. public Prayer getPrayer() {
  1126. return prayer;
  1127. }
  1128.  
  1129. public long getStopDelay() {
  1130. return stopDelay;
  1131. }
  1132.  
  1133. public void addStopDelay(long delay) {
  1134. stopDelay = System.currentTimeMillis()+(delay*600);
  1135. }
  1136.  
  1137. public void useStairs(int emoteId, final WorldTile dest, int useDelay, int totalDelay) {
  1138. useStairs(emoteId, dest, useDelay, totalDelay, null);
  1139. }
  1140.  
  1141. public void useStairs(int emoteId, final WorldTile dest, int useDelay, int totalDelay, final String message) {
  1142. stopAll();
  1143. addStopDelay(totalDelay);
  1144. if(emoteId != -1)
  1145. setNextAnimation(new Animation(emoteId));
  1146. if(useDelay == 0)
  1147. setNextWorldTile(dest);
  1148. else {
  1149. WorldTasksManager.schedule(new WorldTask() {
  1150. @Override
  1151. public void run() {
  1152. if(isDead())
  1153. return;
  1154. setNextWorldTile(dest);
  1155. if(message != null)
  1156. getPackets().sendGameMessage(message);
  1157. }
  1158. }, useDelay-1);
  1159. }
  1160. }
  1161. public Bank getBank() {
  1162. return bank;
  1163. }
  1164.  
  1165. public int getMusicId() {
  1166. return musicId;
  1167. }
  1168.  
  1169. public void setMusicId(int musicId) {
  1170. this.musicId = musicId;
  1171. musicDelay = System.currentTimeMillis();
  1172. if(!started)
  1173. return;
  1174. getPackets().sendMusic(musicId);
  1175. String musicName = Region.getMusicName(getRegionId());
  1176. getPackets().sendIComponentText(187, 14, musicName == null ? "None" : musicName);
  1177. }
  1178.  
  1179. public long getMusicDelay() {
  1180. return musicDelay;
  1181. }
  1182.  
  1183. public ForceMovement getNextForceMovement() {
  1184. return nextForceMovement;
  1185. }
  1186.  
  1187. public void setNextForceMovement(ForceMovement nextForceMovement) {
  1188. this.nextForceMovement = nextForceMovement;
  1189. }
  1190.  
  1191. public ControlerManager getControlerManager() {
  1192. return controlerManager;
  1193. }
  1194.  
  1195. public void switchMouseButtons() {
  1196. mouseButtons = !mouseButtons;
  1197. refreshMouseButtons();
  1198. }
  1199.  
  1200. public void switchAllowChatEffects() {
  1201. allowChatEffects = !allowChatEffects;
  1202. refreshAllowChatEffects();
  1203. }
  1204.  
  1205. public void refreshAllowChatEffects() {
  1206. getPackets().sendConfig(171, allowChatEffects ? 0 : 1);
  1207. }
  1208.  
  1209. public void refreshMouseButtons() {
  1210. getPackets().sendConfig(170, mouseButtons ? 0 : 1);
  1211. }
  1212.  
  1213. public void switchAllowSplitChat() {
  1214. splitChat = !splitChat;
  1215. refreshSplitChat();
  1216. }
  1217.  
  1218. public void refreshSplitChat() {
  1219. getPackets().sendConfig(287, splitChat ? 1 : 0);
  1220. }
  1221.  
  1222. public boolean isForceNextMapLoadRefresh() {
  1223. return forceNextMapLoadRefresh;
  1224. }
  1225.  
  1226. public void setForceNextMapLoadRefresh(boolean forceNextMapLoadRefresh) {
  1227. this.forceNextMapLoadRefresh = forceNextMapLoadRefresh;
  1228. }
  1229.  
  1230. public FriendsIgnores getFriendsIgnores() {
  1231. return friendsIgnores;
  1232. }
  1233.  
  1234. /*
  1235. * do not use this, only used by pm
  1236. */
  1237. protected void setUsername(String username) {
  1238. this.username = username;
  1239. }
  1240.  
  1241. public void setDisplayName(String displayName) {
  1242. if(Utils.formatPlayerNameForProtocol(username).equals(displayName))
  1243. this.displayName = null;
  1244. else
  1245. this.displayName = displayName;
  1246. }
  1247.  
  1248.  
  1249. }
Add Comment
Please, Sign In to add comment