summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/map/maps.conf1
-rw-r--r--db/constants.conf8
-rw-r--r--db/map_index.txt127
-rw-r--r--maps/re/012-8.mcachebin0 -> 80 bytes
-rw-r--r--npc/003-2/_import.txt2
-rw-r--r--npc/012-1/_import.txt1
-rw-r--r--npc/012-1/estate.txt199
-rw-r--r--npc/012-8/_import.txt4
-rw-r--r--npc/012-8/_warps.txt3
-rw-r--r--npc/012-8/doorbell.txt327
-rw-r--r--npc/_import.txt1
-rw-r--r--npc/functions/estate.txt91
-rw-r--r--npc/scripts.conf1
13 files changed, 701 insertions, 64 deletions
diff --git a/conf/map/maps.conf b/conf/map/maps.conf
index 64734ea16..e6f4ddf8e 100644
--- a/conf/map/maps.conf
+++ b/conf/map/maps.conf
@@ -74,6 +74,7 @@ map_list: (
"012-5",
"012-6",
"012-7",
+ "012-8",
"014-1",
"014-2-1",
"014-2",
diff --git a/db/constants.conf b/db/constants.conf
index f978b5605..a26946525 100644
--- a/db/constants.conf
+++ b/db/constants.conf
@@ -3883,6 +3883,14 @@ constants_db: {
MASK_UNUSED: 512
MASK_SPECIAL: 1024
+ comment__: "Real Estate Collisions"
+ RES_OBJECTS: 1
+ RES_UTILITIES: 5
+ RES_LUXURY: 3
+ RES_DECORATION: 2
+ RES_SITTABLE: 4
+ RES_WALLDECORATION: 6
+
comment__: "speechflags"
S_FIRST_BLANK_LINE: 1
S_LAST_BLANK_LINE: 2
diff --git a/db/map_index.txt b/db/map_index.txt
index 763380451..4a9da3835 100644
--- a/db/map_index.txt
+++ b/db/map_index.txt
@@ -71,66 +71,67 @@
012-5 71
012-6 72
012-7 73
-014-1 74
-014-2-1 75
-014-2 76
-014-3 77
-014-4 78
-014-5 79
-015-1 80
-015-2 81
-015-3 82
-015-4 83
-015-5 84
-015-6 85
-015-7 86
-016-1 87
-016-6 88
-016-7 89
-017-1 90
-017-2-1 91
-017-2-2 92
-017-2 93
-017-3 94
-017-4 95
-017-5 96
-017-6 97
-018-1-1 98
-018-1 99
-018-2-1 100
-018-2-2 101
-018-2-3 102
-018-2-4 103
-018-2 104
-018-3 105
-018-4-1 106
-018-4-2 107
-018-4 108
-018-5 109
-019-1-1 110
-019-1 111
-019-2 112
-019-3 113
-019-4-1 114
-019-4 115
-020-1 116
-020-2 117
-020-3 118
-020-4 119
-020-5 120
-020-6 121
-021-1 122
-021-2 123
-021-3 124
-021-4 125
-022-1 126
-023-1 127
-023-2 128
-024-1 129
-boss 130
-botcheck 131
-sec_pri 132
-soren-2 133
-soren 134
-test 135
-testbg 136
+012-8 74
+014-1 75
+014-2-1 76
+014-2 77
+014-3 78
+014-4 79
+014-5 80
+015-1 81
+015-2 82
+015-3 83
+015-4 84
+015-5 85
+015-6 86
+015-7 87
+016-1 88
+016-6 89
+016-7 90
+017-1 91
+017-2-1 92
+017-2-2 93
+017-2 94
+017-3 95
+017-4 96
+017-5 97
+017-6 98
+018-1-1 99
+018-1 100
+018-2-1 101
+018-2-2 102
+018-2-3 103
+018-2-4 104
+018-2 105
+018-3 106
+018-4-1 107
+018-4-2 108
+018-4 109
+018-5 110
+019-1-1 111
+019-1 112
+019-2 113
+019-3 114
+019-4-1 115
+019-4 116
+020-1 117
+020-2 118
+020-3 119
+020-4 120
+020-5 121
+020-6 122
+021-1 123
+021-2 124
+021-3 125
+021-4 126
+022-1 127
+023-1 128
+023-2 129
+024-1 130
+boss 131
+botcheck 132
+sec_pri 133
+soren-2 134
+soren 135
+test 136
+testbg 137
diff --git a/maps/re/012-8.mcache b/maps/re/012-8.mcache
new file mode 100644
index 000000000..2cae43ce3
--- /dev/null
+++ b/maps/re/012-8.mcache
Binary files differ
diff --git a/npc/003-2/_import.txt b/npc/003-2/_import.txt
index fffe69267..f6711989e 100644
--- a/npc/003-2/_import.txt
+++ b/npc/003-2/_import.txt
@@ -1,4 +1,4 @@
-// Map 003-2: Tulimshar Guild
+// Map 003-2: Tulimshar Guild
// This file is generated automatically. All manually added changes will be removed when running the Converter.
"npc/003-2/_warps.txt",
"npc/003-2/eistein.txt",
diff --git a/npc/012-1/_import.txt b/npc/012-1/_import.txt
index c9898eea0..57e4e73f5 100644
--- a/npc/012-1/_import.txt
+++ b/npc/012-1/_import.txt
@@ -5,6 +5,7 @@
"npc/012-1/andrei.txt",
"npc/012-1/bot.txt",
"npc/012-1/dyrinthetraveler.txt",
+"npc/012-1/estate.txt",
"npc/012-1/guards.txt",
"npc/012-1/gwendolyn.txt",
"npc/012-1/hinnak.txt",
diff --git a/npc/012-1/estate.txt b/npc/012-1/estate.txt
new file mode 100644
index 000000000..57f578f1d
--- /dev/null
+++ b/npc/012-1/estate.txt
@@ -0,0 +1,199 @@
+// TMW2: Moubootaur Legends scripts.
+// Author:
+// Jesusalva
+// Description:
+// Real Estate System
+
+// ID: 1
+// $ESTATE_OWNER[.id] → Account ID owner of the Real Estate
+// $ESTATE_OWNERNAME$[.id] → Human readable name of Real Estate owner
+// $ESTATE_RENTTIME[.id] → When the rent will expire
+// $ESTATE_MOBILIA_2[.id] → Bitmask of mobilia currently purchased on Monster Collision (6) (Use on walls only)
+// $ESTATE_MOBILIA_4[.id] → Bitmask of mobilia currently purchased on Air Collision (2)
+// $ESTATE_MOBILIA_8[.id] → Bitmask of mobilia currently purchased on Water Collision (3)
+// $ESTATE_MOBILIA_32[.id] → Bitmask of mobilia currently purchased on Yellow Collision (4)
+// $ESTATE_MOBILIA_64[.id] → Bitmask of mobilia currently purchased on Player Collision (5)
+// $ESTATE_MOBILIA_128[.id] → Bitmask of mobilia currently purchased on Normal Collision (1)
+// $ESTATE_PASSWORD$[.id] → Password to enter the estate. If it is "", then no password required
+// Note: GMs and Administrators can always use super password "mouboo" to enter a locked estate
+// $ESTATE_DOORBELL[.id] → If doorbell is disabled (enabled by default)
+
+// REAL_ESTATE_CREDITS → Credits equivalent to GP the player have. Will be used first.
+
+// The sign is the main controller
+012-1,94,70,0 script Sign#RES_0128 NPC_SWORDS_SIGN,{
+
+ if ($ESTATE_RENTTIME[.id] < gettimetick(2))
+ goto L_RentAvailable;
+
+ if ($ESTATE_OWNER[.id] == getcharid(3))
+ goto L_Manage;
+
+ mesc l("This estate currently belongs to @@.", $ESTATE_OWNERNAME$[.id]);
+ mesc l("Press the doorbell?");
+ next;
+ if (askyesno() == ASK_YES)
+ doevent "Doorbell#RES_0128::OnDoorbell";
+ close;
+
+L_RentAvailable:
+ mesc l("This Real Estate is available for rent for only @@ GP!", format_number(.price));
+ .@gp=REAL_ESTATE_CREDITS+Zeny;
+ mesc l("You currently have: @@ GP and mobiliary credits", format_number(.@gp));
+ next;
+ select
+ rif(.@gp > .price, l("Rent it! Make it mine!")),
+ l("Information"),
+ l("Don't rent it");
+
+ // You want to rent
+ if (@menu == 1) {
+ if ($ESTATE_RENTTIME[.id] > gettimetick(2)) {
+ mesc l("Somebody already rented it before you!");
+ close;
+ }
+ REAL_ESTATE_CREDITS=REAL_ESTATE_CREDITS-.price;
+ if (REAL_ESTATE_CREDITS < 0) {
+ Zeny+=REAL_ESTATE_CREDITS;
+ REAL_ESTATE_CREDITS=0;
+ }
+
+ // Payment done, you can now acquire the house for a month
+ $ESTATE_RENTTIME[.id]=gettimetick(2)+.time;
+
+ // If you're not the previous owner
+ // Remove previous owner furniture and reset room password
+ if ($ESTATE_OWNER[.id] != getcharid(3)) {
+ $ESTATE_MOBILIA_2[.id]=0;
+ $ESTATE_MOBILIA_4[.id]=0;
+ $ESTATE_MOBILIA_8[.id]=0;
+ $ESTATE_MOBILIA_32[.id]=0;
+ $ESTATE_MOBILIA_64[.id]=0;
+ $ESTATE_MOBILIA_128[.id]=0;
+ $ESTATE_PASSWORD$[.id]="";
+ $ESTATE_DOORBELL[.id]=false;
+ }
+
+ // Register your info so you can manage it
+ $ESTATE_OWNER[.id]=getcharid(3);
+ $ESTATE_OWNERNAME$[.id]=strcharinfo(0);
+
+ mesc l("Rent successful for 30 days!");
+ } else if (@menu == 2) {
+ mesc l("You can rent this house to make it yours.");
+ mesc l("Then you'll be able to buy furniture and utility.");
+ mesc l("The door is password-protected, so your friends can enter but strangers stay outside.");
+ next;
+ mesc l("Both rent and furniture are bought using money, however, there are mobiliary credits.");
+ mesc l("Mobiliary Credits is a special currency which can only be used on real estate.");
+ mesc l("It's obtained with ADMINS or by selling furniture. It is sumed to money and used first.");
+ }
+ close;
+
+L_Manage:
+ mesc l("@@'s Estate", strcharinfo(0));
+ mesc ".:: "+ l("Managment Menu") + " ::.";
+
+ .@gp=REAL_ESTATE_CREDITS+Zeny;
+ mesc l("Rent time available: @@", FuzzyTime($ESTATE_RENTTIME[.id]));
+ mesc l("Total Credits and GP: @@", format_number(.@gp));
+ mes "";
+ mesc l("Rent Renew Price: @@ GP", format_number(.price));
+ mesc l("Room password: @@", $ESTATE_PASSWORD$[.id]);
+ if ($ESTATE_DOORBELL[.id])
+ mesc l("Doorbell is disabled"), 1;
+
+ next;
+ select
+ l("Leave"),
+ l("Enable/disable doorbell"),
+ l("Set room password"),
+ rif(.@gp >= .price && $ESTATE_RENTTIME[.id] < gettimetick(2)+.time, l("Renew Rent"));
+
+ switch (@menu) {
+ case 1:
+ close;
+ break;
+ case 2:
+ $ESTATE_DOORBELL[.id]=!$ESTATE_DOORBELL[.id];
+ break;
+ case 3:
+ mesc l("(Leave the password blank to disable)");
+ mesc l("Current Room password: @@", $ESTATE_PASSWORD$[.id]);
+ mesc l("Input new password: ");
+ input .@password$;
+ mesc l("Repeat new password: ");
+ input .@passwordc$;
+ if (.@password$ == .@passwordc$) {
+ $ESTATE_PASSWORD$[.id]=.@password$;
+ mesc l("Password changed with success!"), 3;
+ } else {
+ mesc l("The passwords doesn't match."), 1;
+ }
+ break;
+ case 4:
+ // The check is performed before showing the menu option
+ // I guess it could be hacked, but I'll probably see negative GP...
+ REAL_ESTATE_CREDITS=REAL_ESTATE_CREDITS-.price;
+ if (REAL_ESTATE_CREDITS < 0) {
+ Zeny+=REAL_ESTATE_CREDITS;
+ REAL_ESTATE_CREDITS=0;
+ }
+
+ // Payment done, you can now acquire the house for a month
+ // If you lost the rent on the meanwhile, it'll renew
+ // If you lost the rent and somebody else rented it, you lose the GP
+ $ESTATE_RENTTIME[.id]+=.time;
+ break;
+ }
+ goto L_Manage;
+ close;
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 3;
+
+ // Estate Settings
+ .id=1; // Estate ID
+ .price=120000; // Monthly rent price
+ .time=60*60*24*30; // How long last default rent time. In future could consider month.
+ end;
+
+}
+
+// Door entrance
+012-1,95,69,0 script #RES_0128 NPC_HIDDEN,0,0,{
+ end;
+OnTouch:
+ if ($ESTATE_RENTTIME[.id] < gettimetick(2))
+ goto L_RentAvailable;
+
+ if ($ESTATE_OWNER[.id] == getcharid(3) || $ESTATE_PASSWORD$[.id] == "")
+ goto L_Warp;
+
+ mesc l("The door is locked");
+ next;
+ mesc l("However, it can be unlocked if you know the password:");
+ if (is_gm()) mesc l("You can use super password \"mouboo\" to unlock the door."), 1;
+ input .@password$;
+ // GMs can use super password "mouboo"
+ if (.@password$ == $ESTATE_PASSWORD$[.id] || (is_gm() && .@password$ == "mouboo"))
+ goto L_Warp;
+ close;
+
+L_Warp:
+ warp "012-8", 33, 33;
+ closeclientdialog;
+ close;
+
+L_RentAvailable:
+ dispbottom l("This estate is available for rent, talk to the sign to rent it.");
+ close;
+
+OnInit:
+ // Estate Settings
+ .id=1; // Estate ID
+ end;
+
+}
+
diff --git a/npc/012-8/_import.txt b/npc/012-8/_import.txt
new file mode 100644
index 000000000..b156ebd12
--- /dev/null
+++ b/npc/012-8/_import.txt
@@ -0,0 +1,4 @@
+// Map 012-8: Real Estate
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+"npc/012-8/_warps.txt",
+"npc/012-8/doorbell.txt",
diff --git a/npc/012-8/_warps.txt b/npc/012-8/_warps.txt
new file mode 100644
index 000000000..e431d2be4
--- /dev/null
+++ b/npc/012-8/_warps.txt
@@ -0,0 +1,3 @@
+// This file is generated automatically. All manually added changes will be removed when running the Converter.
+// Map 012-8: Real Estate warps
+012-8,34,34,0 warp #012-8_34_34 1,0,012-1,95,70
diff --git a/npc/012-8/doorbell.txt b/npc/012-8/doorbell.txt
new file mode 100644
index 000000000..833872c05
--- /dev/null
+++ b/npc/012-8/doorbell.txt
@@ -0,0 +1,327 @@
+// TMW2: Moubootaur Legends scripts.
+// Author:
+// Jesusalva
+// Description:
+// Real Estate System
+// Doorbell allows you to purchase mobilia, besides loading it when server starts
+// Each layer can have 32 different furniture pieces because bitmask limit.
+// This file is custom to every room
+
+// ID: 1
+// $ESTATE_OWNER[.id] → Account ID owner of the Real Estate
+// $ESTATE_OWNERNAME$[.id] → Human readable name of Real Estate owner
+// $ESTATE_RENTTIME[.id] → When the rent will expire
+// $ESTATE_MOBILIA_2[.id] → Bitmask of mobilia currently purchased on Monster Collision (6) (Use on walls only)
+// $ESTATE_MOBILIA_4[.id] → Bitmask of mobilia currently purchased on Air Collision (2)
+// $ESTATE_MOBILIA_8[.id] → Bitmask of mobilia currently purchased on Water Collision (3)
+// $ESTATE_MOBILIA_32[.id] → Bitmask of mobilia currently purchased on Yellow Collision (4)
+// $ESTATE_MOBILIA_64[.id] → Bitmask of mobilia currently purchased on Player Collision (5)
+// $ESTATE_MOBILIA_128[.id] → Bitmask of mobilia currently purchased on Normal Collision (1)
+// $ESTATE_PASSWORD$[.id] → Password to enter the estate. If it is "", then no password required
+// Note: GMs and Administrators can always use super password "mouboo" to enter a locked estate
+// $ESTATE_DOORBELL[.id] → If doorbell is disabled (enabled by default)
+
+// REAL_ESTATE_CREDITS → Credits equivalent to GP the player have. Will be used first.
+
+// The sign is the main controller
+012-8,32,34,0 script Doorbell#RES_0128 NPC_NO_SPRITE,{
+ // Name, Layer, Price, ID, x1, y1, x2, y2,
+ function create_object {
+ array_push(.name$, getarg(0));
+ array_push(.layer, getarg(1));
+ array_push(.price, getarg(2));
+ array_push(.objid, getarg(3));
+ array_push(.x1, getarg(4));
+ array_push(.y1, getarg(5));
+ array_push(.x2, getarg(6));
+ array_push(.y2, getarg(7));
+ return;
+ }
+
+ if ($ESTATE_OWNER[.id] == getcharid(3))
+ goto L_Manage;
+
+ mesc l("This estate currently belongs to @@.", $ESTATE_OWNERNAME$[.id]);
+ close;
+
+// If someone press the doorbell from outside and doorbell is enabled
+OnDoorbell:
+ if (!$ESTATE_DOORBELL[.id])
+ end;
+
+ if (.dpost < gettimetick(2)) {
+ npctalk ("@@ is pressing the doorbell.", strcharinfo(0));
+ }
+ .dpost=gettimetick(2)+.delay;
+ end;
+
+// Managment Menu
+L_Manage:
+ mesc l("@@'s Estate", strcharinfo(0));
+ mesc ".:: "+ l("Managment Menu") + " ::.";
+
+ .@gp=REAL_ESTATE_CREDITS+Zeny;
+ mesc l("Rent time available: @@", FuzzyTime($ESTATE_RENTTIME[.id]));
+ mesc l("Total Credits and GP: @@", format_number(.@gp));
+ mes "";
+ mesc l("Room password: @@", $ESTATE_PASSWORD$[.id]);
+ if ($ESTATE_DOORBELL[.id])
+ mesc l("Doorbell is disabled"), 1;
+
+ next;
+ select
+ l("Leave"),
+ l("Enable/disable doorbell"),
+ l("Manage Furniture"),
+ l("Set room password");
+
+ switch (@menu) {
+ case 1:
+ close;
+ break;
+ case 2:
+ $ESTATE_DOORBELL[.id]=!$ESTATE_DOORBELL[.id];
+ break;
+ case 3:
+ goto L_Furniture;
+ break;
+ case 4:
+ mesc l("(Leave the password blank to disable)");
+ mesc l("Current Room password: @@", $ESTATE_PASSWORD$[.id]);
+ mesc l("Input new password: ");
+ input .@password$;
+ mesc l("Repeat new password: ");
+ input .@passwordc$;
+ if (.@password$ == .@passwordc$) {
+ $ESTATE_PASSWORD$[.id]=.@password$;
+ mesc l("Password changed with success!"), 3;
+ } else {
+ mesc l("The passwords doesn't match."), 1;
+ }
+ break;
+ }
+ goto L_Manage;
+
+L_Furniture:
+ mesc l("@@'s Estate", strcharinfo(0));
+ mesc ".:: "+ l("Furniture Menu") + " ::.";
+
+ .@gp=REAL_ESTATE_CREDITS+Zeny;
+ mesc l("Total Credits and GP: @@", format_number(.@gp));
+
+ next;
+ select
+ l("Finish"),
+ l("Manage Beds"),
+ l("Manage Utilities"),
+ l("Manage Luxury furniture"),
+ l("Manage Decoration"),
+ l("Manage Chairs"),
+ l("Manage Paintings");
+ mes "";
+
+ switch (@menu) {
+ case 1:
+ goto L_Manage;
+ break;
+ case 2:
+ mesc ".:: "+ l("Beds") + " ::.", 3;
+ @re_col=RES_OBJECTS;
+ break;
+ case 3:
+ mesc ".:: "+ l("Utilities") + " ::.", 3;
+ @re_col=RES_UTILITIES;
+ break;
+ case 4:
+ mesc ".:: "+ l("Luxury furniture") + " ::.", 3;
+ @re_col=RES_LUXURY;
+ break;
+ case 5:
+ mesc ".:: "+ l("Decoration") + " ::.", 3;
+ @re_col=RES_DECORATION;
+ break;
+ case 6:
+ mesc ".:: "+ l("Chairs") + " ::.", 3;
+ @re_col=RES_SITTABLE;
+ break;
+ case 7:
+ mesc ".:: "+ l("Paintings") + " ::.", 3;
+ @re_col=RES_WALLDECORATION;
+ break;
+ }
+
+// L_ContinuousLoop
+// Requires the following variables:
+// @re_col
+// Target Collision ID
+L_ContinuousLoop:
+ deletearray @valid_ids;
+
+ // Create a second array (@valid_ids) with the ID of objects within @re_col group
+ for (.@i=0; .@i < getarraysize(.layer); .@i++) {
+ //debugmes "Found object ID %d named %s on layer %s coords (%d,%d) - Looking for layer %d", .@i, .name$[.@i], .layer[.@i], .x1[.@i], .y1[.@i], @re_col;
+ if (.layer[.@i] == @re_col)
+ array_push(@valid_ids, .@i);
+ }
+ //debugmes "Found %d valid objects", getarraysize(@valid_ids);
+
+ // Create the menu with @valid_ids - Check if you already have the item to decide if you're buying or selling
+ @menuentries$="Finish:";
+ for (.@j=0; .@j < getarraysize(@valid_ids); .@j++) {
+ .@i=@valid_ids[.@j];
+ if (realestate_hasmobilia(.id, .layer[.@i], .objid[.@i]))
+ @menuentries$+=l("Sell ")+.name$[.@i]+l(" for ") + format_number( realestate_sellprice(.id,.price[.@i]) ) +":";
+ else
+ @menuentries$+=l("Purchase ")+.name$[.@i]+(" for ") + format_number( .price[.@i] )+":";
+ }
+ select (@menuentries$);
+ mes "";
+
+ // First option to return to previous menu
+ if (@menu == 1)
+ goto L_Furniture;
+
+ // Otherwise, we know then that (@menu-2) is the ID in @valid_ids
+ // So we save .@id with the correct ID in object arrays.
+ // We also calculate how much aggregated money you have.
+ .@id=@valid_ids[@menu-2];
+ .@gp=REAL_ESTATE_CREDITS+Zeny;
+
+ if (realestate_hasmobilia(.id, .layer[.@id], .objid[.@id])) {
+ // If you have the mobilia, you're selling it for Mobiliary Credits
+ realestate_togglemobilia(.id, .layer[.@id], .objid[.@id]);
+ REAL_ESTATE_CREDITS+=realestate_sellprice(.id,.price[.@i]);
+ delcells realestate_cellname(.id, .@id);
+ mesc l("Sale successful!");
+ next;
+ } else {
+ // Else, you're buying it, so we must check if you have the moolah first
+ .@price=.price[.@id];
+ if (.@gp > .@price) {
+ realestate_payment(.@price);
+ realestate_togglemobilia(.id, .layer[.@id], .objid[.@id]);
+ setcells .mapa$, .x1[.@id], .y1[.@id], .x2[.@id], .y2[.@id], .layer[.@id], realestate_cellname(.id, .@id);
+ mesc l("Purchase successful!");
+ next;
+ } else {
+ mesc l("Not enough funds!");
+ next;
+ }
+ }
+
+ // This loops forever
+ goto L_ContinuousLoop;
+
+
+OnInit:
+ .sex = G_OTHER;
+ .distance = 3;
+
+ // Estate Settings
+ .id=1; // Estate ID
+ .delay=15; // Forced wait between rings
+ .dpost=0; // Last doorbell ring
+ .mapa$="012-8";
+
+ // Arrays
+ // We go element by element on the array building the menu
+ .name$="";
+ .layer=0;
+ .price=0;
+ .objid=0;
+ .x1=0;
+ .y1=0;
+ .x2=0;
+ .y2=0;
+
+ // Furniture Settings
+ // Name, Collision Layer, Price, ID, x1, y1, x2, y2
+ // For Collision Layer, see constants.conf ("Real Estate Collisions")
+ create_object("Placeholder" ,99,999999,99999, 99, 99, 99, 99);
+
+ create_object("Bed 01" , 1, 5000, 1, 24, 24, 25, 27);
+ create_object("Bed 02" , 1, 5000, 2, 26, 24, 27, 27);
+ create_object("Bed 03" , 1, 5000, 4, 28, 24, 29, 27);
+ create_object("Bed 04" , 1, 5000, 8, 30, 24, 31, 27);
+ create_object("Bed 05" , 1, 5000, 16, 24, 29, 25, 32);
+ create_object("Bed 06" , 1, 5000, 32, 26, 29, 27, 32);
+ create_object("Bed 07" , 1, 5000, 64, 28, 29, 29, 32);
+ create_object("Bed 08" , 1, 5000, 128, 30, 29, 31, 32);
+
+ create_object("Wardrobe" , 5, 7000, 1, 21, 23, 22, 23);
+ create_object("Cauldron" , 5, 5000, 2, 28, 24, 29, 24);
+ create_object("Shelf 01" , 5, 2000, 4, 25, 23, 25, 23);
+ create_object("Shelf 02" , 5, 2000, 8, 26, 23, 26, 23);
+ create_object("Shelf 03" , 5, 2000, 16, 27, 23, 27, 23);
+ create_object("Shelf 04" , 5, 2000, 32, 30, 23, 30, 23);
+ create_object("Shelf 05" , 5, 2000, 64, 31, 23, 31, 23);
+ create_object("Shelf 06" , 5, 2000, 128, 32, 23, 32, 23);
+ create_object("Shelf 07" , 5, 2000, 256, 33, 23, 33, 23);
+ create_object("Shelf 08" , 5, 2000, 512, 34, 23, 34, 23);
+ create_object("Shelf 09" , 5, 2000, 1024, 35, 23, 35, 23);
+ create_object("Shelf 10" , 5, 2000, 2048, 36, 23, 36, 23);
+ create_object("Shelf 11" , 5, 2000, 4096, 37, 23, 37, 23);
+ create_object("Shelf 12" , 5, 2000, 8192, 38, 23, 38, 23);
+
+ create_object("Piano" , 3, 10000, 1, 33, 25, 35, 25);
+
+ create_object("Left Desk" , 2, 5000, 1, 20, 25, 22, 27);
+ create_object("Right Desk" , 2, 5000, 2, 36, 30, 38, 32);
+
+ create_object("Left Chair" , 4, 2000, 1, 21, 28, 21, 28);
+ create_object("Right Chair" , 4, 2000, 2, 37, 29, 37, 29);
+
+ create_object("Painting 01" , 6, 3000, 1, 21, 20, 21, 20);
+ create_object("Painting 02" , 6, 3000, 2, 23, 21, 23, 21);
+ create_object("Painting 03" , 6, 3000, 4, 25, 20, 25, 20);
+ create_object("Painting 04" , 6, 3000, 8, 28, 21, 28, 21);
+ create_object("Painting 05" , 6, 3000, 16, 31, 20, 31, 20);
+ create_object("Painting 06" , 6, 3000, 32, 36, 20, 36, 20);
+
+ // Load Mobilia already existing
+ debugmes "[REAL ESTATE] Now loading mobilia";
+ for (.@i=0; .@i < getarraysize(.layer); .@i++) {
+ switch (.layer[.@i]) {
+ case 1:
+ if ($ESTATE_MOBILIA_128[.id] & .objid[.@i])
+ array_push(.valid_ids, .@i);
+ break;
+ case 2:
+ if ($ESTATE_MOBILIA_4[.id] & .objid[.@i])
+ array_push(.valid_ids, .@i);
+ break;
+ case 3:
+ if ($ESTATE_MOBILIA_8[.id] & .objid[.@i])
+ array_push(.valid_ids, .@i);
+ break;
+ case 4:
+ if ($ESTATE_MOBILIA_32[.id] & .objid[.@i])
+ array_push(.valid_ids, .@i);
+ break;
+ case 5:
+ if ($ESTATE_MOBILIA_64[.id] & .objid[.@i])
+ array_push(.valid_ids, .@i);
+ break;
+ case 6:
+ if ($ESTATE_MOBILIA_2[.id] & .objid[.@i])
+ array_push(.valid_ids, .@i);
+ break;
+ default:
+ // We do nothing by default
+ //debugmes("[ERROR] [CRITICAL] [REAL ESTATE]: Object %d have Invalid Collision Type: %d (must range 1~6)", .@i, .layer[.@i]);
+ break;
+ }
+ }
+ debugmes "Found %d valid objects", getarraysize(.valid_ids);
+ for (.@j=0; .@j < getarraysize(.valid_ids); .@j++) {
+ .@id=.valid_ids[.@j];
+ setcells .mapa$, .x1[.@id], .y1[.@id], .x2[.@id], .y2[.@id], .layer[.@id], realestate_cellname(.id, .@id);
+ debugmes "Creating %s in %s", realestate_cellname(.id, .@id), .mapa$;
+ }
+ deletearray .valid_ids;
+ stopnpctimer;
+ end;
+
+}
+
+
diff --git a/npc/_import.txt b/npc/_import.txt
index 378e19221..94ecf1c6a 100644
--- a/npc/_import.txt
+++ b/npc/_import.txt
@@ -73,6 +73,7 @@
@include "npc/012-5/_import.txt"
@include "npc/012-6/_import.txt"
@include "npc/012-7/_import.txt"
+@include "npc/012-8/_import.txt"
@include "npc/014-1/_import.txt"
@include "npc/014-2-1/_import.txt"
@include "npc/014-2/_import.txt"
diff --git a/npc/functions/estate.txt b/npc/functions/estate.txt
new file mode 100644
index 000000000..5eb508e1b
--- /dev/null
+++ b/npc/functions/estate.txt
@@ -0,0 +1,91 @@
+// TMW2: Moubootaur Legends scripts.
+// Author:
+// Jesusalva
+// Description:
+// Real Estate System
+// Script Helpers
+// WARNING: They affect directly the real estate global variables!
+
+// This function reduces payment accordingly
+// realestate_payment ( amount )
+function script realestate_payment {
+ REAL_ESTATE_CREDITS=REAL_ESTATE_CREDITS-getarg(0);
+ if (REAL_ESTATE_CREDITS < 0) {
+ Zeny+=REAL_ESTATE_CREDITS;
+ REAL_ESTATE_CREDITS=0;
+ }
+ return;
+}
+
+// Generate unique name for setcells
+// realestate_cellname ( estate_id, object_id )
+function script realestate_cellname {
+ return "RESObj_"+getarg(0)+"_"+getarg(1);
+}
+
+// Generate sell price for furniture based on original price and estate ID
+// realestate_sellprice ( estate_id, price )
+function script realestate_sellprice {
+ .@timeleft=$ESTATE_RENTTIME[getarg(0)]-gettimetick(2); // Number of seconds
+ .@daysleft=.@timeleft/86400; // Number of days left of rent
+ .@weeksleft=.@timeleft/604800; // Number of weeks left of rent
+
+ //debugmes "Your contract is valid for %d weeks more - %d days", .@weeksleft, .@daysleft;
+ //debugmes "The divisor is %d", max(1, 8-.@weeksleft);
+
+ return (getarg(1)/max(1, 8-.@weeksleft)) - max(0, 60-.@daysleft);
+}
+
+// This will toggle if mobilia was purchased or not, in the right group
+// realestate_togglemobilia ( estate_id, layer_id, object_id )
+function script realestate_togglemobilia {
+ switch (getarg(1)) {
+ case 1:
+ $ESTATE_MOBILIA_128[getarg(0)] = $ESTATE_MOBILIA_128[getarg(0)] ^ getarg(2);
+ break;
+ case 2:
+ $ESTATE_MOBILIA_4[getarg(0)] = $ESTATE_MOBILIA_4[getarg(0)] ^ getarg(2);
+ break;
+ case 3:
+ $ESTATE_MOBILIA_8[getarg(0)] = $ESTATE_MOBILIA_8[getarg(0)] ^ getarg(2);
+ break;
+ case 4:
+ $ESTATE_MOBILIA_32[getarg(0)] = $ESTATE_MOBILIA_32[getarg(0)] ^ getarg(2);
+ break;
+ case 5:
+ $ESTATE_MOBILIA_64[getarg(0)] = $ESTATE_MOBILIA_64[getarg(0)] ^ getarg(2);
+ break;
+ case 6:
+ $ESTATE_MOBILIA_2[getarg(0)] = $ESTATE_MOBILIA_2[getarg(0)] ^ getarg(2);
+ break;
+ default:
+ debugmes("[ERROR] [CRITICAL] [REAL ESTATE]: Object %d have Invalid Collision Type: %d (must range 1~6)", getarg(2), getarg(1));
+ break;
+ }
+ return;
+}
+
+
+// Like the previous function, but returns true if player have said mobilia
+// realestate_hasmobilia ( estate_id, layer_id, object_id )
+function script realestate_hasmobilia {
+ switch (getarg(1)) {
+ case 1:
+ return $ESTATE_MOBILIA_128[getarg(0)] & getarg(2);
+ case 2:
+ return $ESTATE_MOBILIA_4[getarg(0)] & getarg(2);
+ case 3:
+ return $ESTATE_MOBILIA_8[getarg(0)] & getarg(2);
+ case 4:
+ return $ESTATE_MOBILIA_32[getarg(0)] & getarg(2);
+ case 5:
+ return $ESTATE_MOBILIA_64[getarg(0)] & getarg(2);
+ case 6:
+ return $ESTATE_MOBILIA_2[getarg(0)] & getarg(2);
+ default:
+ debugmes("[ERROR] [CRITICAL] [REAL ESTATE]: Object %d have Invalid Collision Type: %d (must range 1~6)", getarg(2), getarg(1));
+ return false;
+ }
+ return false;
+}
+
diff --git a/npc/scripts.conf b/npc/scripts.conf
index 6bd601436..07c1b0397 100644
--- a/npc/scripts.conf
+++ b/npc/scripts.conf
@@ -37,6 +37,7 @@
"npc/functions/bank.txt",
"npc/functions/daily.txt",
"npc/functions/doors.txt",
+"npc/functions/estate.txt",
"npc/functions/fishing.txt",
"npc/functions/hammocks.txt",
"npc/functions/lockpicks.txt",