// TMW-2 Script // Author: // Jesusalva // Description: // Nivalis shopkeeper & forge master. He deals with the equipment which Nicholas, // Silversmith and Nahred doesn't works with. // TODO FIXME: Rewrite Meltdown to don't allow if countitem(id) > 1 // Also, use deletion by ID (reliable). // delitemidx is HOPELESSY BROKEN 020-5,31,25,0 script Bracco NPC_M_SHOPKEEPER,{ goto L_Start; // NewMeltdown( item ) // Meltdown the item for realz function NewMeltdown { .@const$ = data_to_string(getarg(0)); // Shady code by gumi if (startswith(.@const$, "Craft")) { // infer the item constant from the craft constant .@recipe = getarg(0); .@item = string_to_data(substr(.@const$, 5, getstrlen(.@const$) - 1)); } else { // infer the craft constant from the item constant .@recipe = string_to_data(sprintf("Craft%s", .@const$)); .@item = getarg(0); } if (.@item <= 0) { // target item not found consolebug("ERROR, INVALID ITEM ID DETECTED at NewMeltdown"); return; } // More shady code by gumi for (.@inv = 0; .@inv < 9; ++.@inv) { .@size = getcraftrecipe(.@recipe, .@inv, .@qty[0], .@item_id[0]); if (.@size < 0) { if (.@size == -1) { // recipe does not exist return 0; break; } // inventory does not exist return 0; break; } // More shady code for (.@it = 0; .@it < .@size; ++.@it) { .@recipe_item = .@item_id[.@it]; .@recipe_qty = .@qty[.@it]; if (.@recipe_item <= 0) { break; } // "Unique" items are never refunded if (.@recipe_qty <= 1) continue; // Coal is NEVER refunded if (.@recipe_item == Coal) continue; // New rates .@mini = .@recipe_qty * 3 / 10 + 1; // Minimum: 30% + 1 .@maxi = .@recipe_qty / 2; // Maximum: 50% + 1 // Some sanitizing (should never happen but you can never be sure) // (Could only happen if qty == 1, which is skipped) if (.@mini > .@maxi) .@maxi = .@mini; .@ammo = rand2(.@mini, .@maxi); getitem .@recipe_item, .@ammo; mesc l("* Acquired @@ @@!", .@ammo, getitemlink(.@recipe_item)); } } return .@item; } // Meltdown( item, price ) function Meltdown { if (countitem(getarg(0)) != 1) { mesc l("Wait, if you try to melt more than one item, manaplus will get buggy."), 1; mesc l("Please try again later!"), 1; close; } .@index=getarg(0); .@price=getarg(1, getiteminfo(.@item, ITEMINFO_SELLPRICE)/20); .@price=POL_AdjustPrice(.@price); // Confirmation mesn; mesc l("Really melt down your @@? It'll cost you @@ GP. This action cannot be undone!", getitemlink(.@index), .@price), 1; next; if (askyesno() == ASK_NO || Zeny < .@price) return; // Report it was done mesc l("@@ melt down your @@...", .name$, getitemlink(.@index)), 2; delitem .@index, 1; POL_PlayerMoney(.@price); // TODO: Inventoryplace. // Add Items (if inventory is full, your fault and not mine) NewMeltdown(.@index); @indexisbroken=true; return; } // MassMeltdown( item, price ) function MassMeltdown { .@id=getarg(0); .@price=getarg(1); .@total=countitem(.@id); if (!.@total) { mesc l("You don't have any %s.", getitemlink(.@id)), 1; mesc l("Please try again later!"), 1; next; return; } .@price=POL_AdjustPrice(.@price); // Skip Confirmation mesn; mesc l("Really melt down all your @@? It'll cost you @@ GP each. This action cannot be undone!", getitemlink(.@id), .@price), 1; next; if (askyesno() == ASK_NO || Zeny < .@price) return; delinventorylist(); getinventorylist(); debugmes "Requested to melt down %d %s (%s)", .@total, getitemname(.@id), strcharinfo(0); freeloop(true); for (.@index=0; .@index < @inventorylist_count; .@index++) { .@x=@inventorylist_id[.@index]; if (.@x == getarg(0) && Zeny >= .@price) { //delitemidx .@index, 1; POL_PlayerMoney(.@price); // Report it was done mesc l("@@ melt down your @@...", .name$, getitemlink(.@x)), 2; // Really melt it down NewMeltdown(getarg(0)); } } freeloop(false); // TODO: Put this in a timer so it can't be exploited // For now, we'll produce logs so I can go after cheaters with a banhammer delitem .@id, .@total; // Delete first, no refunds debugmes "Success melting down %d %s (%s)", .@total, getitemname(.@id), strcharinfo(0); @indexisbroken=true; return; } // blacksmith_create( BaseItem1, Amount, BaseItem2, Amount, PrizeItem, Price ) function blacksmith_create { .@base1=getarg(0); .@amon1=getarg(1); .@base2=getarg(2); .@amon2=getarg(3); .@prize=getarg(4); .@price=getarg(5); .@price=POL_AdjustPrice(.@price); mesn; mesq l("Do you want to craft @@? For that I will need:", getitemlink(.@prize)); mesc l("@@/@@ @@", countitem(.@base1), .@amon1, getitemlink(.@base1)); mesc l("@@/@@ @@", countitem(.@base2), .@amon2, getitemlink(.@base2)); mesc l("@@/@@ GP", format_number(Zeny), format_number(.@price)); select l("Yes"), l("No"); if (@menu == 2) return; if (countitem(.@base1) >= .@amon1 && countitem(.@base2) >= .@amon2 && Zeny >= .@price) { inventoryplace .@prize, 1; delitem .@base1, .@amon1; delitem .@base2, .@amon2; POL_PlayerMoney(.@price); getitem .@prize, 1; .@xp=getiteminfo(.@base1, ITEMINFO_SELLPRICE)*.@amon1+getiteminfo(.@base2, ITEMINFO_SELLPRICE)*.@amon2; .@xp=.@xp*2/3; getexp .@xp, rand(1,10); mes ""; mesn; mesq l("Many thanks! Come back soon."); } else { speech S_FIRST_BLANK_LINE,// | S_LAST_NEXT, l("You don't have enough material, sorry."); } return; } // Start L_Start: mesn; mesq l("Welcome to my fine establishment!"); mes ""; select l("Trade"), l("I'm actually looking for an item forged!"), l("I would like an item melted!"), l("I would like all Knifes and Daggers on me melted!"), l("Leave"); mes ""; if (@menu == 2) goto L_Forge; if (@menu == 3) goto L_Meltdown; if (@menu == 4) goto L_Irreversible; closedialog; if (@menu == 1) { npcshopattach(.name$); shop .name$; } goodbye; close; // Note: the prices are absurd atm, but hey hey, every single one of them are cap items currently L_Forge: mesn; mesq l("Well, if you want warrior craft, perhaps you should look for @@ or @@.", l("Nicholas"), l("Nahrec")); mes ""; select l("Nothing, sorry!"), l("I want leather armbands!"), l("I want copper armbands!"), l("I want iron armbands!"); mes ""; switch (@menu) { case 1: close; break; case 2: blacksmith_create(LeatherPatch, 40, TitaniumIngot, 1, Armbands, 6500); break; case 3: blacksmith_create(CopperIngot, 10, Coal, 30, CopperArmbands, 11000); break; case 4: blacksmith_create(IronIngot, 40, Coal, 80, IronArmbands, 21000); break; } goto L_Forge; L_Irreversible: mesn; mesq l("Quite the guts! The price is taxed individually, if you run out of GP it is your loss."); mesc l("Are you sure?"), 1; next; menuint l("I'm not."), 0, l("Rusty Knife"), RustyKnife, l("Small Knife"), SmallKnife, l("Knife"), Knife, l("Sharp Knife"), SharpKnife, l("Dagger"), Dagger; mes ""; .@it=@menuret; switch (@menuret) { // Copy Paste from normal Meltdown case RustyKnife: MassMeltdown(.@it, 15, IronOre, any(0, 0, 0, 1, 1)); break; case SmallKnife: MassMeltdown(.@it, 15, IronOre, any(0, 0, 1, 1, 1)); break; case Knife: MassMeltdown(.@it, 25, IronOre, any(0, 1, 1, 2)); break; case SharpKnife: MassMeltdown(.@it, 50, IronOre, any(1, 2, 2, 3)); break; case Dagger: MassMeltdown(.@it, 100, IronOre, any(2, 2, 3, 3, 4)); break; // MISSING } close; L_Meltdown: mesn; mesc l("What item do you want to melt down? This is irreversible, and may return some ingots to you, but there is no way to tell how many you'll receive!"), 1; mesc l("Each item have it's own tax."); .@id=requestitem(); if (.@id <= 0) close; mes ""; // Returns 30~50% of invested ingots, rounded down. Never returns Coal. switch (.@id) { // Special Exceptions case SilverMirror: Meltdown(.@id, 500, SilverOre, rand2(2, 5)); // Exception break; case RustyKnife: Meltdown(.@id, 15, IronOre, any(0, 0, 0, 1, 1)); // Exception break; case SmallKnife: Meltdown(.@id, 15, IronOre, any(0, 0, 1, 1, 1)); // Exception break; case Knife: Meltdown(.@id, 25, IronOre, any(0, 1, 1, 2)); // Exception break; case SharpKnife: Meltdown(.@id, 50, IronOre, any(1, 2, 2, 3)); // Exception break; case Dagger: Meltdown(.@id, 100, IronOre, any(2, 2, 3, 3, 4, 5)); // Exception break; case GoldenRing: Meltdown(.@id, 1500, GoldPieces, rand2(2,3)); break; default: if (!Meltdown(.@id)) { mesn; mesq l("I cannot melt this. I only melt down equipment, and not everything I know how to!"); next; } break; } //mesc l("Melt something else?"); //if (askyesno() == ASK_NO) // close; //mes ""; //goto L_Meltdown; mesc l("Thanks for using my services!"); close; OnInit: .@npcId = getnpcid(.name$); setunitdata(.@npcId, UDT_HEADTOP, NPCEyes); setunitdata(.@npcId, UDT_HEADMIDDLE, TneckSweater); setunitdata(.@npcId, UDT_HEADBOTTOM, RaidTrousers); setunitdata(.@npcId, UDT_WEAPON, FurBoots); setunitdata(.@npcId, UDT_HAIRSTYLE, 26); setunitdata(.@npcId, UDT_HAIRCOLOR, 2); sleep(SHOPWAIT); tradertype(NST_MARKET); sellitem BritShield, -1, 1; sellitem BladeShield, -1, 1; sellitem MiereCleaver, -1, 1; sellitem ShortSword, -1, 1; sellitem LeatherShirt, -1, 1; sellitem LeatherShield, 5000, 1; sellitem ShortBow, -1, 1; sellitem ArrowAmmoBox,-1,rand(8,12); sellitem IronAmmoBox,-1,rand(3,5); npcsit; .sex = G_MALE; .distance = 5; end; OnWed0000: OnThu0400: OnFri0800: OnSat1200: OnSun1600: OnMon2000: restoreshopitem BritShield, 1; restoreshopitem BladeShield, 1; restoreshopitem MiereCleaver, 1; restoreshopitem ShortSword, 1; restoreshopitem LeatherShirt, 1; restoreshopitem LeatherShield, 5000, 1; restoreshopitem ShortBow, 1; restoreshopitem ArrowAmmoBox,rand(8,12); restoreshopitem IronAmmoBox,rand(3,5); end; // Pay your taxes! OnBuyItem: debugmes("Purchase confirmed"); PurchaseTaxes(); end; OnSellItem: debugmes("Sale confirmed"); SaleTaxes(); end; }