////////////////////////////////////////////////////// // Resident Evil Online Housing System Include File // // Created by Zunath // ////////////////////////////////////////////////////// #include "inc_system_const" #include "inc_mysql_tables" #include "inc_helper_funcs" #include "colors_inc" #include "rwt_include" #include "nwnx_areas" ////////////////////////// // SYSTEM CONFIGURATION // ////////////////////////// // Linux has the ability to create and destroy copies of areas on the fly. // Windows version uses simulated area instances. // Set this to TRUE if your server is hosted on Linux // Set this to FALSE if your server is hosted on Windows const int RHS_USING_LINUX = TRUE; // The amount of time to add to a player's rent payment. Number is in terms of days. // Default: 7 (1 Week) const int RHS_RENT_LENGTH = 7; // The maximum number of furniture objects that a player can place in a single area // Default: 100 const int RHS_MAX_FURNITURE = 100; // The maximum character length a house's name can be. You shouldn't set this higher than 32. // Default: 32 const int RHS_MAX_HOUSE_NAME_LENGTH = 32; // The minimum character length a house's name can be. You shouldn't set this lower than 3. // Default: 3 const int RHS_MIN_HOUSE_NAME_LENGTH = 3; // The maximum distance in meters furniture objects will be picked up from. The higher you set this, the more // furniture objects will display in the furniture menu. // Default: 2.5 const float RHS_FURNITURE_DISTANCE = 2.5; // Percentage of money received when a piece of furniture is sold. // The player will receve this fraction of the full price when furniture is sold. // Do not set this higher than 1.00! // Default: 0.50 (50%) const float RHS_FURNITURE_SELL_BACK_PERCENTAGE = 0.50; // The amount of time a preview of a furniture object will exist. After this time, // the furniture will be destroyed. // Default: 6.0 (6 seconds) const float RHS_FURNITURE_PREVIEW_LENGTH = 6.0; // The capitialized version of the term used for houses // Default: House const string RHS_HOUSE_TERM_PROPER = "Room"; // The lower case version of the term used for houses // Default: house const string RHS_HOUSE_TERM_LOWER = "room"; // The capitalized, plural version of the term used for houses // Default: Houses const string RHS_HOUSE_TERM_PROPER_PLURAL = "Rooms"; // The lower case, plural version of the term used for houses // Default: houses const string RHS_HOUSE_TERM_LOWER_PLURAL = "rooms"; // The name of the schema used by the database for this system // Default: rhs_housing const string RHS_SCHEMA = "reo_housing"; /////////////////////////////// // SYSTEM CONSTANTS - MODULE // /////////////////////////////// // Prefix of the specific area instance arrays. Followed by the area's resref const string RHS_HOUSE_INSTANCE_PREFIX = "RHS_INSTANCE_"; /////////////////////////////// // SYSTEM CONSTANTS - HOUSES // /////////////////////////////// // House publicity ID types const int RHS_HOUSE_PUBLICITY_TYPE_PRIVATE = 1; // Only the owner can visit the house const int RHS_HOUSE_PUBLICITY_TYPE_FRIENDS = 2; // Only specified friends can visit the house const int RHS_HOUSE_PUBLICITY_TYPE_PUBLIC = 3; // Everyone can visit the house const int RHS_HOUSE_PUBLICITY_TYPE_TRUSTEES = 4; // Only specified trustees can visit the house // Friend access ID types const int RHS_HOUSE_FRIEND_TYPE_FRIEND = 1; // The default setting: Friends can visit the house but can't modify furniture const int RHS_HOUSE_FRIEND_TYPE_TRUSTEE = 2; // Trustees can modify furniture // Name of the location variable which tracks the entry point in an instanced house. const string RHS_HOUSE_ENTRY_WAYPOINT = "RHS_HOUSE_ENTRY_WAYPOINT"; // Name of the tag and resref of the waypoint which is used as the warp-in spot for players entering an instanced house. const string RHS_HOUSE_WAYPOINT_RESREF = "rhs_house_wp"; // Name of the integer variable which tracks the ID number of the player who owns the area instance. For later use with furniture manipulation. const string RHS_HOUSE_OWNER_ID_NUMBER = "RHS_HOUSE_OWNER_ID_NUMBER"; // Name of the conversation script which fires when a PC uses a "House Door" (I.E: The entry door) const string RHS_HOUSE_ENTRY_CONVERSATION = "rhs_house_menu"; // Name of the integer variable which tracks what owner ID is CURRENTLY being used by the house instance const string RHS_IN_USE_ID = "RHS_IN_USE_ID"; // Name of the boolean variable which tracks whether or not an area is a house interior // Stored on the house area const string RHS_HOUSE_MARKER = "RHS_HOUSE"; //////////////////////////////// // SYSTEM CONSTANTS - PLAYERS // //////////////////////////////// // Name of the boolean variable which tracks whether or not a player currently has a house rented // Whether or not that rent is paid doesn't matter - this only tracks whether there's specific data // in the database for this player const string RHS_PLAYER_HOUSE_RENTED = "RHS_PLAYER_HOUSE_RENTED"; // Name of the string variable which tracks a player's original position (I.E: The position they were at before entering a house instance) const string RHS_PLAYER_ORIGINAL_POSITION = "RHS_PLAYER_ORIGINAL_POSITION"; // Tracks whether or not the system is listening for text input by the player - used for inputting the house's name const string RHS_PAGE_TEMP_LISTENING = "RHS_PAGE_TEMP_LISTENING"; // Tracks the text input by player when naming his or her house const string RHS_PAGE_TEMP_NEW_HOUSE_NAME = "RHS_PAGE_TEMP_NEW_HOUSE_NAME"; // House permissions settings for friends const int RHS_FRIEND_TYPE_INVALID = 0; // Not a friend const int RHS_FRIEND_TYPE_FRIEND = 1; // Friend level permissions const int RHS_FRIEND_TYPE_TRUSTEE = 2; // Trustee level permissions ////////////////////////////////// // SYSTEM CONSTANTS - FURNITURE // ////////////////////////////////// // Tracks a particular furniture object's ID number const string RHS_FURNITURE_ID_NUMBER = "RHS_FURNITURE_ID_NUMBER"; // Tag and resref of the tool used to manipulate furniture const string RHS_FURNITURE_TOOL_RESREF = "rhs_furn_tool"; // Name of the string variable which tracks the location targeted using the furniture tool // Stored on the PC that used the furniture tool const string RHS_FURNITURE_TOOL_TARGET_LOCATION = "RHS_FURNITURE_TOOL_TARGET_LOCATION"; // Name of the dialogue script used for furniture manipulation const string RHS_FURNITURE_MENU = "rhs_furn_menu"; // Name of the boolean variable which tracks whether or not a furniture object should be moved the next time // a player uses his or her furniture tool const string RHS_FURNITURE_MOVING_OBJECT = "RHS_FURNITURE_MOVING_OBJECT"; // Name of the object variable which tracks the object oPC is moving to a new location const string RHS_FURNITURE_MOVING_OBJECT_REFERENCE = "RHS_FURNITURE_MOVING_OBJECT_REFERENCE"; ////////////////////////////////// // SYSTEM CONSTANTS - LANDLORDS // ////////////////////////////////// // Array of integers which tracks what houses are rented out by a particular landlord NPC const string RHS_LANDLORD_HOUSES_AVAILABLE_ARRAY = "RHS_LANDLORD_HOUSES"; //////////////// // PROTOTYPES // //////////////// // Replaces a player's house information with this new information. // This essentially start's a player's house from scratch by removing all information about it. Make sure you // warn the player in advance before calling this function. // ***NOTE: Friends list and furniture will be completely deleted. Make SURE you know what you're doing when you call this! // oPC = The player whose house we're setting // iHouseType = The house ID number listed in the RHS_TABLE_HOUSE_TYPES table // iPublicity = RHS_HOUSE_PUBLICITY_TYPE_* void RHS_SetPlayerHouse(object oPC, int iHouseType, int iPublicity = RHS_HOUSE_PUBLICITY_TYPE_PRIVATE); // Deletes all information about oPC's house from the database. // Be careful about calling this function - once the house is deleted, it's irreversible. // If there are any players inside the house instance, they will all be ported back outside. // * Removes the following: // * House specific information (in RHS_TABLE_HOUSES) // * Furniture (in RHS_TABLE_FURNITURE_#) // * Friends (in RHS_TABLE_FRIENDS_#) // oPC = The player object // iGold = If this is set greater than zero, this amount of gold will be given to oPC. Useful for returning money from sold furniture. void RHS_RemovePlayerHouse(object oPC, int iGold = 0); // Marks a player's house to a specified publicity level. // oPC = The player whose house we're changing // iPublicity = The new publicity level void RHS_SetHousePublicity(object oPC, int iPublicity = RHS_HOUSE_PUBLICITY_TYPE_PRIVATE); // Changes the name of oPC's house to sNewName. // oPC = The player object // sNewName = The new name to set the house to. If this is left blank the name willl default to "Name's House" where Name is the name of oPC void RHS_SetHouseName(object oPC, string sNewName = ""); // Adds a specified number of days to a player's rent. They will lose access to their house on this date until they pay the rent. // oPC = The player whose house's rent we're extending // iDays = The number of days we're adding on to their rent payment date // iPCID = If set greater than 0, the function will use this PC ID instead of the one assigned for oPC. This is useful if oPC cannot be obtained (I.E: They're offline) void RHS_ExtendHouseRent(object oPC, int iDays, int iPCID = -1); // Adds a particular furniture object to oPC's house's furniture table // oPC = The player object // oFurniture = The furniture you want to add // iPCID = If set, the function will use this specific ID number instead of oPC's void RHS_AddFurniture(object oPC, object oFurniture, int iPCID = -1); // Removes a particular furniture object from oPC's house's furniture table // oPC = The player object // oFurniture = The furniture you want to remove. // iPCID = If set, the function will use this specific ID number instead of oPC's // ***NOTE: Make sure you call this before you physically destroy the furniture object with DestroyObject void RHS_RemoveFurniture(object oPC, object oFurniture, int iPCID = -1); // Sells all of the furniture in a player's household. // Money is given to oPC and all of the furniture is removed from the table. // oPC = The player whose furniture we're selling. // ***NOTE: This also destroys all of the furniture objects inside the house instance, if the house instance exists. void RHS_SellAllFurniture(object oPC); // Adds a friend to oPC's list of friends. This makes it so that the friend can enter the house if permissions are set to "friends only" // oPC = The player object // iFriendID = If set, the function will use this specific ID number // oFriend = If set, the function will get the friend ID from this friend object // iSetting = The level of permission the friend has for oPC's house. Uses RHS_HOUSE_FRIEND_TYPE_* constants void RHS_AddFriend(object oPC, int iFriendID = -1, object oFriend = OBJECT_INVALID, int iSetting = RHS_HOUSE_FRIEND_TYPE_FRIEND); // Deletes a friend from oPC's list of friends. This makes it so that the friend can't enter the house unless permissions are set to "public" // oPC = The player object // iFriendID = If set, the function will use this specific ID number // oFriend = If set, the function will get the friend ID from this friend object // If iFriendID is less than 1 and oFriend is invalid, this function will do nothing void RHS_RemoveFriend(object oPC, int iFriendID = -1, object oFriend = OBJECT_INVALID); // Creates a furniture table for oPC's house, based off the template already in the database // oPC = The player object void RHS_CreateFurnitureTable(object oPC); // Creates a friends table for oPC's house, based off the template already in the database // oPC = The player object void RHS_CreateFriendsTable(object oPC); // Spawns all of a player's furniture into the instance of their house. // oPC = The owner of the house. Set this to OBJECT_INVALID if you want to use iPCID instead // oAreaInstance = The area instance in which to spawn the furniture // iPCID = If greater than 0, the function will use this PC ID instead of the one assigned for oPC. This is useful if oPC cannot be obtained (I.E: They're offline) void RHS_LoadHouseFurniture(object oPC, object oAreaInstance, int iPCID = -1); // Creates a new area from the house template oPC is currently renting and returns the area instance // oPC = The player object // iPCID = If set greater than 0, the function will use this PC ID instead of the one assigned for oPC. This is useful if oPC cannot be obtained (I.E: They're offline) // sHouseName = If set, the house name will be set to this value // bPreviewArray = If TRUE, the previewing array will be used to track this instance as opposed to the standard instance array // iHouseType = Used for previews - will force a specific house type to be created. // Returns OBJECT_INVALID on error object RHS_CreateHouseInstance(object oPC, int iPCID = -1, string sHouseName = "", int bPreviewArray = FALSE, int iHouseType = -1); // Creates a house preview for oPC. No one but that player can enter it. // oPC = The player previewing the house // iHouseType = The database ID of a house type (Located in table RHS_TABLE_HOUSE_TYPES) // sHouseName = If this is set, the house name will be set to it. Otherwise a generic "(PREVIEW) House Name" will be used as the area's name void RHS_PreviewHouse(object oPC, int iHouseType, string sHouseName = ""); // Forces oPC to enter the house of oOwner. // An instanced copy of the owner's house will be created and oPC will be teleported inside. All furniture will be spawned. // If the instanced copy already exists, oPC will simply be sent to that copy instead of creating another. // oPC = The player entering the house // oOwner = The owner of the house, set this to OBJECT_INVALID if you're using iOwnerID instead // iOwnerID = If set greater than 0, the function will use this Owner ID instead of the one assigned for oOwner. This is useful if oOwner cannot be obtained (I.E: They're offline) // sHouseName = If set, the area's name will be set to this value. Useful for when PCs preview houses // ***NOTE: oPC and oOwner can be the same object void RHS_EnterHouse(object oPC, object oOwner = OBJECT_INVALID, int iOwnerID = -1, string sHouseName = ""); // Call this on the module's OnChat event. // When a player has the necessary temporary variables, this will mark the next thing that player says // for later use in the house renaming menu. void RHS_OnPlayerChat(); // Call this on your module's OnEnter event. // If a player doesn't have a furniture tool item, they will be given one. // This tool should be undroppable. void RHS_OnModuleEnter(); // Returns RHS_FRIEND_TYPE_INVALID if oFriend is not listed as a friend of oOwner's house. // Returns RHS_FRIEND_TYPE_FRIEND if oFriend IS listed as a friend of oOwner's house. // Returns RHS_FRIEND_TYPE_TRUSTEE if oFriend is a trustee of oOwner's house. // oFriend = The friend we're checking // oOwner = The owner of the house // iFriendID = If this is greater than zero, this ID number will be used instead of the one listed on oFriend // iOwnerID = If this is greater than zero, this ID number will be used instead of the one listed on oOwner int RHS_IsPlayerFriend(object oFriend, object oOwner, int iFriendID = -1, int iOwnerID = -1); // Returns TRUE if the rent is paid for oOwner's house // Returns FALSE if the rent is due for oOwner's house // Returns -1 on error // oOwner = The house owner object // iOwnerID = If this is greater than zero, this ID number will be used instead of the one listed on oOwner. Useful if oOwner is offline. int RHS_IsRentPaid(object oOwner, int iOwnerID = -1); // Calculates and returns the total worth of oOwner's furniture after the sell back penalty is applied. // oOwner = The owner of the house // iOwnerID = If this is greater than zero, this ID number will be used instead of the one listed on oOwner. Useful if oOwner is offline. // Returns -1 on error. int RHS_CalculateTotalFurnitureValue(object oOwner, int iOwnerID = -1); // Call this on the door that's used to exit your house areas. // It will teleport the user back to his or her stored location (I.E: The location they were at before entering the house) // If there are no more players in the area, the area instance will be destroyed. void RHS_OnDoorAreaTransitionClick(); // Returns the area object instance currently in use based on the owner's ID number // iOwnerID = The ID number of the house's owner // sAreaResref = The resref of the area instance // Returns OBJECT_INVALID on error. object RHS_GetAreaInstance(int iOwnerID, string sAreaResref); // Destroys all of the items inside the inventory of a placeable or other object with inventory void RHS_ClearInventory(object oObject); /////////////// // FUNCTIONS // /////////////// void RHS_SetPlayerHouse(object oPC, int iHouseType, int iPublicity = RHS_HOUSE_PUBLICITY_TYPE_PRIVATE) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPCID = IntToString(iPCID); string sCharName = SQLEncodeSpecialChars(GetName(oPC)); string sAccessibleUntil = RWT_GetTimestampFromUnix(RWT_CreateCooldown(RHS_RENT_LENGTH * RWT_NUMBER_OF_SECONDS_IN_DAY)); string sHouseName = SQLEncodeSpecialChars(sCharName + "'s " + RHS_HOUSE_TERM_PROPER); string sPublicityCode; if(iPublicity == RHS_HOUSE_PUBLICITY_TYPE_PRIVATE) sPublicityCode = "O"; else if(iPublicity == RHS_HOUSE_PUBLICITY_TYPE_FRIENDS) sPublicityCode = "F"; else if(iPublicity == RHS_HOUSE_PUBLICITY_TYPE_PUBLIC) sPublicityCode = "P"; else if(iPublicity == RHS_HOUSE_PUBLICITY_TYPE_TRUSTEES) sPublicityCode = "T"; // Remove any existing data about the player's house string sSQL = "DELETE FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " WHERE Player_ID=" + sPCID + "; "; SQLExecDirect(sSQL); sSQL = "DROP TABLE " + RHS_SCHEMA + "." + RHS_TABLE_FURNITURE + sPCID + "; "; SQLExecDirect(sSQL); sSQL = "DROP TABLE " + RHS_SCHEMA + "." + RHS_TABLE_FRIENDS + sPCID + "; "; SQLExecDirect(sSQL); // Add the new row's information sSQL = "INSERT INTO " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " (Player_ID, House_Name, Character_Name, House_Type, Publicity, Accessible_Until) VALUES ("; sSQL += sPCID + ", '" + sHouseName + "', '" + sCharName + "', " + IntToString(iHouseType) + ", '" + sPublicityCode + "', '" + sAccessibleUntil + "');"; SQLExecDirect(sSQL); // Create the house's furniture and friends tables RHS_CreateFurnitureTable(oPC); RHS_CreateFriendsTable(oPC); // Mark player as having a house SetLocalInt(oDatabase, RHS_PLAYER_HOUSE_RENTED, TRUE); } object RHS_GetAreaInstance(int iOwnerID, string sAreaResref) { object oArea; object oModule = GetModule(); string sArray = RHS_HOUSE_INSTANCE_PREFIX + sAreaResref; int iCurArea = 1; do { oArea = GetLocalArrayObject(oModule, sArray, iCurArea); // Found it - return the area if(GetLocalInt(oArea, RHS_IN_USE_ID) == iOwnerID) { return oArea; } iCurArea++; }while(GetIsObjectValid(oArea)); // Didn't find the area - return OBJECT_INVALID return OBJECT_INVALID; } void RHS_RemovePlayerHouse(object oPC, int iGold = 0) { object oModule = GetModule(); object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); int iHouseType = StringToInt(GetMySQLData(RHS_TABLE_HOUSES, "House_Type", iPCID, "Player_ID", RHS_SCHEMA)); string sPCID = IntToString(iPCID); string sAreaResref = GetMySQLData(RHS_TABLE_HOUSE_TYPES, "Resref", iHouseType, "ID", RHS_SCHEMA); // Grab the area currently used by the instance object oArea = RHS_GetAreaInstance(iPCID, sAreaResref); // If the area is valid, kick everyone inside out and make the house vacant if(GetIsObjectValid(oArea)) { //SendMessageToPC(oPC, "House instance is valid"); // DEBUG // Make the house vacant DeleteLocalInt(oArea, RHS_IN_USE_ID); // Find all players in the instance area and kick them out object oPlayerInInstance = GetFirstPC(); while(GetIsObjectValid(oPlayerInInstance)) { // If the player's area matches the instance area boot the player out of the house if(GetArea(oPlayerInInstance) == oArea && !GetIsDM(oPC)) { object oPlayerInInstanceDatabase = GetItemPossessedBy(oPlayerInInstance, PC_DATABASE); string sPlayerInInstanceOriginalLocation = GetLocalString(oPlayerInInstanceDatabase, RHS_PLAYER_ORIGINAL_POSITION); location lPlayerInInstanceOriginalLocation = APSStringToLocation(sPlayerInInstanceOriginalLocation); FloatingTextStringOnCreature(ColorTokenRed() + "The owner of this " + RHS_HOUSE_TERM_LOWER + " has moved out. You have been kicked out." + ColorTokenEnd(), oPlayerInInstance, FALSE); AssignCommand(oPlayerInInstance, ActionJumpToLocation(lPlayerInInstanceOriginalLocation)); } oPlayerInInstance = GetNextPC(); } } // Remove from global houses table string sSQL = "DELETE FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " WHERE Player_ID=" + sPCID + ";"; SQLExecDirect(sSQL); // Remove house's specific tables sSQL = "DROP TABLE " + RHS_SCHEMA + "." + RHS_TABLE_FURNITURE + sPCID + ";"; SQLExecDirect(sSQL); sSQL = "DROP TABLE " + RHS_SCHEMA + "." + RHS_TABLE_FRIENDS + sPCID + ";"; SQLExecDirect(sSQL); // Remove information from oPC DeleteLocalInt(oDatabase, RHS_PLAYER_HOUSE_RENTED); // If gold was passed through, give oPC that money AssignCommand(oPC, GiveGoldToCreature(oPC, iGold)); } void RHS_SellAllFurniture(object oPC) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); // Safety check - ensure that iPCID is greater than 0. Otherwise, bail out if(iPCID <= 0) return; string sPCID = IntToString(iPCID); string sTable = RHS_TABLE_FURNITURE + sPCID; // Calculate and give the gold value to oPC int iGold = RHS_CalculateTotalFurnitureValue(OBJECT_INVALID, iPCID); AssignCommand(oPC, GiveGoldToCreature(oPC, iGold)); // Check if there's a house instance created for oPC's house object oModule = GetModule(); // Look for the area instance int iHouseType = StringToInt(GetMySQLData(RHS_TABLE_HOUSES, "House_Type", iPCID, "Player_ID", RHS_SCHEMA)); string sAreaResref = GetMySQLData(RHS_TABLE_HOUSE_TYPES, "Resref", iHouseType, "ID", RHS_SCHEMA); object oArea = RHS_GetAreaInstance(iPCID, sAreaResref); // Area was found - destroy all of the furniture in that area if(GetIsObjectValid(oArea)) { object oFurniture = GetFirstObjectInArea(oArea); while(GetIsObjectValid(oFurniture)) { // Don't destroy anything that isn't a furniture object // We use the furniture's unique ID number to confirm this if(GetLocalInt(oFurniture, RHS_FURNITURE_ID_NUMBER) > 0) { DestroyObject(oFurniture); } oFurniture = GetNextObjectInArea(oArea); } } // Now delete all the furniture information from the table string sSQL = "DELETE FROM " + RHS_SCHEMA + "." + sTable + ";"; SQLExecDirect(sSQL); } void RHS_SetHousePublicity(object oPC, int iPublicity = RHS_HOUSE_PUBLICITY_TYPE_PRIVATE) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPCID = IntToString(iPCID); // Convert publicity to the correct code string sPublicity = "O"; if(iPublicity == RHS_HOUSE_PUBLICITY_TYPE_FRIENDS) { sPublicity = "F"; } else if(iPublicity == RHS_HOUSE_PUBLICITY_TYPE_PUBLIC) { sPublicity = "P"; } else if(iPublicity == RHS_HOUSE_PUBLICITY_TYPE_TRUSTEES) { sPublicity = "T"; } string sSQL = "UPDATE " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " SET Publicity='" + sPublicity + "' WHERE Player_ID=" + sPCID + ";"; SQLExecDirect(sSQL); } void RHS_SetHouseName(object oPC, string sNewName = "") { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPCID = IntToString(iPCID); // If blank, default to "oPC's House" if(sNewName == "") sNewName = GetName(oPC) + "'s " + RHS_HOUSE_TERM_PROPER; sNewName = SQLEncodeSpecialChars(sNewName); string sSQL = "UPDATE " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " SET House_Name='" + sNewName + "' WHERE Player_ID=" + sPCID + ";"; SQLExecDirect(sSQL); } void RHS_ExtendHouseRent(object oPC, int iDays, int iPCID = -1) { // Can't pass anything less than 1 as an extension if(iDays <= 0) return; // If oPC is valid and iPCID wasn't passed as a parameter, get the PC ID from oPC if(GetIsObjectValid(oPC) && iPCID <= 0) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); } // Safety check - ensure that iPCID is greater than 0. Otherwise, bail out if(iPCID <= 0) return; string sPCID = IntToString(iPCID); // I'm sure there's a better way to do this but I don't know SQL that well int iUnixTime; int iCurrentUnixTime; string sSQL = "SELECT UNIX_TIMESTAMP(Accessible_Until), UNIX_TIMESTAMP() FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " WHERE Player_ID=" + sPCID; SQLExecDirect(sSQL); while(SQLFetch() == SQL_SUCCESS) { iUnixTime = StringToInt(SQLGetData(1)); iCurrentUnixTime = StringToInt(SQLGetData(2)); } // Add time on to the current extension date if(iCurrentUnixTime < iUnixTime) { // Add the number of days to the accessible_until date iUnixTime += iDays * RWT_NUMBER_OF_SECONDS_IN_DAY; } // Rent payment has expired - new payments update time to now plus the number of days extended else { iUnixTime = iCurrentUnixTime + (iDays * RWT_NUMBER_OF_SECONDS_IN_DAY); } // Update it in the table sSQL = "UPDATE " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " SET Accessible_Until=FROM_UNIXTIME(" + IntToString(iUnixTime) + ") WHERE Player_ID=" + IntToString(iPCID) + ";"; SQLExecDirect(sSQL); } void RHS_AddFurniture(object oPC, object oFurniture, int iPCID = -1) { if(iPCID <= 0) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); } // Check friend ID number again - if it's less than or equal to zero at this point bail out. if(iPCID <= 0) return; vector vPosition = GetPosition(oFurniture); string sPCID = IntToString(iPCID); string sTable = RHS_TABLE_FURNITURE + sPCID; string sName = SQLEncodeSpecialChars(GetName(oFurniture)); string sTag = SQLEncodeSpecialChars(GetTag(oFurniture)); string sResref = SQLEncodeSpecialChars(GetResRef(oFurniture)); string sPositionX = FloatToString(vPosition.x); string sPositionY = FloatToString(vPosition.y); string sPositionZ = FloatToString(vPosition.z); string sFacing = FloatToString(GetFacing(oFurniture)); string sSQL = "INSERT INTO " + RHS_SCHEMA + "." + sTable + " (Name, Tag, Resref, Position_X, Position_Y, Position_Z, Facing, Timestamp) VALUES ('"; sSQL += sName + "', '" + sTag + "', '" + sResref + "', '" + sPositionX + "', '" + sPositionY + "', '" + sPositionZ + "', '" + sFacing + "', CURRENT_TIMESTAMP);"; SQLExecDirect(sSQL); sSQL = "SELECT LAST_INSERT_ID();"; SQLExecDirect(sSQL); // Mark the furniture's ID number if(SQLFetch() == SQL_SUCCESS) { SetLocalInt(oFurniture, RHS_FURNITURE_ID_NUMBER, StringToInt(SQLGetData(1))); } // Always make the furniture plot (I.E: Unable to be destroyed) SetPlotFlag(oFurniture, TRUE); // If the object is listed as "useable" in the furniture types table, make sure this object is marked as useable too int bUseable = StringToInt(GetMySQLDataKeyString(RHS_TABLE_FURNITURE_TYPES, "Useable", sResref, "Resref", RHS_SCHEMA)); if(bUseable) { SetUseableFlag(oFurniture, TRUE); } else { SetUseableFlag(oFurniture, FALSE); } } void RHS_RemoveFurniture(object oPC, object oFurniture, int iPCID = -1) { if(iPCID <= 0) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); } // Check friend ID number again - if it's less than or equal to zero at this point bail out. if(iPCID <= 0) return; int iFurnitureID = GetLocalInt(oFurniture, RHS_FURNITURE_ID_NUMBER); string sPCID = IntToString(iPCID); string sFurnitureID = IntToString(iFurnitureID); string sTable = RHS_TABLE_FURNITURE + sPCID; string sSQL = "DELETE FROM " + RHS_SCHEMA + "." + sTable + " WHERE ID=" + sFurnitureID; SQLExecDirect(sSQL); } void RHS_AddFriend(object oPC, int iFriendID = -1, object oFriend = OBJECT_INVALID, int iSetting = RHS_HOUSE_FRIEND_TYPE_FRIEND) { // Invalid parameters were passed, can't continue so bail out if(iFriendID <= 0 && oFriend == OBJECT_INVALID) return; if(iFriendID <= 0) { object oFriendDatabase = GetItemPossessedBy(oFriend, PC_DATABASE); iFriendID = GetLocalInt(oFriendDatabase, PC_ID_NUMBER); } // Check friend ID number again - if it's less than or equal to zero at this point bail out. if(iFriendID <= 0) return; // By this point we've got the friend's ID number. We can go ahead and input it into the friends table object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPCID = IntToString(iPCID); string sFriendID = IntToString(iFriendID); string sTable = RHS_TABLE_FRIENDS + sPCID; string sSetting; // Convert friend types if(iSetting == RHS_HOUSE_FRIEND_TYPE_TRUSTEE) sSetting = "T"; else sSetting = "F"; // **************************************************************************************** // NOTE: Add the 'Name' field after you figure out how to refer to info in another table ** // **************************************************************************************** string sSQL = "DELETE FROM " + RHS_SCHEMA + "." + sTable + " WHERE ID=" + sFriendID + ";"; SQLExecDirect(sSQL); sSQL = "INSERT INTO " + RHS_SCHEMA + "." + sTable + " (ID, Setting) VALUES (" + sFriendID + ", '" + sSetting + "');"; SQLExecDirect(sSQL); } void RHS_RemoveFriend(object oPC, int iFriendID = -1, object oFriend = OBJECT_INVALID) { // Invalid parameters were passed, can't continue so bail out if(iFriendID <= 0 && oFriend == OBJECT_INVALID) return; if(iFriendID <= 0) { object oFriendDatabase = GetItemPossessedBy(oFriend, PC_DATABASE); iFriendID = GetLocalInt(oFriendDatabase, PC_ID_NUMBER); } // Check friend ID number again - if it's less than or equal to zero at this point bail out. if(iFriendID <= 0) return; object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPCID = IntToString(iPCID); string sFriendID = IntToString(iFriendID); string sTable = RHS_TABLE_FRIENDS + sPCID; string sSQL = "DELETE FROM " + RHS_SCHEMA + "." + sTable + " WHERE ID=" + sFriendID; SQLExecDirect(sSQL); } void RHS_CreateFurnitureTable(object oPC) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPCID = IntToString(iPCID); string sSQL = "CREATE TABLE " + RHS_SCHEMA + "." + RHS_TABLE_FURNITURE + sPCID + " LIKE " + RHS_SCHEMA + "." + RHS_TABLE_FURNITURE_TEMPLATE; SQLExecDirect(sSQL); } void RHS_CreateFriendsTable(object oPC) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPCID = IntToString(iPCID); string sSQL = "CREATE TABLE " + RHS_SCHEMA + "." + RHS_TABLE_FRIENDS + sPCID + " LIKE " + RHS_SCHEMA + "." + RHS_TABLE_FRIENDS_TEMPLATE; SQLExecDirect(sSQL); } void RHS_LoadHouseFurniture(object oPC, object oAreaInstance, int iPCID = -1) { // If oPC is valid and iPCID wasn't passed as a parameter, get the PC ID from oPC if(GetIsObjectValid(oPC) && iPCID <= 0) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); } // Safety check - ensure that iPCID is greater than 0. Otherwise, bail out if(iPCID <= 0) return; string sPCID = IntToString(iPCID); // Spawn furniture string sSQL = "SELECT ID, Resref, Position_X, Position_Y, Position_Z, Facing FROM " + RHS_SCHEMA + "." + RHS_TABLE_FURNITURE + sPCID; SQLExecDirect(sSQL); while(SQLFetch() == SQL_SUCCESS) { int iFurnitureID = StringToInt(SQLGetData(1)); string sResref = SQLGetData(2); vector vPosition = Vector(StringToFloat(SQLGetData(3)), StringToFloat(SQLGetData(4)), StringToFloat(SQLGetData(5))); location lLocation = Location(oAreaInstance, vPosition, StringToFloat(SQLGetData(6))); object oFurniture = CreateObject(OBJECT_TYPE_PLACEABLE, sResref, lLocation); SetLocalInt(oFurniture, RHS_FURNITURE_ID_NUMBER, iFurnitureID); // Make unusable - temporary until I set up usability options SetUseableFlag(oFurniture, FALSE); // Make the furniture not able to be destroyed by normal means SetPlotFlag(oFurniture, TRUE); } } object RHS_CreateHouseInstance(object oPC, int iPCID = -1, string sHouseName = "", int bPreviewArray = FALSE, int iHouseType = -1) { object oModule = GetModule(); object oArea = OBJECT_INVALID; string sHouseResref; string sSQL; // If oPC is valid and iPCID wasn't passed as a parameter, get the PC ID from oPC if(GetIsObjectValid(oPC) && iPCID <= 0) { object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); } // Safety check - ensure that iPCID is greater than 0. Otherwise, bail out if(iPCID <= 0) return oArea; string sPCID = IntToString(iPCID); if(iHouseType <= 0) { sSQL = "SELECT House_Name, House_Type FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " WHERE Player_ID=" + sPCID + ";"; SQLExecDirect(sSQL); while(SQLFetch() == SQL_SUCCESS) { // Only use the one in the database if a house name wasn't passed for this function if(sHouseName == "") sHouseName = SQLDecodeSpecialChars(SQLGetData(1)); iHouseType = StringToInt(SQLGetData(2)); } // Safety check - ensure house ID is at least 1 if(iHouseType <= 0) return oArea; } sSQL = "SELECT Resref FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSE_TYPES + " WHERE ID=" + IntToString(iHouseType) + ";"; SQLExecDirect(sSQL); while(SQLFetch() == SQL_SUCCESS) { sHouseResref = SQLDecodeSpecialChars(SQLGetData(1)); } // Safety check - ensure house resref is not null if(sHouseResref == "") return oArea; // We've got the necessary data - create the area instance oArea = CreateArea(sHouseResref); // Set the area's name SetAreaName(oArea, sHouseName); // Find an open index number for the array for this house int iIndex = 0; object oArrayArea; do { iIndex++; oArrayArea = GetLocalArrayObject(oModule, RHS_HOUSE_INSTANCE_PREFIX + sHouseResref, iIndex); }while(GetIsObjectValid(oArrayArea)); //SendMessageToPC(oPC, "DEBUG: iIndex = " + IntToString(iIndex)); // DEBUG // Add instance to array of instances SetLocalArrayObject(oModule, RHS_HOUSE_INSTANCE_PREFIX + sHouseResref, iIndex, oArea); // Mark owner's ID number on the instanced area - previews do not get this set if(!bPreviewArray) SetLocalInt(oArea, RHS_HOUSE_OWNER_ID_NUMBER, iPCID); // Mark the entry waypoint on the area object oEntry = GetFirstObjectInArea(oArea); while(GetIsObjectValid(oEntry)) { // oEntry matches the entry waypoint - store the location of the waypoint on the area // and break out of the loop. if(GetResRef(oEntry) == RHS_HOUSE_WAYPOINT_RESREF) { location lEntryLocation = GetLocation(oEntry); SetLocalLocation(oArea, RHS_HOUSE_ENTRY_WAYPOINT, lEntryLocation); break; } oEntry = GetNextObjectInArea(oArea); } return oArea; } void RHS_PreviewHouse(object oPC, int iHouseType, string sHouseName = "") { object oModule = GetModule(); string sResref; string sSQL = "SELECT Name, Resref FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSE_TYPES + " WHERE ID=" + IntToString(iHouseType) + ";"; SQLExecDirect(sSQL); if(SQLFetch() == SQL_SUCCESS) { // Add (PREVIEW) to beginning of area's name, if no name was passed through if(sHouseName == "") { sHouseName = "(PREVIEW) " + SQLDecodeSpecialChars(SQLGetData(1)); } sResref = SQLGetData(2); } // Something messed up - inform player else { SendMessageToPC(oPC, ColorTokenRed() + "ERROR: Resref and name of area instance could not be found. Ensure MySQL is running correctly." + ColorTokenEnd()); return; } // Look for a vacant area instance and use it, if it exists object oArea; int iIndex = 1; int bFoundArea = FALSE; do { oArea = GetLocalArrayObject(oModule, RHS_HOUSE_INSTANCE_PREFIX + sResref, iIndex); //SendMessageToPC(oPC, "Index = " + IntToString(iIndex) + ", In Use ID = " + IntToString(GetLocalInt(oArea, RHS_IN_USE_ID))); // DEBUG if(GetLocalInt(oArea, RHS_IN_USE_ID) == 0) { int bFoundArea = TRUE; break; } iIndex++; }while(GetIsObjectValid(oArea) && !bFoundArea); // No instances are vacant - create a new one if(!GetIsObjectValid(oArea)) { //SendMessageToPC(oPC, "Firing RHS_CreateHouseInstance dude"); // DEBUG oArea = RHS_CreateHouseInstance(oPC, -1, sHouseName, TRUE, iHouseType); } object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); location lLocation = GetLocalLocation(oArea, RHS_HOUSE_ENTRY_WAYPOINT); AssignCommand(oPC, ActionJumpToLocation(lLocation)); SetLocalInt(oArea, RHS_HOUSE_OWNER_ID_NUMBER, iPCID); SetLocalInt(oArea, RHS_IN_USE_ID, iPCID); // Store the player's original location - for later use when they leave the instance area location lOriginalLocation = GetLocation(oPC); string sOriginalLocation = APSLocationToString(lOriginalLocation); SetLocalString(oDatabase, RHS_PLAYER_ORIGINAL_POSITION, sOriginalLocation); } void RHS_EnterHouse(object oPC, object oOwner = OBJECT_INVALID, int iOwnerID = -1, string sHouseName = "") { // If oPC is valid and iPCID wasn't passed as a parameter, get the PC ID from oPC if(GetIsObjectValid(oOwner) && iOwnerID <= 0) { object oDatabase = GetItemPossessedBy(oOwner, PC_DATABASE); iOwnerID = GetLocalInt(oDatabase, PC_ID_NUMBER); } // Safety check - ensure that iOwnerID is greater than 0. Otherwise, bail out if(iOwnerID <= 0) return; string sOwnerID = IntToString(iOwnerID); object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); string sPublicitySetting; int iHouseType; // Fire SQL to get Publicity level and area Resref string sSQL = "SELECT Publicity, House_Type FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " WHERE Player_ID=" + sOwnerID + ";"; SQLExecDirect(sSQL); if(SQLFetch() == SQL_SUCCESS) { sPublicitySetting = SQLGetData(1); iHouseType = StringToInt(SQLGetData(2)); } int iFriendLevel = RHS_IsPlayerFriend(OBJECT_INVALID, OBJECT_INVALID, iPCID, iOwnerID); // Owner only setting if(sPublicitySetting == "O" && oPC != oOwner) { FloatingTextStringOnCreature(ColorTokenRed() + "The owner of that " + RHS_HOUSE_TERM_LOWER + " has set his or her privacy setting to 'Owner Only'. You cannot enter." + ColorTokenEnd(), oPC, FALSE); return; } // Friends only setting else if(sPublicitySetting == "F" && oPC != oOwner) { // Check if oPC is on the list of friends if(iFriendLevel == RHS_FRIEND_TYPE_INVALID) { FloatingTextStringOnCreature(ColorTokenRed() + "The owner of that " + RHS_HOUSE_TERM_LOWER + " has set his or her privacy setting to 'Friends Only'. You cannot enter because you are not set as a friend." + ColorTokenEnd(), oPC, FALSE); return; } } // Trustees only setting else if(sPublicitySetting == "T" && oPC != oOwner) { // Check if oPC is on the list of friends AND is a trustee if(iFriendLevel != RHS_FRIEND_TYPE_TRUSTEE) { FloatingTextStringOnCreature(ColorTokenRed() + "The owner of that " + RHS_HOUSE_TERM_LOWER + " has set his or her privacy setting to 'Trustees Only'. You cannot enter because you are not set as a trustee." + ColorTokenEnd(), oPC, FALSE); return; } } object oModule = GetModule(); string sAreaResref = GetMySQLData(RHS_TABLE_HOUSE_TYPES, "Resref", iHouseType, "ID", RHS_SCHEMA); // Look for the current house instance in use int iCurArea = 1; object oArea; do { oArea = GetLocalArrayObject(oModule, RHS_HOUSE_INSTANCE_PREFIX + sAreaResref, iCurArea); // The house we found is currently in use. Send the PC to this area if(GetLocalInt(oArea, RHS_IN_USE_ID) == iOwnerID) { break; } iCurArea++; }while(GetIsObjectValid(oArea)); // No house instance was found to be in use. Find the first open area if(!GetIsObjectValid(oArea)) { do { oArea = GetLocalArrayObject(oModule, RHS_HOUSE_INSTANCE_PREFIX + sAreaResref, iCurArea); if(GetLocalInt(oArea, RHS_IN_USE_ID) == 0) { break; } iCurArea++; }while(GetIsObjectValid(oArea)); } // No house instances are open - create a new instance if(!GetIsObjectValid(oArea)) { // Create instance and mark the entry location oArea = RHS_CreateHouseInstance(OBJECT_INVALID, iOwnerID, sHouseName); // Safety check - don't want to create non-existant areas if(GetIsObjectValid(oArea)) { // Spawn the owner's furniture in the house RHS_LoadHouseFurniture(OBJECT_INVALID, oArea, iOwnerID); } } // Otherwise rename the area else { SetAreaName(oArea, sHouseName); } // Mark the owner ID who is currently using this area SetLocalInt(oArea, RHS_IN_USE_ID, iOwnerID); SetLocalInt(oArea, RHS_HOUSE_OWNER_ID_NUMBER, iOwnerID); // By this point we know which area to send the player to. Store the PC's current location and // then go ahead and send him or her inside // Store the player's original location - for later use when they leave the instance area location lOriginalLocation = GetLocation(oPC); string sOriginalLocation = APSLocationToString(lOriginalLocation); SetLocalString(oDatabase, RHS_PLAYER_ORIGINAL_POSITION, sOriginalLocation); // Send the player into the instanced house AssignCommand(oPC, ActionJumpToLocation(GetLocalLocation(oArea, RHS_HOUSE_ENTRY_WAYPOINT))); } void RHS_OnPlayerChat() { object oPC = GetPCChatSpeaker(); string sMessage = GetPCChatMessage(); int bListening = GetLocalInt(oPC, RHS_PAGE_TEMP_LISTENING); // Remove temporary variables and inform player they need to hit the next button on the conversation menu if(bListening) { SetLocalString(oPC, RHS_PAGE_TEMP_NEW_HOUSE_NAME, sMessage); DeleteLocalInt(oPC, RHS_PAGE_TEMP_LISTENING); SetPCChatMessage(""); FloatingTextStringOnCreature(ColorTokenGreen() + "New name set! Press 'Finish Entering New " + RHS_HOUSE_TERM_PROPER + " Name' to continue." + ColorTokenEnd(), oPC, FALSE); } } int RHS_IsPlayerFriend(object oFriend, object oOwner, int iFriendID = -1, int iOwnerID = -1) { // If oFriend is valid and iFriendID wasn't passed as a parameter, get the Friend ID from oFriend if(GetIsObjectValid(oFriend) && iFriendID <= 0) { object oDatabase = GetItemPossessedBy(oFriend, PC_DATABASE); iFriendID = GetLocalInt(oDatabase, PC_ID_NUMBER); } if(iFriendID <= 0) return RHS_FRIEND_TYPE_INVALID; // Do the same for the owner if(GetIsObjectValid(oOwner) && iOwnerID <= 0) { object oDatabase = GetItemPossessedBy(oOwner, PC_DATABASE); iOwnerID = GetLocalInt(oDatabase, PC_ID_NUMBER); } if(iOwnerID <= 0) return RHS_FRIEND_TYPE_INVALID; string sFriendID = IntToString(iFriendID); string sOwnerID = IntToString(iOwnerID); string sSQL = "SELECT Setting FROM " + RHS_SCHEMA + "." + RHS_TABLE_FRIENDS + sOwnerID + " WHERE ID=" + sFriendID + ";"; SQLExecDirect(sSQL); while(SQLFetch() == SQL_SUCCESS) { return StringToInt(SQLGetData(1)); } // If we make it to this point, they're either not listed or something went wrong. Default to RHS_FRIEND_TYPE_INVALID return RHS_FRIEND_TYPE_INVALID; } void RHS_OnDoorAreaTransitionClick() { object oPC = GetClickingObject(); if(GetIsDM(oPC)) return; object oDoor = OBJECT_SELF; object oModule = GetModule(); object oArea = GetArea(oDoor); object oDatabase = GetItemPossessedBy(oPC, PC_DATABASE); string sLocation = GetLocalString(oDatabase, RHS_PLAYER_ORIGINAL_POSITION); location lLocation = APSStringToLocation(sLocation); int bDestroyArea = TRUE; //int iPCID = GetLocalInt(oDatabase, PC_ID_NUMBER); int iOwnerID = GetLocalInt(oArea, RHS_HOUSE_OWNER_ID_NUMBER); AssignCommand(oPC, ActionJumpToLocation(lLocation)); object oCurPlayer = GetFirstPC(); while(GetIsObjectValid(oCurPlayer)) { // Just in case the PC leaving the area is picked up // Or a DM was picked up if(oCurPlayer != oPC && !GetIsDM(oPC)) { // If the current player is in the instance area, we don't want to destroy it if(GetArea(oCurPlayer) == oArea) { bDestroyArea = FALSE; break; } } oCurPlayer = GetNextPC(); } // No one in the instance - mark this area as vacant, ready for the next person's use // Also destroy all furniture if(bDestroyArea) { object oCurFurniture = GetFirstObjectInArea(oArea); while(GetIsObjectValid(oCurFurniture)) { if(GetLocalInt(oCurFurniture, RHS_FURNITURE_ID_NUMBER) > 0) { RHS_ClearInventory(oCurFurniture); DestroyObject(oCurFurniture); } oCurFurniture = GetNextObjectInArea(oArea); } if(GetIsObjectValid(oArea)) { //SendMessageToPC(oPC, "Destroying area instance"); // DEBUG //DestroyArea(oArea); // Removed because the server seg-faults if an area is destroyed } DeleteLocalInt(oArea, RHS_IN_USE_ID); DeleteLocalInt(oArea, RHS_HOUSE_OWNER_ID_NUMBER); } } int RHS_IsRentPaid(object oOwner, int iOwnerID = -1) { int bRentPaid = FALSE; // If oOwner is valid and iOwnerID wasn't passed as a parameter, get the Owner ID from oOwner if(GetIsObjectValid(oOwner) && iOwnerID <= 0) { object oDatabase = GetItemPossessedBy(oOwner, PC_DATABASE); iOwnerID = GetLocalInt(oDatabase, PC_ID_NUMBER); } if(iOwnerID <= 0) return -1; string sOwnerID = IntToString(iOwnerID); string sSQL = "SELECT UNIX_TIMESTAMP(), UNIX_TIMESTAMP(Accessible_Until) FROM " + RHS_SCHEMA + "." + RHS_TABLE_HOUSES + " WHERE Player_ID=" + sOwnerID + ";"; SQLExecDirect(sSQL); while(SQLFetch() == SQL_SUCCESS) { int iUnixTime = StringToInt(SQLGetData(1)); int iAccessibleUnix = StringToInt(SQLGetData(2)); if(iUnixTime >= iAccessibleUnix) bRentPaid = FALSE; else bRentPaid = TRUE; } return bRentPaid; } int RHS_CalculateTotalFurnitureValue(object oOwner, int iOwnerID = -1) { // If oOwner is valid and iOwnerID wasn't passed as a parameter, get the Owner ID from oOwner if(GetIsObjectValid(oOwner) && iOwnerID <= 0) { object oDatabase = GetItemPossessedBy(oOwner, PC_DATABASE); iOwnerID = GetLocalInt(oDatabase, PC_ID_NUMBER); } if(iOwnerID <= 0) return -1; string sOwnerID = IntToString(iOwnerID); int iGold; string sTable = RHS_SCHEMA + "." + RHS_TABLE_FURNITURE + sOwnerID; string sSQL = "SELECT SUM(Gold_Cost) FROM " + RHS_SCHEMA + "." + RHS_TABLE_FURNITURE_TYPES + ", " + sTable + " WHERE "; sSQL += RHS_TABLE_FURNITURE_TYPES + ".Resref = " + sTable + ".Resref;"; SQLExecDirect(sSQL); while(SQLFetch() == SQL_SUCCESS) { iGold = StringToInt(SQLGetData(1)); iGold = FloatToInt(iGold * RHS_FURNITURE_SELL_BACK_PERCENTAGE); } return iGold; } void RHS_OnModuleEnter() { object oPC = GetEnteringObject(); if(!GetIsPC(oPC) || GetIsDM(oPC)) return; if(!GetIsObjectValid(GetItemPossessedBy(oPC, RHS_FURNITURE_TOOL_RESREF))) { CreateItemOnObject(RHS_FURNITURE_TOOL_RESREF, oPC, 1); } } void RHS_ClearInventory(object oObject) { object oInventory = GetFirstItemInInventory(oObject); while(GetIsObjectValid(oInventory)) { DestroyObject(oInventory); oInventory = GetNextItemInInventory(oObject); } } // Error checking void main(){}