// TMW2 Script // Evol scripts. // Author: // Travolta // Jesusalva // Description: // NPC to use shovel (dig, bury etc) // TODO: A function to retrieve a list of all walkable cells on a map // would be a great improvement to shovel_* functions. As long that it doesn't // a huge loop, of course... // shovel_scriptItem( map, x, y, item, {amount} ) function script shovel_scriptItem { .@map$=getarg(0); .@x=getarg(1); .@y=getarg(2); .@id=getarg(3); .@amount=getarg(4,1); // Players can't walk on this cell, why bother? if (!checkcell(.@map$, .@x, .@y, cell_chkpass)) return; // Bury the item, they're renewed daily at 00:00 .@wtc = getarraysize($@WBT_Random_id); $@WBT_Random_id[.@wtc] = .@id; $@WBT_Random_amount[.@wtc] = .@amount; $@WBT_Random_map$[.@wtc] = .@map$; $@WBT_Random_x[.@wtc] = .@x; $@WBT_Random_y[.@wtc] = .@y; //debugmes "Buried"+.@amount+" "+getitemname(.@id); return; } // shovel_scatter( map, x1, y1, x2, y2, amount, item1, {item2, item3...} ) function script shovel_scatter { .@map$=getarg(0); .@x1=getarg(1); .@y1=getarg(2); .@x2=getarg(3); .@y2=getarg(4); .@amount=getarg(5,1); .@dbgamm=.@amount; // debug message .@wta = getarraysize($@WBT_Random_id); // wta - original .@wtb = .@wta+.@amount; // wtb - future .@tries=3; do { freeloop(true); // DANGEROUS for (.@i = 0; .@i < .@amount; .@i++) shovel_scriptItem(.@map$, rand(.@x1,.@x2), rand(.@y1,.@y2), getarg(rand2(getargcount()-6)+6)); freeloop(false); .@wtc = getarraysize($@WBT_Random_id); // wtc - current .@amount=.@wtb-.@wtc; //debugmes "WTA %d WTB %d. WTC %d, tries %d, amount %d and dbg %d", .@wta, .@wtb, .@wtc, .@tries, .@amount, .@dbgamm; if (.@wtc >= .@wtb) .@tries=0; else .@tries-=1; } while (.@tries > 0); debugmes "Scattered "+.@dbgamm+" items on "+.@map$+". Currently scattered: "+.@wtc; return; } // Here we begin - script Shovel -1,{ function CheckDigLocation; function AddDigRect; function PlayerIsTired; function Dig { // First check: Did some player burried a TREASURE? O.o getmapxy(.@map$, .@x, .@y, 0); for (.@i = 0; .@i < getarraysize($WorldBuriedTreasures_id); .@i++) { if (!strcmp($WorldBuriedTreasures_map$[.@i], .@map$) && $WorldBuriedTreasures_x[.@i] == .@x && $WorldBuriedTreasures_y[.@i] == .@y) { .@id = $WorldBuriedTreasures_id[.@i]; .@amount = $WorldBuriedTreasures_amount[.@i]; inventoryplace .@id, .@amount; deletearray $WorldBuriedTreasures_id[.@i], 1; deletearray $WorldBuriedTreasures_amount[.@i], 1; deletearray $WorldBuriedTreasures_map$[.@i], 1; deletearray $WorldBuriedTreasures_x[.@i], 1; deletearray $WorldBuriedTreasures_y[.@i], 1; getitem .@id, .@amount; mesn strcharinfo(0); mesc l("You found something!"); mesc l("It's @@ @@.", .@amount, getitemname(.@id)); next; closeclientdialog; return 1; } } // Second check: Perhaps here is a rare, random ore? freeloop(true); for (.@i = 0; .@i < getarraysize($@WBT_Random_id); .@i++) { if (!strcmp($@WBT_Random_map$[.@i], .@map$) && $@WBT_Random_x[.@i] == .@x && $@WBT_Random_y[.@i] == .@y) { .@id = $@WBT_Random_id[.@i]; .@amount = $@WBT_Random_amount[.@i]; inventoryplace .@id, .@amount; deletearray $@WBT_Random_id[.@i], 1; deletearray $@WBT_Random_amount[.@i], 1; deletearray $@WBT_Random_map$[.@i], 1; deletearray $@WBT_Random_x[.@i], 1; deletearray $@WBT_Random_y[.@i], 1; getitem .@id, .@amount; mesn strcharinfo(0); mesc l("You found something!"); mesc l("It's @@ @@.", .@amount, getitemname(.@id)); next; closeclientdialog; return 1; } } freeloop(false); dispbottom l("Sadly, you found nothing but dirt."); return 0; } function Bury { narrator S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE, l("What would you like to bury?"); .@items$ = ""; mes "##B" + l("Drag and drop an item from your inventory.") + "##b"; .@id = requestitem(); // If ID is invalid, there's not enough items, it is an Iron Shovel, it is bound = Cannot bury // NOBODY bypass notrade check. (ITR_NONE is 0) if (.@id < 1) close; if (.@id < 1 || countitem(.@id) < 1 || .@id == IronShovel || .@id == SteelShovel || checkbound(.@id) || (!getiteminfo(.@id, ITEMINFO_TRADE)) ) { @ShovelLastUsed = 0; if (.@id == IronShovel || .@id == SteelShovel || checkbound(.@id)) mesc l("You cannot bury this item!"); else if (!getiteminfo(.@id, ITEMINFO_TRADE)) mesc l("This item is too precious, you cannot part with it!"); else mesc l("You give up."); close; return; } .@amount = 1; if (countitem(.@id) > 1) { narrator S_FIRST_BLANK_LINE | S_LAST_BLANK_LINE, l("Amount?"); input .@amount, 0, countitem(.@id); } if (.@amount == 0 || .@amount > countitem(.@id)) { close; return; } getmapxy(.@map$, .@x, .@y, 0); delitem .@id, .@amount; .@wtc = getarraysize($WorldBuriedTreasures_id); $WorldBuriedTreasures_id[.@wtc] = .@id; $WorldBuriedTreasures_amount[.@wtc] = .@amount; $WorldBuriedTreasures_map$[.@wtc] = .@map$; $WorldBuriedTreasures_x[.@wtc] = .@x; $WorldBuriedTreasures_y[.@wtc] = .@y; narrator S_FIRST_BLANK_LINE, l("You buried @@ @@.", .@amount, getitemname(.@id)); close; return 0; } // Scope: ShovelQuests_ → x, y, map, func{tion} function ShovelQuests { getmapxy(.@map$, .@x, .@y, 0); for (.@i = 0; .@i < getarraysize(ShovelQuests_func$); .@i++) { if (!strcmp(ShovelQuests_map$[.@i], .@map$) && ShovelQuests_x[.@i] == .@x && ShovelQuests_y[.@i] == .@y) { .@func$ = ShovelQuests_func$[.@i]; deletearray ShovelQuests_func$[.@i], 1; deletearray ShovelQuests_map$[.@i], 1; deletearray ShovelQuests_x[.@i], 1; deletearray ShovelQuests_y[.@i], 1; callfunc(.@func$); return 1; } } return 0; } OnDig: if (!CheckDigLocation()) { dispbottom l("I can't use the shovel here."); end; } if (PlayerIsTired()) end; if (!ShovelQuests()) Dig(); end; OnBury: if (!CheckDigLocation()) { dispbottom l("I can't use the shovel here."); end; } if (PlayerIsTired()) end; Bury(); end; function CheckDigLocation { getmapxy(.@map$, .@x, .@y, 0); for (.@i = 0; .@i < getarraysize(.WorldDigRect_Map$); .@i++) { if (!strcmp(.WorldDigRect_Map$[.@i], .@map$) && .WorldDigRect_x1[.@i] <= .@x && .WorldDigRect_x2[.@i] >= .@x && .WorldDigRect_y1[.@i] <= .@y && .WorldDigRect_y2[.@i] >= .@y) { return 1; } } return 0; } function AddDigRect { if (getargcount() < 5) { debugmes "usage: AddDigRect(map$,x1,y1,x2,y2)"; return 0; } .@map$ = str(getarg(0)); .@x1 = getarg(1); .@y1 = getarg(2); .@x2 = getarg(3); .@y2 = getarg(4); .@size = getarraysize(.WorldDigRect_Map$); .WorldDigRect_Map$[.@size] = .@map$; .WorldDigRect_x1[.@size] = .@x1; .WorldDigRect_y1[.@size] = .@y1; .WorldDigRect_x2[.@size] = .@x2; .WorldDigRect_y2[.@size] = .@y2; return 1; } function PlayerIsTired { /* // GMs can do this in an unrestricted way if (is_gm()) return 0; */ // I changed the rule to: No restriction on Aeros! (GM or not) (May be laggy) if (getmap() == "001-1") return 0; .@tick = gettimetick(2); .@playertick = .PlayerTiredTime - (readparam(bStr)/5) - (readparam(bVit)/10); // Dig and Bury more with Steel Shovel if (countitem(SteelShovel)) { .@playertick-=(.PlayerTiredTime*2)/3; } if (@ShovelLastUsed + max(5, .@playertick) > .@tick) { .@time$=FuzzyTime(@ShovelLastUsed + max(5, .@playertick)); dispbottom lg("You are exhausted, you should rest @@.", "You are exhausted, you should rest @@.", .@time$); return 1; } @ShovelLastUsed = .@tick; return 0; } OnInit: // Define constants .PlayerTiredTime = 25; // You can bury & dig on all mines AddDigRect("007-1", 20, 20, 180, 190); AddDigRect("011-1", 20, 20, 180, 180); AddDigRect("015-1", 20, 20, 180, 180); // Aeros can be used too (for events) AddDigRect("001-1", 20, 20, 342, 158); // LoF Areas AddDigRect("018-1", 20, 20, 80, 80); OnHour00: // Clear random treasure deletearray $@WBT_Random_id; deletearray $@WBT_Random_amount; deletearray $@WBT_Random_map$; deletearray $@WBT_Random_x; deletearray $@WBT_Random_y; // Scatter Treasure. // There are 25600 possible cells, and about 60% of them are collisions. // As we don't prevent treasure from falling on collision, it is pretty high. // If two treasures fall on same place, the previous treasure will be ignored. // Theoretical chance of uncovering a treasure on an attempt is 0.12% to 0.70% // 2019-05-27: Doubled ammount of treasures. New rates should be 0.24% ~ 1.40% shovel_scatter("007-1", 20, 20, 180, 180, rand(60,360), TreasureKey,CoinBag,TreasureKey,SulfurPowder,Coal, IronOre,CopperOre,LeadOre,TinOre,SilverOre,GoldOre,PlatinumOre,IridiumOre,TitaniumOre, Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst, CursedAmmoBox,ThornAmmoBox,SacredBullet); shovel_scatter("011-1", 20, 20, 180, 180, rand(60,360), TreasureKey,CoinBag,TreasureKey,SulfurPowder,Coal, IronOre,CopperOre,LeadOre,TinOre,SilverOre,GoldOre,PlatinumOre,IridiumOre,TitaniumOre, Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst, CursedAmmoBox,ThornAmmoBox,SacredBullet); shovel_scatter("015-1", 20, 20, 180, 180, rand(60,360), TreasureKey,CoinBag,TreasureKey,SulfurPowder,Coal, IronOre,CopperOre,LeadOre,TinOre,SilverOre,GoldOre,PlatinumOre,IridiumOre,TitaniumOre, Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst, CursedAmmoBox,ThornAmmoBox,SacredBullet); // Extra burried treasure (25~65 over 3600 tiles: aprox. 0.70% to 1.80%) // New Rate: 1.40% ~ 3.60% since 2019-05-27 shovel_scatter("018-1", 20, 20, 80, 80, rand(50,130), TreasureKey,CoinBag,TreasureKey,SulfurPowder,Coal, IronOre,CopperOre,LeadOre,TinOre,SilverOre,GoldOre,PlatinumOre,IridiumOre,TitaniumOre, Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst, CursedAmmoBox,ThornAmmoBox,SacredBullet); // Aeros can't be forgotten shovel_scatter("001-1", 171, 20, 340, 160, rand(160,360), TreasureKey,CoinBag,TreasureKey,SulfurPowder,Coal, IronOre,CopperOre,LeadOre,TinOre,SilverOre,GoldOre,PlatinumOre,IridiumOre,TitaniumOre, Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst); shovel_scatter("001-1", 20, 20, 140, 140, rand(160,360), TreasureKey,CoinBag,TreasureKey,SulfurPowder,Coal, IronOre,CopperOre,LeadOre,TinOre,SilverOre,GoldOre,PlatinumOre,IridiumOre,TitaniumOre, Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst); end; } function script shovel_addquest { if (getargcount() < 4) { debugmes "usage: shovel_addquest(map$,x,y,func$)"; return 0; } .@map$ = str(getarg(0)); .@x = getarg(1); .@y = getarg(2); .@func$ = str(getarg(3)); .@size = getarraysize(ShovelQuests_func$); ShovelQuests_func$[.@size] = .@func$; ShovelQuests_map$[.@size] = .@map$; ShovelQuests_x[.@size] = .@x; ShovelQuests_y[.@size] = .@y; return 1; } function script shovel_adddigrect { if (getargcount() < 5) { debugmes "usage: shovel_adddigrect(map$,x1,y1,x2,y2)"; return 0; } .@map$ = str(getarg(0)); .@x1 = getarg(1); .@y1 = getarg(2); .@x2 = getarg(3); .@y2 = getarg(4); .@size = getarraysize(getvariableofnpc(.WorldDigRect_Map$, strnpcinfo(3))); set getvariableofnpc(.WorldDigRect_Map$[.@size], strnpcinfo(3)), .@map$; set getvariableofnpc(.WorldDigRect_x1[.@size], strnpcinfo(3)), .@x1; set getvariableofnpc(.WorldDigRect_y1[.@size], strnpcinfo(3)), .@y1; set getvariableofnpc(.WorldDigRect_x2[.@size], strnpcinfo(3)), .@x2; set getvariableofnpc(.WorldDigRect_y2[.@size], strnpcinfo(3)), .@y2; return 1; } function script shovel_getcity { .@a$=getarg(0); // else is not required (return prevails) if (.@a$ == "007-1") return l("Tulimshar Mines"); if (.@a$ == "011-1") return l("Halinarzo Mines"); if (.@a$ == "015-1") return l("Hurnscald Mines"); if (.@a$ == "018-1") return l("Sincerity Island"); return .@a$; } // [Treasure Map] functions function script shovel_randomtreasure { .@id=any(TreasureKey,CoinBag,TreasureKey,CoinBag,CoinBag,GoldPieces, Diamond,Ruby,Emerald,Sapphire,Topaz,Amethyst, StrangeCoin, CasinoCoins, MercBoxA, AncientBlueprint); delitem TreasureMap, 1; .@amount=any(1,1,2); if (.@id == TreasureKey || .@id == CoinBag) .@amount+=any(0,1,0,1,2); if (.@id == StrangeCoin || .@id == CasinoCoins) .@amount+=rand2(0,8); if (.@id == MercBoxA || .@id == AncientBlueprint) .@amount=1; getitem .@id, .@amount; ShovelQuests_AssignedMAP$=""; ShovelQuests_AssignedX=0; ShovelQuests_AssignedY=0; mesn strcharinfo(0); mesc l("You found something!"); mesc l("It's @@ @@.", .@amount, getitemname(.@id)); next; closeclientdialog; return; } function script shovel_genrandtreasure { .@m$=any("007-1", "011-1", "015-1", "018-1"); // Dangerous do { .@x=rand2(20, getmapinfo(MAPINFO_SIZE_X, .@m$)-20); .@y=rand2(20, getmapinfo(MAPINFO_SIZE_Y, .@m$)-20); } while (!checkcell(.@m$, .@x, .@y, cell_chkpass)); // Success if (checkcell(.@m$, .@x, .@y, cell_chkpass)) { shovel_addquest(.@m$, .@x, .@y, "shovel_randomtreasure"); ShovelQuests_AssignedMAP$=shovel_getcity(.@m$); ShovelQuests_AssignedX=.@x; ShovelQuests_AssignedY=.@y; } return; }