// TMW2 scripts. // Authors: // Jesusalva // Description: // Controls world events so Saulc and I can take vacations. // See also: seasons.txt, command/event.txt, aurora.txt // 003-1/events.txt, soulmenhir.txt and, of course, the event maps (if any). // Schedule, if needed to change, can be found in the OnInit loop. // An event, obviously, cannot last more than 7... 15 days at WORST. // Therefore, month checks aren't included in day checks. - script sPatrick NPC_HIDDEN,{ OnInit: setarray .maps$, "005-1", "013-1", "014-1", "014-2", "014-3", "014-4", "014-5", "017-1", "018-2", "018-4", "018-5", "soren"; end; OnMyMobDeath: end; OnClock0000: OnClock6000: OnClock1200: OnClock1500: OnClock1800: OnClock2100: .@d=gettime(GETTIME_DAYOFMONTH); // Patrick Day should work only in 2 luck days according to Saulc // If this is required use $PATRICK_DAYCTRL so the days before $@PATRICK_DAYMAX // act with 100% chances (determinism). // As it is being spawn 4 times at a day (like TMW-BR events), because it is // flatly and outright IMPOSSIBLE to add a permanent spawn, that is not required. if ($EVENT$ == "Patrick" && .@d <= $@PATRICK_DAYMAX) { for (.@i=0; .@i < getarraysize(.maps$); .@i++) { .@m$=.maps$[.@i]; .@x=getmapinfo(MAPINFO_SIZE_X, .@m$)-20; .@y=getmapinfo(MAPINFO_SIZE_Y, .@m$)-20; // Remove previously spawned clovers killmonster(.@m$, "sPatrick::OnMyMobDeath"); // It is one clover for each 225 tiles (about a 25x25 square) .@maparea=(.@x-20)*(.@y-20); .@mobs=max(1, .@maparea/225); areamonster .@m$, 20, 20, .@x, .@y, strmobinfo(1, StPatricksClover), StPatricksClover, .@mobs, "sPatrick::OnMyMobDeath"; } } end; // Remove previously spawned clovers for event end // And then disables the NPC OnCleanUp: for (.@i=0; .@i < getarraysize(.maps$); .@i++) { .@m$=.maps$[.@i]; killmonster(.@m$, "sPatrick::OnMyMobDeath"); } disablenpc "sPatrick"; donpcevent "Aurora::OnRestore"; end; } function script sThanksgiving { // Variables: // #THANKS_DAY // #THANKS_STREAK // @thanks_card // Already spinned if (#THANKS_DAY == gettime(5) || $EVENT$ != "Thanksgiving") return; // Not spinned yet showavatar 1102; mes l(".:: Thanksgiving ::."); mesc l("Spin daily the card to get prizes!"); select l("SPIN!"), l("Later"); mes ""; if (@menu == 2) { setskin ""; closeclientdialog; return; } // Spin it // Your prize is saved in .@luck. Rigged against fruits .@luck=rand2(0,11); .@luck=(.@luck == 10 ? rand2(0,11) : .@luck); // A fruit before 10 days: rig to Arcmage or to blueprint if (.@luck == 10 && #THANKS_STREAK < 10) .@luck+=any(-1,1); // A fruit before 20 days: Lower chances from 4% to 2% if (.@luck == 10 && #THANKS_STREAK < 20) .@luck=rand2(0,11); // Extra spins .@extra=rand2(1,3); .@spins=.@extra*11+.@luck; //.@extra=0; // Show the spins for (.@i=0;.@i<=.@spins;.@i++) { .@cur=(.@i%11); showavatar 1103+.@cur; sleep2(60); } mes l(".:: Congratulations ::."); #THANKS_DAY = gettime(5); #THANKS_STREAK+=1; if (debug || $@GM_OVERRIDE) { mes l("You got a %d", .@luck); mesf "Spins: %d/%d (cur %d extra %d)", .@i, .@spins, .@cur, .@extra; mes ""; //.@luck=$@GM_OVERRIDE; } // Switch the reward switch (.@luck) { case 0: // EXP .@p=BaseLevel*#THANKS_STREAK; .@p*=3; getexp .@p, 0; mes l("You got %d EXP!", .@p); break; case 1: // JEXP .@p=BaseLevel*#THANKS_STREAK; .@p=.@p*15/10; getexp 0, .@p; mes l("You got %d JEXP!", .@p); break; case 2: // GP .@p=BaseLevel*#THANKS_STREAK; Zeny+=.@p; mes l("You got %d GP!", .@p); break; case 3: // MOBPT .@p=BaseLevel*#THANKS_STREAK; Mobpt+=.@p; mes l("You got %d Monster Points!", .@p); break; case 4: // RES .@p=BaseLevel*#THANKS_STREAK; .@p*=3; REAL_ESTATE_CREDITS+=.@p; mes l("You got %d Real Estate Credits!", .@p); break; case 5: // GIFT .@p=BronzeGift; .@p=(#THANKS_STREAK > 7 ? SilverGift : .@p); .@p=(#THANKS_STREAK > 15 ? GoldenGift : .@p); .@p=(#THANKS_STREAK > 22 ? PrismGift : .@p); .@p=(#THANKS_STREAK > 27 ? SupremeGift : .@p); mes l("You got a(n) %s gift!", getitemlink(.@p)); getitem .@p, 1; break; case 6: // STR C .@p=#THANKS_STREAK; getitem StrangeCoin, .@p; mes l("You got %d %s!", .@p, getitemlink(StrangeCoin)); break; case 7: // HERO C .@p=#THANKS_STREAK; .@p+=getq2(LoFQuest_HH)*max(1,#THANKS_STREAK/10); getitem HeroCoin, .@p; mes l("You got %d %s!", .@p, getitemlink(HeroCoin)); break; case 8: // MERC .@p=any(MercCard_GonzoDark, MercCard_Rosa, MercCard_Soren, MercCard_Apane); .@p=(#THANKS_STREAK > 7 ? any(MercCard_EarthWitch, MercCard_Demure, MercCard_Jesusalva, MercCard_Pookie) : .@p); .@p=(#THANKS_STREAK > 14 ? any(MercCard_Arthur, MercCard_LawnCable, MercCard_Crazyfefe, MercCard_Saulc) : .@p); .@p=(#THANKS_STREAK > 21 ? any(MercCard_Swezanne, MercCard_DragonStar, MercCard_Msawis, MercCard_Aisen) : .@p); .@p=(#THANKS_STREAK > 27 ? any(MercCard_Xanthem, MercCard_Woody, MercCard_Lilanna) : .@p); getitem .@p, 1; mes l("You got a %s!", getitemlink(.@p)); break; case 9: // CARD .@p=any(NatureCard, NinjaCard, MageCard, DruidCard, ClericCard, KnightCard, HeroCard, NecromancerCard); .@p=(#THANKS_STREAK > 24 ? any(SpeedCard, ReflectCard, PowerCard, WallCard) : .@p); getitem .@p, 1; mes l("You got a %s!", getitemlink(.@p)); break; case 10: // FRUIT .@p=MysteriousFruit; getitem .@p, 1; mes l("You got a %s!", getitemlink(.@p)); break; case 11: // BLUE .@p=any(EquipmentBlueprintA, EquipmentBlueprintA, AlchemyBlueprintA); .@p=(#THANKS_STREAK > 7 ? any(EquipmentBlueprintB, EquipmentBlueprintB, AlchemyBlueprintB) : .@p); .@p=(#THANKS_STREAK > 14 ? any(EquipmentBlueprintC, EquipmentBlueprintC, AlchemyBlueprintC) : .@p); .@p=(#THANKS_STREAK > 21 ? any(EquipmentBlueprintD, EquipmentBlueprintD, AlchemyBlueprintD) : .@p); .@p=(#THANKS_STREAK > 27 ? any(EquipmentBlueprintE, EquipmentBlueprintE, AlchemyBlueprintE) : .@p); getitem .@p, 1; mes l("You got a %s!", getitemlink(.@p)); break; } // Special bonus if (#THANKS_STREAK % 7 == 0) { getitem StrangeCoin, 10; mesc l("%d day streak! Gained %d bonus %s!", #THANKS_STREAK, 10, getitemlink(StrangeCoin)); } // Close next; setskin ""; closeclientdialog; return; } // ChocolateDay() function script ChocolateDay { if (!playerattached()) return; // Date check if (gettime(6) != JULY) return; if (gettime(5) != 7) return; // Max. 80% chances, 0.4% per monster level .@lv=min(200, getmonsterinfo(killedrid, MOB_LV)); if (rand2(10000) < (.@lv*40)) { // Chocolate Bar: 73%; Chocolate Dye: 6.7% .@choco=any(ChocolateBar, ChocolateBar, ChocolateBar, ChocolateBar, ChocolateMouboo, ChocolateBiscuit, ChocolateBunny, ChocolateBar, ChocolateBar, ChocolateBar, ChocolateBar, ChocolateDye, ChocolateBar, ChocolateBar, ChocolateBar); getmapxy(.@m$, .@x, .@y, 0); .@x+=rand2(-1,1); .@y+=rand2(-1,1); makeitem(.@choco, 1, .@m$, .@x, .@y); } return; } // CoffeeDay() function script CoffeeDay { if (!playerattached()) return; // Date check if (gettime(6) != OCTOBER) return; if (gettime(5) != 1) return; // Max. 22% chances, 0.1% per monster level .@lv=min(200, getmonsterinfo(killedrid, MOB_LV)); if (rand2(10000) < (.@lv*11)) { getmapxy(.@m$, .@x, .@y, 0); .@x+=rand2(-1,1); .@y+=rand2(-1,1); makeitem(Coffee, 1, .@m$, .@x, .@y); } return; } // FSFDay() function script FSFDay { if (!playerattached()) return; // Date check if (gettime(6) != SEPTEMBER) return; if (gettime(5) != 9) return; // Max. 0.16% chances, 0.008% per monster level .@lv=min(200, getmonsterinfo(killedrid, MOB_LV)); if (rand(1000000) < (.@lv*8)) { getmapxy(.@m$, .@x, .@y, 0); .@x+=rand2(-1,1); .@y+=rand2(-1,1); // Ancient 50%, Equipment 25%, Alchemy 25% .@bp = any(AncientBlueprint, AncientBlueprint, AncientBlueprint, AncientBlueprint, AncientBlueprint, AncientBlueprint, AncientBlueprint, AncientBlueprint, AncientBlueprint, AncientBlueprint, EquipmentBlueprintA, EquipmentBlueprintB, EquipmentBlueprintC, EquipmentBlueprintD, EquipmentBlueprintE, AlchemyBlueprintA, AlchemyBlueprintB, AlchemyBlueprintC, AlchemyBlueprintD, AlchemyBlueprintE); makeitem(.@bp, 1, .@m$, .@x, .@y); } return; } 000-0,0,0,0 script #EventCore NPC_HIDDEN,{ end; // confEvent(event ID, stday, stmon, endday, endmon) function confEvent { setd("."+getarg(0)+"_stday", getarg(1)); setd("."+getarg(0)+"_stmon", getarg(2)); setd("."+getarg(0)+"_endday", getarg(3)); setd("."+getarg(0)+"_endmon", getarg(4)); // Save the event key? //.@confname=".conf_"+getarg(2)+"$"; //setd(.@confname+"["+getarraysize(.@confname)+"]", getarg(0)); // Save only the day? (And use if statement) .@confname$=".conf_"+getarg(2); .@size=getarraysize(getd(.@confname$)); setd(.@confname$+"["+.@size+"]", getarg(1)); //debugmes "CONFIGURE EVENT, %s[%d] = %d", .@confname$, .@size, getarg(1); //debugmes "CNAME: %s", getarg(0); return; } // Event Schedule (all dates are inclusive) // NEVER, ever, include the last day of the month. OnInit: confEvent("valentine", 13, FEBRUARY, 16, FEBRUARY); confEvent("tmw2day", 1, MARCH, 7, MARCH); confEvent("patrick", 15, MARCH, 19, MARCH); confEvent("easter", 17, APRIL, 24, APRIL); confEvent("worker", 27, APRIL, 3, MAY); confEvent("thanks", 1, NOVEMBER, 29, NOVEMBER); // NEVER use the last day of the month here confEvent("xmas", 19, DECEMBER, 2, JANUARY); // Some setup .@isinit=true; disablenpc "sPatrick"; FYE_Normalize(); // Check for events every midnight OnClock0000: // No events on test server if (debug && !$@GM_OVERRIDE) end; // Prepare variables .@d=gettime(GETTIME_DAYOFMONTH); .@m=gettime(GETTIME_MONTH); .@o=gettime(GETTIME_WEEKDAY); // Resets at 0 (sunday) debugmes "A new day begins! Today is %02d/%02d", .@d, .@m; // Override the server-wide randomness resetrng(); // Initialize the event core if ($@DEBUG_OD) .@d=$@DEBUG_OD; if ($@DEBUG_OM) .@m=$@DEBUG_OM; debugmes "EVENT CORE, the %02d/%02d", .@d, .@m; // Is there another event this week? if (!$HARDCORE && .@o == MONDAY && !.@isinit) { .@dofy=true; .@confname$=".conf_"+.@m; // NOTE: Maybe make a single .annuals array and cycle it // Gather the ST variable from interest...? for (.@i=0;.@i < getarraysize(getd(.@confname$)); .@i++) { .@val=getd(.@confname$+"["+.@i+"]"); //debugmes "Looping, %d = %d", .@i, .@val; // Erm. if (.@val == 0) continue; // This script has a weakness: It cannot predict events starting // at the start or the end of the month. // So they might still overlap. // A possible solution is to, eventually, record start and end date. // And only inhibit FY event if the MONDAY is within the event...? // XXX: Now it inhibits by itself; But it should NOT begin a FYE if // another (annual) event is scheduled for the same week. // Namely: TMW2 Day and Thanksgiving debugmes "%d >= %d && %d <= %d", .@val, .@d-6, .@val, .@d+6; // In this case there's already an event! // .@d == .@val <= .@d+6 AND if ( .@val >= .@d-6 && .@val <= .@d+6 ) { .@dofy=false; break; } // continue... } // Stop previous event FYStopEvent(); // Trigger event framework if (.@dofy && $EVENT$ == "") FYNewEvent(); else debugmes "\033[1mAnother event is scheduled!"; } // Handle Valentine Day if (.@m >=.valentine_stmon && .@m <= .valentine_endmon) { // It's tomorrow: Send out an announcement if (.@d == .valentine_stday - 1) { kamibroadcast("Valentine Day will start tomorrow!"); } // Last Day: Send out an announcement if (.@d == .valentine_endday) { kamibroadcast("It's the last day for Valentine Event! Hurry up!"); } // Begin the event if (.@d == .valentine_stday) { kamibroadcast("Valentine Day begun!"); if ($EVENT$ != "") FYStopEvent(); $EVENT$="Valentine"; $@VALENTINE_LOVELETTER = htnew(); $@VALENTINE_GIFTSTACKS = htnew(); } // End the event the day after if (.@d == .valentine_endday+1) { kamibroadcast("Valentine Day ended!"); sClear(); $EVENT$=""; } } // Handle TMW2 Day if (.@m >=.tmw2day_stmon && .@m <= .tmw2day_endmon) { // It's tomorrow: Send out an announcement if (.@d == .tmw2day_stday - 1) { kamibroadcast("Moubootaur Legends Anniversary will start tomorrow!"); } // Last Day: Send out an announcement if (.@d == .tmw2day_endday) { kamibroadcast("It's the last day of our Anniversary Event! Hurry up!"); } // Begin the event if (.@d == .tmw2day_stday) { kamibroadcast("Moubootaur Legends Anniversary Event begun!"); if ($EVENT$ != "Anniversary") $BCONFB_EXPR+=50; $EVENT$="Anniversary"; } // End the event the day after if (.@d == .tmw2day_endday+1) { kamibroadcast("Our Special Anniversary Event ended! Thanks!"); sClear(); $EVENT$=""; } } // Handle St. Patrick Day // During this day, a special four leaf clover is spawned daily, at 4 times in the day // in all forests: 6:00, 12:00, 18:00 and 00:00. // $PATRICK_DAYMAX if (.@m >=.patrick_stmon && .@m <= .patrick_endmon) { // It's tomorrow: Send out an announcement if (.@d == .patrick_stday - 1) { kamibroadcast("St. Patrick Day will start tomorrow!"); } // Last Day: Send out an announcement else if (.@d == .patrick_endday) { kamibroadcast("It's the last day for St. Patrick Event! Hurry up!"); } // Begin the event else if (.@d == .patrick_stday) { kamibroadcast("St. Patrick Day begun!"); if ($EVENT$ != "") FYStopEvent(); $EVENT$="Patrick"; $@PATRICK_DAYMAX=.patrick_endday; enablenpc "sPatrick"; setnpcdisplay("Aurora", "Patrick Saulc", NPC_WEIRDGREEN); enablenpc "St. Patrick Gold Pot"; donpcevent "St. Patrick Gold Pot::OnForcedMove"; } // End the event the day after else if (.@d == .patrick_endday+1) { kamibroadcast("St. Patrick Day ended!"); sClear(); $EVENT$=""; donpcevent "sPatrick::OnCleanUp"; } } // Handle Easter if (.@m >=.easter_stmon && .@m <= .easter_endmon) { // It's tomorrow: Send out an announcement if (.@d == .easter_stday - 1 && .@m == .easter_stmon) { kamibroadcast("Easter will start tomorrow!"); } // Last Day: Send out an announcement else if (.@d == .easter_endday && .@m == .easter_endmon) { kamibroadcast("It's the last day for Easter Event! Hurry up!"); } // Begin the event else if (.@d == .easter_stday && .@m == .easter_stmon) { kamibroadcast("Easter begun!"); if ($EVENT$ != "") FYStopEvent(); sEaster(); } // End the event the day after else if (.@d == .easter_endday+1 && .@m == .easter_endmon) { kamibroadcast("Easter ended!"); sClear(); $EVENT$=""; } } // Handle Worker Day if (.@m >=.worker_stmon && .@m <= .worker_endmon) { // It's tomorrow: Send out an announcement if (.@d == .worker_stday - 1 && .@m == .worker_stmon) { kamibroadcast("Worker Day will start tomorrow!"); } // Last Day: Send out an announcement else if (.@d == .worker_endday && .@m == .worker_endmon) { kamibroadcast("It's the last day for Worker Day Event! Hurry up!"); } // Begin the event else if (.@d == .worker_stday && .@m == .worker_stmon) { kamibroadcast("Worker Day begun!"); if ($EVENT$ != "") FYStopEvent(); $EVENT$="Worker"; } // End the event the day after else if (.@d == .worker_endday+1 && .@m == .worker_endmon) { kamibroadcast("Worker Day ended!"); sClear(); $EVENT$=""; } } // Handle Thanksgiving Day if (.@m >=.thanks_stmon && .@m <= .thanks_endmon) { // It's tomorrow: Send out an announcement if (.@d == .thanks_stday - 1 && .@m == .thanks_stmon) { kamibroadcast("Thanksgiving will start tomorrow!"); } // Last Day: Send out an announcement else if (.@d == .thanks_endday && .@m == .thanks_endmon) { kamibroadcast("It's the last day for Thanksgiving Event! Hurry up!"); } // Begin the event else if (.@d == .thanks_stday && .@m == .thanks_stmon) { kamibroadcast("Thanksgiving begun!"); if ($EVENT$ != "") FYStopEvent(); $EVENT$="Thanksgiving"; } // End the event the day after else if (.@d == .thanks_endday+1 && .@m == .thanks_endmon) { kamibroadcast("Thanksgiving ended!"); sClear(); $EVENT$=""; } } // Handle Christmas. It goes past the year so the rule is different, BEWARE if (.@m == .xmas_stmon || .@m == .xmas_endmon) { // It's tomorrow: Send out an announcement if (.@d == .xmas_stday - 1 && .@m == .xmas_stmon) { kamibroadcast("Christmas will start tomorrow!"); } // Last Day: Send out an announcement else if (.@d == .xmas_endday && .@m == .xmas_endmon) { kamibroadcast("It's the last day for Christmas Event! Hurry up!"); } // Begin the event else if (.@d == .xmas_stday && .@m == .xmas_stmon) { kamibroadcast("Christmas begun!"); if ($EVENT$ != "") FYStopEvent(); $EVENT$="Christmas"; DelQuestFromEveryPlayer(SQuest_Christmas); sChristmas(); } // End the event the day after else if (.@d == .xmas_endday+1 && .@m == .xmas_endmon) { kamibroadcast("Christmas ended!"); sClear(); $EVENT$=""; } } debugmes "EVENT CORE has finished"; end; }