// TMW2 Script // Modified by Jesusalva // Evol scripts. // Authors: // gumi // Reid function script Banking { do { if (BankVault > 0) { speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You currently have @@ GP on your bank account.", format_number(BankVault)), l("What do you want to do with your money?"); } else { speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("What do you want to do with your money?"); } select rif(Zeny > 0, l("Deposit.")), rif(BankVault > 0, l("Withdraw.")), l("Buy a Housing Letter"), l("I'm done."); switch (@menu) { case 1: speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("How much do you want to deposit?"); menuint l("Other."), -1, rif(Zeny >= 1000, format_number(1000) + " GP."), 1000, rif(Zeny >= 2500, format_number(2500) + " GP."), 2500, rif(Zeny >= 5000, format_number(5000) + " GP."), 5000, rif(Zeny >= 10000, format_number(10000) + " GP."), 10000, rif(Zeny >= 25000, format_number(25000) + " GP."), 25000, rif(Zeny >= 50000, format_number(50000) + " GP."), 50000, rif(Zeny >= 100000, format_number(100000) + " GP."), 100000, l("All of my money."), -2, l("I changed my mind."), -3; switch (@menuret) { case -1: input @menuret; break; case -2: @menuret = Zeny; } if (@menuret > 0) { if (@menuret > Zeny) { speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You do not have enough Gold on yourself."); break; } @menuret = min(MAX_BANK_ZENY, @menuret); // make sure the variable can't overflow .@before = BankVault; // amount before the deposit .@max = MAX_BANK_ZENY - BankVault; // maximum possible deposit .@deposit = min(.@max, @menuret); // actual deposit if (.@deposit > 0) { BankVault += .@deposit; // add to bank Zeny -= .@deposit; // remove from inventory speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You made a cash deposit of @@ GP.", format_number(.@deposit)); } } break; case 2: speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("How much do you want to withdraw?"); menuint l("Other."), -1, rif(BankVault >= 1000, format_number(1000) + " GP."), 1000, rif(BankVault >= 2500, format_number(2500) + " GP."), 2500, rif(BankVault >= 5000, format_number(5000) + " GP."), 5000, rif(BankVault >= 10000, format_number(10000) + " GP."), 10000, rif(BankVault >= 25000, format_number(25000) + " GP."), 25000, rif(BankVault >= 50000, format_number(50000) + " GP."), 50000, rif(BankVault >= 100000, format_number(100000) + " GP."), 100000, l("All of my money."), -2, l("I changed my mind."), -3; switch (@menuret) { case -1: input @menuret; break; case -2: @menuret = BankVault; } if (@menuret > 0) { if (@menuret > BankVault) { speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You do not have enough Gold Pieces on your bank account."); break; } @menuret = min(MAX_ZENY, @menuret); // make sure the variable can't overflow .@before = Zeny; // amount before the withdrawal .@max = MAX_ZENY - Zeny; // maximum possible withdrawal .@withdrawal = min(.@max, @menuret); // actual withdrawal if (.@withdrawal > 0) { Zeny += .@withdrawal; // add to inventory BankVault -= .@withdrawal; // remove from bank speech S_FIRST_BLANK_LINE | S_LAST_NEXT, l("You withdrew a total of @@ GP.", format_number(.@withdrawal)); } } break; case 3: .@gp=REAL_ESTATE_CREDITS+Zeny; mesc l("You currently have @@ mobiliary credits + GP at your disposal.", format_number(.@gp)); mesc l("@@ - @@ - @@", getitemlink(HousingLetterI), getitemlink(HousingLetterII), getitemlink(HousingLetterIII)); next; select l("Nothing"), rif(.@gp >= 11000, l("Housing Letter I for 11,000 GP")), rif(.@gp >= 101000, l("Housing Letter II for 101,000 GP")), rif(.@gp >= 1001000, l("Housing Letter III for 1,001,000 GP")); mes ""; switch (@menu) { case 2: realestate_payment(11000); getitem HousingLetterI, 1; break; case 3: realestate_payment(101000); getitem HousingLetterII, 1; break; case 4: realestate_payment(1001000); getitem HousingLetterIII, 1; break; } break; default: return; } } while (true); } function script BKInfo { speech S_LAST_NEXT, l("We organize some auction and we help local merchants to launch their businesses."), l("We also feature some services like a storage and a bank for members."), l("Registration is open to everybody, but newcomers need to pay a fee for all of the paperwork."), l("If you have... references, we may also be able to offer you... premium storing."); narrator S_FIRST_BLANK_LINE, l("The bank and item storage is shared between all characters within a same account."), l("With it, you can safely move items and funds between your characters."), l("The Premium and Deluxe Storages are only available for characters which were reborn at least once."); return; } // name, city, price, ID function script BKReg { .@price=max(2000, getarg(2)-#BankP); .@id=getarg(3, 1); @menu=3; do { mesn getarg(0); mesq l("Register fee is @@.", .@price); mesc l("The fee only need to be paid once and will work in every town."); next; select rif(Zeny >= .@price, l("Register")), l("Not at the moment"), l("Information"); mes ""; if (@menu == 1) { Zeny=Zeny-.@price; setq General_Banker, .@id; #BankP=#BankP+(rand2(150,400)*(.@id**2)); mesn getarg(0); mesq l("Registered! You can now use any banking service, of any town!"); } else if (@menu == 3) { BKInfo(); } } while (@menu == 3); return; } // name, city, price (defaults to 10k) function script Banker { .@bankId = getvariableofnpc(.bankId, strnpcinfo(0)); mesn getarg(0); mesq l("Welcome! My name is @@, I am a representative of the Merchant Guild on @@.", getarg(0), getarg(1)); next; if (getq(General_Banker) == 0) { BKReg(getarg(0), getarg(1), getarg(2,10000)); } else { do { select l("I would like to store some items."), l("I would like to perform money transactions."), l("Did I received any mail?"), rif(REBIRTH || is_sponsor(), l("I would like to use the Premium Storage.")), rif(REBIRTH, l("I would like to use the Deluxe Storage.")), rif(getcharid(2) > 0, l("I would like to use the Guild Storage.")), l("What is this guild for?"), rif(.@bankId && Zeny < 50000, l("Can I help the Guild in any way?")), l("Bye."); switch (@menu) { case 1: closeclientdialog; openstorage; close; break; case 2: Banking(); break; case 3: // NOTE: This value is HARDCODED, do not try changing it! mesc l("Note: Transfering items on mail cost @@ GP/item", 500); mesc l("Money transference by mail is, however, free."); next; closeclientdialog; openmail(); close; break; case 4: if (getq(General_Banker) < 2) { mesn; mesq l("The Premium Storage is available to all our sponsors and anyone with... references. Such as yourself!"); next; .@price=25000; mesn; mesq l("It will allow you to store %d extra items, with unlimited weight or size limit, for only %s GP! Although premium clients such as yourself... deserve a discount!", 300, fnum(.@price)); next; BKReg(getarg(0), getarg(1), .@price, 2); } if (getq(General_Banker) >= 2) { closeclientdialog; openstorage 4; close; } break; case 5: if (getq(General_Banker) < 2) { mesn; mesq l("This option is not yet available for you; Please purchase the Premium Storage first, and then we can get started on the deluxe."); break; } if (getq(General_Banker) < 3) { mesn; mesq l("The Deluxe Storage is available only to our best customers, and how lucky you! YOU are eligible!"); next; .@price=100000; mesn; mesq l("It will allow you to store %d extra items, with unlimited weight or size limit, for only %s GP! Although premium clients such as yourself... deserve a discount!", 500, fnum(.@price)); next; BKReg(getarg(0), getarg(1), .@price, 3); } if (getq(General_Banker) >= 3) { closeclientdialog; openstorage 5; close; } break; case 6: // FIXME: Raises a console warning of invalid map closeclientdialog; doevent "Guild Storage::OnStorage"; close; break; case 7: mes ""; BKInfo(); break; case 8: mes ""; callfunc("MerchantQuest", .@bankId - 1); break; } if (@menu != 9) { speech S_FIRST_BLANK_LINE | S_LAST_NEXT | S_NO_NPC_NAME, l("Something else?"); } } while (@menu != 9); } closedialog; goodbye; close; } // This function registers a bank for guild purposes // .bankId = RegisterBank(Town, {Main Quest Stage at which banks become available}) function script RegisterBank { array_push($@BANK_NAME$, strnpcinfo(1)); array_push($@BANK_TOWN$, getarg(0)); array_push($@BANK_MINLV, getarg(1,1)); return getarraysize($@BANK_NAME$); // bankId actually is offset in 1 for rif() } // Quests for Banking System, to provide poor players a way for quick bucks // MerchantQuest(.@bankId) function script MerchantQuest { mes ""; // Quest Type, Quest Data, Quest Timer .@q=getq(General_MerchantRequest); .@q2=getq2(General_MerchantRequest); .@q3=getq3(General_MerchantRequest); .@id=getarg(0); // Cooldown if (.@q3 > gettimetick(2)) { mesn $@BANK_NAME$[.@id]; mesq l("There are no tasks for you right now."); mesc l("Please come back later, in %s.", FuzzyTime(.@q3)); next; return; } // TODO: Submit/Abort current request switch (.@q) { case MERCQ_LETTER: if (.@id == .@q2) { mesn $@BANK_NAME$[.@id]; mesq l("Thanks for the letter! Your efforts are greatly appreciated."); Zeny+=rand2(7, 12) * 57; getexp 67, 9; setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2)+900; return; } else { mesn $@BANK_NAME$[.@id]; mesq l("Current task: Deliver a letter to %s", $@BANK_TOWN$[.@q2]); next; select l("Continue"), l("Abort") + " ["+l("Change task")+"]"; mes ""; if (@menu == 1) return; setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2); } break; /* ***************************************** */ case MERCQ_GOODS: .@cont=ASK_NO; if (countitem(.@q2)) { mesc l("Deliver %s?", getitemlink(.@q2)); .@cont=askyesno(); } if (.@cont == ASK_YES) { mesn $@BANK_NAME$[.@id]; mesq l("Thanks for the %s! Your efforts are greatly appreciated.", getitemlink(.@q2)); delitem .@q2, 1; .@price = getiteminfo(.@q2, ITEMINFO_SELLPRICE); Zeny+=.@price + rand2(12, 18) * 57; getexp 120, 18; setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2)+1200; return; } else { mesn $@BANK_NAME$[.@id]; mesq l("Current task: Purchase a(n) %s", getitemlink(.@q2)); next; select l("Continue"), l("Abort") + " ["+l("Change task")+"]"; mes ""; if (@menu == 1) return; setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2); } break; /* ***************************************** */ case MERCQ_SCOUT: // This remains challenging even at high levels, but not if you use ship. if (.@id == .@q2) { // TODO: Dismiss the timer, or fail if MERCHANT_ID points to nothing // Fail 1: Merchant_ID is no longer valid if (getunittype(MERCHANT_ID) != UNITTYPE_MOB) { mesn $@BANK_NAME$[.@id]; mesq l("Our associate warped away... No thanks to you!"); setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2)+900; close; } // Fail 2: Merchant was left behind if (!gettimer(0, getcharid(3), "Malindou::OnScoutPing")) { mesn $@BANK_NAME$[.@id]; mesq l("...Did you lose our associate? Please try again."); setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2)+900; close; } // Complete the quest deltimer("Malindou::OnScoutPing"); mesn $@BANK_NAME$[.@id]; mesq l("Thanks for scorting our associate! Your efforts are greatly appreciated."); Zeny+=rand2(24, 52) * 57; getexp 360, 44; setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2)+1800; //Original: 43200 unitkill(MERCHANT_ID); MERCHANT_ID = 0; return; } else { mesn $@BANK_NAME$[.@id]; mesq l("Current task: Scout guild member to %s", $@BANK_TOWN$[.@q2]); next; select l("Continue"), l("Abort"); mes ""; if (@menu == 1) return; deltimer("Malindou::OnScoutPing"); setq General_MerchantRequest, MERCQ_NONE, 0, gettimetick(2); unitkill(MERCHANT_ID); MERCHANT_ID = 0; } break; } do { mesc l("The %s Merchant Guild has a few requests for you:", $@BANK_TOWN$[.@id]); .@town = .@id; while (.@town == .@id || getq(General_Narrator) < $@BANK_MINLV[.@town]) { .@town=rand2(getarraysize($@BANK_TOWN$)); } select l("How does this works?"), rif(.@town != .@id, l("★ Deliver a letter")), l("★★ Purchase goods"), rif(.@town != .@id, l("★★★ Scout a merchant")), l("Sorry, I won't accept any."); mes ""; switch (@menu) { case 1: mesc l("The Merchant Guild spawns multiple continents, and we can offer you a few tasks for them. Be careful as you might not be able to finish them and you'll have to abort!"); mesc l("The more stars, the harder it is."); next; mesc l("After completing a request, there'll be a cooldown, proportional to the difficulty."); mesc l("You can only have one Merchant Guild request active at same time."); next; break; // Deliver a letter case 2: mesc l("We need you to deliver this important letter to %s! Avoid the roads and bandits!", $@BANK_NAME$[.@town]); next; mesc l("Accept request?"); if (askyesno() == ASK_YES) { mesc l("I'm counting on you!"); setq General_MerchantRequest, MERCQ_LETTER, .@town, gettimetick(2); return; } break; // Purchase goods case 3: // Most can be bought or found in Candor, Tulimshar, Nivalis or LoF .@item=any(YellowDye, Knife, InfantryHelmet, LeatherGloves, SilkRobe, CroconutBox, FishBox, Coal, IronIngot, Aquada, Ruby, Diamond, Beer, ShortSword, LeatherShirt, ShortBow, ArrowAmmoBox, LOFCoin, TrainingWand, DesertHat, LousyMoccasins); mesc l("The merchant guild needs %s! Purchase it and deliver at the nearest merchant guild member!", getitemlink(.@item)); next; mesc l("Accept request?"); if (askyesno() == ASK_YES) { mesc l("I'm counting on you!"); setq General_MerchantRequest, MERCQ_GOODS, .@item, gettimetick(2); return; } break; // Scout a guild member case 4: mesc l("The merchant guild needs you to scout a Guild Member to %s! Absolutely don't let they get injuried!", $@BANK_NAME$[.@town]); next; mesc l("Accept request?"); if (askyesno() == ASK_YES) { mesc l("I'm counting on you!"); getmapxy(.@m$, .@x, .@y, 0); MERCHANT_ID=monster(.@m$, .@x, .@y, "Merchant", any(GameMaster, GameMistress), 1, "Malindou::OnScoutPing", Size_Medium, 2); // Could also be a Gladiator, as long that you can distinguish them setunitdata(MERCHANT_ID, UDT_MAXHP, 1); setunitdata(MERCHANT_ID, UDT_HP, 1); setunitdata(MERCHANT_ID, UDT_DEF, 2); setunitdata(MERCHANT_ID, UDT_MDEF, 2); setunitdata(MERCHANT_ID, UDT_FLEE, 2); setunitdata(MERCHANT_ID, UDT_LEVEL, 1); // Timer which makes Merchant follow you every once in a while @merc_map$ = getmap(); addtimer(rand2(10000), "Malindou::OnScoutPing"); setq General_MerchantRequest, MERCQ_SCOUT, .@town, gettimetick(2); return; } break; default: return; } } while (true); return; } // still_owed = TakeMoney (amount, reason) // This function is meant to be used from clientversion, when a quest failed // to take money from user. function script TakeMoney { .@still_owed = getarg(0); .@reason$ = getarg(1); .@take = min(Zeny, .@still_owed); Zeny -= .@take; .@still_owed -= .@take; .@take = min(BankVault, .@still_owed); BankVault -= .@take; .@still_owed -= .@take; if (.@still_owed > 0) consoleinfo("%s STILL OWES %s for %s.", strcharinfo(0), fnum(.@leftover), .@reason$); dispbottom col(l("%s were deducted for %s", fnum(10000-.@leftover), .@reason$), 1); return .@still_owed; }