[Tutorial] Make your own house system (with vehicles)
#1

Hey. This is the rebuild of this tutorial. Now I won't use one single file, but every house one file. This is NOT recommended for home hosted servers! - It's gonna be slow if you save ALL the houses.
Whatever, let's start

What do you need?
You need, of course, pawno. And we are

Step 1 - Making defines etc
Well, the 'title' says it. Let's make the defines. I'm gonna explain what what is, and what the function is.
First of all, we need to include some includes -.-". I won't only use a_samp. To store all the data in a file, we're gonna use the famous Dini!.
You can download it here: http://dracoblue.net/download/dini-16/35/ . I am also gonna use a streamer! But that one is not recommended. Only recommended if you're gonna use more map icons then the max allowed in samp!
That's standard 100. So if you want more then 100, you're gonna need the streamer! Whatever, you can download the streamer here: http://forum.sa-mp.com/showthread.ph...treamer+plugin [Incognito's streamer].
And btw, the includes are called: a_samp, Dini and streamer. You already know it of course, but you have to do that with #include. Here's the code:
pawn Code:
#include <a_samp>
#include <Dini>
#include <streamer>
As second, we need some defines. Just some colors and MAX defines.
The 'MAX_HOUSES' -> Change it to the max houses you want. NOTE: If you're gonna use an 'save all houses' function (not includes) : How more houses, how longer IN MINUTES it will take (if you're just using home hosted)
Hosts are (mostly) faster. Then it'll save faster too. Whatever:
pawn Code:
#define MAX_HOUSES 200
I am gonna use max 200 houses. So that's over the SAMP map icon limit! Now I'll give the color codes. No explaination for that. You have to know that! If you don't know how to define colors, I'll suggest you to learn scripting! ^^
pawn Code:
#define COLOR_WHITE 0xFFFFFFAA //White color
#define COLOR_RED 0xFF0000AA //Red Color
#define COLOR_GREEN 0x00FF00AA //Green color
Now, the house options! We need all the info of the house! I am gonna include the next options:
* Entrance X : The X position of the entrance of the house
* Entrance Y : The Y position of the entrance of the house
* Entrance Z : The Z position of the entrance of the house
* Exit X : The X position of the exit (interior door)
* Exit Y : The Y position of the exit (interior door)
* Exit Z : The Z position of the exit (interior door)
* Inside int : The interior of the house interior
* Inside vir : The virtual world of the house interior
* Outside int : Interior of the house itself
* Outside vir : The virtual world of the house itself
* Owned : bool - Is house owned? TRUE or FALSE
* Owner : The owner of the house
* Price : The price of the house
* Pickup : The house pickup
* Icon : The house icon
* Vehicle model : Model of the housecar
* Vehicle X : X location of the housecar
* Vehicle Y : Y location of the housecar
* Vehicle Z : Z location of the housecar
* Vehicle A : Angle of the housecar
** HouseCar : The only one that won't be in the hInfo enum. That's to prevent a bug

That's not nothing! :O - But it's the most 'basic' if you want an good house system.
Let's now make it. We are gonna use an enum. This stores more strings etc in one ... packet (idk how to subscribe, sorry).
We are gonna call the 'packet' hInfo. :
pawn Code:
enum hInfo
{
    Float:hEnterX, //Entrance X. It's an float! example: 0.0000000. I'm gonna use the same with the other entrances/exits
    Float:hEnterY,
    Float:hEnterZ,
    Float:hExitX,
    Float:hExitY,
    Float:hExitZ,
    hInsideInt, //The inside interior.. DUH!
    hInsideVir, //Already subscribed above
    hOutsideInt,
    hOutsideVir,
    bool:hOwned, //boolean! Is house owned? NO = False, YES = True
    hOwner[MAX_PLAYER_NAME], //The house owner! I'm gonna use MAX_PLAYER_NAME, because a player can't have a longer name :')
    hPrice, //Will store the price
    hPickup, //The pickup. This is used to remove/move the pickup icon!
    hIcon, //The map icon. Also used to remove/move it! We are going to need an ID. Without an ID we can't do NOTHING!
    hVecModel, //The housecar's model
    Float:hVecX, //X location. En float too.
    Float:hVecY,
    Float:hVecZ,
    Float:hVecA
};
Like I said in the comments; The pickup and icon: We need an ID! Every pickup/mapicon has it's own ID. If you're gonna use an sellhouse/buyhouse command, the green house mapicon will change into red. For that, we need the ID! I hope you get this.
Hmm. We can't use anything now. At least, nothing usual. We need to make a string, where everything will be stored in! Just the new stuff. We are gonna call it the "HouseInfo".
pawn Code:
new HouseInfo[MAX_HOUSES][hInfo];
Like you saw, there ain't an "hID" (or something like that) in the enum to store an house ID! But we need the ID's. For buying houses etc. With no ID, only house ID 0 will work, or ALL the houses.
Whatever, the [MAX_HOUSES] part is the house ID - If you have MAX_HOUSES as 200, the house ID's will be from '0' to '199'. (-.-).
The 'hInfo' is the 'packet' we've made. So, to get/change the price of house ID 0 to 100, it will look like this: HouseInfo[i][hPrice] = 100;. I hope that you understand this! If you understand it: - Then the tutorial's good enough. If you don't understand it, then my tutorial is OR not good enough, OR you didn't read it good (I personally think, that I've explained it good).
But okay. We need to store the ID of the house vehicle. We'll call it "HouseCar". Here's the code:
pawn Code:
new HouseCar[MAX_HOUSES];
It's one vehicle per house! That's why I use MAX_HOUSES and not MAX_VEHICLES. If you use MAX_VEHICLES, it will be bugged (maybe)!.
Whatever, let's make the functions etc!

Step 2 - The functions
Yeah. What do we need? Guess it. No just kidding. We need at least the following functions:
* Save House (ID) : Save house data into an file
* Load House (ID) : Get house data from the file and store it into the HouseInfo
* Load House Visual (ID) : Add pickup/mapicon/housevehicle etc...
You can also add an Unload House (ID) (I am using that for my new gamemode).

Load House
As first, we need to check if the file of the house exists. We won't save all the data in one file. We're gonna use multilple files, using Dini.
So we need to create a map in your scriptfiles folder! We're gonna call it, (how basicly) Houses. Do it now.
Now you've created the map Houses in your scriptfiles folder, we're gonna make the function itself.
Let's use STOCK. No need to use an callback. The function is gonna be called LoadHouse(houseid). So it's gonna look like this:
pawn Code:
stock LoadHouse(houseid)
{
Don't forget; if you use an function, longer then one file: USE BRACKETS! ({ & })
As second, we're gonna check if the housefile exists. The file will be named... "houseid". So, the ID of the house. One file will look like this: 2. or 0.
If everything is gonna be good, your scriptfiles/Houses map will look like this:

Whatever. We won't use: "If filename Exists CONTINUE". But we're gonna do it like: "If filename not exists STOP" (with return 0
To check if the filename exists, use an format (for the houseid). This ain't an "LoadAllHouses". That's a bit slow. And an "SaveAllHouses" will just take some minutes :P
But er, LET's DO IT!
pawn Code:
new fstring[10]; //The string for the file [format]
format(fstring, 10, "Houses/%d", houseid); //Format the filename
if(!dini_Exists(fstring)) return 0; //"If Houses/{houseid} not exists then return False (0)"
This script above means:
Code:
new string named 'fstring' with max length 10
format the 'fstring' to "Houses/{houseid}" (this can always be different)
if filename fstring not exists, stop.
I hope that you understand this.
But whatever, now we need to set info into the HouseInfo 'packet'. We're gonna do it like this: HouseInfo[{houseid}][{enum_name}] = {read_string_from_file}.
This is an example; This will read the house price from the file: HouseInfo[{houseid}][hPrice] = dini_Int({filename}, "Price");
dini_Int read's an integer from a file. dini_Get get's a whole string, dini_Bool also get's an integer, but only 0 and 1: True or False, and as last, dini_Float get's an float (for positions etc)
Let's get everything we need. I've explained enough now, so I am gonna give the whole part code.
pawn Code:
HouseInfo[houseid][hEnterX] = dini_Float(fstring, "EnterX");
HouseInfo[houseid][hEnterY] = dini_Float(fstring, "EnterY");
HouseInfo[houseid][hEnterZ] = dini_Float(fstring, "EnterZ");
HouseInfo[houseid][hExitX] = dini_Float(fstring, "ExitX");
HouseInfo[houseid][hExitY] = dini_Float(fstring, "ExitY");
HouseInfo[houseid][hExitZ] = dini_Float(fstring, "ExitZ");
HouseInfo[houseid][hInsideInt] = dini_Int(fstring, "InsideInt");
HouseInfo[houseid][hInsideVir] = dini_Int(fstring, "InsideVir");
HouseInfo[houseid][hOutsideInt] = dini_Int(fstring, "OutsideInt");
HouseInfo[houseid][hOUtsideVir] = dini_Int(fstring, "OutsideVir");
HouseInfo[houseid][hOwned] = dini_Bool(fstring, "Owned") ? true : false; //Because it is an boolean: ? true : false;
strmid(HouseInfo[houseid][hOwner], dini_Get(fstring, "Owner"), 0, false, strlen(dini_Get("Owner"))); //Used this one instead of {string} = {string}. I've ever read that this is faster
HouseInfo[houseid][hPrice] = dini_Int(fstring, "Price");
HouseInfo[houseid][hVecModel] = dini_Int(fstring, "HV_Model");
HouseInfo[houseid][hVecX] = dini_Float(fstring, "HV_PosX");
HouseInfo[houseid][hVecY] = dini_Float(fstring, "HV_PosZ");
HouseInfo[houseid][hVecZ] = dini_Float(fstring, "HV_PosZ");
HouseInfo[houseid][hVecA] = dini_Float(fstring, "HV_PosA");
There is a bit explaination, but I've told the most above the code. Well. Wit hthe LoadHouse command, we still only need to close the brackets.
It's also recommended to add an return 1; To prevent eventually bugs.
pawn Code:
return 1;
}
That's it.

Well. The server now can read integers/strings/floats from the file. We've also done that. Let's make the houses! That's awesome, of course (-.-).
We're gonna call the function "LoadHouseVisual(houseid, bool:reload = false);". I've added an bool:reload = false. That means, if you use "reload = true", delete mapicon,pickup,housecar of the house first to continue.
If you just use LoadHouseVisual(houseid); , it won't be removed first. only use true (LoadHouseVisual(houseid, true)) if you wanna RELOAD it!
Let's continue.
First, we need to stock it... (just like above). Then open the function with an bracket.
pawn Code:
stock LoadHouseVisual(houseid, bool:reload = false)
{
That's basic. YOU NEED TO KNOW THAT. Now, let's use the reload bool. If it's false (standard), nothing will happen. If it's true, it will remove mapicon/pickup/housecar.
pawn Code:
if(reload)
{
    DestroyDynamicMapIcon(HouseInfo[houseid][hIcon]);
    DestroyDynamicPickup(HouseInfo[houseid][hPickup]);
    DestroyVehicle(HouseCar[houseid]);
}
This ain't hard, is it? However, this code means:
Code:
if reload is true
//
Destroy Icon On Map [Houseicon of the 'houseid']
Destroy Pickup [Housepickup of the 'houseid']
Destroy Vehicle [Housecar of the 'houseid']
//
REMEMBER: Don't use return 1; !!!!! - DONT DO THAT!!!. If you now add an return 1; below the DestroyVehicle, the script will 'stop'. So it won't continue with loading.
And don't use an else after the closed bracket. That means, that it will do that 'else' thing (in bracket) only if reload = false. Hmm. What shall we do? - GOOD! We're now gonna load the 'visual' house
We need to make an map icon, pickup and an housecar (if the model is in the range of 400-611!). We also gonna make on the map een red/green house and as pickup green/blue. Just like in GTA SA Single Player.
Blue pickup if house is owned (and you can't buy it). Green pickup if it's free. Also the same with the icon (red/green).
pawn Code:
if(!HouseInfo[houseid][hOwned]) //Also known as 'if(HouseInfo[houseid][hOwned] == false)' - With aan boolean you can use '!{option}' and "{option}"! (!IsPlayerAdmin())) (IsPlayerAdmin())
{
    //So the house is not owned. Let's make an green mapicon and en green house pickup!
    HouseInfo[houseid][hIcon] = CreateDynamicMapIcon(HouseInfo[houseid][hEnterX], HouseInfo[houseid][hEnterY], HouseInfo[houseid][hEnterZ], 31, 0, HouseInfo[houseid][hOutsideVir], HouseInfo[houseid][hOutsideInt]);
    HouseInfo[houseid][hPickup] = CreateDynamicPickup(1273, 1, HouseInfo[houseid][hEnterX], HouseInfo[houseid][hEnterY], HouseInfo[houseid][hEnterZ], HouseInfo[houseid][hOutsideVir], HouseInfo[houseid][hOutsideInt]);
}
else
{
    //House is already owned. Blue pickup and red icon!
    HouseInfo[houseid][hIcon] = CreateDynamicMapIcon(HouseInfo[houseid][hEnterX], HouseInfo[houseid][hEnterY], HouseInfo[houseid][hEnterZ], 31, 0, HouseInfo[houseid][hOutsideVir], HouseInfo[houseid][hOutsideInt]);
    HouseInfo[houseid][hPickup] = CreateDynamicPickup(1273, 1, HouseInfo[houseid][hEnterX], HouseInfo[houseid][hEnterY], HouseInfo[houseid][hEnterZ], HouseInfo[houseid][hOutsideVir], HouseInfo[houseid][hOutsideInt]);
}
To find The pickup types/icons etc. use SA-MP Script King! This code means btw this:
Code:
if House is not owned
    hIcon of the house packet is NEW MAP ICON [Position X, Position Y, Position Z, Icon ID 31, color 0 (use 0 if you want standard color), Outside Vir of the house, Outside Int of the house;
    hPickup of the house packet is NEW PICKUP [Pickup model 1273, type 1, Position X, Pos Y, Pos Z, Vir Outside, Int Outside]
else, if house is already owned
    hIcon of the house packet is NEW MAP ICON [Position X, Position Y, Position Z, Icon ID 32, color 0 (use 0 if you want standard color), Outside Vir of the house, Outside Int of the house;
    hPickup of the house packet is NEW PICKUP [Pickup model 1272, type 1, Position X, Pos Y, Pos Z, Vir Outside, Int Outside]
At the pickup, you see as second parameter: 1. This means that the pickup won't dissapear when you touch it!
Omg do you know this: We only need to add housecar now, and the houses do exist! You can't do anything with it yet (And you need already house files).
Let's add the housecar. It is the same idea as the icon and the pickup. So I don't need to explain it. And I don't need an 'if not owned' and an 'else' for it. Unless if you want that an owned house has locked doors. https://sampwiki.blast.hk/wiki/SetVehicleParamsEx (0.3c only!)
pawn Code:
if(IsValidVehicleModel(HouseInfo[houseid][hVecModel])) //Is the vehicle model valid? In the range of 400-611? Function below
    HouseCar[houseid] = CreateVehicle(HouseInfo[houseid][hVecModel], HouseInfo[houseid][hVecX], HouseInfo[houseid][hVecY], HouseInfo[houseid][hVecZ], HouseInfo[houseid][hVecA], -1, -1, -1); //Color1 -1, Color2 -1, -1 respawn (only respawn with function or on vehicle death)
For one single line you don't need brackets! And here's the function IsValidVehicleModel:
pawn Code:
stock IsValidVehicleModel(vehiclemodel)
{
    if(vehiclemodel >= 400 && vehiclemodel <= 611)
        return true;
    return false;
}
Now close the function "LoadHouseVisual". It's done .

Omg we have the full load function. But you need files! To make a file, do it manuel (not recommended), or make an SAVE FUNCTION. Let's do the last one :')
pawn Code:
stock SaveHouse(houseid)
{
Again... XD. We are gonna use dini. Floats,integers,strings and a bool. It's not the same as LoadHouse! I'll give the code.
NOTE: You need the fstring stuff again! See the "LoadHouse" function how to make it.
pawn Code:
dini_FloatSet(fstring, "EnterX", HouseInfo[houseid][hEnterX]);
dini_FloatSet(fstring, "EnterY", HouseInfo[houseid][hEnterY]);
dini_FloatSet(fstring, "EnterZ", HouseInfo[houseid][hEnterZ]);
dini_FloatSet(fstring, "ExitX", HouseInfo[houseid][hExitX]);
dini_FloatSet(fstring, "ExitY", HouseInfo[houseid][hExitY]);
dini_FloatSet(fstring, "ExitZ", HouseInfo[houseid][hExitZ]);
dini_IntSet(fstring, "InsideInt", HouseInfo[houseid][hInsideInt]);
dini_IntSet(fstring, "InsideVir", HouseInfo[houseid][hInsideVir]);
dini_IntSet(fstring, "OutsideInt", HouseInfo[houseid][hOutsideInt]);
dini_IntSet(fstring, "OutsideVir", HouseInfo[houseid][hOUtsideVir]);
dini_BoolSet(fstring, "Owned", HouseInfo[houseid][hOwned]);
dini_Get(fstring, "Owner", HouseInfo[houseid][hOwner]); //No, not "GetSet"! :P
dini_IntSet(fstring, "Price", HouseInfo[houseid][hPrice]);
dini_IntSet(fstring, "HV_Model", HouseInfo[houseid][hVecModel]);
dini_FloatSet(fstring, "HV_PosX", HouseInfo[houseid][hVecX]);
dini_FloatSet(fstring, "HV_PosZ", HouseInfo[houseid][hVecY]);
dini_Float(fstring, "HV_PosZ", HouseInfo[houseid][hVecZ]);
dini_Float(fstring, "HV_PosA", HouseInfo[houseid][hVecA]);
And close the function with the bracket. And er, sorry that I didn't gave an explaination here. I don't know how to explain this. I just hope that you get this :P
And hmm.. OMG we can save+load houses now! The most important is done <3. Let's continue with the house options etc.

Step 3 - Some important stuff[u]
We won't use the command /enter and /exit. We're gonna use ENTER_VEHICLE to enter+exit (standard F and ENTER).
Let's do that with "OnPlayerKeyStateChange". Player may not be in an vehicle.
pawn Code:
public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
{
    if(newkeys & 16 && !IsPlayerInAnyVehicle(playerid)) //If player pressed ENTER_VEHICLe and if he's not in an vehicle
    {
        for(new i = 0; i < MAX_HOUSES; i++) //Loop through all the houses
        {
            if(IsPlayerInRangeOfPoint(playerid, 1.5, HouseInfo[i][hEnterX], HouseInfo[i][hEnterY], HouseInfo[i][hEnterZ]) && GetPlayerInterior(playerid) == HouseInfo[i][hOutsideInt] && GetPlayerVirtualWorld(playerid) == HouseInfo[i][hOutsideVir]) //Is player near house entrance, and if player is in interior of that house + virtual world
            {
                SetPlayerPos(playerid, HouseInfo[i][hExitX], HouseInfo[i][hExitY], HouseInfo[i][hExitZ]);
                SetPlayerInterior(playerid, HouseInfo[i][hInsideInt]);
                SetPlayerVirtualWorld(playerid, HouseInfo[i][hInsideVir]);
                //This will put the player IN the house
            }
            else if(IsPlayerInRangeOfPoint(playerid, 1.5, HouseInfo[i][hExitX], HouseInfo[i][hExitY], HouseInfo[i][hExitZ]) && GetPlayerInterior(playerid) == HouseInfo[i][hInsideInt] && GetPlayerVirtualWorld(playerid) == HouseInfo[i][hInsideVir]) //Same as the previous IsPlayerInRangeOfPoint, but now if the player is near the house exit+int+vir
            {
                SetPlayerPos(playerid, HouseInfo[i][hEnterX], HouseInfo[i][hEnterY], HouseInfo[i][hEnterZ]);
                SetPlayerInterior(playerid, HouseInfo[i][hOutsideInt]);
                SetPlayerVirtualWorld(playerid, HouseInfo[i][hOutsideVir]);
            }
        }
    }
    return 1;
}
Sorry, my explaination is starting to get worser :S. Getting tired of this . Whatever I gave some of it. I hope you understand this! This isn't meant to be an copy paste tutorial. It's intended to learn you something! You need to understand this!
However, this was it! You can now enter/exit houses! Isn't that cool?
Now, let's make an gametext, so a player can see how expensive the house is - And who the owner is, if it's owned.
We won't use OnPlayerPickupPickUp! We'll use an own made callback! We'll also use an timer! Let's make the timer first in OnGameModeInit:
pawn Code:
public OnGameModeInit()
{
    SetTimer("UpdatePlayersHouseInfo", 1000, true); //Every 1000 milli seconds (1 sec.) it will be used again
    return 1;
}
Use OnFilterScriptInit if you're gonna make an filterscript! (this script is only tested as an gamemode !)
Now the callback. Before you can use an 'public' callback, some one that isn't standard you need to forward it! So put an 'forward UpdatePlayersHouseInfo();' above your script! Below the includes and defines! (I prefer that. Some people prefer to putt it above the callback)
And the callback itself now. We're gonna make an string, and format it. Then, show it.
pawn Code:
public UpdatePlayersHouseInfo()
{
    new str[100]; //The string we are gonna format
    for(new i = 0; i < MAX_PLAYERS; i++) //Loop through all the players
    {
        for(new j = 0; j < MAX_HOUSES; j++) //Loop through all the houses
        {
            if(IsPlayerInRangeOfPoint(j, HouseInfo[j][hEnterX], HouseInfo[j][hEnterY], HouseInfo[j][hEnterZ]) && GetPlayerInterior(i) == HouseInfo[j][hOutsideInt] && GetPlayerVirtualWorld(i) == HouseInfo[j][hOutsideVir]) //You already know this! If you don't know it, do step 3 again!
            {
                if(HouseInfo[j][hOwned]) //Is house owned?
                    format(str, 100, "~w~House owned by ~r~%s", HouseInfo[j][hOwner]); //Will give: {white_color}House owned by {yellow_color}OWNER
                else //House isn't owned
                    format(str, 100, "~w~House for sale!~n~Price: ~g~$%d,-", HouseInfo[j][hPrice]); //Will give: {white_color}House for sale!{new line}Price: {green_color}$PRICE
                GameTextForPlayer(i, str, 2000, 3); //Show the text 2 seconds!
            }
         }
    }
    return 1;
}
Damn I'm really getting tired now :S. Whatever, we only need command right now! So ehm.. YIPPIE! The house system is almost done. We are far!

Step 4 - The commands.
It won't give alot explaination. And I'll give the next commands:
* Buy house
* Sell house
* TP Housecar
I'll give explaination IN the commands. So it's gonna be a bit copy paste
And don't forget: You need to use OnPlayerCommandText

/buyhouse
We're gonna check for the following things:
* Has the player enough money?
* Is the house not owned yet?
* Is the player in range of a house?
pawn Code:
if(!strcmp(cmdtext, "/buyhouse", true))
{
    new pName[MAX_PLAYER_NAME]; //For the player's name - For the house
    GetPlayerName(playerid, pName, MAX_PLAYER_NAME); //Get the name of the player and store it in [u]pName
    for(new i = 0; i < MAX_HOUSES; i++) //Last time I'm gonna say it: Loop through all the houses
    {
        if(IsPlayerInRangeOfPoint(playerid, 1.5, HouseInfo[i][hEnterX], HouseInfo[i][hEnterY], HouseInfo[i][hEnterZ]) && GetPlayerInterior(playerid) == HouseInfo[i][hOutsideInt] && GetPlayerVirtualWorld(playerid) == HouseInfo[i][hOutsideVir]) //Is player near house entrance, and if player is in interior of that house + virtual world (Last time I said this too!)
        {
            if(HouseInfo[i][hOwned]) return SendClientMessage(playerid, COLOR_RED, "This house is already owned!"); //Is the house owned? Then send message that it's owned and stop.
            if(GetPlayerMoney(playerid) < HouseInfo[i][hPrice]) return SendClientMessage(playerid, COLOR_RED, "You don't have enough money for this!"); //Has player too less money? Send him a message!
     
            HouseInfo[i][hOwned] = true; //The house is owned, where the player used /buyhouse
            strmid(HouseInfo[i][hOwner], pName, 0, false, strlen(pName)); //Put the players name into the "hOwner" of the house
            GivePlayerMoney(playerid, -HouseInfo[i][hPrice]); //Remove some money of the player.. The value of the house
            SendClientMessage(playerid, COLOR_GREEN, "House bought!"); //Send the player an message.
            SaveHouse(i);
            LoadHouseVisual(i, true); //Load House Visual. Now, I've added ', true': It will RELOAD now!
            return 1;
        }
    }
    return 1;
}
/sellhouse
We're gonna check for the following things:
* Is the player the owner of the house?
* Is the player in range of a house?
pawn Code:
if(!strcmp(cmdtext, "/sellhouse", true))
{
    new pName[MAX_PLAYER_NAME]; //See /buyhouse
    GetPlayerName(playerid, pName, MAX_PLAYER_NAME); //See new pName[MAX_PLAYER_NAME];
    for(new i = 0; i < MAX_HOUSES; i++)
    {
        if(IsPlayerInRangeOfPoint(playerid, 1.5, HouseInfo[i][hEnterX], HouseInfo[i][hEnterY], HouseInfo[i][hEnterZ]) && GetPlayerInterior(playerid) == HouseInfo[i][hOutsideInt] && GetPlayerVirtualWorld(playerid) == HouseInfo[i][hOutsideVir])
        {
            if(!strcmp(HouseInfo[i][hOwner], pName, false)) //Is the owner of the house the same as the players name (is the player the owner?? !)
            {
                strmid(HouseInfo[i][hOwner], "For Sale", 0, false, 8); //Set the owner of the house to "For Sale"
                HouseInfo[i][hOwned] = false; //House is not owner anymore!
                GivePlayerMoney(playerid, HouseInfo[i][hPrice]/2); //Give the player 50% of the house value back!
                SendClientMessage(playerid, COLOR_GREEN, "House sold!");
                SaveHouse(i);
                LoadHouseVisual(i, true); //Load House Visual. Now, I've added ', true': It will RELOAD now!
                return 1;
            }
         }
    }
    return 1;
}
/tphousecar
This uses an parameter. We need STRTOK! (I didn't use DCMD/ZCMD, idk why :P - Don't wanna change it now.)
It's like this: /tphousecar HOUSEID. You need to be the owner of the house!
pawn Code:
if(!strcmp(cmdtext, "/tphousecar", true))
{
    new pName[MAX_PLAYER_NAME], Float:X, Float:Y, Float:Z;
    new houseid = cmdtext[10]; //The param. /tphousecar is 0-8. With a space, 9. Then, the param is at 10.
    GetPlayerName(playerid, pName, MAX_PLAYER_NAME);
    if(!strcmp(HouseInfo[houseid][hOwner], pName, false)) return SendclientMessage(playerid, COLOR_RED, "You are not the owner of the house!");
    if(!IsPlayerInAnyVehicle(playerid)) return SendClientMessage(playerid, COLOR_RED, "You must be in an vehicle!"); //if is player not in an vehicle, send an message and stop (RETURN [message])
    GetVehiclePos(GetPlayerVehicleID(playerid), X, Y, Z);
    GetVehicleZAngle(GetPlayerVehicleID(playerid), A);
    HouseInfo[houseid][hVecX] = X;
    HouseInfo[houseid][hVecY] = Y;
    HouseInfo[houseid][hVecZ] = Z;
    HouseInfo[houseid][hVecA] = A;
    return 1;
}
For the other commands, it's a bit the same like this.
TP HOUSE (EXIT): Just set the EnterX-Y-Z / ExitX-Y-Z to X,Y,Z (getplayerpos). For the exit, get also interior+virtual world. Easy
With housecar model: Easy too; hVecModel = {model};

Sorry for the end, the bad explaination. I'm tired now xD. And sorry for the late release: I fixed a bug first, and I had holiday
I was somewhere else. Whatever, I'm just back 30 minuted and I've finished it.

Bugs
No idea. This one is different then mine. I used it as a gamemode, and the player can have 1 house there (don't check for playername-housename, but houseid-player own house id)

And ehm, I won't give the whole script. This is an tutorial (I guess), not an filterscript! You should be able to make your own system right now.
But of course, I can help you if you have still problems.

Kind Regards,
Kevin
Reply
#2

Looks nice.
Reply
#3

Nice tutorial,
Helps alot of people starting to make RP scripts etc.
Good job.
Reply
#4

Great! But make it better, SetHInterior - Set House Interior
Reply
#5

Thank You All (A)
and @willsuckformoney:
This is just a tutorial, not a filterscript, I didn't give all the commands that can be usefully
Reply
#6

Well make a FS with this.
Reply
#7

Nah, Maybe later
Reply
#8

Great tutorial.
Reply
#9

Nice tutorial!
Reply
#10

I downloaded the FS then i add that in server.cfg

if i start server then samp-server.exe crash what is problem?
Reply
#11

Like I said: I created it as an GameMode.
It is still 'public OnGameModeInit' - You need to change that to 'public OnFilterScriptInit'

[EDIT]
Oops I forgot to give one file: the 'Houses.cfg'. I am busy with it :$
Reply
#12

Okay busy too.
And thanks for placing a reaction, I forgot to post the Houses.cfg
I'll do it OR in one and a half our, OR tomorrow morning.

Kind Regards,
Kwarde
Reply
#13

Why while loading the houses 'split', and for the commands 'sscanf'?
Reply
#14

Rofl, this is not tutorial, this is another example of bad house structure >_<
if(IsPlayerInAnyVehicle(playerid)) //Is Player In any vehicle? xDDDDDDDDDDDDDDD
Reply
#15

Quote:
Originally Posted by toneysix
View Post
if(IsPlayerInAnyVehicle(playerid)) //Is Player In any vehicle? xDDDDDDDDDDDDDDD
xD

Quote:
Originally Posted by toneysix
View Post
Rofl, this is not tutorial, this is another example of bad house structure >_<
Well. Now you've said that... You're right :P
Reply
#16

And if you didnt know, when you add this house system in your mode, server will get crash
Reply
#17

Its a larp style system.. Very good for beginers
Reply
#18

Quote:
Originally Posted by [H]265
View Post
And if you didnt know, when you add this house system in your mode, server will get crash
Did you make the file with all the standard house settings?
Reply
#19

Why you don't work this with ZCMD? :S
Reply
#20

Quote:
Originally Posted by Aleluja
View Post
Why you don't work this with ZCMD? :S
You can rescript all commands to be in ZCMD in less of 2 mins.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)