You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

429 lines
9.6 KiB

  1. module.exports = {
  2. name: 'Fishing Tournament',
  3. description: 'Catch the heaviest Ancient Carp for a chance to win Angler\'s Marks. Speak with Angler Nayla for more info.',
  4. distance: -1,
  5. cron: '0 19 * * *',
  6. notifications: [{
  7. mark: 0,
  8. msg: 'Angler Nayla: The Fishing Tournament begins in 10 minutes.',
  9. desc: 'Begins in 10 minutes.'
  10. }, {
  11. mark: 857,
  12. msg: 'Angler Nayla: The Fishing Tournament begins in 5 minutes.',
  13. desc: 'Begins in 5 minutes.'
  14. }, {
  15. mark: 1543,
  16. msg: 'Angler Nayla: The Fishing Tournament begins in 1 minute.',
  17. desc: 'Begins in 1 minute.'
  18. }, {
  19. mark: 1714,
  20. msg: 'Angler Nayla: The Fishing Tournament has begun!',
  21. desc: ''
  22. }, {
  23. mark: 2571,
  24. msg: 'Angler Nayla: The Fishing Tournament ends in 5 minutes.',
  25. desc: 'Ends in 5 minutes.'
  26. }, {
  27. mark: 3256,
  28. msg: 'Angler Nayla: The Fishing Tournament ends in 1 minute.',
  29. desc: 'Ends in 1 minute.'
  30. }, {
  31. mark: 3428,
  32. msg: 'Angler Nayla: The Fishing Tournament is over.'
  33. }],
  34. duration: 4285,
  35. prizeTime: 3428,
  36. descBase: 'Catch the heaviest Ancient Carp for a chance to win Angler\'s Marks. Speak with Angler Nayla for more info.',
  37. descLeaderboard: null,
  38. descTimer: null,
  39. events: {
  40. afterGiveRewards: function (events) {
  41. let event = events.getEvent('Fishing Tournament');
  42. event.descBase = 'The tournament has ended.';
  43. event.descLeaderboard = null;
  44. event.descTimer = null;
  45. events.setEventDescription('Fishing Tournament', this.description);
  46. },
  47. beforeSetDescription: function (events) {
  48. let event = events.getEvent('Fishing Tournament');
  49. event.description = event.descBase;
  50. if (event.descLeaderboard)
  51. event.description += '<br /><br />' + event.descLeaderboard;
  52. if (event.descTimer)
  53. event.description += '<br /><br />' + event.descTimer;
  54. }
  55. },
  56. helpers: {
  57. updateRewards: function (event, anglerNayla) {
  58. event.ranks = {};
  59. event.rewards = {};
  60. event.weights = {};
  61. let tempFish = anglerNayla.inventory.items
  62. .filter(i => (i.name.indexOf('Ancient Carp') > -1))
  63. .sort((a, b) => (b.stats.weight - a.stats.weight));
  64. let fish = [];
  65. tempFish.forEach(function (t) {
  66. if (!fish.some(f => (f.owner === t.owner)))
  67. fish.push(t);
  68. });
  69. let rewardCounts = [35, 20, 10];
  70. let tpl = {
  71. name: 'Angler\'s Mark',
  72. sprite: [12, 9],
  73. noDrop: true,
  74. noDestroy: true,
  75. noSalvage: true
  76. };
  77. let consolationQty = 2;
  78. let rank = 0;
  79. let lastWeight = fish[0].stats.weight;
  80. for (let i = 0; i < fish.length; i++) {
  81. let f = fish[i];
  82. if (event.rewards[f.owner])
  83. continue;
  84. if (f.stats.weight < lastWeight) {
  85. lastWeight = f.stats.weight;
  86. rank++;
  87. }
  88. event.ranks[f.owner] = rank + 1;
  89. event.weights[f.owner] = f.stats.weight;
  90. let rewardQty = rewardCounts[rank] || consolationQty;
  91. event.rewards[f.owner] = [extend(true, {
  92. quantity: rewardQty
  93. }, tpl)];
  94. }
  95. },
  96. updateDescription: function (event, events) {
  97. let ranks = event.ranks;
  98. let weights = event.weights;
  99. let desc = 'Leaderboard:<br />';
  100. for (let playerName in ranks)
  101. desc += `${ranks[playerName]}: ${playerName} (${weights[playerName]}) <br />`;
  102. desc = desc.substr(0, desc.length - 6);
  103. event.config.descLeaderboard = desc;
  104. events.setEventDescription('Fishing Tournament');
  105. },
  106. updateWinText: function (event, events) {
  107. let ranks = event.ranks;
  108. let winText = 'Angler Nayla: ';
  109. let winners = Object.keys(ranks).filter(r => (ranks[r] === 1));
  110. let wLen = winners.length;
  111. winners.forEach(function (w, i) {
  112. winText += ((wLen > 1) && (i === wLen - 1)) ? `and ${w} ` : `${w} `;
  113. });
  114. winText += 'won!';
  115. events.setWinText('Fishing Tournament', winText);
  116. },
  117. giveFish: function (source, target) {
  118. let srcInventory = source.inventory;
  119. let tgtInventory = target.inventory;
  120. srcInventory.items
  121. .filter(i => (i.name.indexOf('Ancient Carp') > -1))
  122. .sort((a, b) => (b.stats.weight - a.stats.weight))
  123. .forEach(function (f, i) {
  124. if (i === 0) {
  125. f.owner = source.name;
  126. tgtInventory.getItem(extend(true, {}, f));
  127. }
  128. srcInventory.destroyItem(f.id);
  129. });
  130. },
  131. getRank: function (event, playerName) {
  132. let ranks = event.ranks;
  133. if (!event.ranks)
  134. return -1;
  135. return (event.ranks[playerName] || -1);
  136. }
  137. },
  138. phases: [{
  139. type: 'spawnMob',
  140. endMark: 1714,
  141. mobs: {
  142. name: 'Angler Nayla',
  143. attackable: false,
  144. level: 20,
  145. cell: 69,
  146. id: 'anglerNayla',
  147. hpMult: 1,
  148. pos: {
  149. x: 140,
  150. y: 46
  151. },
  152. dialogue: {
  153. auto: true,
  154. config: {
  155. 1: {
  156. msg: [{
  157. msg: 'Hi there, are you here to compete?',
  158. options: [1.1, 1.2, 1.3]
  159. }],
  160. options: {
  161. 1.1: {
  162. msg: 'What\'s happening here?',
  163. goto: 2
  164. },
  165. 1.2: {
  166. msg: 'Could I please have a Competition Rod?',
  167. goto: 5
  168. },
  169. 1.3: {
  170. msg: 'I would like to trade some Angler\'s Marks.',
  171. goto: 'tradeBuy'
  172. }
  173. }
  174. },
  175. 2: {
  176. msg: 'Why, the Grand Fishing Tournament, of course! Anglers come from all over to compete in this esteemed event.',
  177. options: {
  178. 2.1: {
  179. msg: 'How does it work?',
  180. goto: 3
  181. }
  182. }
  183. },
  184. 3: {
  185. msg: 'Simply catch fish during the tournament. If you\'re lucky, you\'ll catch an Ancient Carp. Bring them to me and if you catch the heaviest one, you win!',
  186. options: {
  187. 3.1: {
  188. msg: 'What are the prizes?',
  189. goto: 4
  190. }
  191. }
  192. },
  193. 4: {
  194. msg: 'The top three participants will win Angler\'s Marks that can be exchanged for Fishing Rods and Cerulean Pearls.',
  195. options: {
  196. 4.1: {
  197. msg: 'I would like to ask something else.',
  198. goto: 1
  199. }
  200. }
  201. },
  202. 5: {
  203. msg: [{
  204. msg: '',
  205. options: [1.1, 1.2, 1.3, 1.4]
  206. }],
  207. cpn: 'dialogue',
  208. method: 'getItem',
  209. args: [{
  210. item: {
  211. name: 'Competition Rod',
  212. slot: 'tool',
  213. sprite: [11, 1],
  214. type: 'Fishing Rod',
  215. worth: 0,
  216. noSalvage: true,
  217. noAugment: true,
  218. stats: {
  219. catchSpeed: 50,
  220. catchChance: 25
  221. }
  222. },
  223. successMsg: 'May it cast true.',
  224. existsMsg: 'Oh, it seems that you already have one.'
  225. }]
  226. },
  227. tradeBuy: {
  228. cpn: 'trade',
  229. method: 'startBuy',
  230. args: [{
  231. targetName: 'angler nayla'
  232. }]
  233. }
  234. }
  235. },
  236. trade: {
  237. items: {
  238. min: 0,
  239. max: 0
  240. },
  241. forceItems: [{
  242. name: 'Cerulean Pearl',
  243. material: true,
  244. sprite: [11, 9],
  245. infinite: true,
  246. quality: 3,
  247. worth: {
  248. currency: 'Angler\'s Mark',
  249. amount: 4
  250. }
  251. }, {
  252. name: 'Common Fishing Rod',
  253. type: 'Fishing Rod',
  254. slot: 'tool',
  255. quality: 0,
  256. worth: {
  257. currency: 'Angler\'s Mark',
  258. amount: 5
  259. },
  260. sprite: [11, 0],
  261. infinite: true,
  262. stats: {
  263. stats: '???'
  264. }
  265. }, {
  266. name: 'Magic Fishing Rod',
  267. type: 'Fishing Rod',
  268. slot: 'tool',
  269. quality: 1,
  270. worth: {
  271. currency: 'Angler\'s Mark',
  272. amount: 15
  273. },
  274. sprite: [11, 0],
  275. infinite: true,
  276. stats: {
  277. stats: '???'
  278. }
  279. }, {
  280. name: 'Rare Fishing Rod',
  281. type: 'Fishing Rod',
  282. slot: 'tool',
  283. quality: 2,
  284. worth: {
  285. currency: 'Angler\'s Mark',
  286. amount: 45
  287. },
  288. sprite: [11, 0],
  289. infinite: true,
  290. stats: {
  291. stats: '???'
  292. }
  293. }],
  294. faction: {
  295. id: 'anglers'
  296. },
  297. level: {
  298. min: 1,
  299. max: 5
  300. },
  301. markup: {
  302. buy: 0.25,
  303. sell: 2.5
  304. }
  305. }
  306. }
  307. }, {
  308. type: 'hookEvents',
  309. endMark: 3428,
  310. auto: true,
  311. events: {
  312. beforeGatherResource: function (gatherResult, gatherer) {
  313. if (gatherResult.nodeType !== 'fish')
  314. return;
  315. let hasCompRod = gatherer.inventory.items.some(i => ((i.name === 'Competition Rod') && (i.eq)));
  316. if (!hasCompRod)
  317. return;
  318. gatherResult.items.forEach(function (g) {
  319. extend(true, g, {
  320. name: 'Ancient Carp',
  321. sprite: [11, 4],
  322. noDrop: true
  323. });
  324. });
  325. },
  326. beforeEnterPool: function (gatherResult, gatherer) {
  327. if (gatherResult.nodeName === 'Sun Carp')
  328. gatherResult.nodeName = 'Ancient Carp';
  329. }
  330. }
  331. }, {
  332. type: 'modifyDialogue',
  333. endMark: 3428,
  334. mobId: 'anglerNayla',
  335. dialogue: {
  336. add: {
  337. 1: {
  338. 1.4: {
  339. msg: 'I\'d like to hand in some fish.',
  340. prereq: function (obj) {
  341. let fishies = obj.inventory.items.find(i => (i.name.indexOf('Ancient Carp') > -1));
  342. return !!fishies;
  343. },
  344. goto: 'giveFish'
  345. }
  346. },
  347. giveFish: {
  348. msg: [{
  349. msg: '',
  350. options: [1.1, 1.2, 1.3, 1.4]
  351. }],
  352. method: function (obj) {
  353. let eventConfig = this.instance.events.getEvent('Fishing Tournament');
  354. if (!eventConfig)
  355. return;
  356. let helpers = eventConfig.helpers;
  357. let event = eventConfig.event;
  358. let oldRank = helpers.getRank(event, obj.name);
  359. helpers.giveFish(obj, this);
  360. helpers.updateRewards(event, this);
  361. let newRank = helpers.getRank(event, obj.name);
  362. helpers.updateDescription(event, this.instance.events);
  363. if (oldRank !== newRank) {
  364. helpers.updateWinText(event, this.instance.events);
  365. return {
  366. 1: 'Wow, that one\'s huge. You took first place!',
  367. 2: 'Nice catch. You took second place!',
  368. 3: 'Not bad at all. You took third place!'
  369. }[newRank];
  370. } else if (newRank === 1)
  371. return 'Great, you\'re still in first place!';
  372. return 'Not quite heavy enough, keep trying!';
  373. }
  374. }
  375. }
  376. }
  377. }, {
  378. type: 'modifyDialogue',
  379. mobId: 'anglerNayla',
  380. dialogue: {
  381. remove: {
  382. 1: {
  383. 1.4: null
  384. },
  385. giveFish: null
  386. }
  387. }
  388. }]
  389. };