#include forward OnPropertyCreated(propertyid); forward OnPropertyDeleted(propertyid); #define INVALID_PROPERTY_ID -1 #define MAX_PROP_DESCRIPTION 129 #define MAX_PROP_ADDRESS 37 // Blank pickup model 19300 #define PROP_PICKUP 19524 #define PROP_PICKUP_DISTANCE 20.00 #define TYPE_HOUSE 10 #define TYPE_BIZ_STORE 20 #define TYPE_BIZ_CLOTHING 21 #define TYPE_BIZ_BAR 22 #define TYPE_BIZ_CASINO 23 #define TYPE_BIZ_FURNITURE 24 #define TYPE_BIZ_RESTAURANT 25 #define TYPE_ENT_NONE 40 #define TYPE_ENT_POLICE 41 static PropOwnerSQLID[MAX_PROPERTIES]; static PropType[MAX_PROPERTIES]; static PropDescription[MAX_PROPERTIES][MAX_PROP_DESCRIPTION]; static PropAddress[MAX_PROPERTIES][MAX_PROP_ADDRESS]; static PropPrice[MAX_PROPERTIES]; static PropPickup[MAX_PROPERTIES]; static PropOutsideInt[MAX_PROPERTIES]; static PropInsideInt[MAX_PROPERTIES]; static PropOutsideVW[MAX_PROPERTIES]; static Float:PropExtPosX[MAX_PROPERTIES]; static Float:PropExtPosY[MAX_PROPERTIES]; static Float:PropExtPosZ[MAX_PROPERTIES]; static Float:PropExtPosA[MAX_PROPERTIES]; static Float:PropIntPosX[MAX_PROPERTIES]; static Float:PropIntPosY[MAX_PROPERTIES]; static Float:PropIntPosZ[MAX_PROPERTIES]; static Float:PropIntPosA[MAX_PROPERTIES]; new Iterator:Property; new Iterator:House; new Iterator:Business; new Iterator:Entrance; hook OnMySQLConnected() { inline const OnPropertyFound() { for(new i; i < cache_num_rows(); i++) { if(Iter_Free(Property) == INVALID_ITERATOR_SLOT) { printf("The maximum amount of properties has been reached. (%d)", Iter_Count(Property)); break; } new propertyid = INVALID_ITERATOR_SLOT; cache_get_value_name_int(i, "id", propertyid); cache_get_value_name_int(i, "owner_id", PropOwnerSQLID[propertyid]); cache_get_value_name_int(i, "type", PropType[propertyid]); cache_get_value_name(i, "description", PropDescription[propertyid]); cache_get_value_name(i, "address", PropAddress[propertyid]); cache_get_value_name_int(i, "price", PropPrice[propertyid]); cache_get_value_name_int(i, "outside_int", PropOutsideInt[propertyid]); cache_get_value_name_int(i, "inside_int", PropInsideInt[propertyid]); cache_get_value_name_int(i, "outside_vw", PropOutsideVW[propertyid]); cache_get_value_name_float(i, "ext_pos_x", PropExtPosX[propertyid]); cache_get_value_name_float(i, "ext_pos_y", PropExtPosY[propertyid]); cache_get_value_name_float(i, "ext_pos_z", PropExtPosZ[propertyid]); cache_get_value_name_float(i, "ext_pos_a", PropExtPosA[propertyid]); cache_get_value_name_float(i, "int_pos_x", PropIntPosX[propertyid]); cache_get_value_name_float(i, "int_pos_y", PropIntPosY[propertyid]); cache_get_value_name_float(i, "int_pos_z", PropIntPosZ[propertyid]); cache_get_value_name_float(i, "int_pos_a", PropIntPosA[propertyid]); PropPickup[propertyid] = CreateDynamicPickup(PROP_PICKUP, 1, PropExtPosX[propertyid], PropExtPosY[propertyid], PropExtPosZ[propertyid], PropOutsideVW[propertyid], PropOutsideInt[propertyid]); switch(PropType[propertyid]) { case 10..19: Iter_Add(House, propertyid); case 20..39: Iter_Add(Business, propertyid); case 40..60: Iter_Add(Entrance, propertyid); } Iter_Add(Property, propertyid); } } MySQL_TQueryInline(MySQL_GetHandle(), using inline OnPropertyFound, "SELECT * FROM properties"); } CMD:createproperty(playerid, params[]) { if(Iter_Free(Property) == INVALID_ITERATOR_SLOT) return SendErrorMessage(playerid, "The maximum amount of properties has been reached."); if(isnull(params)) return SendSyntaxMessage(playerid, "/createproperty (options: house, business, entrance)"); new address[MAX_PROP_ADDRESS]; new description[MAX_PROP_DESCRIPTION]; new zoneName[MAX_MAP_ZONE_NAME]; new price; new interiorid; new type = TYPE_HOUSE; new propertyid = Iter_Free(Property); new outsideInt = GetPlayerInterior(playerid); new outsideVW = GetPlayerVirtualWorld(playerid); new MapZone:zone = GetPlayerMapZone(playerid); new Float:eX, Float:eY, Float:eZ, Float:eA; GetPlayerPos(playerid, eX, eY, eZ); GetPlayerFacingAngle(playerid, eA); GetMapZoneName(zone, zoneName); if(!strcmp(params, "house", true, 5)) { if(sscanf(params, "{s[6]}ii", interiorid, price)) return SendSyntaxMessage(playerid, "/createproperty house (interior) (price)"); format(address, sizeof(address), "%d, %s, Los Santos", propertyid + 1000, zoneName); format(description, sizeof(description), "House"); } else if(!strcmp(params, "business", true, 8)) { if(sscanf(params, "{s[9]}iii", type, interiorid, price)) { SendSyntaxMessage(playerid, "/createproperty business (type) (interior) (price)"); return va_SendClientMessage(playerid, 0xc2a3a3ff, "Types: %d (Store) | %d (Clothing) | %d (Bar) | %d (Casino) | %d (Furniture) | %d (Restaurant)", TYPE_BIZ_STORE, TYPE_BIZ_CLOTHING, TYPE_BIZ_BAR, TYPE_BIZ_CASINO, TYPE_BIZ_FURNITURE, TYPE_BIZ_RESTAURANT); } if(!IsBusinessTypeValid(type)) { SendErrorMessage(playerid, "That business type is not valid."); return va_SendClientMessage(playerid, 0xc2a3a3ff, "Types: %d (Store) | %d (Clothing) | %d (Bar) | %d (Casino) | %d (Furniture) | %d (Restaurant)", TYPE_BIZ_STORE, TYPE_BIZ_CLOTHING, TYPE_BIZ_BAR, TYPE_BIZ_CASINO, TYPE_BIZ_FURNITURE, TYPE_BIZ_RESTAURANT); } format(address, sizeof(address), "%s, Los Santos", zoneName); format(description, sizeof(description), "Business"); } else if(!strcmp(params, "entrance", true, 8)) { if(sscanf(params, "{s[9]}iis[128]", type, interiorid, description)) { SendSyntaxMessage(playerid, "/createproperty entrance (type) (interior) (description)"); return va_SendClientMessage(playerid, 0xc2a3a3ff, "Types: %d (None) | %d (Police)", TYPE_ENT_NONE, TYPE_ENT_POLICE); } if(!IsEntranceTypeValid(type)) { SendErrorMessage(playerid, "That entrance type is not valid."); return va_SendClientMessage(playerid, 0xc2a3a3ff, "Types: %d (None) | %d (Police)", TYPE_ENT_NONE, TYPE_ENT_POLICE); } if(strlen(description) > MAX_PROP_DESCRIPTION - 1) return SendErrorMessageF(playerid, "Invalid description length, it must be below %d characters.", MAX_PROP_DESCRIPTION - 1); format(address, sizeof(address), "%s, Los Santos", zoneName); } else return SendSyntaxMessage(playerid, "/createproperty (options: house, business, entrance)"); if(!IsValidInterior(interiorid)) return SendErrorMessage(playerid, "You specified an invalid interior ID."); if(price < 0) return SendErrorMessage(playerid, "Please enter a valid price."); new Float:iX, Float:iY, Float:iZ, Float:iA; new insideInt = Interior_GetInterior(interiorid); Interior_GetPosition(interiorid, iX, iY, iZ, iA); PropType[propertyid] = type; PropDescription[propertyid] = description; PropAddress[propertyid] = address; PropPrice[propertyid] = price; PropOutsideInt[propertyid] = outsideInt; PropInsideInt[propertyid] = insideInt; PropOutsideVW[propertyid] = outsideVW; PropExtPosX[propertyid] = eX; PropExtPosY[propertyid] = eY; PropExtPosZ[propertyid] = eZ; PropExtPosA[propertyid] = eA; PropIntPosX[propertyid] = iX; PropIntPosY[propertyid] = iY; PropIntPosZ[propertyid] = iZ; PropIntPosA[propertyid] = iA; PropPickup[propertyid] = CreateDynamicPickup(PROP_PICKUP, 1, PropExtPosX[propertyid], PropExtPosY[propertyid], PropExtPosZ[propertyid], PropOutsideVW[propertyid], PropOutsideInt[propertyid]); new query[582]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "INSERT INTO properties (id, type, description, address, price, outside_int, inside_int, outside_vw, ext_pos_x, ext_pos_y, ext_pos_z, ext_pos_a, int_pos_x, int_pos_y, int_pos_z, int_pos_a) VALUES (%d, %d, '%e', '%e', %d, %d, %d, %d, %f, %f, %f, %f, %f, %f, %f, %f)", propertyid, type, description, address, price, outsideInt, insideInt, outsideVW, eX, eY, eZ, eA, iX, iY, iZ, iA); mysql_tquery(MySQL_GetHandle(), query); switch(PropType[propertyid]) { case 10..19: Iter_Add(House, propertyid); case 20..39: Iter_Add(Business, propertyid); case 40..60: Iter_Add(Entrance, propertyid); } Iter_Add(Property, propertyid); CallRemoteFunction("OnPropertyCreated", "i", propertyid); SendAdminWarningF(playerid, "You have created a property. ID: %d, Type: %d - %s, Price: $%s, Description: %s", propertyid, type, Property_GetTypeName(type), MoneyFormat(price), description); return 1; } CMD:deleteproperty(playerid, params[]) { new propertyid = INVALID_PROPERTY_ID; if(isnull(params)) { propertyid = GetCurrentProperty(playerid); if(propertyid == INVALID_PROPERTY_ID) { propertyid = GetNearbyProperty(playerid); if(propertyid == INVALID_PROPERTY_ID) return SendErrorMessage(playerid, "You need to be at one of the properties to delete it. (or type /deleteproperty id)"); } } else { if(sscanf(params, "i", propertyid)) return SendSyntaxMessage(playerid, "/deleteproperty (id)"); if(!IsValidProperty(propertyid)) return SendErrorMessage(playerid, "You specified an invalid property."); } foreach(new i : Player) if(GetCurrentProperty(i) == propertyid) { SendAdminWarning(i, "This property has been deleted."); SetPlayerPos(i, PropExtPosX[propertyid], PropExtPosY[propertyid], PropExtPosZ[propertyid]); SetPlayerFacingAngle(i, PropExtPosA[propertyid]); SetPlayerInterior(i, PropOutsideInt[propertyid]); SetPlayerVirtualWorld(i, PropOutsideVW[propertyid]); SetCameraBehindPlayer(i); } DestroyDynamicPickup(PropPickup[propertyid]); new query[78]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "DELETE FROM properties WHERE id = %d", propertyid); mysql_tquery(MySQL_GetHandle(), query); Iter_Remove(House, propertyid); Iter_Remove(Business, propertyid); Iter_Remove(Entrance, propertyid); Iter_Remove(Property, propertyid); CallRemoteFunction("OnPropertyDeleted", "i", propertyid); SendAdminWarningF(playerid, "You have deleted a property. (ID %d)", propertyid); return 1; } CMD:gotoproperty(playerid, params[]) { new propertyid; if(sscanf(params, "i", propertyid)) return SendSyntaxMessage(playerid, "/gotoproperty (id)"); if(!IsValidProperty(propertyid)) return SendErrorMessage(playerid, "You specified an invalid property."); SetPlayerPos(playerid, PropExtPosX[propertyid], PropExtPosY[propertyid], PropExtPosZ[propertyid]); SetPlayerFacingAngle(playerid, PropExtPosA[propertyid]); SetPlayerInterior(playerid, PropOutsideInt[propertyid]); SetPlayerVirtualWorld(playerid, PropOutsideVW[propertyid]); SetCameraBehindPlayer(playerid); SendAdminWarningF(playerid, "You have teleported to a property. (ID %d)", propertyid); return 1; } CMD:enter(playerid, params[]) { new propertyid = GetNearbyProperty(playerid); if(propertyid == INVALID_PROPERTY_ID) return 1; SetPlayerPos(playerid, PropIntPosX[propertyid], PropIntPosY[propertyid], PropIntPosZ[propertyid]); SetPlayerInterior(playerid, PropInsideInt[propertyid]); SetPlayerVirtualWorld(playerid, propertyid + 1000); SetPlayerFacingAngle(playerid, PropIntPosA[propertyid]); SetCameraBehindPlayer(playerid); return 1; } CMD:exit(playerid, params[]) { new propertyid = GetCurrentProperty(playerid); if(propertyid == INVALID_PROPERTY_ID) return 1; if(IsPlayerInRangeOfPoint(playerid, 1.5, PropIntPosX[propertyid], PropIntPosY[propertyid], PropIntPosZ[propertyid])) { SetPlayerPos(playerid, PropExtPosX[propertyid], PropExtPosY[propertyid], PropExtPosZ[propertyid]); SetPlayerInterior(playerid, PropOutsideInt[propertyid]); SetPlayerVirtualWorld(playerid, PropOutsideVW[propertyid]); SetPlayerFacingAngle(playerid, PropExtPosA[propertyid]); SetCameraBehindPlayer(playerid); } return 1; } stock GetNearbyProperty(playerid) { foreach(new i : Property) { if(IsPlayerInRangeOfPoint(playerid, 1.5, PropExtPosX[i], PropExtPosY[i], PropExtPosZ[i])) { if(GetPlayerVirtualWorld(playerid) == PropOutsideVW[i] && GetPlayerInterior(playerid) == PropOutsideInt[i]) return i; } } return INVALID_PROPERTY_ID; } stock GetCurrentProperty(playerid) { new propertyid = GetPlayerVirtualWorld(playerid) - 1000; if(!IsValidProperty(propertyid)) { return INVALID_PROPERTY_ID; } return propertyid; } stock Property_SetOwnerSQLID(propertyid, ownerid) { PropOwnerSQLID[propertyid] = ownerid; new query[84]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE properties SET owner_id = %d WHERE id = %d", ownerid, propertyid); mysql_tquery(MySQL_GetHandle(), query); } stock Property_GetOwnerSQLID(propertyid) { return PropOwnerSQLID[propertyid]; } stock Property_SetType(propertyid, type) { PropType[propertyid] = type; new query[84]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE properties SET type = %d WHERE id = %d", type, propertyid); mysql_tquery(MySQL_GetHandle(), query); } stock Property_GetType(propertyid) { return PropType[propertyid]; } stock Property_GetTypeName(type) { new string[18]; switch(type) { case TYPE_HOUSE: strcat(string, "House"); case TYPE_BIZ_STORE: strcat(string, "Store"); case TYPE_BIZ_CLOTHING: strcat(string, "Clothing"); case TYPE_BIZ_BAR: strcat(string, "Bar"); case TYPE_BIZ_CASINO: strcat(string, "Casino"); case TYPE_BIZ_FURNITURE: strcat(string, "Furniture Store"); case TYPE_BIZ_RESTAURANT: strcat(string, "Restaurant"); case TYPE_ENT_NONE: strcat(string, "None"); case TYPE_ENT_POLICE: strcat(string, "Police"); } return string; } stock Property_SetDescription(propertyid, const description[]) { format(PropDescription[propertyid], MAX_PROP_DESCRIPTION, description); new query[178]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE properties SET description = '%e' WHERE id = %d", description, propertyid); mysql_tquery(MySQL_GetHandle(), query); } stock Property_GetDescription(propertyid) { return PropDescription[propertyid]; } stock Property_SetAddress(propertyid, const address[]) { format(PropAddress[propertyid], MAX_PROP_ADDRESS, address); new query[112]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE properties SET address = '%e' WHERE id = %d", address, propertyid); mysql_tquery(MySQL_GetHandle(), query); } stock Property_GetAddress(propertyid) { return PropAddress[propertyid]; } stock Property_SetPrice(propertyid, price) { PropPrice[propertyid] = price; new query[84]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE properties SET price = %d WHERE id = %d", price, propertyid); mysql_tquery(MySQL_GetHandle(), query); } stock Property_GetPrice(propertyid) { return PropPrice[propertyid]; } stock Property_GetPickup(propertyid) { return PropPickup[propertyid]; } stock Property_GetOutsideInterior(propertyid) { return PropOutsideInt[propertyid]; } stock Property_GetInsideInterior(propertyid) { return PropInsideInt[propertyid]; } stock Property_GetOutsideVW(propertyid) { return PropOutsideVW[propertyid]; } stock Property_SetExtPos(propertyid, world, interior, Float:x, Float:y, Float:z, Float:a) { PropOutsideVW[propertyid] = world; PropOutsideInt[propertyid] = interior; PropExtPosX[propertyid] = x; PropExtPosY[propertyid] = y; PropExtPosZ[propertyid] = z; PropExtPosA[propertyid] = a; DestroyDynamicPickup(PropPickup[propertyid]); PropPickup[propertyid] = CreateDynamicPickup(PROP_PICKUP, 1, x, y, z, world, interior, -1, PROP_PICKUP_DISTANCE); new query[208]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE properties SET outside_vw = %d, outside_int = %d, ext_pos_x = %f, ext_pos_y = %f, ext_pos_z = %f, ext_pos_a = %f WHERE id = %d", world, interior, x, y, z, a, propertyid); mysql_tquery(MySQL_GetHandle(), query); } stock Property_GetExtPos(propertyid, &Float:x, &Float:y, &Float:z, &Float:a = 0.0) { #pragma unused x, y, z, a x = PropExtPosX[propertyid]; y = PropExtPosY[propertyid]; z = PropExtPosZ[propertyid]; a = PropExtPosA[propertyid]; } stock Property_SetIntPos(propertyid, interior, Float:x, Float:y, Float:z, Float:a) { PropInsideInt[propertyid] = interior; PropIntPosX[propertyid] = x; PropIntPosY[propertyid] = y; PropIntPosZ[propertyid] = z; PropIntPosA[propertyid] = a; new query[178]; mysql_format(MySQL_GetHandle(), query, sizeof(query), "UPDATE properties SET inside_int = %d, int_pos_x = %f, int_pos_y = %f, int_pos_z = %f, int_pos_a = %f WHERE id = %d", interior, x, y, z, a, propertyid); mysql_tquery(MySQL_GetHandle(), query); } stock Property_GetIntPos(propertyid, &Float:x, &Float:y, &Float:z, &Float:a = 0.0) { #pragma unused x, y, z, a x = PropIntPosX[propertyid]; y = PropIntPosY[propertyid]; z = PropIntPosZ[propertyid]; a = PropIntPosA[propertyid]; } stock IsValidProperty(propertyid) { if(Iter_Contains(Property, propertyid)) { return true; } return false; } stock IsPropertyAHouse(propertyid) { if(Iter_Contains(House, propertyid)) { return true; } return false; } stock IsPropertyABusiness(propertyid) { if(Iter_Contains(Business, propertyid)) { return true; } return false; } stock IsPropertyAnEntrance(propertyid) { if(Iter_Contains(Entrance, propertyid)) { return true; } return false; } stock IsHouseTypeValid(type) { switch(type) { case TYPE_HOUSE: return true; } return false; } stock IsBusinessTypeValid(type) { switch(type) { case TYPE_BIZ_STORE, TYPE_BIZ_CLOTHING, TYPE_BIZ_BAR, TYPE_BIZ_CASINO, TYPE_BIZ_FURNITURE, TYPE_BIZ_RESTAURANT: return true; } return false; } stock IsEntranceTypeValid(type) { switch(type) { case TYPE_ENT_NONE, TYPE_ENT_POLICE: return true; } return false; }