// TMW2 Scripts // Author: // Jesusalva // Description: // Celestia Yeti King's quest. This controls Soren's House Indoors. It will // handle Lobby event, and is called by Soren's House script. // It'll then spawn monsters and/or items, but with addtimer technology. // Once all monsters are dead, and minimum time is over, a portal will show up. // This later control is done by npctimer. The spawn logic continues, though. // The addtimer will use compareandsetq, and the warp will use it too, so if // you haven't spawned your quota, you won't be able to use the portal. // // The use of compareandsetq HurnscaldQuest_Celestia // Ensures you're NOT capable of skipping to final stage in order to finish // the quest. Nice attempt, but that won't work. The scripts will advance, // but you'll stay at the same quest state, and when it's checked, you will // be with bound hands. // // OnCheck: // Everytime you kill a monster, this checks if all mobs are dead, and you // have finished your share of spawns. Friends can really make your life // harder. // OnSanctum: // This runs every once in a while, and may either spawn things, or drop // items. ...Needless to say, if it spawn things, everyone on the room will // get mad at you. Luck you, here's not PVP. // // One last thing. If you're way past your share, you'll get warnings about // messing other players life. Simply use the warp, or leave the house and // come back. If you don't, you'll be kicked from the game via @kick. // Why? Because Jesusalva did this script. soren-2,38,29,0 script #SorenSanctum NPC_NO_SPRITE,0,0,{ if (@sorensanctum == 0 && $@GM_OVERRIDE && is_admin()) doevent("#SorenSanctum::OnStart"); end; OnTouch: if (@sorensanctum >= 5 && !mobcount(.map$, "#SorenSanctum::OnCheck")) { /* dispbottom l("Error, contact Jesusalva! Missing warp. Healing & Reseting temporaly."); percentheal 100, 100;*/ @sorensanctum=0; compareandsetq HurnscaldQuest_Celestia, 4, 5; warp "001-7", 30, 42; } end; OnCheck: // This doesn't works (or didn't used to), maybe because the way it's called if (!mobcount("soren-2", "#SorenSanctum::OnCheck")) setnpcdisplay "#SorenSanctum", NPC_SUMMONING_CIRC; else setnpcdisplay "#SorenSanctum", NPC_NO_SPRITE; // Repeat if possible if (!playerattached()) end; if (getmap() == "soren-2") addtimer2(10000, "#SorenSanctum::OnCheck"); end; OnSanctum: ++@sorensanctum; if (ispcdead() || !isin("soren-2", 24, 27, 40, 36)) end; // Decide if we'll spawn or add items. Previous failures are NOT considerated. .@odds=rand(1, 10000); .@amount=(rand2(0, 5)/2)+1; .@lx=24; .@ly=27; .@ux=40; .@uy=36; // Core Logic, Part 1 // Decide rarity // 1%: Super Rare drop // 9%: Rare Drop // 20%: Normal Drop // 40%: Normal Spawn // 10%: Rare Spawn // 19%: Drop + Spawn // 1%: Super Rare Spawn if (.@odds <= 100 || .@odds >= 9900) { .@bonus=2; } else if (.@odds <= 1000 || (.@odds >= 7000 && .@odds < 8000)) { .@bonus=1; } // Generate which monster/item would be dropped, depending on your (un)luck at ODDS (FIXME - Mobs vs Player level) .@mid=rand2(1,10)+.@bonus; switch (.@mid) { case 1: .@monsterId = AngryRedScorpion ; break; case 2: .@monsterId = IceMaggot ; break; case 3: .@monsterId = SeaSlime ; break; case 4: .@monsterId = AlphaMouboo ; break; case 5: .@monsterId = LavaSlime ; break; case 6: .@monsterId = BlackScorpion ; break; case 7: .@monsterId = Snake ; break; case 8: .@monsterId = FallenGuard2 ; break; case 9: .@monsterId = FallenGuard1 ; break; case 10: .@monsterId = Moonshroom ; break; default: .@monsterId = Yeti ; break; } // Item Gen .@mid=rand(1,10)+.@bonus; switch (.@mid) { case 1: .@itemId = Acorn ; break; case 2: .@itemId = Bread ; break; case 3: .@itemId = Aquada ; break; case 4: .@itemId = StrengthPotion ; break; case 5: .@itemId = Plushroom ; break; case 6: .@itemId = Piberries ; break; case 7: .@itemId = Croconut ; break; case 8: .@itemId = Chagashroom ; break; case 9: .@itemId = Manana ; break; case 10: .@itemId = HastePotion ; break; default: .@itemId = rand(CopperOre, TitaniumOre) ; break; } // Rare drop if (rand(1,6900) == 1337) .@itemId=RaidTrousers; // Core Logic, part 3 // Make Items or Monsters if (.@odds <= 3333) { makeitem(.@itemId, 1, .map$, rand(.@lx, .@ux), rand(.@ly, .@uy)); } else if (.@odds <= 7000 || .@odds > 9900) { areamonster .map$, .@lx, .@ly, .@ux, .@uy, strmobinfo(1, .@monsterId), .@monsterId, .@amount; } else { areamonster .map$, .@lx, .@ly, .@ux, .@uy, strmobinfo(1, .@monsterId), .@monsterId, .@amount; makeitem(.@itemId, 1, .map$, rand(.@lx, .@ux), rand(.@ly, .@uy)); } // Revert sprite if needed if (.@odds > 2000) { setnpcdisplay .name$, NPC_NO_SPRITE; } else if (!mobcount(.map$, "#SorenSanctum::OnCheck")) { setnpcdisplay .name$, NPC_SUMMONING_CIRC; } // Handle maximum overtime you can do here: 10 cycles, or 3m20s ~ 6m40s if (@sorensanctum == 8) { specialeffect(28); dispbottom col(l("WARNING: Do not spend unecessary time on Soren's House, you'll be disconnected!"), 1); percentheal -5, -20; } if (@sorensanctum == 9) { specialeffect(28); dispbottom col(l("FINAL WARNING: Do not spend unecessary time on Soren's House, you'll be disconnected!!"), 1); percentheal -20, -100; } if (@sorensanctum >= 10) { atcommand "@kick "+strcharinfo(0); npctalk l("The power of Soren's House kicks @@ like a game master.", strcharinfo(0)); } // Random 20~40 seconds before next cycle. (Minimum 100~200 seconds, or 1m40s~3m20s) // If you're past minimum, it'll be a little slower to don't affect other players too much. // These values are for single player. If there are more users, the timer will tick for longer. if (@sorensanctum < 5) addtimer(rand(15000, 35000)+getusers(1)*5000, "#SorenSanctum::OnSanctum"); else addtimer(rand(25000, 35000)+getusers(1)*5000, "#SorenSanctum::OnSanctum"); // Enforce the policy addtimer2(10000, "#SorenSanctum::OnCheck"); goto OnCheck; OnStart: // If you're not on stage 4, skip this. I could set here to stage 5, so this // intro won't play again. But if it plays again, your progress is reset, and // it is harder this way, so I'm not touching on quest state :> if (getq(HurnscaldQuest_Celestia) != 4) end; addtimer(200, "#SorenSanctum::OnStep1"); // Allow client to update stuff end; OnStep1: // When we reach here, we have both a player attached, and the player was already warped. // I don't know if you walked in and out the house, though. If you do, this will loop... // Which is actually bad for you, as that will reset your progress!! npctalk3 l("Well well well, @@, good job in reaching Soren's House.", strcharinfo(0)); addtimer(3000, "#SorenSanctum::OnStep2"); end; OnStep2: //setnpcdisplay .name$, NPC_YETI_KING; npctalk3 l("You done well in getting so far. I didn't thought you would make it."); addtimer(3000, "#SorenSanctum::OnStep3"); end; OnStep3: npctalk3 l("The Cave Of Trials, and the Soren's Village... There's only one thing left."); addtimer(3000, "#SorenSanctum::OnStep4"); end; OnStep4: npctalk3 l("...You still have not overcome his house."); addtimer(3000, "#SorenSanctum::OnStep5"); end; OnStep5: //setnpcdisplay .name$, NPC_NO_SPRITE; npctalk3 l("Defeat a few waves of Soren's House. Once you're done, this will become a warp. Hurry before it closes."); @sorensanctum=0; addtimer(5000, "#SorenSanctum::OnSanctum"); end; OnInit: end; }