[Tutorial] Creating a house system with checkpoints!
#1

Introduction
Hello y'all (:
I was wondering around the forums, and certainly it popped in to my head to make a house system tutorial.
Well it won't be an advanced one, but you can edit it to your style.
For this tutorial we will only use 1 interior for the houses.

Resources
Well for this tutorial, we will need:
  • SII (Credits to [Drug]Slick)
  • sscanf (Credits to Y_less)
  • Streamer (Credits to Incognito)
  • ZCMD (Credits to Zeex)
Basic scripting
Lets start of by creating the enum
P.S: If you don't know what enums are, I won't explain, try reading some tutorials, and searching ******(Click).
This enum will be to store all the house info instead of creating each and every var.
pawn Code:
#define MAX_HOUSES 100//Lets define that we can have the max limit of our houses to 100.
enum HouseInfo//Naming the enum
{  
Owner[24],//This will be where it will store the house owner name, in a 24 bit size array.
Owned,//To store if the house is owned or not.
Price,//How much the house will cost.
Float:XPos,//Float X position of the checkpoint
Float:YPos,//Self explanatory.
Float:ZPos,//Self explanatory.
VirtualWorld,//The checkpoints virtual world.
Text3D:HouseLabel//That label where it says "Owned Price..."
}
new HInfo[MAX_HOUSES][HouseInfo];//This is the var where we will read the house info.
Ok great.
Now lets create the normal vars to know which house id is the last.
pawn Code:
new HouseCount;//To check how many houses have we created.
new HouseEnter[MAX_HOUSES];//This will be where we will store the house entrance checkpoint
new HouseExit[MAX_HOUSES];//This will be where we will store the house exit checkpoint.
new PlayerInHouseID[MAX_PLAYERS];//To check what house id is the player in.
Ok compiled, no errors?! Great!

Scripting it

Now this will be a bit hard for me to explain, because I have done so many house system's that it's hard for me to explain :b
So lets create the /createhouse command.

pawn Code:
CMD:createhouse(playerid,params[])
{
if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid,-1,"You aren't an admin!");//Check if the player is currently rcon logged in.
new HousePrice,id = HouseCount;//Creating the house price for the selected value in the command, and the last house id created.
if(sscanf(params,"i",HousePrice)) return SendClientMessage(playerid,-1,"USAGE: /createhouse <price>");//Checking if the player uses the correct syntax. The parameter "i" in sscanf means integer, also could be used as "d".
new Float:x,Float:y,Float:z;//Creating the floats, to store the player's position.
GetPlayerPos(playerid,x,y,z);//Getting the player's position and storing it
HInfo[id][Price] = HousePrice;//Setting the house price to the selected one.
HInfo[id][Owned] = 0;//Setting the house id owned = 0
HInfo[id][XPos] = x;//Storing the XPos value to the player's x.
HInfo[id][YPos] = y;//Storing the YPos value to the player's y.
HInfo[id][ZPos] = z;//Storing the ZPos value to the player's z.
HInfo[id][VirtualWorld] = GetPlayerVirtualWorld(playerid);
format(HInfo[id][Owner],24,"Nonusablenameforthishouse");//Formating the "Owner" house id value to "Nonusablenameforthishouse".
SendClientMessage(playerid,-1,"House created");
HouseEnter[id] = CreateDynamicCP(x,y,z,1.5,GetPlayerVirtualWorld(pl ayerid));//Creating the checkpoint and storing it in the HouseEnter value.
HouseExit[id] = CreateDynamicCP(443.9237,509.4609,1001.4195,1.5,Ge tPlayerVirtualWorld(playerid));//Creating the house exit checkpoint and storing it in the HouseExit value.
new file[40],labelstring[100];//Creating the "file", and the labelstring var.
format(file,sizeof(file),"FHouse/Houses/%i.ini",id);//Formating the var to the selected house directory.
INI_Open(file);//Opening the file with SII.
INI_WriteInt("Price",HousePrice);//Writing in the place "Price" the inputted "Price" value.
INI_WriteInt("Owned",0);//Setting to "Owned" = 0 in the ini file.
INI_WriteInt("VirtualWorld",GetPlayerVirtualWorld( playerid));//Writing "VirtualWorld" = GetPlayerVirtualWorld(..);
INI_WriteFloat("XPos",x);//Writing the players pos for the check point position.
INI_WriteFloat("YPos",y);//Self explanatory.
INI_WriteFloat("ZPos",z);//Self explanatory.
INI_WriteString("Owner","Nonusablenameforthishouse ");//Writing a string in "Owned" to "Nonusablenameforthishouse"
INI_Save();//Saving file with SII.
INI_Close();//Closing the file with SII.
format(labelstring,sizeof(labelstring),"Owned: No \nPrice: %i",HousePrice);
HInfo[id][HouseLabel] = Create3DTextLabel(labelstring,0xFF0000FF,x,y,z,25. 0,GetPlayerVirtualWorld(playerid));
HouseCount++;
return 1;
}
Making it buyable

Ok if you compiled the previous steps and no errors occured, continue the tutorial else try posting it and we may discuss about it.

Lets make the /buy command.
pawn Code:
CMD:buy(playerid,params[])
{
for(new i = 0; i < MAX_HOUSES;i++)//Loop threw all houses.
{
if(!IsPlayerInRangeOfPoint(playerid,8.0,HInfo[i][XPos],HInfo[i][YPos],HInfo[i][ZPos])) continue;//Check if the player is near a house checkpoint
if(GetPlayerMoney(playerid) < HInfo[i][Price]) return SendClientMessage(playerid,-1,"You don't have enough money");//Checking the players money, to see if he has enough to buy the house.
if(HInfo[i][Owned] == 1) return SendClientMessage(playerid,-1,"This house is already owned");//Checking if the house is already owned.
HInfo[i][Owned] = 1;//Setting the house owned var to 1.
new file[60],pName[24],string[100];//Creating the necessary vars.
GetPlayerName(playerid,pName,sizeof(pName));//Retrieving the player's name.
format(HInfo[i][Owner],24,"%s",pName);//Setting the House Owner's var
format(file,sizeof(file),"FHouse/Houses/%i.ini",i);//Formating the house file
INI_Open(file);//Opening the house file
INI_WriteInt("Owned",1);//Setting in the ini file "Owned" to 1
INI_WriteString("Owner",pName);//Setting the "Owner" to the player's name.
INI_Save();//Saving the ini
INI_Close();//Closing the ini
format(string,sizeof(string),"Owned: Yes \nPrice: %i \nOwner: %s",HInfo[i][Price],pName);//Formating the string, so we can update the label of the house
Update3DTextLabelText(HInfo[i][HouseLabel],0xFF0000FF,string);//Updating the label with a red color
GivePlayerMoney(playerid,-HInfo[i][Price]);
return 1;
}
SendClientMessage(playerid,-1,"You aren't near a house!");
return 1;
}
Putting it up for sale again
For every house system there should be a sell command. (:
pawn Code:
CMD:sell(playerid,params[])
{
for(new i = 0; i < MAX_HOUSES;i++)//Loop threw all houses.
{
if(!IsPlayerInRangeOfPoint(playerid,8.0,HInfo[i][XPos],HInfo[i][YPos],HInfo[i][ZPos])) continue;//Check if the player is near a house checkpoint
if(HInfo[i][Owned] == 0) return SendClientMessage(playerid,-1,"This house isn't owned");//Checking if the house is already owned.
new pName[24];
GetPlayerName(playerid,pName,sizeof(pName));//Retrieving the player's name.
if(HInfo[i][Owned] == 1 && strcmp(pName,HInfo[i][Owner]) != 0) return SendClientMessage(playerid,-1,"You aren't the owner of this house!");//Checking if the house is owned but the owners name is different
HInfo[i][Owned] = 0;//Setting the house owned var to 1.
new file[60],string[100];//Creating the necessary vars.
format(HInfo[i][Owner],24,"Nonusablenameforthishouse");//Setting the House Owner's var
format(file,sizeof(file),"FHouse/Houses/%i.ini",i);//Formating the house file
INI_Open(file);//Opening the house file
INI_WriteInt("Owned",0);//Setting in the ini file "Owned" to 0
INI_WriteString("Owner","Nonusablenameforthishouse ");//Setting the "Owner" to the "Nonusablenameforthishouse".
INI_Save();//Saving the ini
INI_Close();//Closing the ini
format(string,sizeof(string),"Owned: No \nPrice: %i \nOwner: None",HInfo[i][Price],pName);//Formating the string, so we can update the label of the house
Update3DTextLabelText(HInfo[i][HouseLabel],0xFF0000FF,string);//Updating the label with a red color
return 1;
}
SendClientMessage(playerid,-1,"You aren't near a house!");
return 1;
}
Checking if the player enters the checkpoint
Aswell, every house system needs to check if the player wants to enter his house (:
pawn Code:
public OnPlayerEnterDynamicCP(playerid,checkpointid)
{  
for(new i = 0; i < MAX_HOUSES;i++)//Looping threw all houses.
{
if(checkpointid == HouseEnter[i])//Checking if the checkpoint id corresponds to one of the house interiors
{
new pName[24];//Creating the new var for the players name
GetPlayerName(playerid,pName,24);//Storing the players name
if(HInfo[i][Owned] == 1 && strcmp(HInfo[i][Owner],pName) == 0)//String comparing between the players name and the house owners name, to check if they match.
{
SetPVarInt(playerid,"PlayersInteriorHouse",GetPlay erInterior(playerid));//Storing, so later we can reset it back
SetPVarInt(playerid,"PlayerVirtualWorldHouse",GetP layerVirtualWorld(playerid));//Storing, so later we can reset it back
SetPlayerInterior(playerid,12);//Setting the players interior.
SetPlayerPos(playerid,446.7281,507.0475,1001.4195) ;//Setting the players position.
SetPlayerVirtualWorld(playerid,HInfo[i][VirtualWorld]);//Preventing players from different houses, finding each other.
PlayerInHouseID[playerid] = i;
}
if(HInfo[i][Owned] == 1 && strcmp(HInfo[i][Owner],pName) != 0)//Checking if the house is owned but the house owner and the players name don't match.
{
SendClientMessage(playerid,-1,"You don't own this house");
}
if(HInfo[i][Owned] == 0)//Simply checking if the house isn't owned.
{
SendClientMessage(playerid,-1,"/buy to buy this lovely house");
}
}
if(checkpointid == HouseExit[i])//Checking if the checkpointid is an House exit
{
SetPlayerPos(playerid,HInfo[i][XPos]+3,HInfo[i][YPos],HInfo[i][ZPos]);//Setting the players position to checkpoint position +3
SetPlayerInterior(playerid,GetPVarInt(playerid,"Pl ayersInteriorHouse"));//Setting the players interior to the one we stored
SetPlayerVirtualWorld(playerid,GetPVarInt(playerid ,"PlayerVirtualWorldHouse"));//Setting the players virtual world to the one we stored.
}
}
return 1;
}
+ Dude I sucked in this tut so i deleted it, its bs.

-
Loading the houses
So now we have to make them load, so after a server restart, we can have them back!
pawn Code:
stock LoadHouses()//Creating the stock function
{
new file[60],houseowner[24];//creating the "file" var. And also creating the "houseowner" var so we can store it, when we are reading the house owner ini line.
for(new i = 0; i < MAX_HOUSES;i++)//Looping threw every house
{
format(file,sizeof(file),"FAdmin/Houses/%i.ini",i);//Opening the house file with the current selected number with "i".
if(!INI_Exist(file)) continue;//Checking if the ini house file exist, if not to stop there.
INI_Open(file);//Opening the house ini
HInfo[i][Price] = INI_ReadInt("Price");//Reading the price.
HInfo[i][Owned] = INI_ReadInt("Owned");//Reading if it's owned.
HInfo[i][XPos] = INI_ReadInt("XPos");//Reading the X float position.
HInfo[i][YPos] = INI_ReadInt("YPos");//Reading the Y float position.
HInfo[i][ZPos] = INI_ReadInt("ZPos");//Reading the Z float position.
HInfo[i][VirtualWorld] = INI_ReadInt("VirtualWorld");//Reading the virtual world.
INI_ReadString(houseowner,"Owner");//Reading the house owner.
format(HInfo[i][Owner],24,"%s",houseowner);//Formating the "Owner" house id value to the red one.
HouseEnter[i] = CreateDynamicCP(HInfo[i][XPos],HInfo[i][YPos],HInfo[i][ZPos],1.5,HInfo[i][VirtualWorld]);//Creating the checkpoint and storing it in the HouseEnter value.
HouseExit[i] = CreateDynamicCP(443.9237,509.4609,1001.4195,1.5,HI nfo[i][VirtualWorld]);//Creating the house exit checkpoint and storing it in the HouseExit value.
new labelstring[100];//Creating the labelstring var.
switch(HInfo[i][Owned])//Using the "switch" method to check if the house is owned
{
case 0:{format(labelstring,sizeof(labelstring),"Owned: No \nPrice: %i",HInfo[i][Price]);}//If it isnt...
case 1:{format(labelstring,sizeof(labelstring),"Owned: Yes \nPrice: %i \nOwner: %s",HInfo[i][Price],HInfo[i][Owner]);}//If it is...
}
HInfo[i][HouseLabel] = Create3DTextLabel(labelstring,0xFF0000FF,HInfo[i][XPos],HInfo[i][YPos],HInfo[i][ZPos],25.0,HInfo[i][VirtualWorld]);//Creating the label with the formatted string.
HouseCount++;//+ counting the HouseCount var.
INI_Close();//Closing the SII file.
}
return 1;
}
Reply
#2

Nice tutorial, very well explained!
For sure im gonna add this to the FS&Inc list
Reply
#3

Quote:
Originally Posted by Wesley221
View Post
Nice tutorial, very well explained!
For sure im gonna add this to the FS&Inc list
Thanks (:
This freaking tutorial took me 3 hours lol. :b
With an interval of 10 mins
Reply
#4

Holy cow o.O
Atleast alot of people gonna use this, for sure!
I might aswell consider making a house system sooner or later.. hehe
Reply
#5

Good jawb unawd :>
Reply
#6

Quote:
Originally Posted by [MWR]Blood
View Post
Good jawb unawd :>
Gracias umawd :>
Reply
#7

Looks awsome FireCat! Glad to see you creating this tutorial.
Reply
#8

Quote:
Originally Posted by Kingunit
View Post
Looks awsome FireCat! Glad to see you creating this tutorial.
Thanks man! <3
Reply
#9

Wow, You should at least make this create a house with goat on top! <3

OT: Good job bro.
Reply
#10

Quote:
Originally Posted by Max_Coldheart
View Post
Wow, You should at least make this create a house with goat on top! <3

OT: Good job bro.
Thanks goat buddy (:
Reply
#11

Nice, good job.
Reply
#12

Quote:
Originally Posted by Jafet_Macario
View Post
Nice, good job.
Thanks :b
Reply
#13

good job but what about load and save them ?
Reply
#14

Quote:
Originally Posted by Tigerkiller
View Post
good job but what about load and save them ?
It already saves, but
Quote:

I'll make the loading part later, I've been writing this tutorial for 3 hours -_-
If I forgot something in the previous parts please tell me.

Reply
#15

Very Nice!
Reply
#16

Here is some suggestions for this tutorial
  • PlayerInHouseID is meant to be MAX_PLAYERS not MAX_HOUSES due to the house being per player id.
  • HouseEnter + HouseExit could just go into the enum rather then being different variables because it's just easier to understand.
  • There needs to be better explanation such as with
    pawn Code:
    HInfo[id][YPos] = y;//Self explanatory
    because that isn't really self explanatory to most people. It may seem really boring and you may understand it but others may not. My own house system tutorial has over 2.5k words explaining what I'm doing in the code following with comments in the code too.
  • If someone connected with the name "None" they could enter any house that was not already brought.
  • Rather than having a loop on the /buy and /sell commands, you can set a variable with what house checkpoint the player is in and when the player leaves the house checkpoint, set it back to in no house checkpoint. This takes out a whole loop + 100 IsPlayerInRangeOfPoints.
  • You have just random Player Variables and half non-player vars. Read This for more information on Player Variables.
    Quote:

    99% of the time you do not need, and should not use, PVars

  • You should really finish the tutorial before posting it .
  • Tell them that they need to create the directory FHouse/Houses/ in their scriptfiles.
  • It takes me like a total of 10+ hours to create my proper tutorials.
This does seem similar to my older house system tutorial to be honest.
Reply
#17

Quote:
Originally Posted by [HiC]TheKiller
View Post
Here is some suggestions for this tutorial
  • PlayerInHouseID is meant to be MAX_PLAYERS not MAX_HOUSES due to the house being per player id.
  • HouseEnter + HouseExit could just go into the enum rather then being different variables because it's just easier to understand.
  • There needs to be better explanation such as with
    pawn Code:
    HInfo[id][YPos] = y;//Self explanatory
    because that isn't really self explanatory to most people. It may seem really boring and you may understand it but others may not. My own house system tutorial has over 2.5k words explaining what I'm doing in the code following with comments in the code too.
  • If someone connected with the name "None" they could enter any house that was not already brought.
  • Rather than having a loop on the /buy and /sell commands, you can set a variable with what house checkpoint the player is in and when the player leaves the house checkpoint, set it back to in no house checkpoint. This takes out a whole loop + 100 IsPlayerInRangeOfPoints.
  • You have just random Player Variables and half non-player vars. Read This for more information on Player Variables.
  • You should really finish the tutorial before posting it .
  • Tell them that they need to create the directory FHouse/Houses/ in their scriptfiles.
  • It takes me like a total of 10+ hours to create my proper tutorials.
This does seem similar to my older house system tutorial to be honest.
UHh fine I gtg to school, I'll try to make it better when I come back.
And I only time I checked your house tutorial was like in 2010.
Reply
#18

Quote:
Originally Posted by FireCat
View Post
UHh fine I gtg to school, I'll try to make it better when I come back.
And I only time I checked your house tutorial was like in 2010.
Edit:

Yup it's updated and i'm proud databases are being used in his tutorial
Reply
#19

very Nice
Reply
#20

Thanks
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)