Sehrentos

rAthena NPC script World Boss Event 2.9.5

Jan 27th, 2020 (edited)
1,079
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 61.66 KB | None | 0 0
  1. //===== rAthena Script =======================================
  2. //= World Boss Event
  3. //===== By: ==================================================
  4. //= Musika6988, Sehrentos
  5. //===== Current Version: =====================================
  6. //= 2.9.5
  7. //===== Compatible With: =====================================
  8. //= rAthena Project
  9. //===== Description: =========================================
  10. //= Summon random World Boss and when defeated get treasure.
  11. //= Leader will have option to distribute or dispose loots.
  12. //= GM panel: info/start/stop/skip/lootMode/modify.
  13. //= Boss HP will increase or decrease by 1.500.000 per each
  14. //= player nearby and is updated every 10 seconds.
  15. //= When boss is defeated it will trigger increased exp and
  16. //= drop rates to whole server for 1 hour(IF enabled).
  17. //===== Additional Comments: =================================
  18. //= Depending on server, change all UNITTYPE_* to BL_* or vise versa.
  19. //=
  20. //= 1.x Initial script by Musika6988.
  21. //= 2.0 Sehrentos added reward arrays. Randomly select a reward.
  22. //= 2.1 Sehrentos changed single random reward into random all rewards.
  23. //= 2.2 Sehrentos minor optimizations.
  24. //= 2.3 Sehrentos added more loot options.
  25. //= 2.4 Sehrentos added GM panel, Default mob attributes(.MOB_),
  26. //= Same party check(reward stealing)
  27. //= 2.5 Sehrentos added NPC WorldBossRadar to monitor players nearby,
  28. //= Removed Flee and Perfect Dodge from Treasure Chest,
  29. //= Added timeout to stop the event. Minor text changes.
  30. //= 2.6 Sehrentos added loot mode 1 give one reward to one random party member.
  31. //= Added loot modes 4-5 give all/one rewards to all nearby players and their party members.
  32. //= Added loot modes 6-7 give all/one rewards to all nearby players.
  33. //= 2.7 Sehrentos removed Treasure Chest monster.
  34. //= Added Treasure Chest NPCs.
  35. //= Added multiple events at once, but not in same map.
  36. //= Added loot modes 8-9 give all/one rewards to all players in same map.
  37. //= Added double server rates for 1 hour after boss is killed event.
  38. //= 2.8 Sehrentos added jump_zero optimizations.
  39. //= Fixed WorldBossRates::OnInit first run on the server.
  40. //= Added $@WB_ACCESS_EXPIRE timer. Clean the access array when it expires.
  41. //= 2.9 Sehrentos WorldBossRadar enable/disable option.
  42. //= Added loot modes 10 give all rewards to selected party member.
  43. //= Added loot modes 11 give one random reward to selected party member.
  44. //= 2.9.1 Sehrentos Fixes and additions.
  45. //= Added option to turn off mapflags.
  46. //= Added more default .MOB_ status points.
  47. //= Fix random reward will be selected only once, to avoid abuse ($@WB_REWARD_INDEX).
  48. //= Renamed some values. easier to understand.
  49. //= 2.9.2 Sehrentos Disabled FOG effect.
  50. //= Added more announcements when event fail to start.
  51. //= Added unit checks on OnMobDie event.
  52. //= Added inarray optimizations.
  53. //= 2.9.3 Sehrentos changed the way event starts and announces.
  54. //= Fixed WorldBossRates when .use_floating_rates is enabled(report @Quesooo).
  55. //= 2.9.4 Sehrentos added loots amounts in array (suggest @Radian).
  56. //= 2.9.5 Sehrentos added IP checks.
  57. //= !TODO: Loot mode 12 give each reward to selected party member one by one.
  58. //= !TODO: Enhance .filter_same_ip detection.
  59. //============================================================
  60. - script WorldBoss -1,{
  61. OnInit:
  62. // Settings
  63. .npc_name$ = strnpcinfo(0); // Name of this NPC
  64. .event_sleep = 60000; // Event sleep time in milliseconds(60000 = 1 minute)
  65. .event_timeout = 7200000; // Event timeout time in milliseconds before Boss is disabled(60000 = 1 minute)
  66. .event_access_expire = 900000; // Event access expire time in milliseconds(60000 = 1 minute)
  67. .filter_same_ip = 1; // Give one reward access if same IP is detected (possible multiclient or internet cafe)
  68.  
  69. // Reward distribution
  70. .loot_mode = 4; // Event loot distribution mode. Look npc_loot_mode_desc for descriptions
  71. .loop_max = 200; // Maximum number of loops (When selecting a random party member)
  72. .duplicate_npc_count = 9; // Number of duplicate Treasure Chest NPC's (Important! 0 counts as well)
  73.  
  74. // Experience increases during event(In current event map)
  75. .base_exp_multiplier = 3; // Event base exp rating multiplier(In current event map)
  76. .job_exp_multiplier = 3; // Event job exp rating multiplier(In current event map)
  77. .use_floating_rates = 0; // Increase servers exp and drop rates for 1 hour after boss kill(0=Disable, 1=Enable)
  78.  
  79. // Monsters default attributes
  80. .MOB_MAXHP = 100000000; // How much HP can monster have at maximum
  81. .MOB_HP = 5000000; // How much HP monster has on spawn
  82. .MOB_SPEED = 130; // Speed
  83. .MOB_CRIT = 450; // Crit rate (1000=100%)
  84. .MOB_HIT = 300; // Hit rate
  85. .MOB_ATKMIN = 1000; // Base Attack Minimum
  86. .MOB_ATKMAX = 4000; // Base Attack Maximum
  87. .MOB_MATKMIN = 1000; // Magic Attack Minimum
  88. .MOB_MATKMAX = 4000; // Magic Attack Maximum
  89. .MOB_DEF = 35; // Defence
  90. .MOB_MDEF = 35; // Magic Defence
  91. .MOB_FLEE = 200; // Flee rate
  92. .MOB_PDODGE = 60; // Perfect Dodge
  93. .MOB_STR = 150; // Stat strength
  94. .MOB_AGI = 150; // Stat agility
  95. .MOB_VIT = 150; // Stat vitality
  96. .MOB_INT = 150; // Stat intellect
  97. .MOB_DEX = 150; // Stat dexterity
  98. .MOB_LUK = 150; // Stat luck
  99.  
  100. // Floating monster HP
  101. // When player is detected near the mob, update it's HP.
  102. .use_radar = 1; // 0=Disable, 1=Enable
  103.  
  104. // Mapflags effects, monster status, party lock, etc.
  105. .use_mapflags = 1; // 0=Disable, 1=Enable
  106.  
  107. // Event monster ID's
  108. setarray .event_mobs[0],
  109. 1093, // Eclipse
  110. 1096, // Angeling
  111. 1120, // Ghostring
  112. 1388, // Archangeling
  113. 1582, // Deviling
  114. 1795; // Bloody Knight
  115.  
  116. // Event rewards <ID>,<Amount> (One random array is selected)
  117. setarray .loots_0, 501,1, 502,1, 503,2, 504,2, 505,3, 506,3;
  118. setarray .loots_1, 507,1, 508,1, 509,2, 510,2, 511,3, 512,3;
  119. setarray .loots_2, 513,1, 514,1, 515,2, 516,2, 517,3, 518,3;
  120. setarray .loots_3, 519,1, 520,1, 521,2, 522,2, 523,3, 525,3;
  121.  
  122. // Event reward ID's array size (Important!)
  123. // If you add new .loots_<Number> arrays. You must change this accordingly.
  124. .loots_count = 3; // 0 count aswell
  125.  
  126. // Event map names
  127. setarray .event_maps$[0],
  128. "prontera", "morocc", "geffen", "payon",
  129. "alberta", "aldebaran", "xmas", "comodo",
  130. "yuno", "amatsu", "gonryun", "umbala",
  131. "louyang", "ayothaya", "einbroch", "hugel",
  132. "rachel", "veins", "moscovia";
  133.  
  134. // Event loot distribution mode description
  135. setarray .loot_mode_desc$[0],
  136. "Give all rewards to all party members", // 0
  137. "Give one reward to one random party member", // 1
  138. "Give all rewards to one random party member", // 2
  139. "Give rewards randomly between all party members", // 3
  140. "Give all rewards to all nearby players and their party members", // 4 (Skip UI)
  141. "Give one reward to all nearby players and their party members", // 5 (Skip UI)
  142. "Give all rewards to all nearby players", // 6 (Skip UI)
  143. "Give one reward to all nearby players", // 7 (Skip UI)
  144. "Give all rewards to all players in the same map", // 8 (Skip UI)
  145. "Give one reward to all players in the same map", // 9 (Skip UI)
  146. "Give all rewards to selected party member", // 10
  147. "Give one random reward to selected party member"; // 11
  148.  
  149. // TESTS
  150. // Log console information
  151. // This will report incorrect monster ID's on script load
  152. /*for( .@i = 0; .@i < getarraysize(.event_mobs); .@i++ ) {
  153. if( getmonsterinfo(.event_mobs[.@i], 0) == "null" ) {
  154. debugmes .npc_name$ + ":OnInit Monster ID:" + .event_mobs[.@i] + " DOES NOT EXIST!";
  155. }
  156. }*/
  157. // Start event on script load (For testing purposes)
  158. //donpcevent .npc_name$ + "::OnEnable";
  159. end;
  160.  
  161. OnEnable:
  162. OnClock0402:
  163. OnClock2359:
  164. // Check free event maps
  165. if ( getarraysize($@WB_MAP$) >= getarraysize(.event_maps$) ) {
  166. debugmes .npc_name$+"::OnEnable all event maps are active!";
  167. //announce "[World Boss] Event has been cancelled! All event maps are active!", BC_ALL, 0xFF0000;
  168. end;
  169. }
  170.  
  171. // Select random monster
  172. .@rand_mob = rand( getarraysize( .event_mobs ) );
  173. .@monster_id = .event_mobs[ .@rand_mob ];
  174.  
  175. // Select random map
  176. .@i = 0;
  177. .@rand_map = rand( getarraysize( .event_maps$ ) ); // Random map index number
  178. while(inarray($@WB_MAP$[0], .event_maps$[.@rand_map]) != -1) {
  179. if(.@i > .loop_max) {
  180. debugmes .npc_name$+"::OnEnable event map max loop count!";
  181. //announce "[World Boss] Event has been cancelled! Could not find free event map!", BC_ALL, 0xFF0000;
  182. end;
  183. }
  184. .@rand_map = rand( getarraysize( .event_maps$ ) );
  185. .@i++;
  186. }
  187. .@map_name$ = .event_maps$[ .@rand_map ];
  188.  
  189. // Announce event will start soon
  190. announce "[World Boss] A rift on time and space is about to be opened! A World Boss will appear in "+(.event_sleep / 60000)+" minute! Prepare your Hunting Party!",BC_ALL,0xFF0000,FW_BOLD,18;
  191.  
  192. // Sleep until X time have passed and then continue script
  193. sleep .event_sleep;
  194.  
  195. // Get last event index
  196. .@index = getarraysize($@WB_MOB_GID);
  197.  
  198. // Set mapflags if enabled
  199. if ( .use_mapflags ) {
  200. // Save event maps original mapflags
  201. setarray $@WB_MF_PARTYLOCK[.@index], getmapflag(.@map_name$, MF_PARTYLOCK);
  202. setarray $@WB_MF_NOMOBLOOT[.@index], getmapflag(.@map_name$, MF_NOMOBLOOT);
  203. setarray $@WB_MF_NOMVPLOOT[.@index], getmapflag(.@map_name$, MF_NOMVPLOOT);
  204. setarray $@WB_MF_NOPENALTY[.@index], getmapflag(.@map_name$, MF_NOPENALTY);
  205. setarray $@WB_MF_NOMOBTELE[.@index], getmapflag(.@map_name$, MF_MONSTER_NOTELEPORT);
  206. setarray $@WB_MF_BASEEXP[.@index], getmapflag(.@map_name$, MF_BEXP);
  207. setarray $@WB_MF_JOBEXP[.@index], getmapflag(.@map_name$, MF_JEXP);
  208. //setarray $@WB_MF_FOG[.@index], getmapflag(.@map_name$, MF_FOG);
  209.  
  210. // Set new mapflags
  211. setmapflag .@map_name$, MF_PARTYLOCK; // Disable changing party(Inviting new players in event map)
  212. setmapflag .@map_name$, MF_NOMOBLOOT; // Disable Normal monster loot drops
  213. setmapflag .@map_name$, MF_NOMVPLOOT; // Disable Boss monster loot drops
  214. setmapflag .@map_name$, MF_NOPENALTY; // Disable Exp and Zeny penalty
  215. setmapflag .@map_name$, MF_MONSTER_NOTELEPORT; // Disable monster teleport
  216. setmapflag .@map_name$, MF_BEXP, ($@WB_MF_BASEEXP[.@index] * .base_exp_multiplier); // Set Base Exp rating
  217. setmapflag .@map_name$, MF_JEXP, ($@WB_MF_JOBEXP[.@index] * .job_exp_multiplier); // Set Job Exp rating
  218. //setmapflag .@map_name$, MF_FOG; // Enable FOG effect
  219. }
  220.  
  221. // Summon event monster unit
  222. monster .@map_name$, 0, 0, "World Boss", .@monster_id, 1, .npc_name$+"::OnMobDie", Size_Large, AI_NONE;
  223. .@gid = $@mobid[0]; // Get monster's Game ID
  224.  
  225. // Change unit data to defaults
  226. setunitdata .@gid, UMOB_MAXHP, .MOB_MAXHP;
  227. setunitdata .@gid, UMOB_HP, .MOB_HP;
  228. setunitdata .@gid, UMOB_SPEED, .MOB_SPEED;
  229. setunitdata .@gid, UMOB_CRIT, .MOB_CRIT;
  230. setunitdata .@gid, UMOB_HIT, .MOB_HIT;
  231. setunitdata .@gid, UMOB_ATKMIN, .MOB_ATKMIN;
  232. setunitdata .@gid, UMOB_ATKMAX, .MOB_ATKMAX;
  233. setunitdata .@gid, UMOB_MATKMIN, .MOB_MATKMIN;
  234. setunitdata .@gid, UMOB_MATKMAX, .MOB_MATKMAX;
  235. setunitdata .@gid, UMOB_DEF, .MOB_DEF;
  236. setunitdata .@gid, UMOB_MDEF, .MOB_MDEF;
  237. setunitdata .@gid, UMOB_FLEE, .MOB_FLEE;
  238. setunitdata .@gid, UMOB_PDODGE, .MOB_PDODGE;
  239. setunitdata .@gid, UMOB_STR, .MOB_STR;
  240. setunitdata .@gid, UMOB_AGI, .MOB_AGI;
  241. setunitdata .@gid, UMOB_VIT, .MOB_VIT;
  242. setunitdata .@gid, UMOB_INT, .MOB_INT;
  243. setunitdata .@gid, UMOB_DEX, .MOB_DEX;
  244. setunitdata .@gid, UMOB_LUK, .MOB_LUK;
  245.  
  246. // Get units updated data
  247. getunitdata(.@gid, .@unit);
  248.  
  249. // Save event arrays
  250. setarray $@WB_MOB_ID[.@index], .@monster_id;
  251. setarray $@WB_MOB_GID[.@index], .@gid;
  252. setarray $@WB_TIMEOUT[.@index], gettimetick(0);
  253. setarray $@WB_RADAR_NEAR[.@index], 0;
  254. setarray $@WB_MAP$[.@index], .@map_name$;
  255. setarray $@WB_X[.@index], .@unit[UMOB_X];
  256. setarray $@WB_Y[.@index], .@unit[UMOB_Y];
  257.  
  258. // Unit talk
  259. unittalk .@gid, "Tremble before me mortals!", BC_AREA;
  260.  
  261. // Announce event started
  262. announce "[World Boss] A "+ getunitname(.@gid) +" has appeared in "+ .@map_name$ +" to wreck havoc!! Form a Hunting Party and stop it!!",BC_ALL,0xFF0000,FW_BOLD,18;
  263.  
  264. // Start unit radar
  265. if ( .use_radar && getarraysize($@WB_MOB_GID) ) {
  266. donpcevent "WorldBossRadar::OnEnable";
  267. }
  268.  
  269. // Start timeout timer
  270. if ( !getnpctimer(1, "WorldBossTimeout") ) {
  271. donpcevent "WorldBossTimeout::OnEnable";
  272. }
  273. end;
  274.  
  275. // Disable event
  276. OnDisable:
  277. //debugmes .npc_name$+"::OnDisable stop event!";
  278. // Stop timeout timer
  279. donpcevent "WorldBossTimeout::OnDisable";
  280.  
  281. // Stop unit radar
  282. if ( .use_radar ) {
  283. donpcevent "WorldBossRadar::OnDisable";
  284. }
  285.  
  286. // Reset server exp and drop rates
  287. if ( .use_floating_rates ) {
  288. donpcevent "WorldBossRates::OnDisable";
  289. }
  290.  
  291. // Loop all events
  292. for ( .@i = 0; .@i < getarraysize($@WB_MOB_GID); .@i++ ) {
  293. // Kill all units
  294. if ( unitexists($@WB_MOB_GID[.@i]) ) {
  295. unitkill($@WB_MOB_GID[.@i]);
  296. }
  297.  
  298. // Reset all mapflags to original values
  299. if ( .use_mapflags ) {
  300. callfunc("WB_ResetMapflags", $@WB_MAP$[.@i], .@i);
  301. }
  302. }
  303. // Kill all script or gm summoned monsters
  304. //killmonster .event_map$, "All";
  305.  
  306. // Reset all event arrays
  307. callfunc("WB_ResetAllGlobals");
  308. end;
  309.  
  310. OnMobDie:
  311. // Event when monster has been killed
  312. // Stop unit radar and timeout if no unit is alive
  313. if ( !getarraysize($@WB_MOB_GID) ) {
  314. if ( .use_radar ) donpcevent "WorldBossRadar::OnDisable";
  315. donpcevent "WorldBossTimeout::OnDisable";
  316. }
  317.  
  318. // Check attached unit
  319. .@unit_gid = getattachedrid();
  320. if ( !.@unit_gid ) {
  321. // No unit attached. Propably killed by unitkill or other script command
  322. //donpcevent .npc_name$+"::OnDisable";
  323. end;
  324. }
  325.  
  326. // Get unit type
  327. .@unit_type = getunittype(.@unit_gid);
  328. if ( .@unit_type == -1 ) {
  329. debugmes .npc_name$+"::OnMobDie FATAL no unit type found!";
  330. donpcevent .npc_name$+"::OnDisable";
  331. end;
  332. }
  333.  
  334. // Get map coordinates (Treasure Chest NPC will need these coordinates)
  335. getmapxy(.event_map$, .event_x, .event_y, .@unit_type);
  336.  
  337. // Announce
  338. announce "[World Boss] The World Boss have been killed! Congratulations!", bc_all, 0xFF0000;
  339.  
  340. // Increase server exp and drop rates for limited time
  341. if ( .use_floating_rates ) {
  342. donpcevent "WorldBossRates::OnEnable";
  343. }
  344.  
  345. // Get index if map name are the same
  346. .@event_index = inarray($@WB_MAP$[0], .event_map$);
  347.  
  348. // Check if index was found and stop if not
  349. if ( .@event_index == -1 ) {
  350. debugmes .npc_name$+"::OnMobDie event index was not found!";
  351. end;
  352. }
  353.  
  354. // Reset mapflags to original values
  355. if ( .use_mapflags ) {
  356. callfunc("WB_ResetMapflags", $@WB_MAP$[.@event_index], .@event_index);
  357. }
  358.  
  359. // If unit is not PC, try to attach unit master to the script
  360. if ( .@unit_type != BL_PC ) {
  361. getunitdata(.@unit_gid, .@data);
  362. if (.@unit_type == BL_NPC) {
  363. // NPC does not have master
  364. debugmes .npc_name$+"::OnMobDie NPC no player attached!";
  365. end;
  366. }
  367. if (.@unit_type == BL_PET) {
  368. if (!attachrid(.@data[UPET_MASTERAID])) {
  369. debugmes .npc_name$+"::OnMobDie PET no player attached!";
  370. end;
  371. }
  372. }
  373. if (.@unit_type == BL_MOB) {
  374. if (!attachrid(.@data[UMOB_MASTERAID])) {
  375. debugmes .npc_name$+"::OnMobDie MOB no player attached!";
  376. end;
  377. }
  378. }
  379. if (.@unit_type == BL_HOM) {
  380. .@name$ = strcharinfo(0,.@data[UHOM_MASTERCID]);
  381. if (!attachrid(getcharid(3,.@name$))) {
  382. debugmes .npc_name$+"::OnMobDie HOM no player attached!";
  383. end;
  384. }
  385. }
  386. if (.@unit_type == BL_MER) {
  387. .@name$ = strcharinfo(0,.@data[UMER_MASTERCID]);
  388. if (!attachrid(getcharid(3,.@name$))) {
  389. debugmes .npc_name$+"::OnMobDie MER no player attached!";
  390. end;
  391. }
  392. }
  393. if (.@unit_type == BL_ELEM) {
  394. .@name$ = strcharinfo(0,.@data[UELE_MASTERCID]);
  395. if (!attachrid(getcharid(3,.@name$))) {
  396. debugmes .npc_name$+"::OnMobDie ELE no player attached!";
  397. end;
  398. }
  399. }
  400. }
  401.  
  402. // Get party ID
  403. .@party_id = getcharid(1);
  404. // Save event arrays
  405. setarray $@WB_MAP$[.@event_index], .event_map$;
  406. setarray $@WB_X[.@event_index], .event_x;
  407. setarray $@WB_Y[.@event_index], .event_y;
  408. setarray $@WB_PARTY_ID[.@event_index], .@party_id;
  409. // Select random reward/loots array
  410. setarray $@WB_REWARD_INDEX[.@event_index], rand(0, .loots_count);
  411.  
  412. // Enable first available Treasure Chest NPC
  413. // Set .event_map$, .event_x, .event_y before enabling ( Important! )
  414. for ( .@i = 0; .@i <= .duplicate_npc_count; .@i++ ) {
  415. .@npc$ = "Treasure Chest#wb_"+ .@i; // Name of the NPC
  416. if ( getnpcid(0, .@npc$) ) { // If NPC exists
  417. if ( !getnpctimer( 1, .@npc$ ) ) { // If has active timer=1
  418. setarray $@WB_NPC_NAME$[.@event_index], .@npc$;
  419. donpcevent .@npc$ +"::OnEnable";
  420. break;
  421. }
  422. } else {
  423. debugmes .npc_name$+"::OnMobDie no Treasure Chest#wb_"+.@i+" NPC found!";
  424. }
  425. }
  426.  
  427. // Switch by loot mode and save character IDs for access
  428. switch( .loot_mode ) {
  429. case 0:
  430. case 1:
  431. case 2:
  432. case 3: // In same party or single player
  433. case 10: // All to selected party member
  434. case 11: // One random to selected party member
  435. // Attach all available party members
  436. if ( getcharid(1) ) {
  437. addrid(2, 0, getcharid(1));
  438. }
  439. break;
  440.  
  441. case 4:
  442. case 5: // In range and party
  443. // Attach all available players in 20 cells from the killer RID
  444. addrid(4, 0, (.event_x - 20),(.event_y - 20), (.event_x + 20),(.event_y + 20));
  445.  
  446. // Attach all available party members
  447. if ( getcharid(1) ) {
  448. addrid(2, 0, getcharid(1));
  449. }
  450. break;
  451.  
  452. case 6:
  453. case 7: // In range
  454. // Attach all available players in 20 cells from the killer RID
  455. addrid(4, 0, (.event_x - 20),(.event_y - 20), (.event_x + 20),(.event_y + 20));
  456. break;
  457.  
  458. case 8:
  459. case 9: // In the same map
  460. addrid(1, 0, getcharid(1));
  461. break;
  462. }
  463.  
  464. // Find matching character IDs from the access array
  465. .@access_index = inarray($@WB_ACCESS[0], getcharid(0));
  466.  
  467. // Find same IP address
  468. if (.filter_same_ip) {
  469. // Exit if same IP already exist
  470. if ( inarray($@WB_IP_ACCESS[0], getcharip()) != -1 ) {
  471. end;
  472. }
  473. }
  474.  
  475. // Exit if character already has access
  476. if ( .@access_index != -1 ) {
  477. end;
  478. }
  479.  
  480. // Save character ID into access array
  481. setarray $@WB_ACCESS[getarraysize($@WB_ACCESS)], getcharid(0);
  482. setarray $@WB_IP_ACCESS[getarraysize($@WB_IP_ACCESS)], getcharip();
  483. setarray $@WB_ACCESS_EXPIRE[getarraysize($@WB_ACCESS_EXPIRE)], gettimetick(0);
  484.  
  485. // Start access expire timer if not already running
  486. if ( !getnpctimer(1, "WorldBossAccessExpire") ) {
  487. donpcevent "WorldBossAccessExpire::OnEnable";
  488. }
  489. end;
  490.  
  491. // Event when player opens Treasure Chest NPC
  492. OnTreasureOpen:
  493. // Get map coordinates of the player
  494. getmapxy(.@event_map$, .@x, .@y, BL_PC);
  495.  
  496. // Search for character ID from the access array
  497. .@access_index = inarray($@WB_ACCESS[0], getcharid(0));
  498.  
  499. // User has no access!
  500. if ( .@access_index == -1 ) {
  501. message strcharinfo(0), "Treasure Chest is empty.";
  502. end;
  503. }
  504.  
  505. // Get event index from the map name array
  506. .@event_index = inarray($@WB_MAP$[0], .@event_map$);
  507.  
  508. // Check if event index was found
  509. if ( .@event_index == -1 ) {
  510. debugmes .@name$+"::OnTreasureOpen event map name ( "+ .@event_map$ +" ) not found!";
  511. message strcharinfo(0), "Treasure Chest is empty.";
  512. end;
  513. }
  514.  
  515. // Select reward array
  516. .@rand_reward = $@WB_REWARD_INDEX[.@event_index];
  517. .@loots_size = getarraysize( getd(".loots_" + .@rand_reward) );
  518. //copyarray .@rewards_id[0], getd(".loots_" + .@rand_reward + "[0]"), .@loots_size; // .loots_0
  519.  
  520. // Rewards array
  521. // Get every second value from array.
  522. .@i = 0;
  523. for( .@j = 0; .@j < .@loots_size; .@j += 2 ) {
  524. setarray .@rewards_id[.@i], getd(".loots_" + .@rand_reward + "[" + .@j + "]");
  525. .@i++;
  526. }
  527. .@reward_size = getarraysize( .@rewards_id );
  528. // Amounts array
  529. // Get every second value from array.
  530. .@i = 0;
  531. for( .@j = 1; .@j < .@loots_size; .@j += 2 ) {
  532. setarray .@rewards_amount[.@i], getd(".loots_" + .@rand_reward + "[" + .@j + "]");
  533. .@i++;
  534. }
  535.  
  536. switch( .loot_mode ) {
  537. case 0: // All to all members
  538. case 2: // All to random member
  539. case 3: // Randomly to all members
  540. case 10: // All to selected party member
  541. case 11: // One random to selected party member
  542. if ( getcharid(1) ) {
  543. goto OnPartyLeader;
  544. } else {
  545. // Has no party
  546. for( .@i = 0; .@i < .@reward_size; .@i++ ) {
  547. getitem .@rewards_id[.@i], .@rewards_amount[.@i];
  548. }
  549. }
  550. break;
  551.  
  552. case 1: // One to random member
  553. if ( getcharid(1) ) {
  554. // Party Leader will distribute loots
  555. goto OnPartyLeader;
  556. } else {
  557. // Has no party
  558. .@rand = rand(.@reward_size);
  559. getitem .@rewards_id[.@rand], .@rewards_amount[.@rand];
  560. }
  561. break;
  562.  
  563. case 4: // All in range and party
  564. case 6: // All in range
  565. case 8: // All in same map
  566. default:
  567. // No UI
  568. for( .@i = 0; .@i < .@reward_size; .@i++ ) {
  569. getitem .@rewards_id[.@i], .@rewards_amount[.@i];
  570. }
  571. break;
  572.  
  573. case 5: // One in range and party
  574. case 7: // One in range
  575. case 9: // One in same map
  576. // No UI
  577. .@rand = rand(.@reward_size);
  578. getitem .@rewards_id[.@rand], .@rewards_amount[.@rand];
  579. break;
  580. }
  581.  
  582. // Remove character ID from the access array (Access is now used)
  583. deletearray $@WB_ACCESS[.@access_index], 1;
  584. deletearray $@WB_IP_ACCESS[.@access_index], 1;
  585. deletearray $@WB_ACCESS_EXPIRE[.@access_index], 1;
  586.  
  587. // Announce player
  588. message strcharinfo(0), "Congratulations! You have been rewarded for killing the World Boss.";
  589.  
  590. // Disable current NPC Treasure Chest
  591. if ( !getarraysize($@WB_ACCESS) ) {
  592. // Disable current NPC Treasure Chest
  593. callfunc("WB_ResetBox", .@event_index);
  594. // Stop access expire timer
  595. donpcevent "WorldBossAccessExpire::OnDisable";
  596. }
  597. end;
  598.  
  599. OnPartyLeader:
  600. // Get party ID
  601. .@party_id = getcharid(1);
  602.  
  603. // Check if player is party leader
  604. if ( getcharid(0) != getpartyleader( .@party_id, 2 ) ) {
  605. message strcharinfo(0), "You're not Party Leader.";
  606. end;
  607. }
  608.  
  609. // Get event index from the party ID array
  610. .@event_index = inarray($@WB_PARTY_ID[0], .@party_id );
  611.  
  612. // Check if party id has access!
  613. if ( .@event_index == -1 ) {
  614. message strcharinfo(0), "Treasure Chest is empty.";
  615. end;
  616. }
  617.  
  618. // Select random reward array
  619. .@rand_reward = $@WB_REWARD_INDEX[.@event_index];
  620. .@loots_size = getarraysize(getd(".loots_" + .@rand_reward));
  621. //copyarray .@rewards_id[0], getd(".loots_" + .@rand_reward + "[0]"), .@loots_size; // .loots_0_id
  622.  
  623. // Rewards array
  624. // Get every second value from array.
  625. .@i = 0;
  626. for( .@j = 0; .@j < .@loots_size; .@j += 2 ) {
  627. setarray .@rewards_id[.@i], getd(".loots_" + .@rand_reward + "[" + .@j + "]");
  628. .@i++;
  629. }
  630. .@reward_size = getarraysize( .@rewards_id );
  631. // Amounts array
  632. // Get every second value from array.
  633. .@i = 0;
  634. for( .@j = 1; .@j < .@loots_size; .@j += 2 ) {
  635. setarray .@rewards_amount[.@i], getd(".loots_" + .@rand_reward + "[" + .@j + "]");
  636. .@i++;
  637. }
  638.  
  639. // Show loot distribution window
  640. mes "[ Loot Distributor ]";
  641. mes "Please ensure you distribute the Rewards. If you cancelled this, your party might not able to receive any rewards.";
  642. mes "^777777Loot mode : ^000000" + .loot_mode_desc$[.loot_mode]; // Loot mode description
  643. next;
  644. mes "[ Loot Distributor ]";
  645. for( .@i = 0; .@i < .@reward_size; .@i++ ) {
  646. mes "^777777 ~ " + .@rewards_amount[.@i] + " x " + getitemname( .@rewards_id[.@i] ) + "^000000";
  647. }
  648. next;
  649. if( select( "Distribute Loots", "Dispose Loots" ) == 1 ) {
  650. // Get party data
  651. getpartymember .@party_id, 0; // Name
  652. getpartymember .@party_id, 1; // Character IDs
  653. getpartymember .@party_id, 2; // Account IDs
  654.  
  655. // Copy the temporary party data
  656. .@party_size = $@partymembercount;
  657. copyarray .@party_cid[0], $@partymembercid[0], .@party_size;
  658. copyarray .@party_aid[0], $@partymemberaid[0], .@party_size;
  659. copyarray .@party_name$[0], $@partymembername$[0], .@party_size;
  660.  
  661. // LOOT MODE 0: Give all rewards to all party members
  662. if( .loot_mode == 0 ) {
  663. mes "[ Loot Distributor ]";
  664. // Loop through each party member
  665. .@count_ip = 0;
  666. for( .@idx = 0; .@idx < .@party_size; .@idx++ ) {
  667. // Filter same IP address
  668. if ( .filter_same_ip ) {
  669. if ( inarray($@WB_IP_ACCESS[0], getcharip(.@party_aid[.@idx])) != -1 ) {
  670. .@count_ip++;
  671. }
  672. }
  673. // Online check
  674. if( isloggedin(.@party_aid[.@idx], .@party_cid[.@idx]) && .@count_ip < 2 ) {
  675. mes " ~ " + strcharinfo(0, .@party_cid[.@idx]) + " was rewarded!";
  676. // Loop through each reward
  677. for( .@i = 0; .@i < .@reward_size; .@i++ ) {
  678. getitem .@rewards_id[.@i], .@rewards_amount[.@i], .@party_aid[.@idx];
  679. }
  680. }
  681. }
  682. }
  683.  
  684. // LOOT MODE 1: Give one reward to one random party member
  685. else if( .loot_mode == 1 ) {
  686. // Select random party member X times.
  687. SelectRandom1:
  688. .@attempts = 0; // Counter for random player select
  689. .@rand_party = rand(.@party_size);
  690. while( !isloggedin(.@party_aid[.@rand_party], .@party_cid[.@rand_party]) ) {
  691. if( .@attempts >= .loop_max ) break;
  692. .@rand_party = rand(.@party_size);
  693. .@attempts++;
  694. }
  695. // Max attempts reached
  696. if( .@attempts >= .loop_max ) {
  697. mes "[ Player not found ]";
  698. mes "Tried to select random player " + .@attempts + " times!";
  699. mes "Do you want to try again?";
  700. next;
  701. if( select("Yes:No") == 1 ) {
  702. goto SelectRandom1;
  703. } else {
  704. goto OnClose;
  705. }
  706. }
  707. // Backup online check (next; will pause script and players can disconnect)
  708. if( !isloggedin(.@party_aid[.@rand_party], .@party_cid[.@rand_party]) ) {
  709. mes "[ Player not online ]";
  710. mes "Member is ^777777offline^000000";
  711. mes "Do you want to try again?";
  712. next;
  713. if( select("Yes:No") == 1 ) {
  714. goto SelectRandom1;
  715. } else {
  716. goto OnClose;
  717. }
  718. }
  719. // Give random reward
  720. .@rand_item = rand(.@reward_size);
  721. .@name$ = strcharinfo(0, .@party_cid[.@rand_party]);
  722. mes "[ Loot Distributor ]";
  723. mes .@name$ + "^777777 ~ " + .@rewards_amount[.@rand_item] + " x " + getitemname( .@rewards_id[.@rand_item] ) + "^000000";
  724. message .@name$, "Gained " + .@rewards_amount[.@rand_item] + " x " + getitemname( .@rewards_id[.@rand_item] ) + " ( Distributed Randomly )";
  725. getitem .@rewards_id[.@rand_item], .@rewards_amount[.@rand_item], .@party_aid[.@rand_party];
  726. }
  727.  
  728. // LOOT MODE 2: Give all rewards to one random party member
  729. else if( .loot_mode == 2 ) {
  730. // Select random party member X times.
  731. SelectRandom2:
  732. .@attempts = 0; // Counter for random player select
  733. .@rand_party = rand(.@party_size);
  734. while( !isloggedin(.@party_aid[.@rand_party], .@party_cid[.@rand_party]) ) {
  735. if( .@attempts >= .loop_max ) break;
  736. .@rand_party = rand(.@party_size);
  737. .@attempts++;
  738. }
  739. // Max attempts reached
  740. if( .@attempts >= .loop_max ) {
  741. mes "[ Player not found ]";
  742. mes "Tried to select random player " + .@attempts + " times!";
  743. mes "Do you want to try again?";
  744. next;
  745. if( select("Yes:No") == 1 ) {
  746. goto SelectRandom2;
  747. } else {
  748. goto OnClose;
  749. }
  750. }
  751. // Backup online check (next; will pause script and players can disconnect)
  752. if( !isloggedin(.@party_aid[.@rand_party], .@party_cid[.@rand_party]) ) {
  753. mes "[ Player not online ]";
  754. mes "Member is ^777777offline^000000";
  755. mes "Do you want to try again?";
  756. next;
  757. if( select("Yes:No") == 1 ) {
  758. goto SelectRandom2;
  759. } else {
  760. goto OnClose;
  761. }
  762. }
  763. // Give rewards
  764. .@name$ = strcharinfo(0, .@party_cid[.@rand_party]);
  765. mes "[ Loot Distributor ]";
  766. // Loop through each reward
  767. for( .@i = 0; .@i < .@reward_size; .@i++ ) {
  768. mes .@name$ + "^777777 ~ " + .@rewards_amount[.@i] + " x " + getitemname( .@rewards_id[.@i] ) + "^000000";
  769. message .@name$, "Gained " + .@rewards_amount[.@i] + " x " + getitemname( .@rewards_id[.@i] ) + " ( Distributed Randomly )";
  770. getitem .@rewards_id[.@i], .@rewards_amount[.@i], .@party_aid[.@rand_party];
  771. }
  772. }
  773.  
  774. // LOOT MODE 3: Give rewards randomly between all party members
  775. else if( .loot_mode == 3 ) {
  776. mes "[ Loot Distributor ]";
  777. // Loop through each reward
  778. for( .@i = 0; .@i < .@reward_size; .@i++ ) {
  779. // Select random party member X times.
  780. SelectRandom3:
  781. .@attempts = 0; // Counter for random player select
  782. .@rand_party = rand(.@party_size);
  783. while( !isloggedin(.@party_aid[.@rand_party], .@party_cid[.@rand_party]) ) {
  784. if( .@attempts >= .loop_max ) break;
  785. .@rand_party = rand(.@party_size);
  786. .@attempts++;
  787. }
  788. // Max attempts reached
  789. if( .@attempts >= .loop_max ) {
  790. mes "[ Player not found ]";
  791. mes "Tried to select random player " + .@attempts + " times!";
  792. mes "Do you want to try again?";
  793. next;
  794. if( select("Yes:No") == 1 ) {
  795. goto SelectRandom3;
  796. } else {
  797. goto OnClose;
  798. }
  799. }
  800. // Backup online check (next; will pause script and players can disconnect)
  801. if( !isloggedin(.@party_aid[.@rand_party], .@party_cid[.@rand_party]) ) {
  802. mes "[ Player not online ]";
  803. mes "Member is ^777777offline^000000";
  804. mes "Do you want to try again?";
  805. next;
  806. if( select("Yes:No") == 1 ) {
  807. goto SelectRandom3;
  808. } else {
  809. goto OnClose;
  810. }
  811. }
  812. // Give single reward
  813. .@name$ = strcharinfo(0, .@party_cid[.@rand_party]);
  814. mes .@name$ + "^777777 ~ " + .@rewards_amount[.@i] + " x " + getitemname( .@rewards_id[.@i] ) + "^000000";
  815. message .@name$, "Gained " + .@rewards_amount[.@i] + " x " + getitemname( .@rewards_id[.@i] ) + " ( Distributed Randomly )";
  816. getitem .@rewards_id[.@i], .@rewards_amount[.@i], .@party_aid[.@rand_party];
  817. }
  818. }
  819.  
  820. // LOOT MODE 10: Give all rewards to selected party member
  821. // LOOT MODE 11: Give one reward to selected party member
  822. else if( .loot_mode >= 10 && .loot_mode <= 11 ) {
  823. SelectMember:
  824. // Open Party Select Menu
  825. .@select = callfunc("WB_PartySelect", 1, 1);
  826.  
  827. // Refresh selected
  828. while ( .@select == -1 ) {
  829. message strcharinfo(0), "Refresh menu!";
  830. .@select = callfunc("WB_PartySelect", 1, 1);
  831. }
  832.  
  833. // Not in a party (Leaved before select or removed)
  834. if ( .@select == -2 ) {
  835. message strcharinfo(0), "You don't have a party.";
  836. end;
  837. }
  838.  
  839. // Is selected member online
  840. if ( !isloggedin(.@party_aid[.@select], .@party_cid[.@select]) ) {
  841. mes "[ Loot Distributor ]";
  842. mes "Selected party member is not online.";
  843. mes "Please select again.";
  844. next;
  845. goto SelectMember;
  846. }
  847.  
  848. // Get more party data
  849. .@party_name$ = getpartyname(.@party_id); // Party Name
  850. .@party_leader_cid = getpartyleader(.@party_id, 2); // Party Leader Character ID
  851. // Party Leader Name
  852. .@party_leader_name$ = "[Offline]";
  853. if ( .@party_leader_cid != -1 ) {
  854. // strcharinfo(0,.@party_leader_cid); will fail if leader is offline!
  855. for (.@i = 0; .@i < .@party_size; .@i++ ) {
  856. // Match leader cid with party member cid
  857. if ( .@party_leader_cid == .@party_member_cid[.@i] ) {
  858. .@party_leader_name$ = .@party_member_name$[.@i];
  859. }
  860. }
  861. }
  862.  
  863. // Double check
  864. // Check for party changes, because players can leave anytime.
  865. .@party_id2 = getcharid(1);
  866. .@check_failed = false;
  867.  
  868. // Not in a party anymore (Leaved after select or removed)
  869. if ( !.@party_id2 ) {
  870. message strcharinfo(0), "You don't have a party.";
  871. mes "[ Loot Distributor ]";
  872. mes "Your party has made changes during selection.";
  873. mes "Please select again.";
  874. close;
  875. }
  876.  
  877. // Check if party ID has changed
  878. if (.@party_id != .@party_id2) {
  879. message strcharinfo(0), "Failed: Party ID has changed!";
  880. mes "[ Loot Distributor ]";
  881. mes "Your party has made changes during selection.";
  882. mes "Please select again.";
  883. close;
  884. }
  885.  
  886. // Get new party data
  887. getpartymember .@party_id2, 0; // names
  888. .@new_party_size = $@partymembercount;
  889. copyarray .@partymembername$[0], $@partymembername$[0], .@new_party_size;
  890.  
  891. // Check if party size has changed during select.
  892. if (.@new_party_size != .@party_size) {
  893. message strcharinfo(0), "Failed: Party size has changed!";
  894. mes "[ Loot Distributor ]";
  895. mes "Your party has made changes during selection.";
  896. mes "Please select again.";
  897. close;
  898. }
  899.  
  900. // Check if party member names has changed during select.
  901. for (.@i = 0; .@i < .@party_size; .@i++ ) {
  902. // Match new and old name
  903. if ( .@partymembername$[.@i] != .@party_member_name$[.@i] ) {
  904. .@check_failed = true;
  905. message strcharinfo(0), "Failed: Party member name has changed!";
  906. break;
  907. }
  908. }
  909.  
  910. // Has any checks failed
  911. if ( .@i >= .@party_size && .@check_failed ) {
  912. mes "[ Loot Distributor ]";
  913. mes "Your party has made changes during selection.";
  914. mes "Please select again.";
  915. close;
  916. }
  917.  
  918. // Success; Give rewards
  919. if (.loot_mode == 10) {
  920. // All rewards to selected member
  921. .@name$ = strcharinfo(0, .@party_cid[.@select]);
  922. mes "[ Loot Distributor ]";
  923. // Loop through each reward
  924. for( .@i = 0; .@i < .@reward_size; .@i++ ) {
  925. mes .@name$ + "^777777 ~ " + .@rewards_amount[.@i] + " x " + getitemname( .@rewards_id[.@i] ) + "^000000";
  926. message .@name$, "Gained " + .@rewards_amount[.@i] + " x " + getitemname( .@rewards_id[.@i] ) + " ( Distributed Randomly )";
  927. getitem .@rewards_id[.@i], .@rewards_amount[.@i], .@party_aid[.@select];
  928. }
  929. }
  930. else if (.loot_mode == 11) {
  931. // Give one random reward to selected member
  932. .@rand_item = rand(.@reward_size);
  933. .@name$ = strcharinfo(0, .@party_cid[.@select]);
  934. mes "[ Loot Distributor ]";
  935. mes .@name$ + "^777777 ~ " + .@rewards_amount[.@rand_item] + " x " + getitemname( .@rewards_id[.@rand_item] ) + "^000000";
  936. message .@name$, "Gained " + .@rewards_amount[.@rand_item] + " x " + getitemname( .@rewards_id[.@rand_item] ) + " ( Distributed Randomly )";
  937. getitem .@rewards_id[.@rand_item], .@rewards_amount[.@rand_item], .@party_aid[.@select];
  938. }
  939. }
  940. } else {
  941. // Disposed loots
  942. mes "[ Loot Distributor ]";
  943. }
  944. mes "Congratulations!";
  945. // Remove all party members access
  946. callfunc("WB_ResetPartyAccess", .@party_id);
  947. close2;
  948. // Disable current NPC Treasure Chest
  949. callfunc("WB_ResetBox", .@event_index);
  950. end;
  951.  
  952. OnClose:
  953. // Close reward window
  954. mes "[ Loot Distributor ]";
  955. mes "Good bye.";
  956. close;
  957. }
  958.  
  959. // Function: Reset all party members access IDs
  960. // callfunc("WB_ResetPartyAccess", <party id>)
  961. function script WB_ResetPartyAccess {
  962. .@party_id = getarg(0);
  963. getpartymember .@party_id, 1; // Character IDs
  964. .@party_size = $@partymembercount;
  965. copyarray .@party_cid[0], $@partymembercid[0], .@party_size;
  966. for ( .@i = 0; .@i < .@party_size; .@i++ ) {
  967. for ( .@j = 0; .@j < getarraysize($@WB_ACCESS); .@j++ ) {
  968. if ( $@WB_ACCESS[.@j] == .@party_cid[.@i] ) {
  969. deletearray $@WB_ACCESS[.@j], 1;
  970. deletearray $@WB_IP_ACCESS[.@j], 1;
  971. deletearray $@WB_ACCESS_EXPIRE[.@j], 1;
  972. }
  973. }
  974. }
  975. // Remove party id
  976. /*for ( .@i = 0; .@i < getarraysize($@WB_PARTY_ID); .@i++ ) {
  977. if ( $@WB_PARTY_ID[.@i] == .@party_id ) {
  978. deletearray $@WB_PARTY_ID[.@i], 1;
  979. }
  980. }*/
  981. return;
  982. }
  983.  
  984. // Function: Reset specific WorldBoss event global arrays
  985. // callfunc("WB_ResetEventGlobals", <index>)
  986. function script WB_ResetEventGlobals {
  987. .@index = getarg(0, 0); // Event index Default=0
  988. deletearray $@WB_MOB_ID[.@index], 1; // Rename from $@WB_ID
  989. deletearray $@WB_MOB_GID[.@index], 1; // Rename from $@WB_GID
  990. deletearray $@WB_TIMEOUT[.@index], 1;
  991. deletearray $@WB_RADAR_NEAR[.@index], 1; // Rename from $@WB_NEAR
  992. deletearray $@WB_MAP$[.@index], 1;
  993. deletearray $@WB_X[.@index], 1;
  994. deletearray $@WB_Y[.@index], 1;
  995. deletearray $@WB_REWARD_INDEX[.@index], 1; // Rename from $@WB_REWARD
  996. deletearray $@WB_PARTY_ID[.@index], 1; // Rename from $@WB_PARTY
  997. deletearray $@WB_NPC_NAME$[.@index], 1; // Rename from $@WB_BOX
  998. //deletearray $@WB_ACCESS[.@index], 1;
  999. //deletearray $@WB_IP_ACCESS[.@index], 1;
  1000. //deletearray $@WB_ACCESS_EXPIRE[.@index], 1;
  1001. deletearray $@WB_MF_PARTYLOCK[.@index], 1;
  1002. deletearray $@WB_MF_NOMOBLOOT[.@index], 1;
  1003. deletearray $@WB_MF_NOMVPLOOT[.@index], 1;
  1004. deletearray $@WB_MF_NOPENALTY[.@index], 1;
  1005. deletearray $@WB_MF_NOMOBTELE[.@index], 1;
  1006. deletearray $@WB_MF_BASEEXP[.@index], 1;
  1007. deletearray $@WB_MF_JOBEXP[.@index], 1;
  1008. //deletearray $@WB_MF_FOG[.@index], 1;
  1009. return;
  1010. }
  1011.  
  1012. // Function: Reset all WorldBoss event global arrays
  1013. // callfunc("WB_ResetAllGlobals")
  1014. function script WB_ResetAllGlobals {
  1015. deletearray $@WB_MOB_ID[0], getarraysize($@WB_MOB_ID);
  1016. deletearray $@WB_MOB_GID[0], getarraysize($@WB_MOB_GID);
  1017. deletearray $@WB_TIMEOUT[0], getarraysize($@WB_TIMEOUT);
  1018. deletearray $@WB_RADAR_NEAR[0], getarraysize($@WB_RADAR_NEAR);
  1019. deletearray $@WB_MAP$[0], getarraysize($@WB_MAP$);
  1020. deletearray $@WB_X[0], getarraysize($@WB_X);
  1021. deletearray $@WB_Y[0], getarraysize($@WB_Y);
  1022. deletearray $@WB_REWARD_INDEX[0], getarraysize($@WB_REWARD_INDEX);
  1023. deletearray $@WB_PARTY_ID[0], getarraysize($@WB_PARTY_ID);
  1024. deletearray $@WB_NPC_NAME$[0], getarraysize($@WB_NPC_NAME$);
  1025. deletearray $@WB_ACCESS[0], getarraysize($@WB_ACCESS);
  1026. deletearray $@WB_IP_ACCESS[0], getarraysize($@WB_IP_ACCESS);
  1027. deletearray $@WB_ACCESS_EXPIRE[0], getarraysize($@WB_ACCESS_EXPIRE);
  1028. deletearray $@WB_MF_PARTYLOCK[0], getarraysize($@WB_MF_PARTYLOCK);
  1029. deletearray $@WB_MF_NOMOBLOOT[0], getarraysize($@WB_MF_NOMOBLOOT);
  1030. deletearray $@WB_MF_NOMVPLOOT[0], getarraysize($@WB_MF_NOMVPLOOT);
  1031. deletearray $@WB_MF_NOPENALTY[0], getarraysize($@WB_MF_NOPENALTY);
  1032. deletearray $@WB_MF_NOMOBTELE[0], getarraysize($@WB_MF_NOMOBTELE);
  1033. deletearray $@WB_MF_BASEEXP[0], getarraysize($@WB_MF_BASEEXP);
  1034. deletearray $@WB_MF_JOBEXP[0], getarraysize($@WB_MF_JOBEXP);
  1035. //deletearray $@WB_MF_FOG[0], getarraysize($@WB_MF_FOG);
  1036. return;
  1037. }
  1038.  
  1039. // Function: Reset all mapflags to original values
  1040. // callfunc("WB_ResetMapflags", <map name>, <index>)
  1041. function script WB_ResetMapflags {
  1042. .@map$ = getarg(0, "null"); // Map name Default="null"
  1043. .@index = getarg(1, 0); // Event index Default=0
  1044. // Map name exists
  1045. if (.@map$ == "" || .@map$ == "null") {
  1046. debugmes "WB_ResetMapflags was given:"+ .@map$;
  1047. return;
  1048. }
  1049. // Party Lock
  1050. if ( $@WB_MF_PARTYLOCK[.@index] )
  1051. setmapflag .@map$, MF_PARTYLOCK;
  1052. else
  1053. removemapflag .@map$, MF_PARTYLOCK;
  1054. // No mob loot
  1055. if ( $@WB_MF_NOMOBLOOT[.@index] )
  1056. setmapflag .@map$, MF_NOMOBLOOT;
  1057. else
  1058. removemapflag .@map$, MF_NOMOBLOOT;
  1059. // No MVP loot
  1060. if ( $@WB_MF_NOMVPLOOT[.@index] )
  1061. setmapflag .@map$, MF_NOMVPLOOT;
  1062. else
  1063. removemapflag .@map$, MF_NOMVPLOOT;
  1064. // No penalty
  1065. if ( $@WB_MF_NOPENALTY[.@index] )
  1066. setmapflag .@map$, MF_NOPENALTY;
  1067. else
  1068. removemapflag .@map$, MF_NOPENALTY;
  1069. // No mob teleport
  1070. if ( $@WB_MF_NOMOBTELE[.@index] )
  1071. setmapflag .@map$, MF_MONSTER_NOTELEPORT;
  1072. else
  1073. removemapflag .@map$, MF_MONSTER_NOTELEPORT;
  1074. // Base Exp
  1075. setmapflag .@map$, MF_BEXP, $@WB_MF_BASEEXP[.@index];
  1076. // Job Exp
  1077. setmapflag .@map$, MF_JEXP, $@WB_MF_JOBEXP[.@index];
  1078. // Effect FOG
  1079. //if ( $@WB_MF_FOG[.@index] )
  1080. // setmapflag .@map$, MF_FOG;
  1081. //else
  1082. // removemapflag .@map$, MF_FOG;
  1083. return;
  1084. }
  1085.  
  1086. // Function: Reset specific Treasure Chest NPC
  1087. // callfunc("WB_ResetBox", <index>)
  1088. function script WB_ResetBox {
  1089. .@index = getarg(0, 0); // Event index Default=0
  1090. if ( $@WB_NPC_NAME$[.@index] != "" ) {
  1091. if ( getnpcid(0, $@WB_NPC_NAME$[.@index]) ) {
  1092. // Do these checks or this will select all NPCs on the server when fail
  1093. donpcevent $@WB_NPC_NAME$[.@index]+"::OnDisable";
  1094. }
  1095. }
  1096. }
  1097.  
  1098. // Function: Reset all Treasure Chest NPC's
  1099. // callfunc("WB_ResetAllBoxes")
  1100. function script WB_ResetAllBoxes {
  1101. for ( .@i = 0; .@i < getarraysize($@WB_NPC_NAME$); .@i++ ) {
  1102. if ( $@WB_NPC_NAME$[.@i] != "" ) {
  1103. if ( getnpcid(0, $@WB_NPC_NAME$[.@i]) ) {
  1104. // Do these checks or this will select all NPCs on the server when fail
  1105. donpcevent $@WB_NPC_NAME$[.@i]+"::OnDisable";
  1106. }
  1107. }
  1108. }
  1109. }
  1110.  
  1111. // Function Party Select
  1112. // callfunc("WB_PartySelect", <INT_show_offline>, <INT_show_refresh>)
  1113. // Return INT=Party index number, -1=Refresh selected, -2=Not in party
  1114. function script WB_PartySelect {
  1115. .@s_offline = getarg(0, 1); // Show offline players in menu? 1=Yes 0=No
  1116. .@s_refresh = getarg(1, 1); // Show refresh menu item? 1=Yes 0=No
  1117. .@party_id = getcharid(1); // Party ID
  1118.  
  1119. // Not in a party
  1120. if ( !.@party_id )
  1121. return -2;
  1122.  
  1123. getpartymember .@party_id, 0; // Names
  1124. getpartymember .@party_id, 1; // Character IDs
  1125. getpartymember .@party_id, 2; // Account IDs
  1126.  
  1127. // Copy the temporary party data
  1128. .@party_size = $@partymembercount;
  1129. copyarray .@party_member_name$[0], $@partymembername$[0], .@party_size;
  1130. copyarray .@party_member_cid[0], $@partymembercid[0], .@party_size;
  1131. copyarray .@party_member_aid[0], $@partymemberaid[0], .@party_size;
  1132.  
  1133. // Create menu
  1134. if ( .@s_refresh )
  1135. .@menu_party$ = "^777777[Refresh]^000000";
  1136. .@menu_party$ = .@menu_party$ + ":";
  1137.  
  1138. // Loop through each party member and add to menu
  1139. for ( .@i = 0; .@i < .@party_size; .@i++ ) {
  1140. if ( isloggedin(.@party_member_aid[.@i], .@party_member_cid[.@i]) ) {
  1141. if (.@s_offline)
  1142. .@menu_party$ = .@menu_party$ + .@party_member_name$[.@i] + " ^00cc36[ON]^000000";
  1143. else
  1144. .@menu_party$ = .@menu_party$ + .@party_member_name$[.@i];
  1145. } else if (.@s_offline)
  1146. .@menu_party$ = .@menu_party$ + .@party_member_name$[.@i] + " ^777777[OFF]^000000";
  1147. .@menu_party$ = .@menu_party$ + ":";
  1148. }
  1149.  
  1150. // Open select menu (-2 select start from 1 and we have [Refresh] at first)
  1151. .@select = select(.@menu_party$) - 2;
  1152. return .@select;
  1153. }
  1154.  
  1155. // Treasure chest NPC
  1156. alberta,0,0,5 script Treasure Chest#wb_0 1324,{
  1157. emotion ET_SURPRISE, getcharid(3); // Emotion on the player
  1158. // Disable current NPC Treasure Chest if empty
  1159. if ( !getarraysize($@WB_ACCESS) ) {
  1160. message strcharinfo(0), "Treasure Chest is empty.";
  1161. donpcevent strnpcinfo(0)+"::OnDisable";
  1162. // Stop access expire timer
  1163. donpcevent "WorldBossAccessExpire::OnDisable";
  1164. end;
  1165. }
  1166. doevent "WorldBoss::OnTreasureOpen";
  1167. end;
  1168.  
  1169. OnInit:
  1170. .@name$ = strnpcinfo(0); //rid2name( .@id );
  1171. .@timer = getnpctimer(1, .@name$);
  1172. getmapxy(.map$, .x, .y, BL_NPC);
  1173. disablenpc .@name$;
  1174. //debugmes .@name$+"::OnInit target=" + .map$ + " NPC="+ .@name$ + " timer="+ .@timer;
  1175. end;
  1176.  
  1177. OnEnable:
  1178. // if enabled getnpctimer(1, strnpcinfo(0)) will return 1
  1179. .@id = getnpcid(0);
  1180. .@name$ = strnpcinfo(0); //rid2name( .@id );
  1181. .@timer = getnpctimer(1, .@name$);
  1182.  
  1183. .@npc$ = "WorldBoss";
  1184. .@map$ = getvariableofnpc(.event_map$, .@npc$);
  1185. .@x = getvariableofnpc(.event_x, .@npc$);
  1186. .@y = getvariableofnpc(.event_y, .@npc$);
  1187.  
  1188. enablenpc( .@name$ );
  1189. unitwarp( .@id, .@map$, .@x, .@y ); // Move to new position
  1190. initnpctimer( .@name$ ); // Start timeout timer
  1191.  
  1192. //debugmes .@name$+"::OnEnable target="+ .@map$ +", "+ .@x +", "+ .@y +" NPC="+ .@name$ +" timer="+ .@timer;
  1193. end;
  1194.  
  1195. // Disable Treasure NPC and clean event array
  1196. OnDisable:
  1197. .@id = getnpcid(0);
  1198. .@name$ = strnpcinfo(0); //rid2name( .@id );
  1199. .@timer = getnpctimer(1, .@name$);
  1200. getmapxy(.@event_map$, .@x, .@y, BL_NPC);
  1201.  
  1202. stopnpctimer( .@name$ ); // Stop timeout timer
  1203. unitwarp( .@id, .map$, .x, .y ); // Return to default position
  1204. disablenpc( .@name$ );
  1205.  
  1206. // Clean event data
  1207. // Get event index from the map name array
  1208. .@index = inarray($@WB_MAP$[0], .@event_map$);
  1209.  
  1210. // Check if index was found
  1211. if ( .@index == -1 ) {
  1212. debugmes .@name$+"::OnDisable event map name ( "+ .@event_map$ +" ) not found!";
  1213. end;
  1214. }
  1215.  
  1216. // Remove current event from the arrays
  1217. callfunc("WB_ResetEventGlobals", .@index);
  1218.  
  1219. //debugmes .@name$+"::OnDisable target="+ .@event_map$ +", "+ .@x +", "+ .@y +" NPC="+ .@name$ +" timer="+ .@timer;
  1220. end;
  1221.  
  1222. //OnTimer30000: // 30 seconds
  1223. //OnTimer120000: // 2 minutes
  1224. //OnTimer300000: // 5 minutes
  1225. OnTimer600000: // 10 minutes
  1226. //OnTimer900000: // 15 minutes
  1227. .@name$ = strnpcinfo(0);
  1228. getmapxy(.@map$, .@x, .@y, BL_NPC);
  1229. //debugmes .@name$+"::OnTimeout target="+ .@map$ +", "+ .@x +", "+ .@y +" NPC="+ .@name$;
  1230. donpcevent .@name$+"::OnDisable";
  1231. end;
  1232. }
  1233.  
  1234. // Treasure Chest duplicates (Add more if you run out)
  1235. // NPC Name = Treasure Chest#wb_<indexNumber> (Important!)
  1236. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_1 1324
  1237. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_2 1324
  1238. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_3 1324
  1239. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_4 1324
  1240. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_5 1324
  1241. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_6 1324
  1242. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_7 1324
  1243. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_8 1324
  1244. alberta,0,0,5 duplicate(Treasure Chest#wb_0) Treasure Chest#wb_9 1324
  1245.  
  1246. // World Boss timeout timer
  1247. - script WorldBossTimeout -1,{
  1248. end;
  1249. OnEnable:
  1250. initnpctimer;
  1251. end;
  1252. OnDisable:
  1253. stopnpctimer;
  1254. end;
  1255. // Update every 1 minutes
  1256. OnTimer60000:
  1257. .@time = gettimetick(0);
  1258. .@timeout = getvariableofnpc(.event_timeout, "WorldBoss");
  1259. .@mapflags = getvariableofnpc(.use_mapflags, "WorldBoss");
  1260. for ( .@i = 0; .@i < getarraysize($@WB_MOB_GID); .@i++ ) {
  1261. // Unit must be alive
  1262. if ( unitexists($@WB_MOB_GID[.@i]) && .@time > ($@WB_TIMEOUT[.@i] + .@timeout) ) {
  1263. announce "[World Boss] World Boss in "+ $@WB_MAP$[.@i] +" has expired!", bc_all, 0xFF0000;
  1264. unitkill( $@WB_MOB_GID[.@i] );
  1265.  
  1266. // Reset event mapflags
  1267. if ( .@mapflags ) {
  1268. callfunc("WB_ResetMapflags", $@WB_MAP$[.@i], .@i);
  1269. }
  1270.  
  1271. // Remove event global arrays
  1272. callfunc("WB_ResetEventGlobals", .@i);
  1273. }
  1274. }
  1275. initnpctimer;
  1276. end;
  1277. }
  1278.  
  1279. // World Boss Unit's Radar
  1280. // Count users around the world boss and increase it's HP by each Player nearby
  1281. - script WorldBossRadar -1,{
  1282. end;
  1283. OnInit:
  1284. .npc_name$ = strnpcinfo(0);
  1285. .radius = 15; // Cell radius
  1286. .HPLevel = 1500000; // HP increase per player
  1287. .MinHP = .HPLevel * 2; // Minimum HP when to stop decreasing HP
  1288. end;
  1289. OnEnable:
  1290. initnpctimer;
  1291. end;
  1292. OnDisable:
  1293. stopnpctimer;
  1294. end;
  1295. // Every 10 secods update all World Boss unit data
  1296. OnTimer10000:
  1297. for ( .@i = 0; .@i < getarraysize($@WB_MOB_GID); .@i++ ) {
  1298. .@unit_gid = $@WB_MOB_GID[.@i];
  1299. if ( unitexists(.@unit_gid) ) {
  1300. getunitdata(.@unit_gid, .@udata);
  1301. .@hp = .@udata[UMOB_HP];
  1302. .@maxhp = .@udata[UMOB_MAXHP];
  1303. .@x = .@udata[UMOB_X];
  1304. .@y = .@udata[UMOB_Y];
  1305. .@users = getareausers(mapid2name(.@udata[UMOB_MAPID]), (.@x - .radius), (.@y - .radius), (.@x + .radius), (.@y + .radius));
  1306. if ( .@users > $@WB_RADAR_NEAR[.@i] ) {
  1307. // Increase HP per each player nearby
  1308. .@new_hp = .@hp + ( .HPLevel * .@users );
  1309. // Stop increasing HP after maximum has been reached
  1310. if ( .@new_hp < .@maxhp ) {
  1311. setunitdata .@unit_gid, UMOB_HP, .@new_hp;
  1312. unittalk .@unit_gid, rid2name(.@unit_gid) + " : Mortals has entered my sight!", bc_area;
  1313. }
  1314. } else if ( .@users < $@WB_RADAR_NEAR[.@i] ) {
  1315. // Decrease HP per each player nearby
  1316. .@new_hp = .@hp - .HPLevel;
  1317. // Stop decreasing HP after minimum has been reached
  1318. if ( .@new_hp > .MinHP ) {
  1319. setunitdata .@unit_gid, UMOB_HP, .@new_hp;
  1320. unittalk .@unit_gid, rid2name(.@unit_gid) + " : Mortals has left my sight!", bc_area;
  1321. }
  1322. }
  1323. // Update users count
  1324. setarray $@WB_RADAR_NEAR[.@i], .@users;
  1325. }
  1326. }
  1327. initnpctimer;
  1328. end;
  1329. }
  1330.  
  1331. // World Boss access expire timer
  1332. // This will clean event access array from getting too big in time.
  1333. - script WorldBossAccessExpire -1,{
  1334. end;
  1335. OnEnable:
  1336. //debugmes strnpcinfo(0)+"::OnEnable";
  1337. initnpctimer;
  1338. end;
  1339. OnDisable:
  1340. //debugmes strnpcinfo(0)+"::OnDisable";
  1341. stopnpctimer;
  1342. end;
  1343. // Update every 5 minutes
  1344. OnTimer300000:
  1345. //debugmes strnpcinfo(0)+"::OnTimer";
  1346. .@time = gettimetick(0);
  1347. .@expires = getvariableofnpc(.event_access_expire, "WorldBoss");
  1348. for ( .@i = 0; .@i < getarraysize($@WB_ACCESS); .@i++ ) {
  1349. // Check if access has expired
  1350. if ( .@time > ($@WB_ACCESS_EXPIRE[.@i] + .@expires) ) {
  1351. // Current access has expired! Remove access and expire time.
  1352. deletearray $@WB_ACCESS[.@i], 1;
  1353. deletearray $@WB_IP_ACCESS[.@i], 1;
  1354. deletearray $@WB_ACCESS_EXPIRE[.@i], 1;
  1355. }
  1356. }
  1357. // Continue timer if access is not empty
  1358. if ( getarraysize($@WB_ACCESS) ) {
  1359. initnpctimer;
  1360. }
  1361. end;
  1362. }
  1363.  
  1364. // World Boss Floating Rates
  1365. - script WorldBossRates -1,{
  1366. OnInit: // Will fire before OnInterIfInitOnce on server start
  1367. // Floating rates are enabled
  1368. if(!getvariableofnpc(.use_floating_rates, "WorldBoss")) end;
  1369.  
  1370. // Reset rates on script load
  1371. if ( $wb_base_exp_rate && getBattleFlag("base_exp_rate") != $wb_base_exp_rate )
  1372. donpcevent strnpcinfo(0)+"::OnDisable";
  1373. end;
  1374.  
  1375. OnInterIfInitOnce: // Will fire after OnInit on server start
  1376. // Floating rates are enabled
  1377. if(!getvariableofnpc(.use_floating_rates, "WorldBoss")) end;
  1378. // Set once on server start
  1379. $wb_battle_flags = 0;
  1380. // Set servers default battle flags
  1381. $wb_base_exp_rate = getBattleFlag("base_exp_rate");
  1382. $wb_job_exp_rate = getBattleFlag("job_exp_rate");
  1383. $wb_item_rate_common = getBattleFlag("item_rate_common");
  1384. $wb_item_rate_common_boss = getBattleFlag("item_rate_common_boss");
  1385. $wb_item_rate_common_mvp = getBattleFlag("item_rate_common_mvp");
  1386. $wb_item_rate_heal = getBattleFlag("item_rate_heal");
  1387. $wb_item_rate_heal_boss = getBattleFlag("item_rate_heal_boss");
  1388. $wb_item_rate_heal_mvp = getBattleFlag("item_rate_heal_mvp");
  1389. $wb_item_rate_use = getBattleFlag("item_rate_use");
  1390. $wb_item_rate_use_boss = getBattleFlag("item_rate_use_boss");
  1391. $wb_item_rate_use_mvp = getBattleFlag("item_rate_use_mvp");
  1392. $wb_item_rate_equip = getBattleFlag("item_rate_equip");
  1393. $wb_item_rate_equip_boss = getBattleFlag("item_rate_equip_boss");
  1394. $wb_item_rate_equip_mvp = getBattleFlag("item_rate_equip_mvp");
  1395. $wb_item_rate_card = getBattleFlag("item_rate_card");
  1396. $wb_item_rate_card_boss = getBattleFlag("item_rate_card_boss");
  1397. $wb_item_rate_card_mvp = getBattleFlag("item_rate_card_mvp");
  1398. $wb_item_rate_mvp = getBattleFlag("item_rate_mvp");
  1399. $wb_item_rate_adddrop = getBattleFlag("item_rate_adddrop");
  1400. $wb_item_rate_treasure = getBattleFlag("item_rate_treasure");
  1401. end;
  1402.  
  1403. OnDisable:
  1404. // Reset normal rates
  1405. if ( $wb_battle_flags ) {
  1406. setBattleFlag("base_exp_rate", $wb_base_exp_rate);
  1407. setBattleFlag("job_exp_rate", $wb_job_exp_rate);
  1408. setBattleFlag("item_rate_common", $wb_item_rate_common);
  1409. setBattleFlag("item_rate_common_boss", $wb_item_rate_common_boss);
  1410. setBattleFlag("item_rate_common_mvp", $wb_item_rate_common_mvp);
  1411. setBattleFlag("item_rate_heal", $wb_item_rate_heal);
  1412. setBattleFlag("item_rate_heal_boss", $wb_item_rate_heal_boss);
  1413. setBattleFlag("item_rate_heal_mvp", $wb_item_rate_heal_mvp);
  1414. setBattleFlag("item_rate_use", $wb_item_rate_use);
  1415. setBattleFlag("item_rate_use_boss", $wb_item_rate_use_boss);
  1416. setBattleFlag("item_rate_use_mvp", $wb_item_rate_use_mvp);
  1417. setBattleFlag("item_rate_equip", $wb_item_rate_equip);
  1418. setBattleFlag("item_rate_equip_boss", $wb_item_rate_equip_boss);
  1419. setBattleFlag("item_rate_equip_mvp", $wb_item_rate_equip_mvp);
  1420. setBattleFlag("item_rate_card", $wb_item_rate_card);
  1421. setBattleFlag("item_rate_card_boss", $wb_item_rate_card_boss);
  1422. setBattleFlag("item_rate_card_mvp", $wb_item_rate_card_mvp);
  1423. setBattleFlag("item_rate_mvp", $wb_item_rate_mvp);
  1424. setBattleFlag("item_rate_adddrop", $wb_item_rate_adddrop);
  1425. setBattleFlag("item_rate_treasure", $wb_item_rate_treasure);
  1426. }
  1427. $wb_battle_flags = 0;
  1428. stopnpctimer;
  1429. end;
  1430.  
  1431. OnEnable:
  1432. // Check already enabled
  1433. if ( !$wb_battle_flags ) {
  1434. // Double server ratings
  1435. setBattleFlag("base_exp_rate", $wb_base_exp_rate * 2);
  1436. setBattleFlag("job_exp_rate", $wb_job_exp_rate * 2);
  1437. setBattleFlag("item_rate_common", $wb_item_rate_common * 2);
  1438. setBattleFlag("item_rate_common_boss", $wb_item_rate_common_boss * 2);
  1439. setBattleFlag("item_rate_common_mvp", $wb_item_rate_common_mvp * 2);
  1440. setBattleFlag("item_rate_heal", $wb_item_rate_heal * 2);
  1441. setBattleFlag("item_rate_heal_boss", $wb_item_rate_heal_boss * 2);
  1442. setBattleFlag("item_rate_heal_mvp", $wb_item_rate_heal_mvp * 2);
  1443. setBattleFlag("item_rate_use", $wb_item_rate_use * 2);
  1444. setBattleFlag("item_rate_use_boss", $wb_item_rate_use_boss * 2);
  1445. setBattleFlag("item_rate_use_mvp", $wb_item_rate_use_mvp * 2);
  1446. setBattleFlag("item_rate_equip", $wb_item_rate_equip * 2);
  1447. setBattleFlag("item_rate_equip_boss", $wb_item_rate_equip_boss * 2);
  1448. setBattleFlag("item_rate_equip_mvp", $wb_item_rate_equip_mvp * 2);
  1449. setBattleFlag("item_rate_card", $wb_item_rate_card * 2);
  1450. setBattleFlag("item_rate_card_boss", $wb_item_rate_card_boss * 2);
  1451. setBattleFlag("item_rate_card_mvp", $wb_item_rate_card_mvp * 2);
  1452. setBattleFlag("item_rate_mvp", $wb_item_rate_mvp * 2);
  1453. setBattleFlag("item_rate_adddrop", $wb_item_rate_adddrop * 2);
  1454. setBattleFlag("item_rate_treasure", $wb_item_rate_treasure * 2);
  1455. }
  1456. announce "[World Boss] Experience and Drop rates has been doubled for one hour! Enjoy!", bc_all, 0x00FF00;
  1457. $wb_battle_flags = 1;
  1458. initnpctimer;
  1459. end;
  1460.  
  1461. OnTimer3600000: // 1 hour
  1462. donpcevent strnpcinfo(0)+"::OnDisable";
  1463. end;
  1464. }
  1465.  
  1466. // NPC World Boss Information
  1467. prontera,147,174,4 script World Boss#info 495,5,5,{
  1468. mes "[ " + strnpcinfo(1) + " ]";
  1469. mes "About the world bosses.";
  1470. if ( getarraysize($@WB_MOB_GID) ) {
  1471. .@time = gettimetick(0);
  1472. .@timeout = getvariableofnpc(.event_timeout, "WorldBoss");
  1473. mes "Status: ^00CC36Active^000000";
  1474. for ( .@i = 0; .@i < getarraysize($@WB_MOB_GID); .@i++ ) {
  1475. .@timeleft = ($@WB_TIMEOUT[.@i] + .@timeout) - .@time;
  1476. mes (.@i + 1) + ". Location : " + $@WB_MAP$[.@i];
  1477. mes " ^777777 Time Left :^000000 " + (.@timeleft / 60000) + " min.";
  1478. }
  1479. mes "Good luck!";
  1480. } else {
  1481. mes "Status: ^CC3300Inactive^000000";
  1482. mes "Event timetable:";
  1483. mes "^777777 ~ 04:02 ^000000";
  1484. mes "^777777 ~ 23:59 ^000000";
  1485. mes "Wait until the event starts.";
  1486. }
  1487. // GM level 60+ has access to menu
  1488. if( getgmlevel() >= 60 ) {
  1489. next;
  1490. switch( select("Information:Start Event:Skip Start Timer:Stop Event:Change Loot Mode:Change Unit Data:Map Flags:Leave") ) {
  1491. case 1: callsub S_Info; break;
  1492. case 2: callsub S_Start; break;
  1493. case 3: callsub S_Skip; break;
  1494. case 4: callsub S_Stop; break;
  1495. case 5: callsub S_Loot; break;
  1496. case 6: callsub S_Unit; break;
  1497. case 7: callsub S_Mapflags; break;
  1498. default: break;
  1499. }
  1500. }
  1501. close;
  1502.  
  1503. S_Info:
  1504. // Set variables
  1505. .@enabled = getarraysize($@WB_MOB_GID);
  1506. .@loot_mode = getvariableofnpc(.loot_mode, .event_npc$);
  1507. .@time = gettimetick(0);
  1508. .@timeout = getvariableofnpc(.event_timeout, "WorldBoss");
  1509. mes "[ " + strnpcinfo(1) + " ]";
  1510. mes "^777777Status: ^000000" + (.@enabled ? "^00CC36Active^000000" : "^CC3300Inactive^000000");
  1511. mes "^777777Loot mode: ^000000" + .event_loot_modes$[.@loot_mode];
  1512. .@menu$ = "Leave:";
  1513. for ( .@i = 0; .@i < getarraysize($@WB_MOB_GID); .@i++ ) {
  1514. if ( $@WB_MOB_GID[.@i] || $@WB_NPC_NAME$[.@i] != "" ) {
  1515. // Monster Unit
  1516. .@timeleft = ($@WB_TIMEOUT[.@i] + .@timeout) - .@time; // ms
  1517. // Get unit data
  1518. if ( unitexists($@WB_MOB_GID[.@i]) ) {
  1519. // Monster unit
  1520. getunitdata($@WB_MOB_GID[.@i], .@udata);
  1521. mes (.@i + 1) +". Monster: " + $@WB_MOB_ID[.@i] +" / "+ getmonsterinfo($@WB_MOB_ID[.@i], 0);
  1522. mes " ^777777 GID: ^000000" + $@WB_MOB_GID[.@i];
  1523. mes " ^777777 Name: ^000000" + rid2name($@WB_MOB_GID[.@i]);
  1524. mes " ^777777 HP: ^000000" + .@udata[UMOB_HP] + " / " + .@udata[UMOB_MAXHP];
  1525. mes " ^777777 Location: ^000000" + mapid2name(.@udata[UMOB_MAPID]) +
  1526. " ^777777 x ^000000" + .@udata[UMOB_X] +
  1527. " ^777777 y ^000000" + .@udata[UMOB_Y];
  1528. mes " ^777777 Time Left :^000000 " + (.@timeleft / 60000) + " min.";
  1529. } else if (unitexists(getnpcid(0, $@WB_NPC_NAME$[.@i]))) {
  1530. // NPC unit
  1531. getunitdata(getnpcid(0, $@WB_NPC_NAME$[.@i]), .@udata);
  1532. mes (.@i + 1) +". Treasure Chest";
  1533. mes " ^777777 GID: ^000000" + getnpcid(0, $@WB_NPC_NAME$[.@i]);
  1534. mes " ^777777 Name: ^000000" + $@WB_NPC_NAME$[.@i];
  1535. mes " ^777777 Location: ^000000" + mapid2name(.@udata[UNPC_MAPID]) +
  1536. " ^777777 x ^000000" + .@udata[UNPC_X] +
  1537. " ^777777 y ^000000" + .@udata[UNPC_Y];
  1538. }
  1539. mes "^777777-------^000000";
  1540. .@menu$ += "Go to "+$@WB_MAP$[.@i];
  1541. }
  1542. .@menu$ += ":";
  1543. }
  1544. .@selected = select(.@menu$) - 2;
  1545. if ( .@selected >= 0 ) {
  1546. if ( unitexists($@WB_MOB_GID[.@selected]) ) {
  1547. // Warp to the monster location
  1548. getunitdata($@WB_MOB_GID[.@selected], .@data);
  1549. warp mapid2name(.@data[UMOB_MAPID]), .@data[UMOB_X], .@data[UMOB_Y];
  1550. } else if ( $@WB_NPC_NAME$[.@selected] != "" ) {
  1551. // Warp to the NPC location
  1552. if (unitexists(getnpcid(0, $@WB_NPC_NAME$[.@selected]))) {
  1553. getunitdata(getnpcid(0, $@WB_NPC_NAME$[.@selected]), .@data);
  1554. warp mapid2name(.@data[UNPC_MAPID]), .@data[UNPC_X], .@data[UNPC_Y];
  1555. }
  1556. }
  1557. end;
  1558. }
  1559. return;
  1560.  
  1561. S_Mapflags:
  1562. mes "[ " + strnpcinfo(1) + " ] Mapflags";
  1563. .@size = getarraysize($@WB_MOB_GID);
  1564. .@mapflags = getvariableofnpc(.use_mapflags, "WorldBoss");
  1565. if ( .@mapflags && .@size ) {
  1566. for ( .@i = 0; .@i < .@size; .@i++ ) {
  1567. .@map$ = $@WB_MAP$[.@i];
  1568. mes .@map$ + " : Original Flags";
  1569. mes " ^777777 PartyLock : " + $@WB_MF_PARTYLOCK[.@i] + "^000000";
  1570. mes " ^777777 NoMobLoot : " + $@WB_MF_NOMOBLOOT[.@i] + "^000000";
  1571. mes " ^777777 NoMVPLoot : " + $@WB_MF_NOMVPLOOT[.@i] + "^000000";
  1572. mes " ^777777 NoPenalty : " + $@WB_MF_NOPENALTY[.@i] + "^000000";
  1573. mes " ^777777 NoMobTele : " + $@WB_MF_NOMOBTELE[.@i] + "^000000";
  1574. mes " ^777777 BaseExp : " + $@WB_MF_BASEEXP[.@i] + "^000000";
  1575. mes " ^777777 JobExp : " + $@WB_MF_JOBEXP[.@i] + "^000000";
  1576. //mes " ^777777 Fog : " + $@WB_MF_FOG[.@i] + "^000000";
  1577. mes .@map$ + " : New Flags";
  1578. mes " ^777777 PartyLock : " + getmapflag(.@map$, MF_PARTYLOCK) + "^000000";
  1579. mes " ^777777 NoMobLoot : " + getmapflag(.@map$, MF_NOMOBLOOT) + "^000000";
  1580. mes " ^777777 NoMVPLoot : " + getmapflag(.@map$, MF_NOMVPLOOT) + "^000000";
  1581. mes " ^777777 NoPenalty : " + getmapflag(.@map$, MF_NOPENALTY) + "^000000";
  1582. mes " ^777777 NoMobTele : " + getmapflag(.@map$, MF_MONSTER_NOTELEPORT) + "^000000";
  1583. mes " ^777777 BaseExp : " + getmapflag(.@map$, MF_BEXP) + "^000000";
  1584. mes " ^777777 JobExp : " + getmapflag(.@map$, MF_JEXP) + "^000000";
  1585. //mes " ^777777 Fog : " + getmapflag(.@map$, MF_FOG) + "^000000";
  1586. mes "^777777-------^000000";
  1587. }
  1588. } else {
  1589. mes "No mapflags has been set.";
  1590. }
  1591. return;
  1592.  
  1593. S_Start:
  1594. donpcevent .event_npc$ + "::OnEnable";
  1595. message strcharinfo(0), "Event has been started!";
  1596. return;
  1597.  
  1598. S_Skip:
  1599. awake .event_npc$; // Cancels any running sleep timers on the NPC
  1600. message strcharinfo(0), "Event timer has been skipped!";
  1601. return;
  1602.  
  1603. S_Stop:
  1604. awake .event_npc$; // Cancels any running sleep timers on the NPC
  1605. donpcevent .event_npc$ + "::OnDisable";
  1606. // Announce event stopped
  1607. announce "[World Boss] The event has been stopped!", bc_all, 0xFF0000;
  1608. message strcharinfo(0), "Event has been stopped!";
  1609. return;
  1610.  
  1611. S_Loot:
  1612. .@size = getarraysize(.event_loot_modes$);
  1613. for( .@i = 0; .@i < .@size; .@i++ ) {
  1614. message strcharinfo(0), "Loot mode "+ .@i +" : " + .event_loot_modes$[.@i];
  1615. }
  1616. // Change event loot mode option
  1617. input .@input, 0, .@size;
  1618. set getvariableofnpc(.loot_mode, .event_npc$), .@input;
  1619. message strcharinfo(0), "Event loot mode changed: " + .event_loot_modes$[.@input];
  1620. return;
  1621.  
  1622. S_Unit:
  1623. // Create menu
  1624. .@menu$ = "Leave:";
  1625. for ( .@i = 0; .@i < getarraysize($@WB_MOB_GID); .@i++ ) {
  1626. if ( unitexists($@WB_MOB_GID[.@i]) ) {
  1627. .@menu$ += $@WB_MAP$[.@i] +" - "+ getmonsterinfo($@WB_MOB_ID[.@i], 0);
  1628. }
  1629. .@menu$ += ":";
  1630. }
  1631. .@selected = select(.@menu$) - 2;
  1632.  
  1633. // Change unit data (HP,Level,Atk,Etc.)
  1634. if ( .@selected >= 0 ) {
  1635. mes "[ " + strnpcinfo(1) + " ]";
  1636. getunitdata($@WB_MOB_GID[.@selected], .@udata);
  1637. for (.@i = 0; .@i < getarraysize(.@udata); .@i++ ) {
  1638. mes .UMOB$[.@i] + " = " + .@udata[.@i];
  1639. }
  1640. .@select = select(.UMOB_menu$) - 1;
  1641. message strcharinfo(0), "Write a new unit ( " + .UMOB$[.@select] + " ) value.";
  1642. input .@val, 0, 1000000000;
  1643. setunitdata($@WB_MOB_GID[.@selected], .@select, .@val);
  1644. // Confim data has changed
  1645. getunitdata($@WB_MOB_GID[.@selected], .@confirm_udata);
  1646. message strcharinfo(0), "New unit data is: " + .@confirm_udata[.@select];
  1647. }
  1648. return;
  1649.  
  1650. OnInit:
  1651. // Event NPC name
  1652. .event_npc$ = "WorldBoss";
  1653.  
  1654. // Event loot mode descriptions
  1655. // Copy array from other NPC
  1656. copyarray .event_loot_modes$[0], getelementofarray(getvariableofnpc(.loot_mode_desc$, .event_npc$),0), getarraysize(getvariableofnpc(.loot_mode_desc$, .event_npc$));
  1657.  
  1658. // Unit data attibute names
  1659. setarray .UMOB$[0],
  1660. "Size","Level","Hp","Max Hp",
  1661. "Master AID","Map ID","Map X","Map Y",
  1662. "Speed","Mode","Ai","Scoption",
  1663. "Sex","Class","Hair style","Hair color",
  1664. "Head bottom","Head middle","Head top","Cloth color",
  1665. "Shield","Weapon","Look dir","Can move tick",
  1666. "Str","Agi","Vit","Int",
  1667. "Dex","Luk","Slave cpymstrmd","Dmg immune",
  1668. "Atk range","Atk min","Atk max","Matk min",
  1669. "Matk max","Def","Mdef","Hit",
  1670. "Flee","Pdodge","Crit","Race",
  1671. "Ele type","Ele level","A-motion","A-delay",
  1672. "D-motion";
  1673.  
  1674. // Unit data menu string
  1675. .UMOB_menu$ = implode(.UMOB$, ":");
  1676.  
  1677. // Set NPC size if class_id supports
  1678. .@npc_class = rand(495, 498);
  1679. .@npc_size = rand(0, 2); // 0=normal, 1=small, 2=big
  1680. setnpcdisplay(strnpcinfo(0), strnpcinfo(1), .@npc_class, .@npc_size);
  1681. end;
  1682.  
  1683. OnTouch:
  1684. // Player attached
  1685. end;
  1686.  
  1687. OnTouchNPC:
  1688. // Monster attached
  1689. .@UNIT_GID = getattachedrid();
  1690. //.@UNIT_NAME$ = rid2name(.@UNIT_GID);
  1691. //debugmes "Target unit name:" + .@UNIT_NAME$;
  1692. // Get unit data as Array
  1693. getunitdata(.@UNIT_GID, .@data);
  1694. .@MASTER_AID = .@data[UMOB_MASTERAID]; // UMOB_MASTERAID=4
  1695. // Unit has a master
  1696. if ( .@MASTER_AID ) {
  1697. .@MASTER_NAME$ = rid2name(.@MASTER_AID);
  1698. .@online = isloggedin(.@MASTER_AID);
  1699. if ( .@online ) {
  1700. end; // Do not target players unit
  1701. }
  1702. }
  1703. // NPC emotion
  1704. emotion ET_KEK;
  1705. // Warp monsters away from the NPC
  1706. unitwarp 0, "this", -1, -1;
  1707. end;
  1708. }
Add Comment
Please, Sign In to add comment