// 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);
freeloop(true); // DANGEROUS
for (.@i = 0; .@i < .@amount; .@i++)
shovel_scriptItem(.@map$, rand(.@x1,.@x2), rand(.@y1,.@y2), getarg(rand(getargcount()-6)+6));
freeloop(false);
.@wtc = getarraysize($@WBT_Random_id);
debugmes "Scattered "+.@amount+" 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?
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;
}
}
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;
.@tick = gettimetick(1);
.@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) {
dispbottom lg("You are exhausted, you should rest a bit.");
return 1;
}
@ShovelLastUsed = .@tick;
return 0;
}
OnInit:
// Define constants
.PlayerTiredTime = 25;
// You can bury & dig on all mines
AddDigRect("007-1", 20, 20, 180, 180);
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);
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)
.@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;
}