Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Firstly, we have to include the samp include, the streamer include,
- the ZCMD include and create our variables. For SQLite, we must have a
- variable to store the database, the database result and the format
- string for our query. DB tag is connected to the database variable and
- the DBResult is connected to the query result.
- */
- #include <a_samp>
- #include <zcmd>
- #include <streamer>
- new DB:database, DBResult:queryresult, fquery[300];
- /*
- Below are some defines that we are using so that we can edit them
- easily any time we want. We have the define MAX_HOUSES that is used
- for creating the houseinformation variable. It's good to have this close
- to the amount of houses you use because the less MAX_HOUSES, the smaller
- the variable and the smaller AMX size. MAX_HOUSES_PER_PLAYER is used later
- in our script to define the max houses a single player can have. Lastly, the
- databasename define defines the name of our database. It should have .db on
- the end as well as the quotes.
- */
- #define MAX_HOUSES 300 //MAX_HOUSES is currently 300.
- #define MAX_HOUSES_PER_PLAYER 2 //MAX_HOUSES_PER_PLAYER is currently 2
- #define databasename "housedb.db" //The Databasename is currently housedb.db
- /*
- We need to now create our enum and the house information variable
- that stores all the information so that we do not need to query the
- SQLite database every time we want to check house information. We use
- a enum so that we don't have to have multiple variables, we can just use
- one. The owner variable in the enum stores the owners name if there is a
- owner of the house. Hname represents the house name, it must be different
- to all of the other house names because it is used as our ID to get information
- such as owner information from the database. Costprice is going to store the cost
- price of the house, pretty self explanatory. EnterPos[3] is going to store the
- house checkpoint position that will show if the player is close enough to
- the house. The 3 cells on the end of EnterPos[3] represents the X Position,
- the Y Position and the Z position. TelePos is similar to the EnterPos. It just
- is the position that we are sent to if we enter the house. The sellprice variable
- is also very self explanatory, it allows us to /sell our house later on in the
- tutorial for the price that you have defined. The interiors variable allows us
- to set the interior of the player when the teleports inside. Lastly in our enum
- comes the checkpointid. The textid variable stores the textid (information 3D text
- label that is outside of our house. I've changed it from gametext to 3D text labels
- in this tutorial because it looks better and it is way easier.
- The checkpointid stores the checkpoint number that our streamer
- has given us. We will use it later to find if the player is near a house / can enter it
- or if the player is inside the house and enters the checkpoint to exit the house.
- The HouseInformation variable is pretty much all of these variable mixed together.
- You can have a maximum amount of houses (Defined above) with the information in
- the enum. The variable houseid shows us what houseid we are currently up to. It
- tells us what the next empty slot to store information in is. The InHouse variable
- pretty much tells us if the player is in a house or not. We will use this later for
- the /sell command and also you can use it somewhere else in your script if needed.
- Lastly, the InHouseCP variable is used to store if the player is in a house checkpoint
- or not. This is if they want to buy the house so we don't have to call multiple loops,
- only one.
- */
- enum hinfo
- {
- owner[24],
- Hname[100],
- costprice,
- Float:EnterPos[3],
- Float:TelePos[3],
- sellprice,
- interiors,
- Text3D:textid,
- checkpointidx[2]
- };
- new HouseInformation[MAX_HOUSES][hinfo], houseid;
- new InHouse[MAX_PLAYERS], InHouseCP[MAX_PLAYERS];
- /*
- First thing is first, we need to have the following two lines under OnGameModeInit
- under OnFilterScriptInit. We need to firstly use the db_open function to connect
- our samp server with the SQLite database. We use the database variable above to save
- our database number in it. Secondly we need to make our table if it doesn't exist.
- You do not need to keep that line in because it only needs to be called once. The
- db_query function allows us to GET / STORE / SET information in our database. In this
- case, we are creating our table. The table allows us to store information in and can
- be used to add more functions like lets say a house car. For this tutorial, we are only
- using it to store the owners name.
- */
- public OnFilterScriptInit()
- {
- database = db_open(databasename);
- db_query(database, "CREATE TABLE IF NOT EXISTS `HOUSEINFO` (housename varchar(51), houseowner varchar(25))");
- CreateHouse("TestHouse1", 1, 2317.130615, 692.398498, 11.460937, 266.857757, 305.001586, 999.148437, 2, 1);
- CreateHouse("TestHouse2", 1, 2346.872802, 692.999267, 11.460937, 266.857757, 305.001586, 999.148437, 2, 1);
- CreateHouse("TestHouse3", 1, 2396.482666, 691.487060, 11.453125, 2196.850341, -1204.343261, 1049.023437, 6, 1);
- CreateHouse("TestHouse4", 1, 2398.476074, 735.344665, 11.460937, 2196.850341, -1204.343261, 1049.023437, 6, 1);
- CreateHouse("TestHouse5", 1, 2368.863525, 733.627502, 11.460937, 2196.850341, -1204.343261, 1049.023437, 6, 1);
- CreateHouse("TestHouse6", 1, 2013.253906, 731.041870, 11.453125, 266.857757, 305.001586, 999.148437, 5, 1);
- CreateHouse("TestHouse7", 1, 2449.826660, 742.588806, 11.460937, 266.857757, 305.001586, 999.148437, 5, 1);
- CreateHouse("TestHouse8", 1, 2449.662353, 714.210693, 11.468292, 266.857757, 305.001586, 999.148437, 5, 1);
- return 1;
- }
- /*
- Now we do the basic job of resetting the variables to -1 (No house id is under this
- variable
- */
- public OnPlayerConnect(playerid)
- {
- InHouse[playerid] = -1;
- InHouseCP[playerid] = -1;
- return 1;
- }
- /*
- Time to get started on the harder stuff! We are going to make our function that creates
- our houses. It will also query our database to see if there is anyone that owns the
- house. We will be using a stock function that creates a single line that we can use to
- store all of the information at once. The format of our stock is
- CreateHouse(HouseName[], CostP, Float:EnterX, Float:EnterY, Float:EnterZ, Float:TeleX, Float:TeleY, Float:TeleZ, SellP, Interiorx)
- HouseName[] - The unique house name that you have chosen for the house (Ex: "Big Mansion5")
- CostP - The Cost price of the house (Ex: 500000)
- Float:EnterX - The X entry point of the house, it will also be where the outside checkpoint will be (Ex: 1264.53433)
- Float:EnterY - The Y entry point of the house, it will also be where the outside checkpoint will be (Ex: 2625.6436)
- Float:EnterZ - The Z entry point of the house, it will also be where the outside checkpoint will be (Ex: 200.532)
- Float:TeleX - The X teleport that teleports the player into the interior (Ex: 432.4234)
- Float:TeleY - The Y teleport that teleports the player into the interior (Ex: 4216.4152)
- Float:TeleZ - The Z teleport that teleports the player into the interior (Ex: 10.53672)
- SellP - It's the selling price that the owner can sell the house for (Ex: 200000)
- Interiorx - The interior ID of the interior that we will teleport to.
- This is just pretty much basic setting the variables into our enum for most of it. When
- it queries the database down the bottom, what we are doing is finding if the house has
- a owner, if so it will store the owners name into the houseinformation variable. If
- there is no owner for the house, the variable will be left blank. We do this by using
- the SELECT statement.
- SELECT [VARIABLE] FROM [TABLENAME] WHERE [ANOTHER VARIABLE] = [A VALUE]
- VARIABLE = houseowner
- TABLENAME = HOUSEINFO
- ANOTHER VARIABLE = housename
- A VALUE = our house name.
- We then use db_num_rows to check if there has been any rows with our house name that
- we have fetched. If there isn't any rows with the house name (no owner) then we will
- just free the result with db_free_result. If there is a row, we will fetch that value
- using db_get_field_assoc.
- For more information on SQLite, visit http://wiki.sa-mp.com/wiki/SQLite
- We also have to add our enter and exit checkpoints into our script using CreateDynamicCP.
- It creates the checkpoints and stores the IDS into checkpointid[0] for the enter CP and
- checkpointid[1] for the exit CP. We are also going to make our 3D text information
- variable with CreateDynamic3DTextLabel and store it into the variable textid.
- */
- stock CreateHouse(HouseName[], CostP, Float:EnterX, Float:EnterY, Float:EnterZ, Float:TeleX, Float:TeleY, Float:TeleZ, Interiorx, SellP)
- {
- format(HouseInformation[houseid][Hname], 100, "%s", HouseName);
- HouseInformation[houseid][costprice] = CostP;
- HouseInformation[houseid][EnterPos][0] = EnterX;
- HouseInformation[houseid][EnterPos][1] = EnterY;
- HouseInformation[houseid][EnterPos][2] = EnterZ;
- HouseInformation[houseid][TelePos][0] = TeleX;
- HouseInformation[houseid][TelePos][1] = TeleY;
- HouseInformation[houseid][TelePos][2] = TeleZ;
- HouseInformation[houseid][sellprice] = SellP;
- HouseInformation[houseid][interiors] = Interiorx;
- format(fquery, sizeof(fquery), "SELECT houseowner FROM HOUSEINFO WHERE housename = '%s'", HouseName); //Formats the SELECT query
- queryresult = db_query(database, fquery); //Query result variable has been used to query the string above.
- if(db_num_rows(queryresult) != 0) db_get_field_assoc(queryresult, "houseowner", HouseInformation[houseid][owner], 24); //Fetches the field information db_free_result(queryresult);
- HouseInformation[houseid][checkpointidx][0] = CreateDynamicCP(EnterX, EnterY, EnterZ, 1.0);
- //CreateDynamicCP(Float:x, Float:y, Float:z, Float:size);
- HouseInformation[houseid][checkpointidx][1] = CreateDynamicCP(TeleX, TeleY, TeleZ, 1.0, 15500000+houseid, Interiorx);
- //CreateDynamicCP(Float:x, Float:y, Float:z, Float:size, worldid, interiorid);
- if(!HouseInformation[houseid][owner][0]) format(fquery, sizeof(fquery), "House Name: %s \n House Price:$%d \n Sell Price: $%d", HouseName, CostP, SellP);
- //If there is nothing in the owners variable, we check if the first cell doesn't have a character.
- else if(HouseInformation[houseid][owner][0] != 0) format(fquery, sizeof(fquery), "House Name: %s \n Owner: %s", HouseName, HouseInformation[houseid][owner]);
- //If there is something in the owners variable we check if the first cell has a character.
- HouseInformation[houseid][textid] = CreateDynamic3DTextLabel(fquery, 0xFFFFFF, EnterX, EnterY, EnterZ + 0.5, 50.0);
- //CreateDynamic3DTextLabel(const text[], color, Float:x, Float:y, Float:z, Float:drawdistance, attachedplayer = INVALID_PLAYER_ID, attachedvehicle = INVALID_VEHICLE_ID, testlos = 0, worldid = -1, interiorid = -1, playerid = -1, Float:distance = 100.0);
- houseid ++; //We go to the next free slot in our variable.
- return 1;
- }
- /*
- Now we are going to make our small functions that will be used later. They are to
- set and delete the owner of a certain house. We are using two basic SQL queries.
- One being INSERT
- INSERT INTO [TABLENAME] ([FIELD1], [FIELD2]) VALUES ([VALUE1], [VALUE2])
- TABLENAME - HOUSEINFO
- FIELD1 - housename
- FIELD2 - houseowner
- VALUE1 - Our housename value
- VALUE2 - Our houseowner value
- And the other being DELETE
- DELETE FROM [TABLENAME] WHERE [FIELD] = [VALUE]
- TABLENAME - HOUSEINFO
- FIELD - housename
- VALUE - the housename
- Then we set the owners variable to the owners name using format. We then after
- we update the 3DTextLabel's Text to being owned / not being owned. It's the same
- for both of them.
- */
- stock SetOwner(HouseName[], ownername[], houseids)
- {
- format(fquery, sizeof(fquery), "INSERT INTO `HOUSEINFO` (`housename`, `houseowner`) VALUES('%s', '%s')", HouseName, ownername);
- db_query(database, fquery); //Queries the SQLite database.
- format(HouseInformation[houseids][owner], 24, "%s", ownername);
- format(fquery, sizeof(fquery), "House Name: %s \n Owner: %s", HouseName, HouseInformation[houseids][owner]);
- UpdateDynamic3DTextLabelText(HouseInformation[houseids][textid], 0xFFFFFF, fquery); //Updates the text label.
- return 1;
- }
- stock DeleteOwner(HouseName[], houseids)
- {
- format(HouseInformation[houseids][owner], 24, "%s", "\0");
- format(fquery, sizeof(fquery), "DELETE FROM `HOUSEINFO` WHERE `housename` = '%s'", HouseName);
- db_query(database, fquery); //Queries the SQLite database.
- format(fquery, sizeof(fquery), "House Name: %s \n House Price:$%d \n Sell Price: $%d", HouseName, HouseInformation[houseids][costprice], HouseInformation[houseids][sellprice]);
- UpdateDynamic3DTextLabelText(HouseInformation[houseids][textid], 0xFFFFFF, fquery); //Updates the text label.
- return 1;
- }
- /*
- Before we make the /buy and /sell commands, we are going to use the OnPlayerEnterDynamicCheckpoint
- callback to either Set the players position in or outside of the house. We make a loop
- calling every single checkpoint variable in our current houses to see if the checkpoint
- is one of our house checkpoints.
- We firstly check if the player is the owner so he can instantly enter the house.
- If so, we will telepor him to inside the house.
- Then it checks if the owner has a owner and sends a message to the player if there
- is no owner.
- Then it checks if the player is in the exit checkpoint and sets his position outside
- of the house.
- Lastly, we use the callback OnPlayerExitDynamicCP to exit the checkpoint
- */
- public OnPlayerEnterDynamicCP(playerid, checkpointid)
- {
- for(new x; x<houseid; x++) //Loops through all current house ids.
- {
- if(HouseInformation[x][checkpointidx][0] == checkpointid) //If the entry checkpoint is entry checkpoint.
- {
- if(InHouse[playerid] != -1)
- {
- InHouse[playerid] = -1; //Sets the player to outside the house.
- return 1;
- }
- InHouseCP[playerid] = x; //Sets the InHouseCP variable.
- new Pname[24]; //Pname variable.
- GetPlayerName(playerid, Pname, 24); //Gets the players name.
- if(HouseInformation[x][owner][0] != 0 && !strcmp(Pname, HouseInformation[x][owner][0]))
- //The line above checks that the owner string has something in it, then it
- //Will compare it to our current player.
- {
- SetPlayerPos(playerid, HouseInformation[x][TelePos][0], HouseInformation[x][TelePos][1], HouseInformation[x][TelePos][2]); //Sets players position where x = houseid.
- SetPlayerInterior(playerid, HouseInformation[x][interiors]); //Sets players interior
- SetPlayerVirtualWorld(playerid, 15500000 + x); //Sets the virtual world
- //This is used if you want multiple houses per interior.
- //Sets the inhouse variable to the house he's in.
- }
- if(!HouseInformation[x][owner][0]) SendClientMessage(playerid, -1, "This house is for sale /buy to buy it!");
- //If there is no owner, it will send a message telling the player to buy it :).
- return 1;
- //We do this so the loop doesn't continue after or it tries to go for more checkpoints
- //We could alternitivly use break;
- }
- if(HouseInformation[x][checkpointidx][1] == checkpointid) //If the player enters the house exit.
- {
- if(InHouse[playerid] == -1)
- {
- InHouse[playerid] = x;
- return 1;
- }
- SetPlayerPos(playerid, HouseInformation[x][EnterPos][0], HouseInformation[x][EnterPos][1], HouseInformation[x][EnterPos][2]);
- SetPlayerInterior(playerid, 0); //Sets the player back to interior 0 (Outside)
- SetPlayerVirtualWorld(playerid, 0); //Sets the players Virtual world to 0.
- return 1;
- //We do this so the loop doesn't continue after or it tries to go for more checkpoints
- //We could alternitivly use break;
- }
- }
- return 1;
- }
- public OnPlayerLeaveDynamicCP(playerid, checkpointid)
- {
- if(InHouseCP[playerid] != - 1) InHouseCP[playerid] = -1; //Sets the players InHouseCP variable to 0.
- return 1;
- }
- /*
- Finally! We get to make our /buy and /sell commands. These commands are pretty self
- explanatory, it buys a house and sells a house :).
- OK, on to the /buy command. We firstly check if the player is in the enterance of a
- house. We will use our InHouseCP variable that we had created earlier. After that,
- we go through the following checks
- Is the house for sale - We check if the owner variable has a value.
- Has the player got enough money - We just check the GetPlayerMoney against the variable.
- Has the player got the max number of houses already - We use a simple database query
- which you will see below.
- Then, all we need to do it use our SetOwner function above to set the houses owner
- and set the players position to inside the house.
- Now we can get onto the /sell command which sells the house if the owner is inside
- their house.
- We only have two errors on this one which is checking if the player is in a house
- and checking if they own it.
- */
- CMD:buy(playerid, params)
- {
- if(InHouseCP[playerid] == -1) return SendClientMessage(playerid, 0xFF0000, "You are not in any house checkpoints!");
- if(HouseInformation[InHouseCP[playerid]][owner][0] != 0) return SendClientMessage(playerid, 0xFF0000, "This house has a owner");
- if(GetPlayerMoney(playerid) < HouseInformation[InHouseCP[playerid]][costprice]) return SendClientMessage(playerid, 0xFF0000, "You don't have enough money!"); //Player has a lack of cash!
- new PlayerName[24];
- GetPlayerName(playerid, PlayerName, 24);
- format(fquery, sizeof(fquery), "SELECT `houseowner` FROM `HOUSEINFO` WHERE `houseowner` = '%s'", PlayerName); //Formats the SELECT query
- queryresult = db_query(database, fquery); //Query result variable has been used to query the string above.
- if(db_num_rows(queryresult) == MAX_HOUSES_PER_PLAYER) return SendClientMessage(playerid, 0xFF0000, "You already have the max amount of houses"); //If the player has the max houses
- db_free_result(queryresult);
- //This is the point where the player can buy the house
- SetOwner(HouseInformation[InHouseCP[playerid]][Hname], PlayerName, InHouseCP[playerid]);
- //SetOwner(HouseName[], ownername[], houseids)
- SetPlayerPos(playerid, HouseInformation[InHouseCP[playerid]][TelePos][0], HouseInformation[InHouseCP[playerid]][TelePos][1], HouseInformation[InHouseCP[playerid]][TelePos][2]); //Sets players position where InHouseCP[playerid] = houseid.
- SetPlayerInterior(playerid, HouseInformation[InHouseCP[playerid]][interiors]); //Sets players interior
- SetPlayerVirtualWorld(playerid, 15500000 + InHouseCP[playerid]); //Sets the virtual world
- GivePlayerMoney(playerid, - HouseInformation[InHouseCP[playerid]][costprice]);
- GameTextForPlayer(playerid, "House ~r~Purchased!", 3000, 3); //Tells them they have purchased a house
- return 1;
- }
- CMD:sell(playerid, params)
- {
- if(InHouse[playerid] == -1) return SendClientMessage(playerid, 0xFF0000, "You have to be inside your house to sell it!");
- new Pname[24];
- GetPlayerName(playerid, Pname, 24);
- if(strcmp(HouseInformation[InHouse[playerid]][owner], Pname) != 0) return SendClientMessage(playerid, 0xFF0000, "This is not your house!");
- //This is the point where the player can sell the house
- DeleteOwner(HouseInformation[InHouse[playerid]][Hname], InHouse[playerid]);
- //DeleteOwner(HouseName[], houseids)
- GivePlayerMoney(playerid, HouseInformation[InHouse[playerid]][sellprice]);
- SetPlayerPos(playerid, HouseInformation[InHouse[playerid]][EnterPos][0], HouseInformation[InHouse[playerid]][EnterPos][1], HouseInformation[InHouse[playerid]][EnterPos][2]);
- SetPlayerInterior(playerid, 0); //Sets the player back to interior 0 (Outside)
- SetPlayerVirtualWorld(playerid, 0); //Sets the players Virtual world to 0.
- InHouseCP[playerid] = InHouse[playerid];
- GameTextForPlayer(playerid, "House ~g~sold!", 3000, 3); //Tells them they have sold a house
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement