// 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(<menu_id>, <condition>, <text>)
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);
}
// 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;
// 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;
}