// TMW2 Script. // Authors: // Jesusalva // Description: // Util functions ///////////////////////////////////////////////////////////////////////////////// // Delete item ID on inventories, storages, guild storages and carts. Also affects mails. // WARNING, irreversible and dangerous! // DelItemFromEveryPlayer( ID ) function script DelItemFromEveryPlayer { if (getarg(0, -1) < 0) return; query_sql("DELETE FROM `inventory` WHERE `nameid`="+getarg(0)); query_sql("DELETE FROM `cart_inventory` WHERE `nameid`="+getarg(0)); query_sql("DELETE FROM `storage` WHERE `nameid`="+getarg(0)); query_sql("DELETE FROM `guild_storage` WHERE `nameid`="+getarg(0)); query_sql("DELETE FROM `rodex_items` WHERE `nameid`="+getarg(0)); query_sql("DELETE FROM `auction` WHERE `nameid`="+getarg(0)); return; } // Delete an acc_reg entry from all players. Full arrays only. Affect num and str db. // WARNING, irreversible and dangerous! // DelAccRegFromEveryPlayer( KEY ) function script DelAccRegFromEveryPlayer { if (getarg(0, "error") == "error") return; query_sql("DELETE FROM `acc_reg_num_db` WHERE `key`='"+getarg(0)+"'"); query_sql("DELETE FROM `acc_reg_str_db` WHERE `key`='"+getarg(0)+"'"); return; } // Delete a quest entry from all players. This includes all counters. Use with caution. // WARNING, irreversible and dangerous! // DelQuestFromEveryPlayer( ID ) function script DelQuestFromEveryPlayer { if (getarg(0, -1) < 0) return; query_sql("DELETE FROM `quest` WHERE `quest_id`="+getarg(0)); return; } // Transforms an item in something else. // ReplaceItemFromEveryPlayer( OldID, NewID ) function script ReplaceItemFromEveryPlayer { if (getarg(0, -1) < 0) return; debugmes("* Server update: %d item was replaced by %d", getarg(0), getarg(1)); query_sql("UPDATE `inventory` SET `nameid`='"+getarg(1)+"' WHERE `nameid`="+getarg(0)); query_sql("UPDATE `cart_inventory` SET `nameid`='"+getarg(1)+"' WHERE `nameid`="+getarg(0)); query_sql("UPDATE `storage` SET `nameid`='"+getarg(1)+"' WHERE `nameid`="+getarg(0)); query_sql("UPDATE `guild_storage` SET `nameid`='"+getarg(1)+"' WHERE `nameid`="+getarg(0)); query_sql("UPDATE `rodex_items` SET `nameid`='"+getarg(1)+"' WHERE `nameid`="+getarg(0)); query_sql("UPDATE `auction` SET `nameid`='"+getarg(1)+"' WHERE `nameid`="+getarg(0)); return; } ///////////////////////////////////////////////////////////////////////////////// // Returns Nard reputation for discounts // Currently ranges from 0 to 16. function script nard_reputation { .@nr=0; // Base reputation // Valon Quest (+1 rep) if (getq(CandorQuest_Trainer) >= 14) .@nr=.@nr+1; // Zegas Quest (+1 rep) if (getq(CandorQuest_Barrel) >= 4) .@nr=.@nr+1; // Hide And Seek Quest (+1 rep) if (getq(CandorQuest_HAS) >= 4) .@nr=.@nr+1; // Sailors Quest (+1 rep) if (getq(CandorQuest_Sailors) >= 3) .@nr=.@nr+1; // Sailors Quest, part 2 (+1 rep) if (getq(CandorQuest_SailorCure) >= 1) .@nr=.@nr+1; // Vincent Quest (+1 rep) if (getq(CandorQuest_Vincent) >= 2) .@nr=.@nr+1; // Tolchi Quest (+1 rep) if (getq(CandorQuest_Tolchi) >= 4) .@nr=.@nr+1; // Maya Quest (+1 rep) if (getq(CandorQuest_Maya) >= 4) .@nr=.@nr+1; // Rosen Quest (+1 rep) if (getq(CandorQuest_Rosen) >= 3) .@nr=.@nr+1; // Ship Crew Quests // Dan Quest (+1 rep) if (getq(ShipQuests_Dan) >= 3) .@nr=.@nr+1; // Chef Gado Quest (+1 rep) if (getq(ShipQuests_ChefGado) >= 2) .@nr=.@nr+1; // Peter Quest (+1 rep) if (getq(ShipQuests_Peter) >= 7) .@nr=.@nr+1; // Tulimshar Quests // Swezanne Quest (+1 rep) if (getq(TulimsharQuest_Swezanne) >= 1) .@nr=.@nr+1; // Sailors Quest (+1 rep) if (getq(TulimsharQuest_Sailors) >= 2) .@nr=.@nr+1; // Hasan Quest (+1 rep) if (getq(TulimsharQuest_Hasan) >= 5) .@nr=.@nr+1; // Dausen Quest (+1 rep) if (getq(TulimsharQuest_WaterForGuard) >= 3) .@nr=.@nr+1; //debugmes "Reputation: "+str(.@nr); return .@nr; } // Returns reputation based on quests completion for discounts. Returns 0~100 int. // Takes one argument (PC_DEST$). Grep for "getarg". function script reputation { .@nr=0; // Base reputation // Tulimshar Quests (16 points) if (getarg(0) == "Tulim") { // Eugene Quest (+1 rep) if (getq(TulimsharQuests_Fishman) >= 2) .@nr=.@nr+1; // Sarah Quest (+1 rep) if (getq(TulimsharQuest_Sarah) >= 1) .@nr=.@nr+1; // Dausen Quest (+1 rep) if (getq(TulimsharQuest_WaterForGuard) >= 3) .@nr=.@nr+1; // Dausen Quest II (+1 rep) if (getq(TulimsharQuest_MobTutorial) >= 8) .@nr=.@nr+1; // Swezanne Quest (+1 rep) if (getq(TulimsharQuest_Swezanne) >= 1) .@nr=.@nr+1; // Silvia Quest (+1 rep) if (getq(TulimsharQuest_Lifestone) >= 2) .@nr=.@nr+1; /* // Eisten Quest (+1 rep) if (getq(TulimsharQuest_Eistein) >= 6) .@nr=.@nr+1; */ // Hasan Quest (+1 rep) if (getq(TulimsharQuest_Hasan) >= 5) .@nr=.@nr+1; // Devoir Quest (+1 rep) if (getq(TulimsharQuest_Devoir) >= 1) .@nr=.@nr+1; // Sailors Quest (+1 rep) if (getq(TulimsharQuest_Sailors) >= 2) .@nr=.@nr+1; // Zarkor Quest (+1 rep) if (getq(TulimsharQuest_DarkInvocator) >= 7) .@nr=.@nr+1; // Anwar Quest (+1 rep) if (getq(TulimsharQuest_AnwarField) >= 10) .@nr=.@nr+1; // Neko Quest (+1 rep) if (getq(TulimsharQuest_Neko) >= 2) .@nr=.@nr+1; // Tycoon Quest (+1 rep) if (getq(MineQuest_Tycoon) >= 15) .@nr=.@nr+1; // Dracoula Quest (+1 rep) if (getq(MineQuest_Dracoula) >= 1) .@nr=.@nr+1; // Caelum Quest (+1 rep) if (getq(MineQuest_Caelum) >= 2) .@nr=.@nr+1; // Veteran Officer Quest (+1 rep) if (getq(TulimsharQuest_WoodenSword) >= 2) .@nr=.@nr+1; // TULIMSHAR Magical Forumula .@nr=.@nr*100/16; // Hurnscald Quests (11 points) } else if (getarg(0) == "Hurns") { // Alan Quest (+1 rep) if (getq(HurnscaldQuest_ForestBow) >= 2) .@nr=.@nr+1; // Gwendolyn Quest (+1 rep) if (getq(HurnscaldQuest_HarkEye) >= 6) .@nr=.@nr+1; // Celestia Quest (+1 rep) if (getq(HurnscaldQuest_TeaParty) >= 2) .@nr=.@nr+1; /* // Yeti King Quest (+1 rep) // Please note that if you challenge it again and lose, it'll reset if (getq(HurnscaldQuest_Celestia) == 6) .@nr=.@nr+1; */ // Farmers Quest (+1 rep) if (getq(HurnscaldQuest_Farmers) >= 5) .@nr=.@nr+1; // Helena Quest (+1 rep) if (getq(HurnscaldQuest_Bandits) >= 8) .@nr=.@nr+1; // Injuried Mouboo Quest (+1 rep) if (getq(HurnscaldQuest_InjuriedMouboo) >= 2) .@nr=.@nr+1; // Blood Donor Quest (+1 rep) if (getq(HurnscaldQuest_BloodDonor) >= 1) .@nr=.@nr+1; // Woody Quest (+1 rep) if (getq(HurnscaldQuest_Woody) >= 5) .@nr=.@nr+1; // Lieutenant Quest (+1 rep) if (getq(HurnscaldQuest_Lieutenant) >= 10) .@nr=.@nr+1; // Thorn Quest (+1 rep) if (getq(HurnscaldQuest_Thorn) >= 1) .@nr=.@nr+1; // Blossom Quest (+1 rep) if (getq(HurnscaldQuest_Blossom) >= 1) .@nr=.@nr+1; // HURNSCALD Magical Forumula .@nr=.@nr*100/11; // Land Of Fire Quests (5 points) } else if (getarg(0) == "LoF") { // The EPISODE //// Tea For Two (+1 rep) if (getq(LoFQuest_EPISODE) >= 2) .@nr=.@nr+1; //// Early Christmas (+1 rep) if (getq(LoFQuest_EPISODE) >= 6) .@nr=.@nr+1; // George Quest (+1 rep) if (getq(LoFQuest_George) >= 3) .@nr=.@nr+1; // Fairy Quest (+1 rep) if (getq(LoFQuest_Fairy) >= 3) .@nr=.@nr+1; // Pet Detective Quest (+1 rep) if (getq(LoFQuest_Pets) >= 1) .@nr=.@nr+1; // LAND OF FIRE Magical Forumula .@nr=.@nr*100/5; // Nivalis Quests (6 points) } else if (getarg(0) == "Nival") { // Nivalis Well Quest (+1 rep) if (getq(NivalisQuest_Well) >= 2) .@nr=.@nr+1; // Nivalis Cindy Quest (+1 rep) if (getq(NivalisQuest_Cindy) >= 5) .@nr=.@nr+1; // Blue Sage: Investigation Quest (+1 rep) if (getq(NivalisQuest_BlueSage) >= 12) .@nr=.@nr+1; // Blue Sage: Slime Hunting Quest (+1 rep) if (getq(NivalisQuest_BlueSageSlimes) >= 12) .@nr=.@nr+1; // Blue Sage: Page Makers Quest (+1 rep) if (getq(NivalisQuest_BlueSagePagemaker) >= 12) .@nr=.@nr+1; // Blue Sage: Page Finders Quest (+1 rep) if (getq(NivalisQuest_BlueSagePagefinder) >= 12) .@nr=.@nr+1; // NIVALIS Magical Forumula .@nr=.@nr*100/6; // Halinarzo Quests (5 points) } else if (getarg(0) == "Halin") { // Foxhound Famine Quest (+1 rep) if (getq(HalinarzoQuest_Foxhound) >= 6) .@nr=.@nr+1; // Charles Quest (+1 rep) if (getq(HalinarzoQuest_TraderKing) >= 2) .@nr=.@nr+1; // Joaquim & Yumi Quest (+1 rep) if (getq(HalinarzoQuest_SickWife) >= 5) .@nr=.@nr+1; // Life Delight Quest (+1 rep) if (getq(HalinarzoQuest_LifeDelight) >= 2) .@nr=.@nr+1; // Sawis Quest (+1 rep) if (getq(HalinarzoQuest_Sawis) >= 2) .@nr=.@nr+1; // HALINARZO Magical Forumula .@nr=.@nr*100/5; // Frostia Quests (2 points) } else if (getarg(0) == "Frostia") { // Rescue Yeti Quest (+1 rep) if (getq(NivalisQuest_Well) >= 2) .@nr=.@nr+1; // Rescue Cindy Quest (+1 rep) if (getq(NivalisQuest_Cindy) >= 5) .@nr=.@nr+1; // FROSTIA Magical Forumula .@nr=.@nr*100/2; // Candor Quests (10 points) } else if (getarg(0) == "Candor") { // Valon Quest (+1 rep) if (getq(CandorQuest_Trainer) >= 14) .@nr=.@nr+1; // Zegas Quest (+1 rep) if (getq(CandorQuest_Barrel) >= 4) .@nr=.@nr+1; // Hide And Seek Quest (+1 rep) if (getq(CandorQuest_HAS) >= 4) .@nr=.@nr+1; // Sailors Quest (+1 rep) if (getq(CandorQuest_Sailors) >= 3) .@nr=.@nr+1; // Sailors Quest, part 2 (+1 rep) if (getq(CandorQuest_SailorCure) >= 1) .@nr=.@nr+1; // Vincent Quest (+1 rep) if (getq(CandorQuest_Vincent) >= 2) .@nr=.@nr+1; // Tolchi Quest (+1 rep) if (getq(CandorQuest_Tolchi) >= 3) .@nr=.@nr+1; // Maya Quest (+1 rep) if (getq(CandorQuest_Maya) >= 4) .@nr=.@nr+1; // Rosen Quest (+1 rep) if (getq(CandorQuest_Rosen) >= 3) .@nr=.@nr+1; // Marggo Quest (+1 rep) if (getq(CandorQuest_Marggo) >= 1) .@nr=.@nr+1; // CANDOR Magical Forumula .@nr=.@nr*100/10; // Final } //debugmes "Reputation: "+str(.@nr); return .@nr; } // Returns time for ship travel. // Can be modified by a factor. function script nard_time { // Estimates time to move by ship from LOCATION$ to getarg(0) // From Candor if (LOCATION$ == "Candor") { if (getarg(0) == "Tulim") return 22000; } // From Tulimshar if (LOCATION$ == "Tulim") { if (getarg(0) == "Candor") return 22000; if (getarg(0) == "Hurns") return 28000; if (getarg(0) == "Nival") return 52000; } // From Hurnscald if (LOCATION$ == "Hurns") { if (getarg(0) == "Candor") return 22000; if (getarg(0) == "Tulim") return 28000; if (getarg(0) == "Nival") return 28000; } // From Nivalis if (LOCATION$ == "Nival") { if (getarg(0) == "Candor") return 46000; if (getarg(0) == "Tulim") return 52000; if (getarg(0) == "Hurns") return 28000; } // Error debugmes "ERROR, INVALID LOCATION AND DESTINATION"; debugmes l("@@ -> @@", LOCATION$, getarg(0)); dispbottom l("An error on your travel time happened. Please report."); return INT_MAX; } // Determines if player is still in range. // eg. // if (reachable(.x, .y, .distance)) { function script reachable { .@x=getarg(0); .@y=getarg(1); .@z=getarg(2); getmapxy(.@mp$, .@xp, .@yp, 0); if (distance(.@x, .@y, .@xp, .@yp) <= .@z) return 1; else return 0; } // Determines if party exp sharing is enabled // ( Party ID ) function script party_expon { .@nb = query_sql("SELECT exp FROM `party` WHERE party_id="+escape_sql(getarg(0))+" LIMIT 2", .@value); return .@value[0]; } // Special rif for books // rif2(, , ) function script rif2 { return rif( getarg(1) ,rif(@menu == getarg(0), "► ") + getarg(2)); } // Prepare Mana Stone // mstone( lvl ) function script mstone { // Fill variable .@v=getarg(0); // Determine how much stats you need, this is based on players // and change based on $Global Variables .int=5; .lvl=15; .jlv=10; return ( MAGIC_LVL == .@v && readparam(bInt) >= $MANA_BINT+(.int*.@v) && BaseLevel >= $MANA_BLVL+(.lvl*.@v) && JobLevel >= $MANA_JLVL+(.jlv*.@v) && readparam(Sp) == readparam(MaxSp)); } /* // Gets how many subclasses were actually filled // total_subclass( ) function script total_subclass { .@i=0; if (MAGIC_SUBCLASS & CL_PALADIN) .@i+=1; if (MAGIC_SUBCLASS & CL_TANKER) .@i+=1; if (MAGIC_SUBCLASS & CL_BERSERKER) .@i+=1; if (MAGIC_SUBCLASS & CL_RANGER) .@i+=1; if (MAGIC_SUBCLASS & CL_SNIPER) .@i+=1; if (MAGIC_SUBCLASS & CL_WIZARD) .@i+=1; if (MAGIC_SUBCLASS & CL_SAGE) .@i+=1; if (MAGIC_SUBCLASS & CL_PRIEST) .@i+=1; return .@i; } // Gets how many subclasses were actually allowed // max_subclass() function script max_subclass { return (MAGIC_LVL/2); } */ // MAGIC_PTS → Amount of used Magic Skill Points // sk_maxpoints() → Max Magic Skill Points you may use // Returns how many points you can use function script sk_maxpoints { // 2 points per magic level .@val=(MAGIC_LVL)*2; // 1 point every twice magic level .@val+=(MAGIC_LVL/2); // Excluding first 15, 1 point every 12 job levels (Up to JL 75) .@val+=min(5, ((JobLevel-15)/12)); // 1 point per being a player .@val+=1; // 1 point per skill permit level .@val+=getskilllv(TMW2_SKILLPERMIT); return .@val; } // Returns how many points you can allocate function script sk_points { return sk_maxpoints()-MAGIC_PTS; } // Returns true if a skill can be leveled up. // sk_canlvup( {cost=1} ) function script sk_canlvup { return ((MAGIC_PTS+getarg(0,1)) <= sk_maxpoints()); } // Level up a skill in 1 level // TODO: Return the point if leveling about Max Level // sk_lvup( sk{, cost=0} ) function script sk_lvup { .@lvl=getskilllv(getarg(0)); getexp 0, 50*(.@lvl+1); addtoskill(getarg(0),.@lvl+1,0); if (getarg(1,0)) { MAGIC_PTS+=getarg(1,0); } return; } // NEW Magic School Learning Interface // mlearn( skill, MAX_LV, AP cost, item, amount ) // returns false if cheater function script mlearn { .@sk=getarg(0); .@ff=getarg(1); .@ap=getarg(2); .@it=getarg(3); .@am=getarg(4); .@learn$=l("learn"); if (getskilllv(.@sk) >= .@ff) { mesc l("You've reached the maximum level for this skill."), 1; return true; } if (getskilllv(.@sk)) { .@ap=1; .@learn$=l("upgrade"); } mesc l("To @@ @@ you'll need @@/@@ point(s).", .@learn$, .@sk, .@ap, sk_points()); mesc l("You'll also need to pay a fee of @@x @@", .@am, getitemlink(.@it)); next; if (askyesno() == ASK_NO) return true; if (countitem(.@it) < .@am && !(countitem(ScholarshipBadge))) return false; if (!sk_canlvup(.@ap)) return false; if (countitem(.@it) < .@am) delitem ScholarshipBadge, 1; else delitem .@it, .@am; sk_lvup(.@sk, .@ap); return true; } /* // Magic School Learning Interface // mlearn( skill, {item 1, amount 1}, {item 2, amount 2}... ) // returns false if cheater function script mlearn { if (getargcount() < 2 || getargcount() % 2 != 1) return Exception("Faulty learning skill command invoked - error"); .@sk=getarg(0); // List required ingredients mesq l("This useful skill will only require:"); for (.@i=1;.@i < getargcount(); .@i++) { mesc l("@@/@@ @@", countitem(getarg(.@i)), (getskilllv(.@sk)+1)*getarg(.@i+1), getitemlink(getarg(.@i))); .@i++; } // getarg(.@i) next; if (askyesno() == ASK_NO) return true; // Count items for (.@i=1;.@i < getargcount(); .@i++) { if (countitem(getarg(.@i)) < (getskilllv(.@sk)+1)*getarg(.@i+1)) return false; .@i++; } // Delete Items for (.@i=1;.@i < getargcount(); .@i++) { delitem getarg(.@i), (getskilllv(.@sk)+1)*getarg(.@i+1); .@i++; } sk_lvup(.@sk); next; return true; } */ // transcheck( {item 1, amount 1}, {item 2, amount 2}... ) // returns true upon success function script transcheck { if (getargcount() < 2 || getargcount() % 2 != 0) return Exception("Faulty learning skill command invoked - error"); // Count items for (.@i=0;.@i < getargcount(); .@i++) { if (countitem(getarg(.@i)) < getarg(.@i+1)) return false; .@i++; } // Delete Items for (.@i=0;.@i < getargcount(); .@i++) { delitem getarg(.@i), getarg(.@i+1); .@i++; } return true; } // Returns a value defining your current magic control (affects success ratio, higher is better) // A value of '5' means perfect control, and a value of '0' means overwhelm. // abizit() function script abizit { .@base=(MAGIC_LVL**3); return min(MAGIC_EXP/.@base, 5); } // anyloot( {item 1, amount 1, chance 1}, {item 2, amount 2, chance 2}... ) // Give chance (standard 1~10000 roll) to obtain item, capped at amount. function script anyloot { if (getargcount() < 3 || getargcount() % 3 != 0) return Exception("Faulty anyloot skill command invoked - error"); // Get Items for (.@i=0;.@i < getargcount(); .@i+=3) { if (rand2(10000) < getarg(.@i+2)) getitem getarg(.@i), rand2(1, getarg(.@i+1)); } return true; } // Returns, based on a 1-5 range, the title for both thief and merc ranks // thiefrank() / mercrank() function script thiefrank { switch (THIEF_RANK) { case 5: return l("Bandit Lord"); case 4: return l("Assassin"); case 3: return l("Rogue"); case 2: return l("Bandit"); case 1: return l("Thief"); default: return l("Error"); } } function script mercrank { switch (MERC_RANK) { case 5: return l("Constable"); case 4: return l("Guardian"); case 3: return l("Merchant"); case 2: return l("Trader"); case 1: return l("Fair Person"); default: return l("Error"); } } // gettimeparam(GETTIME_X) // Returns the number of seconds/minutes/hours/days/months/years since 01/01/1970 function script gettimeparam { .@p=getarg(0, GETTIME_MINUTE); // Seconds .@t=gettimetick(2); if (.@p == GETTIME_SECOND) return .@t; // Minutes (default) .@t=.@t/60; if (.@p == GETTIME_MINUTE) return .@t; // Hours .@t=.@t/60; if (.@p == GETTIME_HOUR) return .@t; // Days .@t=.@t/24; if (.@p == GETTIME_DAYOFMONTH) return .@t; // Weeks (estimative) .@a=.@t+4; // 01/01/1970 was a Thursday. So this will make it float at sunday. .@a=.@a/7; if (.@p == GETTIME_WEEKDAY) return .@a; // Months (estimative) .@t=.@t/30; if (.@p == GETTIME_MONTH) return .@t; // Years (estimative, unused, fallback) .@t=.@t/12; return .@t; } // Upon entering a town // EnterTown( LocName ) function script EnterTown { // Fill variable .@v$=getarg(0); // Validade variable, see npc/000-1/exit.txt first setarray .@locs$, "Candor", "Tulim", "Halin", "Hurns", "LoF", "Lilit", "Nival", "Frostia"; if (array_find(.@locs$, .@v$) < 0) return Exception("Invalid location passed to EnterTown: "+.@v$); LOCATION$=.@v$; return; } // Convert map name to location id // MapToLoc( MapName ) function script MapToLoc { // Fill variable .@v$=getarg(0); // Validade variable, see npc/000-1/exit.txt first setarray .@mapx$, "005-1", "003-1", "009-1", "012-1", "017-1", "018-5", "020-1", "024-1"; setarray .@locs$, "Candor", "Tulim", "Halin", "Hurns", "LoF", "Lilit", "Nival", "Frostia"; .@lx=array_find(.@locs$, .@v$); if (.@lx < 0) return Exception("Invalid map passed to MapToLoc: "+.@v$, RB_DEBUGMES); return .@locs$[.@lx]; } // Grants newcomers exp boost. Returns bonus % // NewcomerEXPDROPUP( - ) function script NewcomerEXPDROPUP { .@AVG_LEVEL=($@hoblvl_value[0]+$@hoblvl_value[1]+$@hoblvl_value[2])/3; .@BONUS=min(50, .@AVG_LEVEL/2); .@BONUS-=BaseLevel; .@BONUS=max(1, .@BONUS); sc_end SC_CASH_PLUSEXP; sc_end SC_CASH_RECEIVEITEM; sc_start SC_CASH_PLUSEXP, 7200000, .@BONUS; sc_start SC_CASH_RECEIVEITEM, 7200000, .@BONUS; return .@BONUS; }