// TMW2 Script
// Author:
// TMW Org. (original code)
// Jesusalva
// Description:
// Crazyfefe will wake up when he smells battle
// Variables:
// $@FEFE_CAVE_LEVEL
// Tracks selected difficulty level.
// 0 - Not started
// 1 - Easy
// 2 - Normal
// 3 - Hard
// 4 - Out of Mind (Exclusive for top 3)
// 5 - Cronqvist Mode (Exclusive for Candor Battle Season)
// $@FEFE_DELAY
// Tracks the delay between challenges. Also used to start the combat. Set it to zero so you can start fight at once.
// $@FEFE_CAVE_HERO$
// Whoever started a fight. Also used to know if a fight is about to begin.
// $@FEFE_CAVE_PLAYER_COUNT
// How many players are there.
// $@FEFE_WAVE
// Current wave
// $@GM_OVERRIDE
// Only possible with @set command, overrides the co-op requeriment. Affects other scripts.
006-1,47,22,0 script Crazyfefe NPC_STATUE_EVILMAN,{
function pleaseWait;
function Scoreboard;
function Challenge;
function aboutCandor;
function StartFight;
function CleanUp;
function CaveLogic;
function NextRound;
// Battle already begun
if ($@FEFE_WAVE)
{
npctalk3 l("Pay attention to the fight, @@!", strcharinfo(0));
dispbottom l("Round @@", $@FEFE_WAVE);
end;
}
if ($@FEFE_CAVE_HERO$ != "") {
pleaseWait();
close;
}
// Main Loop
mesn;
mesq l("Who dares to disturb my slumber?");
next;
do
{
select
l("Sorry, sorry! Please rest, great Crazyfefe!"),
l("I do. I want to challenge the Candor Cave!"),
l("What are current leaderboard?"),
l("What is this place anyway?");
mes "";
switch (@menu) {
case 1: close; break;
case 2: Challenge(); break;
case 3: Scoreboard(); break;
case 4: aboutCandor(); break;
}
} while (true);
close;
/// Functions
function pleaseWait {
// Battle in delay (either to begin or to allow new challenges)
if ($@FEFE_DELAY > gettimetick(2))
{
.@time$=FuzzyTime($@FEFE_DELAY,2,2);
// Less than 30 seconds left, do not open a message window.
if ($@FEFE_DELAY-gettimetick(2) <= 30) {
npctalk3 l("@@!", .@time$);
end;
}
mesn;
mesq l("Be Patient... You still need to wait @@.", .@time$);
close;
}
return;
}
// Are you a Candor Top 3?
// ISCANDORTOP3( - )
function ISCANDORTOP3 {
return (strcharinfo(0) == $@cfefe_name$[0] ||
strcharinfo(0) == $@cfefe_name$[1] ||
strcharinfo(0) == $@cfefe_name$[2]);
}
function Scoreboard {
mesc l("All leaderboards are refreshed hourly."), 1;
mesc l("Your current score: @@", CRAZYPOINTS), 3;
HallOfCandor();
next;
return;
}
function aboutCandor {
mesn;
mesq l("I am @@, guardian of Candor Cave. Below this cave, lies the legendary Fefe, arch-wizard from the Great War.", .name$);
next;
mesn;
mesq l("During the war, the Monster King cursed the place where he died, but he fought back, and cursed the curse.");
next;
mesn;
mesq l("For short, they had a fight with curses, and now there's a talking statue over his grave which can spawn monsters here.");
next;
mesn;
mesq l("If you pay the fee, I'll spawn them, for no longer than 20 minutes. You should not fight alone, instead, you need a group of at least three, because, you know, the curse. Or something.");
next;
return;
}
function Challenge {
pleaseWait();
if ($EVENT$ != "Candor") {
mesn;
mesq l("Very well, but for a fee of @@ GP. There's no free lunch, after all!", .price);
//mesc l("A minimum of %d players at the time of start is required!", 2), 1;
mesc l("If at any moment in the fight there's less than %d players in the room, a severe penalty will be applied, so watch out!", 3), 1;
// Not enough money? We end here.
if (Zeny < .price)
close;
next;
} else {
mesn;
mesq l("Very well, let's see what you are made of!");
mesc l("A minimum of %d players at the time of start is required!", 2), 1;
next;
}
// Difficulty Selection
mesc l("Select difficulty."), 1;
mesc l("Out of Mind mode is only available for Top 3.");
mesc l("Cronqvist mode is only available during Candor Battle.");
mesc l("Only Cronqvist Mode yields more points per wave!");
menuint
l("Easy"), 1,
l("Hard"), 3,
rif(ISCANDORTOP3() || is_master(), l("Out of Mind")), 5,
rif($EVENT$ == "Candor" || is_master(), l("Cronqvist Mode")), 12,
rif($EVENT$ == "Candor" && ISCANDORTOP3() || is_master(), l("Crazyfefe Mode")), 25,
rif($EVENT$ == "Candor" && $GAME_STORYLINE >= 4 || is_master(), l("Monster King Mode")), 100,
rif($EVENT$ == "Candor" && ISCANDORTOP3() && $GAME_STORYLINE >= 4 || is_master(), l("Mooubootaur Mode")), 250;
.@cdif=@menuret;
next;
// Already started?
if ($@FEFE_WAVE || $@FEFE_CAVE_HERO$ != "")
{
mesn;
mesq l("Sorry, @@ already started the fight.", $@FEFE_CAVE_HERO$);
close;
}
menuint
l("Sorry, I misclicked the first button. Have a nice nap, great Crazyfefe!"), -1,
rif(is_gm() || $EVENT$ == "Candor", l("WHAT ARE WE WAITING FOR?! START ALREADY!")), 0,
l("Yeah, I have the money. Give me FIVE minutes, and Bring it on!"), 5,
l("Yeah, I have the money. Give me TEN minutes, and Bring it on!"), 10,
l("Yeah, I have the money. Give me FIFTEEN minutes, and Bring it on!"), 15,
rif(is_gm(), l("I'm GM and got the money. Gimme HALF HOUR to invite everybody!")), 30;
// Cancel?
if (@menuret < 0)
close;
// Already started?
if ($@FEFE_WAVE || $@FEFE_CAVE_HERO$ != "")
{
mesn;
mesq l("Sorry, @@ already started the fight.", $@FEFE_CAVE_HERO$);
close;
}
// Use the money
if ($EVENT$ != "Candor")
Zeny -= .price;
// Time delay
$@FEFE_DELAY = gettimetick(2)+60*@menuret;
$@FEFE_CAVE_HERO$ = strcharinfo(0);
.DIFFICULTY = .@cdif;
// We must begin at once, so ignore normal procedure
if (!@menuret) {
logmes "candor fight - start without announce", LOGMES_ATCOMMAND;
closeclientdialog;
StartFight();
}
// Give you a bonus for starting the fight, and announce the fight.
@crazypoints=1;
initnpctimer;
.@msg$=$@FEFE_CAVE_HERO$+" invites everyone to a challenge against Candor Cave. It'll start in "+FuzzyTime($@FEFE_DELAY,2,2)+". Prepare yourselves!";
kamibroadcast(.@msg$);
mesn;
mesq l("Please wait, the fight will start in @@, as requested.", FuzzyTime($@FEFE_DELAY,2,2));
close;
return;
}
function StartFight {
if (getmapusers("006-1") < 1 && !$@GM_OVERRIDE) {
mapannounce("006-1", "Oh noes! There's not enough players. Fight aborted, no refunds!", bc_map);
CleanUp();
}
$@FEFE_CAVE_LEVEL = .DIFFICULTY;
.DIFFICULTY = 0;
$@FEFE_WAVE = 0;
$@FEFE_DELAY = gettimetick(2)+.delay;
$@FEFE_CAVE_PLAYER_COUNT = getmapusers("006-1");
mapannounce("006-1", "The battle is about to begin!", bc_map);
killmonsterall("006-1"); // Saulc likes to spawn stuff to heat stuff up
// Recalculate difficulty
$@FEFE_DIFFICULTY=0;
areatimer "006-1", 20, 20, 70, 60, 10, "Crazyfefe::OnSumLevel";
initnpctimer;
end;
}
// Recalc difficulty
OnSumLevel:
if (ispcdead()) end;
$@FEFE_DIFFICULTY+=BaseLevel;
end;
// Check if we're ready for next wave. Otherwise, do this check again after 5 seconds.
function CaveLogic {
.wtime+=5; // This is looped every 5 s
$@FEFE_CAVE_PLAYER_COUNT = getmapusers("006-1");
// Victory conditions: Too few players are alive OR twenty minutes went on.
// WARNING, dead players still in cave are counted, we might never finish the fight.
// And a GM might be called to ban everyone inside.
if ($@FEFE_CAVE_PLAYER_COUNT < 1 && !$@GM_OVERRIDE || gettimetick(2) >= $@FEFE_DELAY - 300) {
CleanUp();
}
// Recalculate difficulty
$@FEFE_DIFFICULTY=0;
areatimer "006-1", 20, 20, 70, 60, 10, "Crazyfefe::OnSumLevel";
sleep(15);
// Penalty for being below the player count thresholds
// It merely assumes you *are* within the threshold
if ($@FEFE_CAVE_PLAYER_COUNT < 2)
$@FEFE_DIFFICULTY *= 3;
else if ($@FEFE_CAVE_PLAYER_COUNT < 3)
$@FEFE_DIFFICULTY *= 2;
// New wave condition: All mobs dead, or 90 seconds have passed
if (mobcount("006-1", "Crazyfefe::OnPetDeath") <= 0 || .wtime >= 90)
NextRound();
// reset timer
initnpctimer;
end;
}
function NextRound {
.wtime=0;
$@FEFE_WAVE = $@FEFE_WAVE + 1;
// Prepare next round, and reward survivors
$@FEFE_DIFFICULTY+=$@FEFE_CAVE_PLAYER_COUNT+$@FEFE_WAVE*8;
$@FEFE_DIFFICULTY+=(($@FEFE_WAVE/5)*10);
.@mult=10+(3*$@FEFE_CAVE_LEVEL); // +30% per difficulty setting
$@FEFE_DIFFICULTY=$@FEFE_DIFFICULTY*.@mult/10;
areatimer "006-1", 20, 20, 70, 60, 10, "Crazyfefe::OnReward";
mapannounce "006-1", "The wave nº "+$@FEFE_WAVE+" is starting with " + $@FEFE_CAVE_PLAYER_COUNT + " player(s) left alive." , 0;
.@amount=$@FEFE_WAVE+$@FEFE_CAVE_PLAYER_COUNT+rand2(1,2);
freeloop(true);
for (.@i = 0; .@i < .@amount; ++.@i) {
.@monsterId=Piou;
.@lv=max(1, $@FEFE_DIFFICULTY/10);
// Luck shall interfer with .@lv (up to +20 random levels)
// This prevents from excess of House Maggots, for example
.@lv+=any(0, 0, 0, 1, 1, 2);
//debugmes("[Candor] Difficulty is %d, pool is %d", .@lv, $@FEFE_DIFFICULTY);
.@lv=rand(0, .@lv);
switch (.@lv) {
case 0:
case 1:
case 2:
//.@monsterId = any(HouseMaggot, HouseMaggot, SlimeBlast, HouseMaggot) ; break;
case 3:
.@monsterId = any(AngryScorpion, CaveMaggot, MagicGoblin, ViciousSquirrel, AngryBat, HouseMaggot, SlimeBlast) ; break;
case 4:
case 5:
case 6:
.@monsterId = any(AngryBat, RedSlime, AngryRedScorpion, DesertBandit, Bandit, Sarracenus, VampireBat, Skeleton, GreenSlime) ; break;
case 7:
case 8:
.@monsterId = any(GreenSlime, LavaSlime, Bluepar, RedMushroom, CandiedSlime, RobinBandit, AngryYellowSlime, OldSnake, GrassSnake, BlueSlime) ; break;
case 9:
case 10:
.@monsterId = any(BlueSlime, SaxsoGhost, Snake, BlackSlime, Wolvern, FireSkull, DarkLizard, BlackScorpion) ; break;
case 11:
case 12:
.@monsterId = any(BlackScorpion, DustRifle, DustGatling, DustRevolver, ArmoredSkeleton, Grenadier) ; break;
case 13:
case 14:
.@monsterId = any(DustRifle, DustGatling, DustRevolver, MountainSnake, Yeti, HoodedNinja, FallenGuard1, FallenGuard2) ; break;
case 15:
case 16:
.@monsterId = any(FallenGuard1, FallenGuard2, BanditLord, Yeti, WickedMushroom, Thug, Grenadier) ; break;
case 17:
case 18:
.@monsterId = any(Forain, WickedMushroom, BlackMamba, Michel, Terranite) ; break;
case 19:
case 20:
case 21:
.@monsterId = any(Forain, Archant, BlackMamba, JackO, TerraniteProtector, EliteDuck) ; break;
default:
.@monsterId = any(GoboBear, GiantMutatedBat, TerraniteProtector, Reaper) ; break;
}
.@m=areamonster("006-1", 20, 20, 70, 60, strmobinfo(1, .@monsterId), .@monsterId, 1, "Crazyfefe::OnPetDeath");
set_aggro(.@m);
// We must lower difficulty according to summoned monster. Only 60% is lowered.
// If total level exceeds 250, it will cap at that to prevent excessive "slooping"
.@lower=(limit(1, .@lv, 25)*6);
.@lower=.@lower*7/10; // 70%
$@FEFE_DIFFICULTY=$@FEFE_DIFFICULTY-.@lower;
}
freeloop(false);
return;
}
function CleanUp {
mapannounce "006-1", "Game over! Who will be the next to fall on Crazyfefe's Cave?", 0;
areatimer "006-1", 20, 20, 70, 60, 10, "Crazyfefe::OnReward2";
$@FEFE_OLD = $@FEFE_CAVE_LEVEL;
$@FEFE_CAVE_LEVEL = 0;
$@FEFE_WAVE = 0;
$@FEFE_CAVE_HERO$ = "";
$@FEFE_DELAY=gettimetick(2)+180;
.wtime=0;
killmonster "006-1", "Crazyfefe::OnPetDeath";
stopnpctimer;
initnpctimer;
stopnpctimer;
end;
}
// Special case for survivors.
OnReward2:
if (@crazypoints > CRAZYPOINTS) {
CRAZYPOINTS=@crazypoints;
dispbottom l("Crazyfefe Cave: New Highscore: @@ points", CRAZYPOINTS);
@crazypoints=0;
}
if (!ispcdead() && $@FEFE_OLD >= .BONUS_LVL)
getitem StrangeCoin, limit(1, @crazypoints/25, 5);
// Rewards surviving players between rounds, according to performance, and get rid of dead PCs.
OnReward:
if (ispcdead()) {
recovery(getcharid(3));
warp "Save", 0, 0;
// If your current points is more than your top, update
if (@crazypoints > CRAZYPOINTS) {
CRAZYPOINTS=@crazypoints;
dispbottom l("Crazyfefe Cave: New Highscore: @@ points", CRAZYPOINTS);
@crazypoints=0;
}
end;
}
// Player reward is a random number based on current wave
.@prize=rand($@FEFE_WAVE/2,$@FEFE_WAVE)*2;
// $@FEFE_DIFFICULTY might not be available anymore
if ($@FEFE_WAVE % 5 == 0)
Zeny+=.@prize;
getexp .@prize, rand(1,3);
@crazypoints+=($@FEFE_CAVE_LEVEL >= .BONUS_LVL && $EVENT$ == "Candor" ? 2 : 1);
end;
// Every 5 seconds, handle cave, if fighting. Does nothing when waiting.
OnTimer5000:
if ($@FEFE_CAVE_LEVEL)
CaveLogic();
end;
// Announces and attempts to start the fight once time run out (assuming there are enough players)
OnTimer300000:
if ($@FEFE_CAVE_LEVEL > 0) end;
if ($@FEFE_DELAY <= gettimetick(2)) StartFight();
.@msg$=$@FEFE_CAVE_HERO$+" invites everyone to a challenge against Candor Cave. It'll start in "+FuzzyTime($@FEFE_DELAY)+". Prepare yourselves!";
announce .@msg$, bc_all|bc_npc;
//channelmes("#world", .@msg$);
//kamibroadcast(.@msg$);
initnpctimer;
end;
OnPetDeath:
end;
OnInit:
.sex=G_OTHER;
.distance=5;
.price=400;
.delay=(60*25);
.wtime=0;
.DIFFICULTY=0;
.BONUS_LVL=5;
end;
}