// TMW2 Script // Evol functions. // Authors: // gumi // omatt // Travolta // Jesusalva // Description: // Fishing functions. // Variable // .dir // DOWN Never try or pulled too late // UP Bait dropped // LEFT Fish bite bait // // player log on .dir is DOWN, start by choose bait menu // player chooses bait, script addtimer in npc .dir is UP // if player pulls before signal npc, bait is lost, set .bait to DOWN goto choose bait // if player pulls after pull delay max, bait is lost, set .bait to DOWN goto choose bait // npc signal .dir is LEFT // player pulls between npc signal and pulls delay max, got the fish, set .dir to DOWN goto choose bait function script fishing_cleanup { .@npc$ = getarg(0, ""); if (.@npc$ == "") end; set getvariableofnpc(.char_id, .@npc$), 0; // clean acc id set getvariableofnpc(.account_id, .@npc$), 0; // clean char id set getvariableofnpc(.last_used, .@npc$), gettimetick(2); // set last used time setnpcdir .@npc$, DOWN; // reset direction return; } - script global fishing handler 32767,{ end; OnBite: if (getnpcdir(@fishing_spot$) != UP) end; setnpcdir @fishing_spot$, LEFT; @fishing_tick = gettimetick(0); .@bite_fx=getvariableofnpc(.bite_fx, @fishing_spot$); specialeffect(.@bite_fx ? .@bite_fx : 30, SELF, playerattached()); end; OnCleanUp: dispbottom l("You waited too long and lost the bait..."); specialeffect(getvariableofnpc(.failure_fx, @fishing_spot$), SELF, playerattached()); // event fail OnPCLogoutEvent: fishing_cleanup @fishing_spot$; @fishing_spot$ = ""; // unbind fishing npc end; } // Syntax: fishing() // Syntax: fishing ( OFFSET, COMMON FISHES, RARE FISHES ) // OFFSET: How many fishes are common function script fishing { /////////////////////////////////////////// // Var initialization if (getarg(0, 0) == 0) { setarray .@common_fish, CommonCarp; setarray .@rare_fish, GrassCarp; } else { .@i=0; freeloop(true); for (.@i=1; .@i < getargcount(); .@i++) { if (.@i <= getarg(0)) { .@common_fish[.@i-1]=getarg(.@i); } else { .@rare_fish[.@i-1-getarg(0)]=getarg(.@i); } }; freeloop(false); } //debugmes("[FISH] Initialized with %d common and %d rare fishes", getarraysize(.@common_fish), getarraysize(.@rare_fish)); .@npc$ = strnpcinfo(0); // the full name of the fishing spot .@account_id = getvariableofnpc(.account_id, .@npc$); // the account id of the player using the fishing spot .@char_id = getvariableofnpc(.char_id, .@npc$); // the char id of the player using the fishing spot .@dir = getnpcdir(.@npc$); // direction of the fishing spot .@last_used = getvariableofnpc(.last_used, .@npc$); // when this fishing spot was last used .@baits = getvariableofnpc(.baits, .@npc$); // bait count .@rod = getvariableofnpc(.fishing_rod, .@npc$); // the fishing rod required for this spot .@rod = (.@rod ? .@rod : FishingRod); .@net_ratio = getvariableofnpc(.net_ratio, .@npc$); // How many fishes and baits are required? .@net_ratio = max(1, (.@net_ratio ? .@net_ratio : 1)); .@regen_time = getvariableofnpc(.cooldown, .@npc$); // cooldown for the fishing spot .@regen_time = (.@regen_time ? .@regen_time : 20); .@bp_chance = getvariableofnpc(.bp_chance, .@npc$); // Blueprint chance .@bp_chance = (.@bp_chance ? .@bp_chance : 1); .@success_fx = getvariableofnpc(.success_fx, .@npc$); // effect to show on success .@success_fx = (.@success_fx ? .@success_fx : FX_SUCCESS); .@failure_fx = getvariableofnpc(.failure_fx, .@npc$); // effect to show on failure if (.@failure_fx < 1) { .@failure_fx = FX_FAILURE; set getvariableofnpc(.failure_fx, .@npc$), .@failure_fx; // needed by global handler } .@initial_fx = getvariableofnpc(.initial_fx, .@npc$); // effect to show when throwing the bait .@initial_fx = (.@initial_fx ? .@initial_fx : 29); .@bite_fx = getvariableofnpc(.bite_fx, .@npc$); // effect to show when something bites if (.@bite_fx < 1) { .@bite_fx = 30; set getvariableofnpc(.bite_fx, .@npc$), .@bite_fx; // needed by global handler } .@wait_time_min = getvariableofnpc(.wait_time_min, .@npc$); // min amount of time to wait for the line to sink .@wait_time_min = (.@wait_time_min ? .@wait_time_min : 4000); .@wait_time_max = getvariableofnpc(.wait_time_max, .@npc$); // max amount of time to wait for the line to sink .@wait_time_max = (.@wait_time_max ? .@wait_time_max : 18000); // During night time there are more fishes, and therefore, it is easier to fish // This will make they reply at most 30% faster. Default is a 6 second max delay gain if (is_night()) .@wait_time_max = min(.@wait_time_min, .@wait_time_max*7/10); .@catch_time = getvariableofnpc(.catch_time, .@npc$); // the player must catch the fish within X ms after the line sinks .@catch_time = (.@catch_time ? .@catch_time : 5000); .@pull_rand_max = getvariableofnpc(.pull_rand_max, .@npc$); .@pull_rand_max = (.@pull_rand_max ? .@pull_rand_max : 800); .@fish_id = CommonCarp; // failsafe if (getvariableofnpc(.bait_ids[0], .@npc$) < 1) { // default baits (bait, chance booster) rand(0, 100) setarray getvariableofnpc(.bait_ids[0], .@npc$), SmallTentacles, 4, Bread, 4, Aquada, 8, Tentacles, 10, BugLeg, 2, CaveSnakeTongue, 6, LettuceLeaf, 1, Cheese, 3, RoastedMaggot, 6; } if (.@baits < 1) { // only count it once .@baits = getarraysize(getvariableofnpc(.bait_ids[0], .@npc$)); set getvariableofnpc(.baits, .@npc$), .@baits; } /////////////////////////////////////////// // Logic below if (countitem(.@rod) < 1) { dispbottom l("You don't have any @@.", getitemlink(.@rod)); return -1; } if (.@account_id > 0 && !isloggedin(.@account_id, .@char_id)) { fishing_cleanup .@npc$; // reset .@dir = DOWN; } if (.@char_id != getcharid(CHAR_ID_CHAR) && .@dir != DOWN) { dispbottom l("This fishing spot is already being used!"); return -2; } // pull too soon if (.@dir == UP) { deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup deltimer "global fishing handler::OnBite"; specialeffect(.@failure_fx, SELF, playerattached()); // event fail fishing_cleanup .@npc$; // do it manually instead dispbottom l("You pulled too soon and lost the bait."); return -3; } // pull maybe on time else if (.@dir == LEFT) { deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup fishing_cleanup .@npc$; // do it manually instead getmapxy .@mapbis$, .@xbis, .@ybis, UNITTYPE_PC; // get current char location // Leave spot, lost the bait if (.@mapbis$ != @fishing_loc$[0] || .@xbis != @fishing_loc[0] || .@ybis != @fishing_loc[1] || @fishing_spot$ != .@npc$) { dispbottom l("You left your fishing spot!"); return -4; } // RNG to obtain a fish if (rand2(gettimetick(0) - @fishing_tick) <= .@pull_rand_max) { for (.@i=0 ; .@i < .@net_ratio ; .@i++) { // RNG to obtain a rare fish or common fish // Luck can increase up to 5% when it is at 100. // Level can increase up to 10% when it is at 100. .@boost=(readparam2(bLuk)/20)+(BaseLevel/10); .@bai=getvariableofnpc(.bait_ids[@bait_d+1], .@npc$); // Ancient Blueprint: 0.1% BP Chance - bait weight if (rand2(1000) < .@bp_chance*.@bai) { .@fish_id = AncientBlueprint; } else if (rand2(0, 100) < .@bai+.@boost) { .@fish_id = any_of(.@rare_fish); } else { .@fish_id = any_of(.@common_fish); } specialeffect(.@success_fx, SELF, playerattached()); getexp getvariableofnpc(.bait_ids[@bait_d+1], .@npc$)+(BaseLevel/10), 0; // xp gain is equivalent to bait rarity + BaseLevel boost // MobPt gain is equivalent to bait rarity. if (MPQUEST) Mobpt+=getvariableofnpc(.bait_ids[@bait_d+1], .@npc$); if(!checkweight(.@fish_id, 1)) { dispbottom l("You caught a @@ but had no room in your inventory to carry it.", getitemlink(.@fish_id)); makeitem .@fish_id, 1, .@mapbis$, .@xbis, .@ybis; // drop on the ground return 0; } getitem .@fish_id, 1; } } else { dispbottom l("You pulled too late and lost the bait..."); specialeffect(.@failure_fx, SELF, playerattached()); // event fail .@fish_id = 0; } @fishing_spot$=""; return .@fish_id; } if (gettimetick(2) - .@last_used < .@regen_time) { dispbottom l("This fishing spot has just been used, give it a rest."); return -5; } // This "hack" will prevent you from fishing at two spots (buggy) // It'll cancel the previous fishing too, per logical rule. if (@fishing_spot$ != "") { deltimer "global fishing handler::OnCleanUp"; // cancel auto cleanup deltimer "global fishing handler::OnBite"; fishing_cleanup(@fishing_spot$); // clean up manually @fishing_spot$=""; dispbottom l("You left your fishing spot!"); return -4; } // begin fishing narrator S_LAST_NEXT, l("You see some fish reflecting the sun on the surface of the water."), (.@net_ratio == 1 ? l("What will be the bait for the fish?") : l("You need @@ units of bait for this fishing spot. What will you use?", .@net_ratio)); mes "##B" + l("Drag and drop an item from your inventory.") + "##b"; .@bait = requestitem(); .@bait_c = false; if (.@bait < .@net_ratio) { narrator S_FIRST_BLANK_LINE, l("You take your @@ and leave.", getitemlink(.@rod)); return -6; } if (countitem(.@bait) < .@net_ratio) { mesc l("You do not have enough bait for fishing here."); return -6; } for (.@i = 0; .@i < .@baits; .@i += 2) { if (getvariableofnpc(.bait_ids[.@i], .@npc$) == .@bait) { .@bait_c = true; @bait_d = .@i; break; } } if (.@bait_c != true) { narrator S_FIRST_BLANK_LINE, l("This item cannot be used as bait here."); return -6; } if (getvariableofnpc(.char_id, .@npc$) > 0) { narrator S_FIRST_BLANK_LINE, l("Somebody took your place on this spot!"), l("You take your fishing rod and leave."); return -8; } @fishing_spot$ = .@npc$; // bind player to fishing spot set getvariableofnpc(.account_id, .@npc$), getcharid(CHAR_ID_ACCOUNT); // record account id set getvariableofnpc(.char_id, .@npc$), getcharid(CHAR_ID_CHAR); // record char id set getvariableofnpc(.last_used, .@npc$), gettimetick(2); getmapxy(@fishing_loc$[0], @fishing_loc[0], @fishing_loc[1], 0); // record char pos delitem .@bait, .@net_ratio; // The player uses this spot, his bait is ready, he just has to wait for the signal. closedialog; specialeffect(.@initial_fx, SELF); // throw the bait sleep2 800; // wait 0.8s for synchronize the sound of "plop" in water with the npc dir UP. setnpcdir .@npc$, UP; dispbottom l("Wait for the bait to sink underwater."); .@delay = rand(.@wait_time_min, .@wait_time_max); addtimer .@delay, "global fishing handler::OnBite"; // bite logic addtimer (.@delay + .@catch_time), "global fishing handler::OnCleanUp"; // auto clean up return 0; }