// Fluffy hunting quest // initially by Jenalya // more by alastrim // broken by o11c, then fixed // Variables: // global $@Fluffy_Hunting - state of the quest // 0: nobody is hunting // 1-2: 2 timer iterations to give time for the warp to finish. // 3: somebody is hunting. The script checks every second if there is food on the ground. // global $@Fluffy_Time - the number of seconds since you entered the area // global $@Fluffy_Spawn - how many fluffies have been spawned // global $@Fluffy_Kills - how many fluffies you have killed so far // global $@Fluffy_Min - how many fluffies you have to kill to get a reward // global $@Fluffy_Alive - how many fluffies are currently alive // global $@Fluffy_PC_Deaths - used to keep track of whether the fluffies kill you // global $@Fluffy_Fighter$ - name of the person hunting fluffies (only used for ornamentation) // global $@Fluffy_FighterID - ID of the person hunting fluffies // nibble 0 of QUEST_Barbarians - state for this and adjacent NPCs // 0: haven't talked about it // 1: heard about it // 2: finished quest // 3: got reward // Note: if you're going to reenable the "drop multiple times" feature // 1: please do it every second, not just once you've killed everything - Done // 2: you should change $@Fluffy_Spawn to $@Fluffy_Alive and decrement it on kills // Kept $@Fluffy_Spawn and added $@Fluffy_Alive. The script spawns the amount related to what you drop at each specific time. // 3: add a variable to spawn more fluffies if you drop more than 100 apples, as you kill them // Also, the $@Fluffy_Extra behaviour should be reconsidered (hardly anything spawns ...) // that's the only reason I didn't make that one a local variable like it really is 033-1,74,32,0|script|Kimarr|218 { set @halloween_npc_id, $@halloween_npc_kimarr; callfunc "TrickOrTreat"; if ($@Fluffy_FighterID == getcharid(3)) goto L_Attention; set @state, ((QUEST_Barbarians & $@Q_Barbarians_MASK) >> $@Q_Barbarians_SHIFT); if (@state >= 3) goto L_Again; if (@state == 2) goto L_Reward; if (@state == 1) goto L_Ask; mes "[Barbarian]"; mes "\"Greetings, little person.\""; next; mes "\"I am Kimarr, hunter and warrior of the Mangarr.\""; next; mes "\"You are very small and must be careful in these snowy mountains. It is cold, and dangerous monsters are here.\""; menu "Hello, my name is " + strcharinfo(0) + " and I'm not small. I'm a great warrior!",L_Next, "I'm " + strcharinfo(0) + ", don't underestimate me. I'm an experienced adventurer!",L_Next, "I'm the legendary " + strcharinfo(0) + ", I've fought countless battles.",L_Next; L_Next: mes "Kimarr seems to be amused."; mes "[Kimarr]"; mes "\"Really? Do you want to prove it?\""; menu "Sure! What shall I do?",L_Continue, "No, I don't need to prove anything.",L_Close; L_Continue: mes "\"Every young member of our tribe proves his or her worth by hunting monsters.\""; next; mes "\"The first monsters to hunt are Fluffies. Fluffies give a good meal for a young person and the fur can be used to make clothes and blankets.\""; next; set @state, 1; callsub S_Update_Mask; goto L_ExplainGame; L_ExplainGame: mes "[Kimarr]"; mes "\"In that cave there are living Fluffies. They like to eat apples.\""; next; mes "\"I also saw one of them getting excited about one of those sweet things you call 'cake'.\""; next; mes "\"Go to the cave entrance and throw food on the floor to make them come out.\""; next; mes "\"You should be careful, other monsters living here might like the food as well.\""; next; mes "\"Hunt as many Fluffies as you can until I tell you to stop.\""; next; mes "\"Drop more food when no Fluffies are left.\""; next; goto L_Ask; // dialog starts here if you've asked about it but not done it (@state == 1) L_Ask: if ($@KIMARR_EVENT) goto L_WithEvent; goto L_WithoutEvent; L_WithEvent: if (BaseLevel != 99) goto L_WrongLevel; mes "[Kimarr]"; mes "\"So, are you going to try?\""; menu "Yeah, let's start!",L_Game, "Could you explain again?",L_ExplainGame, "Can you tell me who were the most successful Fluffy hunters?",L_ShowRecord, "On the event, who were the most successful Fluffy hunters?",L_CRC_ShowRecord, "Can you bring me in shape for this event?",L_BringInShape, "Maybe later.",L_Close; L_WrongLevel: mes "[Kimarr]"; mes "For this event you must be level 99!"; mes "I can bring you on that level and give you all focus and magic skills if you want?"; goto L_SureBringInShape; L_BringInShape: mes "[Kimarr]"; mes "I can give you all focus and magic skills if you want?"; goto L_SureBringInShape; L_SureBringInShape: mes "But you must set your stats again and maybe focus somewhere."; mes "Are you sure?"; menu "Yes, do it!",L_GiveAllAndReset, "No.",L_Close; L_GiveAllAndReset: set @debug_mask, 65535; set @debug_shift, 0; setskill SKILL_EMOTE, 1; setskill SKILL_TRADE, 1; setskill SKILL_PARTY, 2; setskill SKILL_POOL, 1; setskill SKILL_MALLARDS_EYE, 9; setskill SKILL_BRAWLING, 9; setskill SKILL_SPEED, 9; setskill SKILL_RESIST_POISON, 9; setskill SKILL_ASTRAL_SOUL, 9; setskill SKILL_RAGING, 9; setskill SKILL_MAGIC, 2; setskill SKILL_MAGIC_LIFE, 2; setskill SKILL_MAGIC_WAR, 2; setskill SKILL_MAGIC_TRANSMUTE, 2; setskill SKILL_MAGIC_NATURE, 2; setskill SKILL_MAGIC_ASTRAL, 2; setskill SKILL_MAGIC_DARK, 2; set MAGIC_EXPERIENCE, (MAGIC_EXPERIENCE & ~(@debug_mask)) | (@mexp << @debug_shift); resetstatus; set BaseLevel, 99; goto L_Close; L_WithoutEvent: mes "[Kimarr]"; mes "\"So, are you going to try?\""; menu "Yeah, let's start!",L_Game, "Could you explain again?",L_ExplainGame, "Can you tell me who were the most successful Fluffy hunters?",L_ShowRecord, "Maybe later.",L_Close; L_AlreadyGotReward: npctalk strnpcinfo(0), strcharinfo(0) + " killed " + $@Fluffy_Kills + " Fluffies and has once again proven to be a good hunter."; message strcharinfo(0), "Kimarr: Once again you prove your worth as a hunter! You killed " + $@Fluffy_Kills + " Fluffies."; callsub S_Clean; goto L_Close; L_Reward1: set @state, ((QUEST_Barbarians & $@Q_Barbarians_MASK) >> $@Q_Barbarians_SHIFT); if (@state >= 2) goto L_AlreadyGotReward; npctalk strnpcinfo(0), "Hooray! " + strcharinfo(0) + " killed " + $@Fluffy_Kills + " Fluffies and is now a worthy hunter."; // as far as I can tell, this fails because it won't resume from the "next" // when the script is executed via the "OnFluffyDeath" callback // (I haven't tried via the 301st call of OnTimer1000) message strcharinfo(0), "Kimarr: Hooray! You hunted " + $@Fluffy_Kills + " Fluffies. Talk to me for your reward."; set @state, 2; callsub S_Update_Mask; callsub S_Clean; goto L_Close; // this label is reached on completion of the quest, or, if you inventory was // full at the time, when you next initiate dialog (with @state == 2) L_Reward: mes "[Kimarr]"; mes "\"That was very impressive. Now you can call yourself a hunter, " + strcharinfo(0) + ".\""; next; getinventorylist; if (@inventorylist_count == 100) goto L_Full_Inv; set @inventorylist_count, 0; mes "\"Take this as a symbol of your strength. You're a member of our tribe now.\""; getitem "YetiSkinShirt", 1; set @state, 3; callsub S_Update_Mask; goto L_Close; L_Full_Inv: mes "\"You can't carry the reward I want to give you.\""; goto L_Close; // dialog starts here after you've completed this quest L_Again: if ($@KIMARR_EVENT) goto L_AgainWithEvent; goto L_AgainWithoutEvent; L_AgainWithEvent: if (BaseLevel != 99) goto L_WrongLevel; mes "[Kimarr]"; mes "\"Does the hunter " + strcharinfo(0) + " want to hunt some Fluffies again?\""; menu "Yeah!",L_Game, "Can you tell me who were the most successful Fluffy hunters?",L_ShowRecord, "On the event, who were the most successful Fluffy hunters?",L_CRC_ShowRecord, "Can you bring me in shape for this event?",L_SureBringInShape, "Not now.",L_Close; L_AgainWithoutEvent: mes "[Kimarr]"; mes "\"Does the hunter " + strcharinfo(0) + " want to hunt some Fluffies again?\""; menu "Yeah!",L_Game, "Can you tell me who were the most successful Fluffy hunters?",L_ShowRecord, "Not now.",L_Close; L_Game: if ($@Fluffy_Hunting) goto L_Someone_Else; set $@Fluffy_Hunting, 1; set $@Fluffy_Kills, 0; set $@Fluffy_PC_Deaths, PC_DIE_COUNTER; set $@Fluffy_Fighter$, strcharinfo(0); set $@Fluffy_FighterID, getcharid(3); set $@Fluffy_Time, 180; set $@Fluffy_Min, 1 + (BaseLevel*7)/10; warp "033-1", 79, 34; initnpctimer; goto L_Close; L_Someone_Else: mes "[Kimarr]"; mes "\"Someone else is hunting right now. Let's wait until that hunt has ended.\""; goto L_Close; L_Attention: message strcharinfo(0), "Kimarr: You should be focused on hunting Fluffies, not talking."; end; OnTimer1000: // Give 3 seconds, so the server can warp and the player can get ready if ($@Fluffy_Hunting == 3) goto L_Action; set $@Fluffy_Hunting, $@Fluffy_Hunting + 1; goto L_ContinueTimer; L_Action: // Checking if player is logged if (attachrid($@Fluffy_FighterID) == 0) goto L_GotOut; // Checking if player is still in the map or used a towel or spell to get out if (getareausers("033-1", 79, 28, 88, 42) == 0) goto L_GotOut; if (PC_DIE_COUNTER > $@Fluffy_PC_Deaths) goto L_Died; // Checking if there is more than 1 player in the fight area if (getareausers("033-1", 79, 28, 88, 42) > 1) areatimer 0, "033-1", 79, 28, 88, 42, 10, "Kimarr::OnTooMany"; if ($@Fluffy_Time == 180) npctalk strnpcinfo(0), strcharinfo(0) + ", you have 3 minutes."; if ($@Fluffy_Time == 120) npctalk strnpcinfo(0), "You have 2 minutes left."; if ($@Fluffy_Time == 60) npctalk strnpcinfo(0), "You have 1 minute left."; if ($@Fluffy_Time == 30) npctalk strnpcinfo(0), "You have 30 seconds left."; if ($@Fluffy_Time == 15) npctalk strnpcinfo(0), "You have 15 seconds left."; if ($@Fluffy_Time == 10) npctalk strnpcinfo(0), "You have 10 seconds left."; if ($@Fluffy_Time == 5) npctalk strnpcinfo(0), "You have 5 seconds left."; set $@Fluffy_Time, $@Fluffy_Time - 1; if ($@Fluffy_Time < 0) goto L_TimeOver; goto L_CheckDrops; L_ContinueTimer: setnpctimer 0; end; L_GotOut: npctalk strnpcinfo(0), "What a strange thing... " + $@Fluffy_Fighter$ + " just disappeared!"; callsub S_Clean; end; OnTooMany: if (getcharid(3) == $@Fluffy_FighterID) end; npctalk strnpcinfo(0), "Hey " + strcharinfo(0) + "! What are you doing there? This hunt is for " + $@Fluffy_Fighter$ + " alone!"; warp "033-1", 77, 34; end; L_Died: warp "033-1", 77, 34; message strcharinfo(0), "You are dead."; npctalk strnpcinfo(0), "Oh no! " + $@Fluffy_Fighter$ + " got overwhelmed!"; callsub S_Clean; end; L_TimeOver: message strcharinfo(0), "Your time is over."; goto L_MaybeRecordScore; L_CheckDrops: set @Fluffy_RedApple, getareadropitem("033-1", 79, 29, 88, 42, "RedApple", 1); set @Fluffy_XmasCake, getareadropitem("033-1", 79, 29, 88, 42, "XmasCake", 1); set @Fluffy_Cake, getareadropitem("033-1", 79, 29, 88, 42, "Cake", 1); set @Fluffy_GreenApple, getareadropitem("033-1", 79, 29, 88, 42, "GreenApple", 1); if (@Fluffy_RedApple || @Fluffy_XmasCake || @Fluffy_Cake || @Fluffy_GreenApple) goto L_BeginHunting; goto L_ContinueTimer; L_BeginHunting: set $@Fluffy_Spawn, @Fluffy_RedApple + 5 * @Fluffy_XmasCake + 3 * @Fluffy_Cake + @Fluffy_GreenApple; // limit the number of monsters that can be spawned, to prevent people creating lag with massive amount of monsters if (($@Fluffy_Spawn + $@Fluffy_Alive) <= 100) goto L_SpawnFluffies; message strcharinfo(0), "Wow, calm down, there are already too many Fluffies around here."; set $@Fluffy_Spawn, 100 - $@Fluffy_Alive; if ($@Fluffy_Spawn <= 0) goto L_ContinueTimer; goto L_SpawnFluffies; L_SpawnFluffies: areamonster "033-1", 79, 29, 88, 42, "", 1089, $@Fluffy_Spawn, "Kimarr::OnFluffyDeath"; set $@Fluffy_Extra, 5 * @Fluffy_XmasCake + 3 * @Fluffy_Cake + 12 * ($@Fluffy_Alive + $@Fluffy_Spawn) + 7 * BaseLevel; if ((BaseLevel > 40) && (rand($@Fluffy_Extra) > 500) && ($@KIMARR_EVENT < 1)) // Ice Goblin areamonster "033-1", 79, 29, 88, 42, "", 1058, 1, "Kimarr::OnIceGoblinDeath"; if ((BaseLevel > 60) && (rand($@Fluffy_Extra) > 550) && ($@KIMARR_EVENT < 1)) // Wolvern areamonster "033-1", 79, 29, 88, 42, "", 1090, 1, "Kimarr::OnWolvernDeath"; if ((BaseLevel > 70) && (rand($@Fluffy_Extra) > 600) && ($@KIMARR_EVENT < 1)) // Yeti areamonster "033-1", 79, 29, 88, 42, "", 1072, 1, "Kimarr::OnYetiDeath"; set $@Fluffy_Extra, 0; set @Fluffy_RedApple, 0; set @Fluffy_XmasCake, 0; set @Fluffy_Cake, 0; set @Fluffy_GreenApple, 0; set $@Fluffy_Alive, $@Fluffy_Alive + $@Fluffy_Spawn; goto L_ContinueTimer; OnIceGoblinDeath: set @MobID, 1058; if (getcharid(3) != $@Fluffy_FighterID) goto L_Punish; set @MobID, 0; end; OnWolvernDeath: set @MobID, 1090; if (getcharid(3) != $@Fluffy_FighterID) goto L_Punish; set @MobID, 0; end; OnYetiDeath: set @MobID, 1072; if (getcharid(3) != $@Fluffy_FighterID) goto L_Punish; set @MobID, 0; end; OnFluffyDeath: set @MobID, 1089; if ($@Fluffy_Hunting == 0) end; if (getcharid(3) != $@Fluffy_FighterID) goto L_Punish; set @MobID, 0; set $@Fluffy_Kills, $@Fluffy_Kills + 1; set $@Fluffy_Alive, $@Fluffy_Alive - 1; if ($@Fluffy_Alive != 0) end; if (attachrid($@Fluffy_FighterID) == 1) goto L_Killedall; goto L_GotOut; L_Punish: if (@MobID == 1089) areamonster "033-1", 79, 29, 88, 42, "", 1089, 1, "Kimarr::OnFluffyDeath"; if (@MobID == 1058) areamonster "033-1", 79, 29, 88, 42, "", 1058, 1, "Kimarr::OnIceGoblinDeath"; if (@MobID == 1090) areamonster "033-1", 79, 29, 88, 42, "", 1090, 1, "Kimarr::OnWolvernDeath"; if (@MobID == 1072) areamonster "033-1", 79, 29, 88, 42, "", 1072, 1, "Kimarr::OnYetiDeath"; npctalk strnpcinfo(0), strcharinfo(0) + "! This hunt is for " + $@Fluffy_Fighter$ + " alone!"; heal -Hp, 0; set @MobID, 0; end; L_Killedall: message strcharinfo(0), "Good job, but you still have time to throw more food on the ground."; end; S_Clean: stopnpctimer; set $@Fluffy_Hunting, 0; set $@Fluffy_Time, 0; set $@Fluffy_PC_Deaths, 0; set $@Fluffy_Fighter$, ""; set $@Fluffy_FighterID, 0; set $@Fluffy_Kills, 0; set $@Fluffy_Spawn, 0; set $@Fluffy_Alive, 0; killmonster "033-1", "Kimarr::OnIceGoblinDeath"; killmonster "033-1", "Kimarr::OnWolvernDeath"; killmonster "033-1", "Kimarr::OnYetiDeath"; killmonster "033-1", "Kimarr::OnFluffyDeath"; set @state, 0; return; L_MaybeRecordScore: warp "033-1", 77, 34; set @loop, 0; set @rank, 0; if ($@KIMARR_EVENT) goto L_CRC_MaybeInsertNext; // No event, keep as usual if ($@Fluffy_Kills < $@Fluffy_Min) goto L_NotGoodEnough; goto L_MaybeInsertNext; L_MaybeInsertNext: if ($@Fluffy_Kills > $Record_Fluffy_Kills[@rank]) goto L_InsertScore; // you already had a better score if (strcharinfo(0) == $Record_Fluffy_Name$[@rank]) goto L_Reward1; set @rank, @rank + 1; if (@rank == MAX_HIGH_SCORES) goto L_Reward1; goto L_MaybeInsertNext; L_InsertScore: set @loop, @rank; goto L_FindLastScore; L_FindLastScore: // comment this out to allow the player to be in the list more than once // though actually, it might be better just to assume the list is full if (strcharinfo(0) == $Record_Fluffy_Name$[@loop]) goto L_MoveStuff; set @loop, @loop + 1; if (@loop == MAX_HIGH_SCORES) goto L_MoveStuff; goto L_FindLastScore; L_MoveStuff: if (@loop == @rank) goto L_FinallyInsertMe; set $Record_Fluffy_Kills[@loop], $Record_Fluffy_Kills[@loop - 1]; set $Record_Fluffy_Name$[@loop], $Record_Fluffy_Name$[@loop - 1]; set $Record_Fluffy_Date$[@loop], $Record_Fluffy_Date$[@loop - 1]; set @loop, @loop - 1; goto L_MoveStuff; L_FinallyInsertMe: set $Record_Fluffy_Kills[@rank], $@Fluffy_Kills; set $Record_Fluffy_Name$[@rank], strcharinfo(0); callfunc "time_stamp"; set $Record_Fluffy_Date$[@rank], @ts_date$ + " " + @ts_time$; set @ts_date$, ""; set @ts_time$, ""; goto L_Reward1; L_NotGoodEnough: npctalk strnpcinfo(0), "What a disappointment, " + strcharinfo(0) + " hunted only " + $@Fluffy_Kills + " Fluffies."; message strcharinfo(0), "Kimarr: What a disappointment, you hunted only " + $@Fluffy_Kills + " Fluffies."; callsub S_Clean; end; L_ShowRecord: set @rank, 0; set @loop, 0; goto L_ShowNextRecord; L_ShowNextRecord: if ($Record_Fluffy_Kills[@loop] == 0) goto L_Close; mes (@loop + 1) + " - " + $Record_Fluffy_Name$[@loop] + " - " + $Record_Fluffy_Kills[@loop] + " Fluffies killed at " + $Record_Fluffy_Date$[@loop]; set @loop, @loop + 1; if (MAX_HIGH_SCORES > 4 && (@loop % 5) == 0 && $Record_Fluffy_Kills[@loop] > 0) goto L_NextShowNextRecord; goto L_ShowNextRecord; L_NextShowNextRecord: next; goto L_ShowNextRecord; L_CRC_MaybeRecordScore: if ($@Fluffy_Kills < $@Fluffy_Min) goto L_NotGoodEnough; set @rank, 0; set @loop, 0; goto L_MaybeInsertNext; L_CRC_MaybeInsertNext: if ($@Fluffy_Kills > $Record_CRC_Fluffy_Kills[@rank]) goto L_CRC_InsertScore; // you already had a better score if (strcharinfo(0) == $Record_CRC_Fluffy_Name$[@rank]) goto L_CRC_MaybeRecordScore; set @rank, @rank + 1; if (@rank == MAX_HIGH_SCORES_CRC) goto L_CRC_MaybeRecordScore; goto L_CRC_MaybeInsertNext; L_CRC_InsertScore: set @loop, @rank; goto L_CRC_FindLastScore; L_CRC_FindLastScore: // comment this out to allow the player to be in the list more than once // though actually, it might be better just to assume the list is full if (strcharinfo(0) == $Record_CRC_Fluffy_Name$[@loop]) goto L_CRC_MoveStuff; set @loop, @loop + 1; if (@loop == MAX_HIGH_SCORES_CRC) goto L_CRC_MoveStuff; goto L_CRC_FindLastScore; L_CRC_MoveStuff: if (@loop == @rank) goto L_CRC_FinallyInsertMe; set $Record_CRC_Fluffy_Kills[@loop], $Record_CRC_Fluffy_Kills[@loop - 1]; set $Record_CRC_Fluffy_Name$[@loop], $Record_CRC_Fluffy_Name$[@loop - 1]; set $Record_CRC_Fluffy_Date$[@loop], $Record_CRC_Fluffy_Date$[@loop - 1]; set @loop, @loop - 1; goto L_CRC_MoveStuff; L_CRC_FinallyInsertMe: set $Record_CRC_Fluffy_Kills[@rank], $@Fluffy_Kills; set $Record_CRC_Fluffy_Name$[@rank], strcharinfo(0); callfunc "time_stamp"; set $Record_CRC_Fluffy_Date$[@rank], @ts_date$ + " " + @ts_time$; set @ts_date$, ""; set @ts_time$, ""; goto L_CRC_MaybeRecordScore; L_CRC_ShowRecord: set @rank, 0; set @loop, 0; goto L_CRC_ShowNextRecord; L_CRC_ShowNextRecord: if ($Record_CRC_Fluffy_Kills[@loop] == 0) goto L_Close; mes (@loop + 1) + " - " + $Record_CRC_Fluffy_Name$[@loop] + " - " + $Record_CRC_Fluffy_Kills[@loop] + " Fluffies killed at " + $Record_CRC_Fluffy_Date$[@loop]; set @loop, @loop + 1; if (MAX_HIGH_SCORES_CRC > 4 && (@loop % 5) == 0 && $Record_CRC_Fluffy_Kills[@loop] > 0) goto L_CRC_NextShowNextRecord; goto L_CRC_ShowNextRecord; L_CRC_NextShowNextRecord: next; goto L_CRC_ShowNextRecord; L_Close: // clear all temporary player variables that are not otherwise cleared // it is not feasible to otherwise clear @loop // but, not all jumpers to L_Close have necessarily used it ... // still, I think it's a good precent to ALWAYS exit via L_Close set @loop, 0; // if you unset @state, it might break the script // If only we had the concept of "local constants" ... close; S_Update_Mask: set QUEST_Barbarians, (QUEST_Barbarians & ~($@Q_Barbarians_MASK)) | (@state << $@Q_Barbarians_SHIFT); return; } function|script|FluffyDebug { mes "[Numa]"; mes "Please select an action."; menu "Enable/Disable Event Scoreboards", L_Enable, "Reset event scoreboards", L_Reset; L_Enable: set $@KIMARR_EVENT, !$@KIMARR_EVENT; return; L_Reset: if (GM < G_EVENT) goto L_Decline; cleararray $Record_CRC_Fluffy_Kills, 0, MAX_HIGH_SCORES; cleararray $Record_CRC_Fluffy_Name$, "", MAX_HIGH_SCORES; cleararray $Record_CRC_Fluffy_Date$, "", MAX_HIGH_SCORES; gmlog strcharinfo(0) + " wiped Fluffy Hunt Event Scoreboards."; return; L_Decline: mes "[Numa]"; mes "I'm sorry, but your GM level does not authorizes you to perform this operation."; return; }