Advertisement
TheKiller

My Houses Tutorial

Sep 2nd, 2011
1,559
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 19.54 KB | None | 0 0
  1. /*
  2. Firstly, we have to include the samp include, the streamer include,
  3. the ZCMD include and create our variables. For SQLite, we must have a
  4. variable to store the database, the database result and the format
  5. string for our query. DB tag is connected to the database variable and
  6. the DBResult is connected to the query result.
  7. */
  8. #include <a_samp>
  9. #include <zcmd>
  10. #include <streamer>
  11.  
  12. new DB:database, DBResult:queryresult, fquery[300];
  13.  
  14. /*
  15.  
  16. Below are some defines that we are using so that we can edit them
  17. easily any time we want. We have the define MAX_HOUSES that is used
  18. for creating the houseinformation variable. It's good to have this close
  19. to the amount of houses you use because the less MAX_HOUSES, the smaller
  20. the variable and the smaller AMX size. MAX_HOUSES_PER_PLAYER is used later
  21. in our script to define the max houses a single player can have. Lastly, the
  22. databasename define defines the name of our database. It should have .db on
  23. the end as well as the quotes.
  24. */
  25.  
  26. #define MAX_HOUSES 300 //MAX_HOUSES is currently 300.
  27. #define MAX_HOUSES_PER_PLAYER 2 //MAX_HOUSES_PER_PLAYER is currently 2
  28. #define databasename "housedb.db" //The Databasename is currently housedb.db
  29.  
  30.  
  31. /*
  32. We need to now create our enum and the house information variable
  33. that stores all the information so that we do not need to query the
  34. SQLite database every time we want to check house information. We use
  35. a enum so that we don't have to have multiple variables, we can just use
  36. one. The owner variable in the enum stores the owners name if there is a
  37. owner of the house. Hname represents the house name, it must be different
  38. to all of the other house names because it is used as our ID to get information
  39. such as owner information from the database. Costprice is going to store the cost
  40. price of the house, pretty self explanatory. EnterPos[3] is going to store the
  41. house checkpoint position that will show if the player is close enough to
  42. the house. The 3 cells on the end of EnterPos[3] represents the X Position,
  43. the Y Position and the Z position. TelePos is similar to the EnterPos. It just
  44. is the position that we are sent to if we enter the house. The sellprice variable
  45. is also very self explanatory, it allows us to /sell our house later on in the
  46. tutorial for the price that you have defined. The interiors variable allows us
  47. to set the interior of the player when the teleports inside. Lastly in our enum
  48. comes the checkpointid. The textid variable stores the textid (information 3D text
  49. label that is outside of our house. I've changed it from gametext to 3D text labels
  50. in this tutorial because it looks better and it is way easier.
  51. The checkpointid stores the checkpoint number that our streamer
  52. has given us. We will use it later to find if the player is near a house / can enter it
  53. or if the player is inside the house and enters the checkpoint to exit the house.
  54. The HouseInformation variable is pretty much all of these variable mixed together.
  55. You can have a maximum amount of houses (Defined above) with the information in
  56. the enum. The variable houseid shows us what houseid we are currently up to. It
  57. tells us what the next empty slot to store information in is. The InHouse variable
  58. pretty much tells us if the player is in a house or not. We will use this later for
  59. the /sell command and also you can use it somewhere else in your script if needed.
  60. Lastly, the InHouseCP variable is used to store if the player is in a house checkpoint
  61. or not. This is if they want to buy the house so we don't have to call multiple loops,
  62. only one.
  63. */
  64.  
  65. enum hinfo
  66. {
  67.     owner[24],
  68.     Hname[100],
  69.     costprice,
  70.     Float:EnterPos[3],
  71.     Float:TelePos[3],
  72.     sellprice,
  73.     interiors,
  74.     Text3D:textid,
  75.     checkpointidx[2]
  76. };
  77.  
  78. new HouseInformation[MAX_HOUSES][hinfo], houseid;
  79. new InHouse[MAX_PLAYERS], InHouseCP[MAX_PLAYERS];
  80.  
  81.  
  82.  
  83. /*
  84. First thing is first, we need to have the following two lines under OnGameModeInit
  85. under OnFilterScriptInit. We need to firstly use the db_open function to connect
  86. our samp server with the SQLite database. We use the database variable above to save
  87. our database number in it. Secondly we need to make our table if it doesn't exist.
  88. You do not need to keep that line in because it only needs to be called once. The
  89. db_query function allows us to GET / STORE / SET information in our database. In this
  90. case, we are creating our table. The table allows us to store information in and can
  91. be used to add more functions like lets say a house car. For this tutorial, we are only
  92. using it to store the owners name.
  93. */
  94.  
  95. public OnFilterScriptInit()
  96. {
  97.     database = db_open(databasename);
  98.     db_query(database, "CREATE TABLE IF NOT EXISTS `HOUSEINFO` (housename varchar(51), houseowner varchar(25))");
  99.     CreateHouse("TestHouse1", 1, 2317.130615, 692.398498, 11.460937, 266.857757, 305.001586, 999.148437, 2, 1);
  100.     CreateHouse("TestHouse2", 1, 2346.872802, 692.999267, 11.460937, 266.857757, 305.001586, 999.148437, 2, 1);
  101.     CreateHouse("TestHouse3", 1, 2396.482666, 691.487060, 11.453125, 2196.850341, -1204.343261, 1049.023437, 6, 1);
  102.     CreateHouse("TestHouse4", 1, 2398.476074, 735.344665, 11.460937, 2196.850341, -1204.343261, 1049.023437, 6, 1);
  103.     CreateHouse("TestHouse5", 1, 2368.863525, 733.627502, 11.460937, 2196.850341, -1204.343261, 1049.023437, 6, 1);
  104.     CreateHouse("TestHouse6", 1, 2013.253906, 731.041870, 11.453125, 266.857757, 305.001586, 999.148437, 5, 1);
  105.     CreateHouse("TestHouse7", 1, 2449.826660, 742.588806, 11.460937, 266.857757, 305.001586, 999.148437, 5, 1);
  106.     CreateHouse("TestHouse8", 1, 2449.662353, 714.210693, 11.468292, 266.857757, 305.001586, 999.148437, 5, 1);
  107.     return 1;
  108. }
  109.  
  110. /*
  111. Now we do the basic job of resetting the variables to -1 (No house id is under this
  112. variable
  113. */
  114. public OnPlayerConnect(playerid)
  115. {
  116.     InHouse[playerid] = -1;
  117.     InHouseCP[playerid] = -1;
  118.     return 1;
  119. }
  120.  
  121. /*
  122. Time to get started on the harder stuff! We are going to make our function that creates
  123. our houses. It will also query our database to see if there is anyone that owns the
  124. house. We will be using a stock function that creates a single line that we can use to
  125. store all of the information at once. The format of our stock is
  126.  
  127. CreateHouse(HouseName[], CostP, Float:EnterX, Float:EnterY, Float:EnterZ, Float:TeleX, Float:TeleY, Float:TeleZ, SellP, Interiorx)
  128. HouseName[] - The unique house name that you have chosen for the house (Ex: "Big Mansion5")
  129. CostP - The Cost price of the house (Ex: 500000)
  130. Float:EnterX - The X entry point of the house, it will also be where the outside checkpoint will be (Ex: 1264.53433)
  131. Float:EnterY - The Y entry point of the house, it will also be where the outside checkpoint will be (Ex: 2625.6436)
  132. Float:EnterZ - The Z entry point of the house, it will also be where the outside checkpoint will be (Ex: 200.532)
  133. Float:TeleX - The X teleport that teleports the player into the interior (Ex: 432.4234)
  134. Float:TeleY - The Y teleport that teleports the player into the interior (Ex: 4216.4152)
  135. Float:TeleZ - The Z teleport that teleports the player into the interior (Ex: 10.53672)
  136. SellP - It's the selling price that the owner can sell the house for (Ex: 200000)
  137. Interiorx - The interior ID of the interior that we will teleport to.
  138.  
  139. This is just pretty much basic setting the variables into our enum for most of it. When
  140. it queries the database down the bottom, what we are doing is finding if the house has
  141. a owner, if so it will store the owners name into the houseinformation variable. If
  142. there is no owner for the house, the variable will be left blank. We do this by using
  143. the SELECT statement.
  144.  
  145. SELECT [VARIABLE] FROM [TABLENAME] WHERE [ANOTHER VARIABLE] = [A VALUE]
  146. VARIABLE = houseowner
  147. TABLENAME = HOUSEINFO
  148. ANOTHER VARIABLE = housename
  149. A VALUE = our house name.
  150.  
  151. We then use db_num_rows to check if there has been any rows with our house name that
  152. we have fetched. If there isn't any rows with the house name (no owner) then we will
  153. just free the result with db_free_result. If there is a row, we will fetch that value
  154. using db_get_field_assoc.
  155. For more information on SQLite, visit http://wiki.sa-mp.com/wiki/SQLite
  156.  
  157. We also have to add our enter and exit checkpoints into our script using CreateDynamicCP.
  158. It creates the checkpoints and stores the IDS into checkpointid[0] for the enter CP and
  159. checkpointid[1] for the exit CP. We are also going to make our 3D text information
  160. variable with CreateDynamic3DTextLabel and store it into the variable textid.
  161.  
  162. */
  163.  
  164.  
  165. stock CreateHouse(HouseName[], CostP, Float:EnterX, Float:EnterY, Float:EnterZ, Float:TeleX, Float:TeleY, Float:TeleZ, Interiorx, SellP)
  166. {
  167.     format(HouseInformation[houseid][Hname], 100, "%s", HouseName);
  168.     HouseInformation[houseid][costprice] = CostP;
  169.     HouseInformation[houseid][EnterPos][0] = EnterX;
  170.     HouseInformation[houseid][EnterPos][1] = EnterY;
  171.     HouseInformation[houseid][EnterPos][2] = EnterZ;
  172.     HouseInformation[houseid][TelePos][0] = TeleX;
  173.     HouseInformation[houseid][TelePos][1] = TeleY;
  174.     HouseInformation[houseid][TelePos][2] = TeleZ;
  175.     HouseInformation[houseid][sellprice] = SellP;
  176.     HouseInformation[houseid][interiors] = Interiorx;
  177.     format(fquery, sizeof(fquery), "SELECT houseowner FROM HOUSEINFO WHERE housename = '%s'", HouseName); //Formats the SELECT query
  178.     queryresult = db_query(database, fquery); //Query result variable has been used to query the string above.
  179.     if(db_num_rows(queryresult) != 0) db_get_field_assoc(queryresult, "houseowner", HouseInformation[houseid][owner], 24); //Fetches the field information  db_free_result(queryresult);
  180.     HouseInformation[houseid][checkpointidx][0] = CreateDynamicCP(EnterX, EnterY, EnterZ, 1.0);
  181.     //CreateDynamicCP(Float:x, Float:y, Float:z, Float:size);
  182.     HouseInformation[houseid][checkpointidx][1] = CreateDynamicCP(TeleX, TeleY, TeleZ, 1.0, 15500000+houseid, Interiorx);
  183.     //CreateDynamicCP(Float:x, Float:y, Float:z, Float:size, worldid, interiorid);
  184.     if(!HouseInformation[houseid][owner][0]) format(fquery, sizeof(fquery), "House Name: %s \n House Price:$%d \n Sell Price: $%d", HouseName, CostP, SellP);
  185.     //If there is nothing in the owners variable, we check if the first cell doesn't have a character.
  186.     else if(HouseInformation[houseid][owner][0] != 0) format(fquery, sizeof(fquery), "House Name: %s \n Owner: %s", HouseName, HouseInformation[houseid][owner]);
  187.     //If there is something in the owners variable we check if the first cell has a character.
  188.     HouseInformation[houseid][textid] = CreateDynamic3DTextLabel(fquery, 0xFFFFFF, EnterX, EnterY, EnterZ + 0.5, 50.0);
  189.     //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);
  190.     houseid ++; //We go to the next free slot in our variable.
  191.     return 1;
  192. }
  193.  
  194.  
  195. /*
  196. Now we are going to make our small functions that will be used later. They are to
  197. set and delete the owner of a certain house. We are using two basic SQL queries.
  198. One being INSERT
  199.  
  200. INSERT INTO [TABLENAME] ([FIELD1], [FIELD2]) VALUES ([VALUE1], [VALUE2])
  201. TABLENAME - HOUSEINFO
  202. FIELD1 - housename
  203. FIELD2 - houseowner
  204. VALUE1 - Our housename value
  205. VALUE2 - Our houseowner value
  206.  
  207. And the other being DELETE
  208.  
  209. DELETE FROM [TABLENAME] WHERE [FIELD] = [VALUE]
  210. TABLENAME - HOUSEINFO
  211. FIELD - housename
  212. VALUE - the housename
  213.  
  214. Then we set the owners variable to the owners name using format. We then after
  215. we update the 3DTextLabel's Text to being owned / not being owned. It's the same
  216. for both of them.
  217. */
  218.  
  219. stock SetOwner(HouseName[], ownername[], houseids)
  220. {
  221.     format(fquery, sizeof(fquery), "INSERT INTO `HOUSEINFO` (`housename`, `houseowner`)  VALUES('%s', '%s')", HouseName, ownername);
  222.     db_query(database, fquery); //Queries the SQLite database.
  223.     format(HouseInformation[houseids][owner], 24, "%s", ownername);
  224.     format(fquery, sizeof(fquery), "House Name: %s \n Owner: %s", HouseName, HouseInformation[houseids][owner]);
  225.     UpdateDynamic3DTextLabelText(HouseInformation[houseids][textid], 0xFFFFFF, fquery); //Updates the text label.
  226.     return 1;
  227. }
  228.  
  229. stock DeleteOwner(HouseName[], houseids)
  230. {
  231.     format(HouseInformation[houseids][owner], 24, "%s", "\0");
  232.     format(fquery, sizeof(fquery), "DELETE FROM `HOUSEINFO` WHERE `housename` = '%s'", HouseName);
  233.     db_query(database, fquery); //Queries the SQLite database.
  234.     format(fquery, sizeof(fquery), "House Name: %s \n House Price:$%d \n Sell Price: $%d", HouseName, HouseInformation[houseids][costprice], HouseInformation[houseids][sellprice]);
  235.     UpdateDynamic3DTextLabelText(HouseInformation[houseids][textid], 0xFFFFFF, fquery); //Updates the text label.
  236.     return 1;
  237. }
  238.  
  239.  
  240. /*
  241. Before we make the /buy and /sell commands, we are going to use the OnPlayerEnterDynamicCheckpoint
  242. callback to either Set the players position in or outside of the house. We make a loop
  243. calling every single checkpoint variable in our current houses to see if the checkpoint
  244. is one of our house checkpoints.
  245.  
  246. We firstly check if the player is the owner so he can instantly enter the house.
  247. If so, we will telepor him to inside the house.
  248.  
  249. Then it checks if the owner has a owner and sends a message to the player if there
  250. is no owner.
  251.  
  252. Then it checks if the player is in the exit checkpoint and sets his position outside
  253. of the house.
  254.  
  255. Lastly, we use the callback OnPlayerExitDynamicCP to exit the checkpoint
  256. */
  257.  
  258. public OnPlayerEnterDynamicCP(playerid, checkpointid)
  259. {
  260.     for(new x; x<houseid; x++) //Loops through all current house ids.
  261.     {
  262.         if(HouseInformation[x][checkpointidx][0] == checkpointid) //If the entry checkpoint is entry checkpoint.
  263.         {
  264.             if(InHouse[playerid] != -1)
  265.             {
  266.                 InHouse[playerid] = -1; //Sets the player to outside the house.
  267.                 return 1;
  268.             }
  269.             InHouseCP[playerid] = x; //Sets the InHouseCP variable.
  270.             new Pname[24]; //Pname variable.
  271.             GetPlayerName(playerid, Pname, 24); //Gets the players name.
  272.             if(HouseInformation[x][owner][0] != 0 && !strcmp(Pname, HouseInformation[x][owner][0]))
  273.             //The line above checks that the owner string has something in it, then it
  274.             //Will compare it to our current player.
  275.             {
  276.                 SetPlayerPos(playerid, HouseInformation[x][TelePos][0], HouseInformation[x][TelePos][1], HouseInformation[x][TelePos][2]); //Sets players position where x = houseid.
  277.                 SetPlayerInterior(playerid, HouseInformation[x][interiors]); //Sets players interior
  278.                 SetPlayerVirtualWorld(playerid, 15500000 + x); //Sets the virtual world
  279.                 //This is used if you want multiple houses per interior.
  280.                  //Sets the inhouse variable to the house he's in.
  281.             }
  282.             if(!HouseInformation[x][owner][0]) SendClientMessage(playerid, -1, "This house is for sale /buy to buy it!");
  283.             //If there is no owner, it will send a message telling the player to buy it :).
  284.             return 1;
  285.             //We do this so the loop doesn't continue after or it tries to go for more checkpoints
  286.             //We could alternitivly use break;
  287.         }
  288.         if(HouseInformation[x][checkpointidx][1] == checkpointid) //If the player enters the house exit.
  289.         {
  290.             if(InHouse[playerid] == -1)
  291.             {
  292.                 InHouse[playerid] = x;
  293.                 return 1;
  294.             }
  295.             SetPlayerPos(playerid, HouseInformation[x][EnterPos][0], HouseInformation[x][EnterPos][1], HouseInformation[x][EnterPos][2]);
  296.             SetPlayerInterior(playerid, 0); //Sets the player back to interior 0 (Outside)
  297.             SetPlayerVirtualWorld(playerid, 0); //Sets the players Virtual world to 0.
  298.             return 1;
  299.             //We do this so the loop doesn't continue after or it tries to go for more checkpoints
  300.             //We could alternitivly use break;
  301.         }
  302.     }
  303.     return 1;
  304. }
  305.  
  306. public OnPlayerLeaveDynamicCP(playerid, checkpointid)
  307. {
  308.     if(InHouseCP[playerid] != - 1) InHouseCP[playerid] = -1; //Sets the players InHouseCP variable to 0.
  309.     return 1;
  310. }
  311.  
  312. /*
  313.  
  314. Finally! We get to make our /buy and /sell commands. These commands are pretty self
  315. explanatory, it buys a house and sells a house :).
  316.  
  317. OK, on to the /buy command. We firstly check if the player is in the enterance of a
  318. house. We will use our InHouseCP variable that we had created earlier. After that,
  319. we go through the following checks
  320.  
  321. Is the house for sale - We check if the owner variable has a value.
  322.  
  323. Has the player got enough money - We just check the GetPlayerMoney against the variable.
  324.  
  325. Has the player got the max number of houses already - We use a simple database query
  326. which you will see below.
  327.  
  328. Then, all we need to do it use our SetOwner function above to set the houses owner
  329. and set the players position to inside the house.
  330.  
  331. Now we can get onto the /sell command which sells the house if the owner is inside
  332. their house.
  333.  
  334. We only have two errors on this one which is checking if the player is in a house
  335. and checking if they own it.
  336. */
  337.  
  338.  
  339. CMD:buy(playerid, params)
  340. {
  341.     if(InHouseCP[playerid] == -1) return SendClientMessage(playerid, 0xFF0000, "You are not in any house checkpoints!");
  342.     if(HouseInformation[InHouseCP[playerid]][owner][0] != 0) return SendClientMessage(playerid, 0xFF0000, "This house has a owner");
  343.     if(GetPlayerMoney(playerid) < HouseInformation[InHouseCP[playerid]][costprice]) return SendClientMessage(playerid, 0xFF0000, "You don't have enough money!"); //Player has a lack of cash!
  344.     new PlayerName[24];
  345.     GetPlayerName(playerid, PlayerName, 24);
  346.     format(fquery, sizeof(fquery), "SELECT `houseowner` FROM `HOUSEINFO` WHERE `houseowner` = '%s'", PlayerName); //Formats the SELECT query
  347.     queryresult = db_query(database, fquery); //Query result variable has been used to query the string above.
  348.     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
  349.     db_free_result(queryresult);
  350.     //This is the point where the player can buy the house
  351.     SetOwner(HouseInformation[InHouseCP[playerid]][Hname], PlayerName, InHouseCP[playerid]);
  352.     //SetOwner(HouseName[], ownername[], houseids)
  353.     SetPlayerPos(playerid, HouseInformation[InHouseCP[playerid]][TelePos][0], HouseInformation[InHouseCP[playerid]][TelePos][1], HouseInformation[InHouseCP[playerid]][TelePos][2]); //Sets players position where InHouseCP[playerid] = houseid.
  354.     SetPlayerInterior(playerid, HouseInformation[InHouseCP[playerid]][interiors]); //Sets players interior
  355.     SetPlayerVirtualWorld(playerid, 15500000 + InHouseCP[playerid]); //Sets the virtual world
  356.     GivePlayerMoney(playerid, - HouseInformation[InHouseCP[playerid]][costprice]);
  357.     GameTextForPlayer(playerid, "House ~r~Purchased!", 3000, 3); //Tells them they have purchased a house
  358.     return 1;
  359. }
  360.  
  361. CMD:sell(playerid, params)
  362. {
  363.     if(InHouse[playerid] == -1) return SendClientMessage(playerid, 0xFF0000, "You have to be inside your house to sell it!");
  364.     new Pname[24];
  365.     GetPlayerName(playerid, Pname, 24);
  366.     if(strcmp(HouseInformation[InHouse[playerid]][owner], Pname) != 0) return SendClientMessage(playerid, 0xFF0000, "This is not your house!");
  367.     //This is the point where the player can sell the house
  368.     DeleteOwner(HouseInformation[InHouse[playerid]][Hname], InHouse[playerid]);
  369.     //DeleteOwner(HouseName[], houseids)
  370.     GivePlayerMoney(playerid, HouseInformation[InHouse[playerid]][sellprice]);
  371.     SetPlayerPos(playerid, HouseInformation[InHouse[playerid]][EnterPos][0], HouseInformation[InHouse[playerid]][EnterPos][1], HouseInformation[InHouse[playerid]][EnterPos][2]);
  372.     SetPlayerInterior(playerid, 0); //Sets the player back to interior 0 (Outside)
  373.     SetPlayerVirtualWorld(playerid, 0); //Sets the players Virtual world to 0.
  374.     InHouseCP[playerid] = InHouse[playerid];
  375.     GameTextForPlayer(playerid, "House ~g~sold!", 3000, 3); //Tells them they have sold a house
  376.     return 1;
  377. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement