Advertisement
Guest User

Untitled

a guest
Dec 16th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.92 KB | None | 0 0
  1. //function happy_holidays()
  2. //{
  3. // if(!G.maps.main.ref.xmas_tree) return; // If this happens, the event is over
  4. // if(character.s.xmas2) return; // If you already have the buff, no need to get re-buffed
  5. // G.maps.main.ref.xmas_tree.return=true;
  6. // If first argument of "smart_move" includes "return"
  7. // You are placed back to your original point
  8. // smart_move(G.maps.main.ref.xmas_tree,function(){
  9. // // This executes when we reach our destination
  10. // parent.socket.emit("interaction",{type:"xmas_tree"});
  11. // });
  12. //}
  13. //setInterval(happy_holidays,60*1000); // Check every minute
  14. //happy_holidays(); // Execute once before the first interval is up
  15.  
  16. game_log("---AutoParty Start---");
  17.  
  18. if(parent.ModulesLoaded == null)
  19. {
  20. parent.ModulesLoaded = [];
  21. }
  22.  
  23. parent.ModulesLoaded.push("AutoParty");
  24.  
  25. var invites = ["Pluu", "Paloo"];
  26. var accept_invites = ["Pluet"];
  27.  
  28. parent.socket.on('invite', (data) => {
  29. if(parent != null)
  30. {
  31. if (accept_invites.includes(data.name)) {
  32. parent.socket.emit('party', { event: 'accept', name: data.name });
  33. }
  34. }
  35. });
  36. parent.socket.on('request', (data) => {
  37. if(parent != null)
  38. {
  39. if (accept_invites.includes(data.name)) {
  40. parent.socket.emit('party', { event: 'raccept', name: data.name });
  41. }
  42. }
  43. });
  44.  
  45. var missing_member_list = [];
  46. var invite_missing_members;
  47.  
  48. function self_invite() {
  49. // Refreshing Handler
  50. Party_Handler = setTimeout(self_invite, 1000);
  51.  
  52. // Short Circuit
  53. if (parent.party_list.length >= 6) { return; }
  54.  
  55. // Inviting
  56. let party_members = parent.party_list;
  57. let missing_members = invites.filter(p => !party_members.includes(p));
  58. let interval = 1000 / missing_members.length;
  59. missing_member_list = missing_members;
  60. invite_missing_members = setInterval(invite_missing, interval);
  61. }
  62. function invite_missing() {
  63. let invite_member = missing_member_list.shift();
  64. if(invite_member != null)
  65. {
  66. invite(invite_member);
  67. }
  68. if (missing_member_list.length <= 0) { clearInterval(invite_missing_members); }
  69. }
  70.  
  71. var Party_Handler = setTimeout(self_invite, 1000);
  72. parent.stop_partying = function () {
  73. clearTimeout(Party_Handler);
  74. }
  75. parent.restart_partying = function () {
  76. clearTimeout(Party_Handler);
  77. self_invite();
  78. }
  79. var invite = (m) => {
  80. if(parent != null && parent.socket != null)
  81. {
  82. console.debug(`Inviting ${m}, ${missing_member_list.length} to go.`);
  83. if(m != null)
  84. {
  85. parent.socket.emit('party', { event: 'invite', name: m });
  86. parent.socket.emit('party', { event: 'request', id: m });
  87. }
  88. }
  89. }
  90.  
  91. parent.invite = invite;
  92.  
  93. var leadName = "Pluet";
  94. setInterval(function(){
  95. if(character.party != null && character.party != leadName)
  96. {
  97. parent.socket.emit("party",{event:"leave"});
  98. }},1000);
  99.  
  100. //Party leader
  101. let leader = get_player(character.party);
  102.  
  103. //Move to leader.
  104. //setInterval(function(){
  105. // if (leader && !character.moving) //Move only if you are not already moving.
  106. // move(leader.real_x - 10, leader.real_y - 10);
  107. //},1000/character.frequency + 30)
  108.  
  109. //Character Skin
  110. if(character.skin != "mm_blue"){parent.socket.emit('activate',{slot:'ring1'});}
  111.  
  112. //Booster Maintenance
  113. setInterval(function(){
  114. shift(0,'goldbooster');
  115. equip(1);
  116. loot();
  117. equip(1);
  118. shift(0,'luckbooster');
  119. },1000); // Loops every 1/4 seconds
  120.  
  121. //Item Maintenance (Send items to Merchant)
  122. setInterval(function(){
  123.  
  124. //set to true if you wish to send items
  125. var sending = true;
  126. //set items you wish to send here
  127. var sendWhitelist = ['hpbelt', 'hpamulet', 'ringsj', 'mistletoe', 'candycane', 'xmasornament', 'strring', 'dexring', 'intring', 'angelwings', 'essenceoffrost', 'gem0', 'feather0', 'lostearring', 'candy1v3', 'candy0v3', 'vitring'];
  128. //set person you wish to send items to here
  129. var reciver = "Ploob";
  130.  
  131. if(sending)
  132. {
  133. for(let i in character.items){
  134. let item = character.items[i];
  135. if(item && sendWhitelist.indexOf(item.name) !== -1){
  136. send_item(reciver,i)
  137. }
  138. }
  139. }
  140. send_gold("Ploob", character.gold - 1000000);
  141.  
  142. },10000);
  143.  
  144. //Elixir Maintenance
  145. var elixirs = ["elixirluck"];
  146. setInterval(check_elixir, 5000);
  147.  
  148. function check_elixir()
  149. {
  150. let active = character.slots["elixir"];
  151. for (let elixir of elixirs)
  152. {
  153. if (!active || !elixirs.includes(active.name))
  154. {
  155. let num = find_item(elixir);
  156. if (num != -1) return parent.socket.emit("equip", {"num":num});
  157. }
  158. }
  159. }
  160.  
  161. function find_item(name)
  162. {
  163. let items=character.items;
  164. for (let i in items) if (items[i] && items[i].name==name) return i;
  165. }
  166.  
  167.  
  168. //////// Potion Maintenance ////////
  169. var purchase_pots = true;
  170. var buy_hp = true;
  171. var buy_mp = true;
  172. var hp_potion = 'hpot1';
  173. var mp_potion = 'mpot1';
  174. var pots_minimum = 50;
  175. var pots_to_buy = 1000;
  176.  
  177. setInterval(function() {
  178.  
  179. //Purchases Potions when below threshold
  180. if (purchase_pots) {
  181. purchase_potions(buy_hp, buy_mp);
  182. }
  183.  
  184. }, 250); //Loop every 1/4 second.
  185.  
  186. //Returns the item slot and the item given the slot to start from and a filter.
  187. function find_item_filter(filter, search_slot) {
  188. let slot = search_slot;
  189. if (!slot)
  190. slot = 0
  191.  
  192. for (let i = slot; i < character.items.length; i++) {
  193. let item = character.items[i];
  194.  
  195. if (item && filter(item))
  196. return [i, character.items[i]];
  197. }
  198.  
  199. return [-1, null];
  200. }
  201.  
  202. ////////////////////////////////////
  203.  
  204. function request_assistance(player_name, entity)
  205. {
  206. if(entity)
  207. {
  208. send_cm(player_name, {name: "assistance_request", id: entity.id, type: entity.type, mtype: entity.mtype, x: entity.real_x, y: entity.real_y, map: entity.in, priority: "low"});
  209. }
  210. else
  211. {
  212. send_cm(player_name, {name: "assistance_request", id: null, type: null, mtype: null, x: character.real_x, y: character.real_y, map: character.map, priority: "low"});
  213. }
  214. }
  215.  
  216.  
  217.  
  218. function handle_death()
  219. {
  220. return 1;
  221. }
  222.  
  223. var last_request = 0;
  224. setInterval(function(){
  225. if(character.rip && !character.c.revival)
  226. {
  227. if(new Date() - last_request > 1000)
  228. {
  229. request_assistance("Maela");
  230. }
  231. }
  232. }, 1000);
  233.  
  234. ///////////////////////////////////////////////////////////////////////////////////////////////////
  235. ///////////////////////////////////////////////////////////////////////////////////////////////////
  236.  
  237. //Working Variables
  238. var lastAttack = 0;
  239. var lastMove = 0;
  240. var lastPotion = 0;
  241. var targeter = new Targeter({bbpompom: 1, rat: 2, snake: 3,}, [], [], {UseGreyList: true, RequireLOS: true, DebugPVP: false, TagTargets: true});
  242.  
  243. //PRIMARY LOOP
  244. setInterval(function(){
  245. clear_drawings();
  246. if(new Date() - lastPotion > 2100)
  247. {
  248. use_hp_or_mp();
  249. lastPotion = new Date();
  250. }
  251.  
  252. switch(character.ctype)
  253. {
  254. case "ranger":
  255. rangerCombat();
  256. break;
  257. case "priest":
  258. priestCombat();
  259. break;
  260. default:
  261. defaultCombat();
  262. }
  263.  
  264. }, 1);
  265.  
  266.  
  267. //CLASS COMBAT BEHAVIORS
  268. function rangerCombat(){
  269. var targets = targeter.GetPriorityTarget(3);
  270. for(var id in targets)
  271. {
  272. var target = targets[id];
  273. draw_circle(target.real_x, target.real_y, 20);
  274. }
  275. if(targets)
  276. {
  277. var primaryTarget = targets[0];
  278.  
  279. if(primaryTarget)
  280. {
  281. if(primaryTarget.mtype != "franky" || primaryTarget.target != null)
  282. {
  283. if(new Date() - lastMove > 100)
  284. {
  285. var targetPoint = pointOnAngle(targets[0], angleToPoint(targets[0].real_x, targets[0].real_y), character.range - 10);
  286. }
  287.  
  288. if(targets.length == 1 || character.level < 60)
  289. {
  290. if(can_attack(primaryTarget) && new Date() - lastAttack > 1000/character.frequency + 30)
  291. {
  292. attack(primaryTarget);
  293. lastAttack = new Date();
  294. }
  295. }
  296. else
  297. {
  298. try3Shot(targets);
  299. attack(primaryTarget);
  300. }
  301. }
  302. }
  303. }
  304. }
  305.  
  306. function priestCombat(){
  307. var lowestHPAlly = getLowestHealthAlly();
  308.  
  309. if(lowestHPAlly.hp/lowestHPAlly.max_hp < 0.99)
  310. {
  311. if(new Date() - lastMove > 100)
  312. {
  313. var targetPoint = pointOnAngle(lowestHPAlly, angleToPoint(lowestHPAlly.real_x, lowestHPAlly.real_y), character.range - 10);
  314. }
  315.  
  316. if(can_attack(lowestHPAlly) && new Date() - lastAttack > 1000/character.frequency + 30)
  317. {
  318. heal(lowestHPAlly);
  319. lastAttack = new Date();
  320. }
  321. }
  322. else
  323. {
  324. var targets = targeter.GetPriorityTarget(1);
  325. for(var id in targets)
  326. {
  327. var target = targets[id];
  328. draw_circle(target.real_x, target.real_y, 20);
  329. }
  330. if(targets)
  331. {
  332. var primaryTarget = targets[0];
  333. if(primaryTarget)
  334. {
  335. if(primaryTarget.mtype != "franky" || primaryTarget.target != null)
  336. {
  337. if(new Date() - lastMove > 100)
  338. {
  339. var targetPoint = pointOnAngle(primaryTarget, angleToPoint(primaryTarget.real_x, primaryTarget.real_y), character.range - 10);
  340. move(targetPoint.x, targetPoint.y);
  341. }
  342.  
  343. if(can_attack(primaryTarget) && new Date() - lastAttack > 1000/character.frequency + 30)
  344. {
  345. attack(primaryTarget);
  346. lastAttack = new Date();
  347. }
  348. }
  349. }
  350. }
  351. }
  352. }
  353.  
  354. function defaultCombat(){
  355. var targets = targeter.GetPriorityTarget(1);
  356. for(var id in targets)
  357. {
  358. var target = targets[id];
  359. draw_circle(target.real_x, target.real_y, 20);
  360. }
  361. if(targets)
  362. {
  363. var primaryTarget = targets[0];
  364.  
  365. if(primaryTarget)
  366. {
  367. if(primaryTarget.mtype != "franky" || primaryTarget.target != null)
  368. {
  369. if(new Date() - lastMove > 100)
  370. {
  371. var targetPoint = pointOnAngle(primaryTarget, angleToPoint(primaryTarget.real_x, primaryTarget.real_y), character.range - 10);
  372. }
  373.  
  374. if(can_attack(primaryTarget) && new Date() - lastAttack > 1000/character.frequency + 30)
  375. {
  376. attack(primaryTarget);
  377. lastAttack = new Date();
  378. }
  379. }
  380. }
  381. }
  382. }
  383.  
  384. //UTILITY FUNCTIONS
  385. function getLowestHealthAlly()
  386. {
  387. var lowestHPEntity;
  388. var lowestPercentage;
  389. for(var id in parent.entities)
  390. {
  391. var entity = parent.entities[id];
  392.  
  393. if(entity.type == "character" && !entity.citizen)
  394. {
  395. var percentHP = entity.hp/entity.max_hp;
  396.  
  397. if(lowestPercentage == null || percentHP < lowestPercentage)
  398. {
  399. lowestHPEntity = entity;
  400. lowestPercentage = percentHP;
  401. }
  402. }
  403. }
  404.  
  405. return lowestHPEntity;
  406. }
  407.  
  408. //ABILITIES
  409. var last3shot;
  410. function try3Shot(targets)
  411. {
  412. var ids = [];
  413.  
  414. for(target in targets)
  415. {
  416. ids.push(targets[target].id);
  417. }
  418.  
  419. if(lastAttack == null || new Date() - lastAttack > 1000/character.frequency + 30)
  420. {
  421. parent.socket.emit("skill", {
  422. name: "3shot",
  423. ids: ids
  424. });
  425. lastAttack = new Date();
  426. }
  427. }
  428.  
  429. //MATH FUNCTIONS
  430. function entityAngle(entity)
  431. {
  432. return (entity.angle * Math.PI)/180;
  433. }
  434.  
  435. function angleFromPointToPoint(x1, y1, x2, y2)
  436. {
  437. var deltaX = x1 - x2;
  438. var deltaY = y1 - y2;
  439.  
  440. return Math.atan2(deltaY, deltaX);
  441. }
  442.  
  443. function angleToPoint(x, y)
  444. {
  445. var deltaX = character.real_x - x;
  446. var deltaY = character.real_y - y;
  447.  
  448. return Math.atan2(deltaY, deltaX);
  449. }
  450.  
  451. function pointOnAngle(entity, angle, distance)
  452. {
  453. var circX = entity.real_x + (distance * Math.cos(angle));
  454. var circY = entity.real_y + (distance * Math.sin(angle));
  455.  
  456. return {x: circX, y: circY};
  457. }
  458.  
  459. function offsetToPoint(x, y)
  460. {
  461. var angle = angleToPoint(x, y) + Math.PI;
  462.  
  463. return angle - characterAngle();
  464.  
  465. }
  466.  
  467.  
  468.  
  469. function distanceToPoint(x, y)
  470. {
  471. return Math.sqrt(Math.pow(character.real_x - x, 2) + Math.pow(character.real_y - y, 2));
  472. }
  473.  
  474. //TARGETING
  475.  
  476. /*
  477. priorityArgs:
  478. An object that describes what priority a mtype will be given.
  479. You will always target an accessible priority 1 monster before a priority 2 monster.
  480. Players are given a priority of zero.
  481. Example:
  482. {
  483. goo: 1,
  484. bee: 2
  485. }
  486.  
  487. whitelist:
  488. An array of player names which defines players that will under no circumstances be targeted.
  489. Example:
  490. ["Foaly", "SpadarFaar"]
  491. blacklist:
  492. An array of player names which defines players that will always be targeted if in a PvP environment.
  493. Example:
  494. ["Foaly", "SpadarFaar"]
  495. args:
  496. An object containing additional optional configuration options.
  497. Example (Default Values):
  498. {
  499. UseGreyList: true, //If this is false then all players not whitelisted are attacked on sight.
  500. RequireLOS: true, //If this is false then monsters located on the other side of obstacles will be targeted.
  501. DebugPVP: false, //If this is true then players will be targeted in non-pvp areas.
  502. TagTargets: true //If this is false then only monsters which are already targeting the party will be targeted.
  503.  
  504. }
  505.  
  506. */
  507. function Targeter(priorityArgs, whitelist, blacklist, args)
  508. {
  509. //Set up configuration
  510. this.TargetingPriority = priorityArgs;
  511. this.WhiteList = whitelist;
  512. this.BlackList = blacklist;
  513. this.GreyList = {};
  514.  
  515. if(args.UseGreyList === undefined){
  516. args.UseGreyList = true;
  517. }
  518. this.UseGreyList = args.UseGreyList;
  519.  
  520. if(args.RequireLOS === undefined){
  521. args.RequireLOS = true;
  522. }
  523. this.RequireLOS = args.RequireLOS;
  524.  
  525. if(args.DebugPVP === undefined){
  526. args.DebugPVP = false;
  527. }
  528. this.DebugPVP = args.DebugPVP;
  529.  
  530. if(args.TagTargets === undefined){
  531. args.TagTargets = true;
  532. }
  533. this.TagTargets = args.TagTargets;
  534.  
  535. /*
  536. Primary targeting function.
  537.  
  538. If you specify count, an array of the top n targets will be returned, otherwise only the closest, highest priority, target will be returned.
  539. */
  540. this.GetPriorityTarget = function(count){
  541. let potentialTargets = [];
  542.  
  543. for(let id in parent.entities)
  544. {
  545. let entity = parent.entities[id];
  546.  
  547. if(this.IsPVP() && entity.type == "character" && !entity.npc)
  548. {
  549. if(this.GreyList[entity.id] === undefined)
  550. {
  551. this.GreyListPlayer(entity);
  552. }
  553.  
  554. if(!this.IsPlayerSafe(entity))
  555. {
  556. let targetArgs = {};
  557. targetArgs.priority = 0;
  558. targetArgs.distance = parent.distance(character, entity);
  559. targetArgs.entity = entity;
  560. potentialTargets.push(targetArgs);
  561. }
  562. }
  563. else
  564. {
  565. if(entity.type == "monster")
  566. {
  567. if((this.TagTargets) || this.IsTargetingParty(entity))
  568. {
  569. if(this.TargetingPriority[entity.mtype] != null || this.IsTargetingParty(entity))
  570. {
  571. if(!this.RequireLOS || can_move_to(entity.real_x, entity.real_y))
  572. {
  573. let targetArgs = {};
  574. targetArgs.priority = this.TargetingPriority[entity.mtype];
  575. targetArgs.distance = parent.distance(character, entity);
  576. targetArgs.entity = entity;
  577. potentialTargets.push(targetArgs);
  578. }
  579. }
  580. }
  581. }
  582. }
  583. }
  584.  
  585. potentialTargets.sort(function(a, b) {
  586. if(a.priority > b.priority)
  587. {
  588. return 1;
  589. }
  590. else if(a.priority < b.priority)
  591. {
  592. return -1;
  593. }
  594. else if(a.distance > b.distance)
  595. {
  596. return 1;
  597. }
  598. else
  599. {
  600. return -1;
  601. }
  602. });
  603.  
  604. if(potentialTargets.length > 0)
  605. {
  606. if(!count)
  607. {
  608. return potentialTargets[0].entity;
  609. }
  610. else
  611. {
  612. return potentialTargets.slice(0, count).map(a => a.entity);
  613. }
  614. }
  615.  
  616. return null;
  617. };
  618.  
  619. /*
  620. Returns if the player is currently in a PvP environment.
  621. */
  622. this.IsPVP = function(){
  623. if(this.DebugPVP || parent.is_pvp || get_map().pvp)
  624. {
  625. return true;
  626. }
  627. else
  628. {
  629. return false;
  630. }
  631. }
  632.  
  633. /*
  634. Returns if the provided entity is targeting either the player or the player's party.
  635. */
  636. this.IsTargetingParty = function(entity){
  637. if(entity.target == character.id)
  638. {
  639. return true;
  640. }
  641.  
  642. if(parent.party_list.indexOf(entity.id) > -1)
  643. {
  644. return true;
  645. }
  646.  
  647. return false;
  648. }
  649.  
  650. /*
  651. Returns if, according to our configuration, a player should be attacked or not.
  652. */
  653. this.IsPlayerSafe = function(entity){
  654.  
  655. if(parent.party_list.indexOf(entity.id) > -1)
  656. {
  657. return true;
  658. }
  659.  
  660. if(this.BlackList.indexOf(entity.id) > -1)
  661. {
  662. return false;
  663. }
  664.  
  665. if(this.WhiteList.indexOf(entity.id) > -1)
  666. {
  667. return true;
  668. }
  669.  
  670. let greyListEntry = this.GreyList[entity.id];
  671.  
  672.  
  673. if(this.UseGreyList && (greyListEntry === undefined || greyListEntry === true))
  674. {
  675. return true;
  676. }
  677.  
  678. return false;
  679. };
  680.  
  681. /*
  682. Adds a player to the GreyList, which is used to allow players to not be attacked unless instigated.
  683. */
  684. this.GreyListPlayer = function(entity){
  685. if(entity.type == "character")
  686. {
  687. game_log("Adding " + entity.id + " to GreyList.");
  688. this.GreyList[entity.id] = true;
  689. }
  690. };
  691.  
  692. /*
  693. Marks a player on the GreyList to be no longer considered safe. This means that they will be attacked in PvP environments.
  694. */
  695. this.RemoveFromGreyList = function(name){
  696. this.GreyList[name] = false;
  697. };
  698.  
  699. /*
  700. Returns whether or not we want to consider hostile action against this player a reason to engage the aggressor in PvP.
  701. */
  702. this.IsPlayerFriendly = function(name){
  703. if(character.id == name)
  704. {
  705. return true;
  706. }
  707.  
  708. if(parent.party_list.indexOf(name) > -1)
  709. {
  710. return true;
  711. }
  712.  
  713. return false;
  714. }
  715.  
  716. //Set up hit event handling to react when attacked
  717.  
  718. //Clean out an pre-existing listeners
  719. if (parent.prev_handlerstargeting) {
  720. for (let [event, handler] of parent.prev_handlerstargeting) {
  721. parent.socket.removeListener(event, handler);
  722. }
  723. }
  724.  
  725. parent.prev_handlerstargeting = [];
  726.  
  727. //handler pattern shamelessly stolen from JourneyOver
  728. function register_targetinghandler(event, handler)
  729. {
  730. parent.prev_handlerstargeting.push([event, handler]);
  731. parent.socket.on(event, handler);
  732. };
  733.  
  734. let targeter = this;
  735. this.hitHandler = function(event){
  736. console.log(event);
  737. if(parent != null)
  738. {
  739.  
  740. var attacker = event.hid;
  741. var attacked = event.id;
  742.  
  743. var attackedEntity = parent.entities[attacked];
  744.  
  745. if(attacked == character.name)
  746. {
  747. attackedEntity = character;
  748. }
  749.  
  750. if(attackedEntity != null && event.heal == null)
  751. {
  752. if(attackedEntity.type == "character" && targeter.IsPlayerFriendly(attacked))
  753. {
  754.  
  755. targeter.RemoveFromGreyList(attacker);
  756. game_log("Removing " + attacker + " from greylist for attacking " + attacked);
  757. }
  758. }
  759. }
  760. }
  761.  
  762. register_targetinghandler("hit", this.hitHandler);
  763. }
  764.  
  765. //Potion Purchasing
  766. function purchase_potions(buyHP, buyMP) {
  767. let [hpslot, hppot] = find_item_filter(i => i.name == hp_potion);
  768. let [mpslot, mppot] = find_item_filter(i => i.name == mp_potion);
  769.  
  770. if (buyHP && (!hppot || hppot.q < pots_minimum)) {
  771. parent.buy(hp_potion, pots_to_buy);
  772. set_message("Buying HP pots.");
  773. }
  774. if (buyMP && (!mppot || mppot.q < pots_minimum)) {
  775. parent.buy(mp_potion, pots_to_buy);
  776. set_message("Buying MP pots.");
  777. }
  778. }
  779.  
  780. //ENTITY AVOIDANCE
  781. //Usages
  782. //move(x,y) has been overridden to operate via vectors, and will allow avoidance while moving
  783. //smart_move has been overridden to allow avoidance to happen during the path following process
  784.  
  785. //CONFIGURATION
  786.  
  787. //Entity Avoidance Configuration
  788. var debugDrawing = false;//Set this to false to stop drawing debug information.
  789. var buffer = 20; //How far out from the minimum range do we want to start?
  790. var charDistance = 30; //Minimum range for players
  791. var avoidPlayers = false;//Do we want to avoid players at all?
  792. var avoidMTypes = [];//What type of monsters do we want to avoid?
  793.  
  794. var entityScaleMult = 20;//How 'Hard' the avoidance vector will push us away.
  795.  
  796. //Override base move to hook into the vector logic
  797. function move(x, y)
  798. {
  799. //Stop smart moving if we are currently doing so.
  800. if(smart.moving)
  801. {
  802. stop();
  803. }
  804. curVectorTarget = {x: x, y: y};
  805. }
  806. //holds the current position that we're trying to get to.
  807. var curVectorTarget;
  808.  
  809. //Loop trying to move along our current calculated vector.
  810. setInterval(function(){
  811. //If we're smart moving update the target position to the current path node.
  812. if(smart.moving)
  813. {
  814. var currentNode = smart.plot[0];
  815.  
  816. if(currentNode != null && currentNode.map == currentNode.map)
  817. {
  818. if(can_move_to(currentNode))
  819. {
  820. curVectorTarget = smart.plot[0];
  821. }
  822. else
  823. {
  824. curVectorTarget = null;
  825. smart_move({x: smart.x, y: smart.y, map: smart.map}, smart.on_done);
  826. }
  827. }
  828. }
  829. MoveOnVector();
  830. }, 50);
  831.  
  832. //Calculate our overall movement vector and move along it.
  833. var lastMove;
  834. function MoveOnVector()
  835. {
  836. if(debugDrawing){
  837. clear_drawings();
  838. if(curVectorTarget)
  839. {
  840. draw_circle(curVectorTarget.x, curVectorTarget.y, 20);
  841. }
  842. }
  843. //Start with a base vector of 0,0
  844. var moveVector = new Vector();
  845.  
  846. //Get the vector which represents a direction which will move us away from any nearby entities and add it to the base vector
  847. var entityAvoidVector = getEntityAvoidVector();
  848. moveVector.add(entityAvoidVector);
  849.  
  850. //If we have somewhere we want to go, add a vector representing that direction to our current base. If we're close scale back the vector to keep us from overshooting.
  851. if(curVectorTarget != null)
  852. {
  853. var dist = distance2D(curVectorTarget.x, curVectorTarget.y);
  854.  
  855. if(dist > 0)
  856. {
  857. var vectorMag = 15;
  858. if(dist < 15)
  859. {
  860. vectorMag = dist;
  861. }
  862.  
  863. var pathVector = new Vector(curVectorTarget.x - character.real_x, curVectorTarget.y - character.real_y).normalize().multiply(vectorMag);
  864. moveVector.add(pathVector);
  865. }
  866. else
  867. {
  868. curVectorTarget = null;
  869. }
  870. }
  871.  
  872. var len = moveVector.length();
  873. //If the vector is too large, scale it back to a maximum
  874. if(len > 25)
  875. {
  876. moveVector = moveVector.normalize().multiply(25);
  877. }
  878.  
  879. //Only move if we have to move an appreciable distance
  880. if(len > 1)
  881. {
  882. if(lastMove == null || new Date() - lastMove > 100)
  883. {
  884. parent.move(moveVector.x + character.real_x, moveVector.y + character.real_y);
  885. lastMove = new Date();
  886. }
  887. }
  888.  
  889. if(debugDrawing)
  890. {
  891. var drawVector = new Vector(moveVector.x, moveVector.y);
  892. var drawLen = drawVector.length();
  893. drawVector.normalize().multiply(drawLen + 10);
  894.  
  895. draw_line(character.real_x, character.real_y, drawVector.x + character.real_x, drawVector.y + character.real_y, 1, 0xEA1010);
  896. }
  897. }
  898.  
  899. //Caculates a vector which opposes all nearby entities which match the configuration.
  900. function getEntityAvoidVector()
  901. {
  902. //Start with a base vector of 0,0
  903. var vector = new Vector();
  904. //Loop through all entities
  905. for(id in parent.entities)
  906. {
  907. var entity = parent.entities[id];
  908.  
  909. //Is this a monster we want to avoid?
  910. var isMonsterToAvoid = avoidMTypes.indexOf(entity.mtype) != -1;
  911.  
  912. //Or a player we want to avoid?
  913. var isPlayerToAvoid = entity.type == "character" && !entity.citizen && avoidPlayers;
  914.  
  915. if(isMonsterToAvoid || isPlayerToAvoid)
  916. {
  917. //Base distance is character distance
  918. var minDist = charDistance;
  919.  
  920. //If it's a monster, use the monsters range
  921. if(entity.mtype)
  922. {
  923. var range = parent.G.monsters[entity.mtype].range;
  924. minDist = range + buffer;
  925. }
  926. //Add our buffer value to this to determine the max distance;
  927. var maxDist = minDist + buffer;
  928.  
  929.  
  930. //What is our current distance to the entity?
  931. var dist = distance2D(entity.real_x, entity.real_y);
  932.  
  933. //If we're within our max distance, we need to start avoiding it.
  934. if(dist < maxDist)
  935. {
  936. if(debugDrawing)
  937. {
  938. draw_circle(entity.real_x, entity.real_y, minDist, 1, 0xDAEA10);
  939. }
  940.  
  941. //Create a normalized vector which represents the direction from the entity towards the player
  942. var entVector = new Vector(character.real_x - entity.real_x, character.real_y - entity.real_y).normalize();
  943.  
  944. //Scale this vector so that maxDist = 0 and minDist = 1
  945. //This allows far entities to push on our character weaker and close entities to push stronger.
  946. var scale = 1 - ((dist - minDist) / (maxDist - minDist));
  947.  
  948. var scaledVector = entVector.multiply(scale*entityScaleMult);
  949.  
  950. //Add the scaled vector to our base.
  951. vector = vector.add(scaledVector);
  952. }
  953. }
  954. }
  955.  
  956. //If our vector is too long, limit it
  957. if(vector.length() > 25)
  958. {
  959. vector = vector.normalize().multiply(25);
  960. }
  961. return vector
  962. }
  963.  
  964. function distance2D(x2, y2)
  965. {
  966. var a = character.real_x - x2;
  967. var b = character.real_y - y2;
  968.  
  969. var c = Math.sqrt( a*a + b*b );
  970.  
  971. return c;
  972. }
  973.  
  974. //Modify Smart Move Logic to let the avoidance code manage the moving.
  975. smart_move_logic = function()
  976. {
  977. if(!smart.moving) return;
  978. if(!smart.searching && !smart.found)
  979. {
  980. start_pathfinding();
  981. }
  982. else if(!smart.found)
  983. {
  984. if(Math.random()<0.1)
  985. {
  986. parent.move(character.real_x+Math.random()*0.0002-0.0001,character.real_y+Math.random()*0.0002-0.0001);
  987. parent.d_text(shuffle(["Hmm","...","???","Definitely left","No right!","Is it?","I can do this!","I think ...","What If","Should be","I'm Sure","Nope","Wait a min!","Oh my"])[0],character,{color:shuffle(["#68B3D1","#D06F99","#6ED5A3","#D2CF5A"])[0]});
  988. }
  989. continue_pathfinding();
  990. }
  991. else if(can_walk(character) && !is_transporting(character))
  992. {
  993. if(!smart.plot.length)
  994. {
  995. smart.moving=false;
  996. smart.on_done(true);
  997. return;
  998. }
  999. var current=smart.plot[0];
  1000.  
  1001. if(current.map == character.map)
  1002. {
  1003.  
  1004. var distCurrent = parent.simple_distance({x: character.real_x, y: character.real_y}, {x: current.x, y: current.y});
  1005.  
  1006. if(distCurrent < 5)
  1007. {
  1008. smart.plot.splice(0,1);
  1009. }
  1010. }
  1011.  
  1012. if(current.town)
  1013. {
  1014. use("town");
  1015. }
  1016. else if(current.transport)
  1017. {
  1018. parent.socket.emit("transport",{to:current.map,s:current.s});
  1019. // use("transporter",current.map);
  1020. }
  1021. }
  1022. }
  1023.  
  1024. /*
  1025. Simple 2D JavaScript Vector Class
  1026. Hacked from evanw's lightgl.js
  1027. https://github.com/evanw/lightgl.js/blob/master/src/vector.js
  1028. */
  1029.  
  1030. function Vector(x, y) {
  1031. this.x = x || 0;
  1032. this.y = y || 0;
  1033. }
  1034.  
  1035. /* INSTANCE METHODS */
  1036.  
  1037. Vector.prototype = {
  1038. negative: function() {
  1039. this.x = -this.x;
  1040. this.y = -this.y;
  1041. return this;
  1042. },
  1043. add: function(v) {
  1044. if (v instanceof Vector) {
  1045. this.x += v.x;
  1046. this.y += v.y;
  1047. } else {
  1048. this.x += v;
  1049. this.y += v;
  1050. }
  1051. return this;
  1052. },
  1053. subtract: function(v) {
  1054. if (v instanceof Vector) {
  1055. this.x -= v.x;
  1056. this.y -= v.y;
  1057. } else {
  1058. this.x -= v;
  1059. this.y -= v;
  1060. }
  1061. return this;
  1062. },
  1063. multiply: function(v) {
  1064. if (v instanceof Vector) {
  1065. this.x *= v.x;
  1066. this.y *= v.y;
  1067. } else {
  1068. this.x *= v;
  1069. this.y *= v;
  1070. }
  1071. return this;
  1072. },
  1073. divide: function(v) {
  1074. if (v instanceof Vector) {
  1075. if(v.x != 0) this.x /= v.x;
  1076. if(v.y != 0) this.y /= v.y;
  1077. } else {
  1078. if(v != 0) {
  1079. this.x /= v;
  1080. this.y /= v;
  1081. }
  1082. }
  1083. return this;
  1084. },
  1085. equals: function(v) {
  1086. return this.x == v.x && this.y == v.y;
  1087. },
  1088. dot: function(v) {
  1089. return this.x * v.x + this.y * v.y;
  1090. },
  1091. cross: function(v) {
  1092. return this.x * v.y - this.y * v.x
  1093. },
  1094. length: function() {
  1095. return Math.sqrt(this.dot(this));
  1096. },
  1097. normalize: function() {
  1098. return this.divide(this.length());
  1099. },
  1100. min: function() {
  1101. return Math.min(this.x, this.y);
  1102. },
  1103. max: function() {
  1104. return Math.max(this.x, this.y);
  1105. },
  1106. toAngles: function() {
  1107. return -Math.atan2(-this.y, this.x);
  1108. },
  1109. angleTo: function(a) {
  1110. return Math.acos(this.dot(a) / (this.length() * a.length()));
  1111. },
  1112. toArray: function(n) {
  1113. return [this.x, this.y].slice(0, n || 2);
  1114. },
  1115. clone: function() {
  1116. return new Vector(this.x, this.y);
  1117. },
  1118. set: function(x, y) {
  1119. this.x = x; this.y = y;
  1120. return this;
  1121. }
  1122. };
  1123.  
  1124. /* STATIC METHODS */
  1125. Vector.negative = function(v) {
  1126. return new Vector(-v.x, -v.y);
  1127. };
  1128. Vector.add = function(a, b) {
  1129. if (b instanceof Vector) return new Vector(a.x + b.x, a.y + b.y);
  1130. else return new Vector(a.x + v, a.y + v);
  1131. };
  1132. Vector.subtract = function(a, b) {
  1133. if (b instanceof Vector) return new Vector(a.x - b.x, a.y - b.y);
  1134. else return new Vector(a.x - v, a.y - v);
  1135. };
  1136. Vector.multiply = function(a, b) {
  1137. if (b instanceof Vector) return new Vector(a.x * b.x, a.y * b.y);
  1138. else return new Vector(a.x * v, a.y * v);
  1139. };
  1140. Vector.divide = function(a, b) {
  1141. if (b instanceof Vector) return new Vector(a.x / b.x, a.y / b.y);
  1142. else return new Vector(a.x / v, a.y / v);
  1143. };
  1144. Vector.equals = function(a, b) {
  1145. return a.x == b.x && a.y == b.y;
  1146. };
  1147. Vector.dot = function(a, b) {
  1148. return a.x * b.x + a.y * b.y;
  1149. };
  1150. Vector.cross = function(a, b) {
  1151. return a.x * b.y - a.y * b.x;
  1152. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement