diff --git a/gamemodes/irresistible/README.md b/gamemodes/irresistible/README.md index 866f161..8bf1b90 100644 --- a/gamemodes/irresistible/README.md +++ b/gamemodes/irresistible/README.md @@ -36,3 +36,5 @@ - Called when a player closes a model preview - `OnGangLoad( gangid )` - Called when a gang is loaded +- `OnGangUnload( gangid, bool: deleted )` + - Called when a gang is unloaded (or deleted) diff --git a/gamemodes/irresistible/cnr/features/gangs/facilities.pwn b/gamemodes/irresistible/cnr/features/gangs/facilities.pwn index 9a08278..2339b10 100644 --- a/gamemodes/irresistible/cnr/features/gangs/facilities.pwn +++ b/gamemodes/irresistible/cnr/features/gangs/facilities.pwn @@ -23,6 +23,10 @@ // #define DIALOG_FACILITY_AMMU ( 9239 ) // #define DIALOG_FACILITY_AMMU_BUY ( 9299 ) +/* ** Macros ** */ +#define Facility_IsValid(%0) \ + (0 <= %0 < MAX_FACILITIES && Iter_Contains(gangfacilities, %0)) + /* ** Variables ** */ enum E_GANG_FACILITIES { @@ -96,12 +100,12 @@ hook OnPlayerEnterDynamicCP( playerid, checkpointid ) foreach ( new facility : gangfacilities ) { - new turfid = g_gangFacilities[ facility ] [ E_TURF_ID ]; - new facility_gangid = Turf_GetFacility( turfid ); - // entrance if ( checkpointid == g_gangFacilities[ facility ] [ E_CHECKPOINT ] [ 0 ] ) { + new turfid = g_gangFacilities[ facility ] [ E_TURF_ID ]; + new facility_gangid = Turf_GetFacility( turfid ); + // not in the gang / not a turf owner if ( ! ( Turf_GetOwner( turfid ) == gangid || facility_gangid == gangid ) ) { @@ -169,9 +173,9 @@ hook OnPlayerEnterDynamicCP( playerid, checkpointid ) } // mechanic - else if ( checkpointid == g_gangFacilities[ facility ] [ E_TRAVEL_CP ] ) + else if ( checkpointid == g_gangFacilities[ facility ] [ E_MECHANIC_CP ] ) { - return ShowPlayerGangVehicleMenu( playerid, facility_gangid ); + return ShowPlayerGangVehicleMenu( playerid, facility ); } // orbital cannon @@ -451,7 +455,7 @@ thread OnGangFaciltiesLoad( ) CreateDynamic3DTextLabel( "[FAST TRAVEL]", COLOR_GOLD, infront_x, infront_y, g_gangFacilityInterior[ type ] [ E_TRAVEL_POS ] [ 2 ], 20.0, .worldid = g_gangFacilities[ id ] [ E_WORLD ] ); // mechanic actor - CreateDynamicActor( 61, g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 0 ], g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 1 ], g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 2 ], g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 3 ], true, 100.0, .worldid = g_gangFacilities[ id ] [ E_WORLD ] ); + CreateDynamicActor( 268, g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 0 ], g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 1 ], g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 2 ], g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 3 ], true, 100.0, .worldid = g_gangFacilities[ id ] [ E_WORLD ] ); infront_x = g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 0 ] + 2.0 * floatsin( -g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 3 ], degrees ); infront_y = g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 1 ] + 2.0 * floatcos( -g_gangFacilityInterior[ type ] [ E_MECHANIC_POS ] [ 3 ], degrees ); @@ -512,12 +516,18 @@ stock GetFacilityInteriorType( gang_sql_id ) } stock GetGangIDFromFacilityID( facilityid ) { - foreach ( new f : gangs ) if ( g_gangFacilities[ facilityid ] [ E_GANG_SQL_ID ] == g_gangData[ g ] [ E_SQL_ID ] ) { + foreach ( new f : gangs ) if ( g_gangFacilities[ facilityid ] [ E_GANG_SQL_ID ] == g_gangData[ f ] [ E_SQL_ID ] ) { return f; } return ITER_NONE; } +stock GetGangFacilityPos( facilityid, &Float: X, &Float: Y, &Float: Z ) { + X = g_gangFacilities[ facilityid ] [ E_X ]; + Y = g_gangFacilities[ facilityid ] [ E_Y ]; + Z = g_gangFacilities[ facilityid ] [ E_Z ]; +} + #if FACILITY_TAKEOVER_ENABLED == true CMD:plant( playerid, params[ ] ) { PlantFacilityC4( playerid, GetPVarInt( playerid, "in_facility" ) ); diff --git a/gamemodes/irresistible/cnr/features/gangs/gangs.pwn b/gamemodes/irresistible/cnr/features/gangs/gangs.pwn index 51df0bb..c858537 100644 --- a/gamemodes/irresistible/cnr/features/gangs/gangs.pwn +++ b/gamemodes/irresistible/cnr/features/gangs/gangs.pwn @@ -792,6 +792,9 @@ stock DestroyGang( gangid, bool: soft_delete, bool: iter_remove = true ) p_GangID[ i ] = INVALID_GANG_ID; } + // Callback + CallLocalFunction( "OnGangUnload", "dd", gangid, ! soft_delete ); + // Reset gang data g_gangData[ gangid ] [ E_SQL_ID ] = 0; g_gangData[ gangid ] [ E_LEADER ] = 0; @@ -985,6 +988,7 @@ stock SetPlayerGang( playerid, joining_gang ) return 1; } +stock GetGangCash( gangid ) return g_gangData[ gangid ] [ E_BANK ]; stock GiveGangCash( gangid, cash ) { g_gangData[ gangid ] [ E_BANK ] += cash; } diff --git a/gamemodes/irresistible/cnr/features/gangs/gvehicles.pwn b/gamemodes/irresistible/cnr/features/gangs/gvehicles.pwn index c4c0ca3..4ebf8df 100644 --- a/gamemodes/irresistible/cnr/features/gangs/gvehicles.pwn +++ b/gamemodes/irresistible/cnr/features/gangs/gvehicles.pwn @@ -1,30 +1,32 @@ /* * Irresistible Gaming (c) 2018 * Developed by Lorenc Pekaj - * Module: - * Purpose: + * Module: cnr\features\gangs\gvehicles.pwn + * Purpose: gang vehicles (requires a gang facility to spawn the vehicles) for gangs */ /* ** Includes ** */ #include < YSI\y_hooks > /* ** Definitions ** */ -#define MAX_GANG_VEHICLES ( 3 ) +#define MAX_GANG_VEHICLES ( 5 ) #define DIALOG_GANG_VEHICLE_MENU 2399 #define DIALOG_GANG_VEHICLE_SPAWN 2400 -#define DIALOG_GANG_VD_BUY 2401 -#define DIALOG_GANG_VD_OPTIONS 2402 -#define DIALOG_GANG_VD_CATEGORY 2403 +#define DIALOG_GANG_VEHICLE_SELL 2401 +#define DIALOG_GANG_VD_BUY 2402 +#define DIALOG_GANG_VD_OPTIONS 2403 +#define DIALOG_GANG_VD_CATEGORY 2404 #define PREVIEW_MODEL_GVEHICLE ( 6 ) /* ** Macros ** */ #define IsValidGangVehicle(%0,%1) \ - ( 0 <= %0 < MAX_GANG_VEHICLES && Iter_Contains( gangvehicles<%0>, %1 ) ) + ( 0 <= %1 < MAX_GANG_VEHICLES && Iter_Contains( gangvehicles<%0>, %1 ) ) /* ** Constants ** */ static const GANG_VEHICLE_PRICE_FACTOR = 4; +static const GANG_VEHICLE_SPAWN_COOLDOWN = 180; /* ** Variables ** */ enum E_GANG_VEHICLE_DATA @@ -37,6 +39,7 @@ enum E_GANG_VEHICLE_DATA new g_gangVehicleData [ MAX_GANGS ] [ MAX_GANG_VEHICLES ] [ E_GANG_VEHICLE_DATA ]; new g_gangVehicleModifications [ MAX_GANGS ] [ MAX_GANG_VEHICLES ] [ MAX_CAR_MODS ]; new Iterator: gangvehicles < MAX_GANGS, MAX_GANG_VEHICLES >; +new bool: g_gangVehicle [ MAX_VEHICLES char ]; /* ** Hooks ** */ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) @@ -47,8 +50,9 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) if ( dialogid == DIALOG_GANG_VEHICLE_MENU && response ) { new gangid = GetPVarInt( playerid, "gang_vehicle_gang" ); + new facilityid = GetPVarInt( playerid, "gang_vehicle_facility" ); - if ( ! IsValidGangID ( gangid ) ) { + if ( ! IsValidGangID ( gangid ) || ! Facility_IsValid( facilityid ) ) { return SendError( playerid, "There was an error processing gang vehicles, please try again." ); } @@ -59,23 +63,77 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) { if ( ! Iter_Count( gangvehicles< gangid > ) ) { SendError( playerid, "This gang does not have any vehicles purchased." ); - return ShowPlayerGangVehicleMenu( playerid, gangid ); + return ShowPlayerGangVehicleMenu( playerid, facilityid ); } - szBigString = ""COL_WHITE"Vehicle\t"COL_WHITE"Availablity\n"; - - foreach ( new slotid : gangvehicles< gangid > ) - { - format( szBigString, sizeof( szBigString ), "%s%s\t%s\n", szBigString, - GetVehicleName( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ), - g_gangVehicleData[ gangid ] [ slotid ] [ E_ACTIVATION_TIME ] > current_time ? ( secondstotime( g_gangVehicleData[ gangid ] [ slotid ] [ E_ACTIVATION_TIME ] - current_time ) ) : ( COL_GREEN # "Available!" ) - ); - } - return ShowPlayerDialog( playerid, DIALOG_GANG_VEHICLE_SPAWN, DIALOG_STYLE_TABLIST_HEADERS, ""COL_WHITE"Gang Vehicles - Spawn", szBigString, "Select", "Close" ); + return GangVehicles_ShowSpawnList( playerid, gangid ); } // buy vehicle case 1: ShowBuyableVehiclesList( playerid, DIALOG_GANG_VD_CATEGORY, "Back" ); + + // sell vehicle + case 2: + { + if ( ! Iter_Count( gangvehicles< gangid > ) ) { + SendError( playerid, "This gang does not have any vehicles purchased." ); + return ShowPlayerGangVehicleMenu( playerid, facilityid ); + } + + if ( ! IsPlayerGangLeader( playerid, gangid ) ) { + SendError( playerid, "You are not the leader of this gang." ); + return ShowPlayerGangVehicleMenu( playerid, facilityid ); + } + + szBigString = ""COL_WHITE"Vehicle\t"COL_WHITE"Sell Price\n"; + + foreach ( new slotid : gangvehicles< gangid > ) + { + new + sell_price = ( GetBuyableVehiclePrice( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ) * GANG_VEHICLE_PRICE_FACTOR ) / 2; + + format( szBigString, sizeof( szBigString ), "%s%s\t"COL_GOLD"%s\n", szBigString, GetVehicleName( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ), cash_format( sell_price ) ); + } + return ShowPlayerDialog( playerid, DIALOG_GANG_VEHICLE_SELL, DIALOG_STYLE_TABLIST_HEADERS, ""COL_WHITE"Gang Vehicles - Sell", szBigString, "Sell", "Back" ); + } + } + return 1; + } + else if ( dialogid == DIALOG_GANG_VEHICLE_SELL ) + { + new gangid = GetPVarInt( playerid, "gang_vehicle_gang" ); + new facilityid = GetPVarInt( playerid, "gang_vehicle_facility" ); + + if ( ! IsValidGangID ( gangid ) || ! Facility_IsValid( facilityid ) ) { + return SendError( playerid, "There was an error processing gang vehicles, please try again." ); + } + + if ( ! response ) { + return ShowPlayerGangVehicleMenu( playerid, facilityid ); + } + + new + x = 0; + + foreach ( new slotid : gangvehicles< gangid > ) + { + if ( x == listitem ) + { + if ( ! IsPlayerGangLeader( playerid, gangid ) ) { + return SendError( playerid, "You are not the leader of this gang." ); + } + + new + sell_price = ( GetBuyableVehiclePrice( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ) * GANG_VEHICLE_PRICE_FACTOR ) / 2; + + GiveGangCash( gangid, sell_price ); + SendServerMessage( playerid, "You have sold %s's %s for "COL_GOLD"%s"COL_WHITE".", g_gangData[ gangid ] [ E_NAME ], GetVehicleName( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ), cash_format( sell_price ) ); + + DestroyGangVehicle( gangid, slotid ); + ShowPlayerGangVehicleMenu( playerid, facilityid ); + break; + } + x ++; } return 1; } @@ -104,6 +162,12 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) } else if ( dialogid == DIALOG_GANG_VD_OPTIONS ) { + new gangid = GetPVarInt( playerid, "gang_vehicle_gang" ); + + if ( ! IsValidGangID ( gangid ) ) { + return SendError( playerid, "There was an error processing gang vehicles, please try again." ); + } + if ( ! response ) { return GangVehicles_ShowBuyableList( playerid, GetPVarInt( playerid, "vehicle_preview" ) ); } @@ -113,7 +177,60 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) // bought the vehicle case 0: { + if ( ! IsPlayerGangLeader( playerid, gangid ) ) { + ShowPlayerDialog( playerid, DIALOG_GANG_VD_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Vehicles - Purchase", "Purchase This Vehicle\nPreview Vehicle", "Select", "Back" ); + return SendError( playerid, "You are not the leader of this gang." ); + } + + new + num_vehicles = Iter_Count( gangvehicles< gangid > ); + + if ( num_vehicles >= MAX_GANG_VEHICLES ) { + ShowPlayerDialog( playerid, DIALOG_GANG_VD_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Vehicles - Purchase", "Purchase This Vehicle\nPreview Vehicle", "Select", "Back" ); + return SendError( playerid, "Your gang has reached the gang vehicle limit of %d.", MAX_GANG_VEHICLES ); + } + + new + data_id = GetPVarInt( playerid, "buying_vehicle" ); + + // VIP Check + if ( g_BuyableVehicleData[ data_id ] [ E_VIP ] ) + { + if ( p_VIPLevel[ playerid ] < VIP_REGULAR ) { + ShowPlayerDialog( playerid, DIALOG_GANG_VD_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Vehicles - Purchase", "Purchase This Vehicle\nPreview Vehicle", "Select", "Back" ); + return SendError( playerid, "You are not a V.I.P, to become one visit "COL_GREY"donate.sfcnr.com" ); + } + + if ( ( ( p_VIPExpiretime[ playerid ] - g_iTime ) / 86400 ) < 3 ) { + ShowPlayerDialog( playerid, DIALOG_GANG_VD_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Vehicles - Purchase", "Purchase This Vehicle\nPreview Vehicle", "Select", "Back" ); + return SendError( playerid, "You need more than 3 days of V.I.P in order to complete this." ); + } + } + + new + final_price = g_BuyableVehicleData[ data_id ] [ E_PRICE ] * GANG_VEHICLE_PRICE_FACTOR; + + // Money check + if ( GetGangCash( gangid ) < final_price ) { + ShowPlayerDialog( playerid, DIALOG_GANG_VD_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Vehicles - Purchase", "Purchase This Vehicle\nPreview Vehicle", "Select", "Back" ); + return SendError( playerid, "Your gang does not have enough money for this vehicle (%s).", cash_format( final_price ) ); + } + // TODO: + new + slotid = CreateGangVehicle( gangid, g_BuyableVehicleData[ data_id ] [ E_MODEL ] ); + + if ( slotid == ITER_NONE ) { + ShowPlayerDialog( playerid, DIALOG_GANG_VD_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Vehicles - Purchase", "Purchase This Vehicle\nPreview Vehicle", "Select", "Back" ); + return SendError( playerid, "Your gang has reached the gang vehicle limit of %d.", MAX_GANG_VEHICLES ); + } + + GiveGangCash( gangid, -final_price ); + StockMarket_UpdateEarnings( E_STOCK_VEHICLE_DEALERSHIP, final_price, 0.05 ); + + SendServerMessage( playerid, "You have bought an "COL_GREY"%s"COL_WHITE" for "COL_GOLD"%s"COL_WHITE"!", g_BuyableVehicleData[ data_id ] [ E_NAME ], cash_format( final_price ) ); + SendServerMessage( playerid, "You can spawn this vehicle using the mechanic at any gang facility.", g_BuyableVehicleData[ data_id ] [ E_NAME ], cash_format( final_price ) ); + return 1; } // preview @@ -127,13 +244,14 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) else if ( dialogid == DIALOG_GANG_VD_CATEGORY ) { new gangid = GetPVarInt( playerid, "gang_vehicle_gang" ); + new facilityid = GetPVarInt( playerid, "gang_vehicle_facility" ); - if ( ! IsValidGangID ( gangid ) ) { + if ( ! IsValidGangID ( gangid ) || ! Facility_IsValid( facilityid ) ) { return SendError( playerid, "There was an error processing gang vehicles, please try again." ); } if ( ! response ) { - return ShowPlayerGangVehicleMenu( playerid, gangid ); + return ShowPlayerGangVehicleMenu( playerid, facilityid ); } return GangVehicles_ShowBuyableList( playerid, listitem + 1 ); @@ -141,13 +259,14 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) else if ( dialogid == DIALOG_GANG_VEHICLE_SPAWN ) { new gangid = GetPVarInt( playerid, "gang_vehicle_gang" ); + new facilityid = GetPVarInt( playerid, "gang_vehicle_facility" ); - if ( ! IsValidGangID ( gangid ) ) { + if ( ! IsValidGangID ( gangid ) || ! Facility_IsValid( facilityid ) ) { return SendError( playerid, "There was an error processing gang vehicles, please try again." ); } if ( ! response ) { - return ShowPlayerGangVehicleMenu( playerid, gangid ); + return ShowPlayerGangVehicleMenu( playerid, facilityid ); } new @@ -158,11 +277,48 @@ hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] ) if ( x == listitem ) { if ( g_gangVehicleData[ gangid ] [ slotid ] [ E_ACTIVATION_TIME ] > current_time ) { + GangVehicles_ShowSpawnList( playerid, gangid ); return SendError( playerid, "This vehicle cannot be spawned for another %s.", secondstotime( g_gangVehicleData[ gangid ] [ slotid ] [ E_ACTIVATION_TIME ] - current_time ) ); } - // TODO: spawn vehicle - SendServerMessage( playerid, "You have spawned slot id %d", slotid ); + new Float: facility_x, Float: facility_y, Float: facility_z, Float: rotation; + GetGangFacilityPos( facilityid, facility_x, facility_y, facility_z ); + + // find nearest dock + if ( IsBoatVehicle( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ) ) { + GetClosestBoatPort( facility_x, facility_y, facility_z, facility_x, facility_y, facility_z ); + } + + // spawn air vehicles in the sky + else if ( IsAirVehicle( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ) ) { + facility_z += 300.0; + } + + // spawn vehicles at the closest road + else { + new Float: nodeX, Float: nodeY, Float: nodeZ, Float: nextX, Float: nextY; + new nodeid = NearestNodeFromPoint( facility_x, facility_y, facility_z ); + new nextNodeid = NearestNodeFromPoint( facility_x, facility_y, facility_z, 9999.9, nodeid ); + + GetNodePos( nextNodeid, nextX, nextY, nodeZ ); + GetNodePos( nodeid, nodeX, nodeY, nodeZ ); + + rotation = atan2( nextY - nodeY, nextX - nodeX ) - 90.0; + + facility_x = nodeX, facility_y = nodeY, facility_z = nodeZ; + } + + new + vehicleid = SpawnGangVehicle( gangid, slotid, facility_x, facility_y, facility_z + 2.0, rotation ); + + if ( vehicleid ) { + SetPlayerInterior( playerid, 0 ); + SetPlayerVirtualWorld( playerid, 0 ); + PutPlayerInVehicle( playerid, vehicleid, 0 ); + SendServerMessage( playerid, "You have spawned the gang's %s.", GetVehicleName( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ) ); + } else { + SendError( playerid, "Could not spawn gang vehicle due to an unexpected error." ); + } break; } x ++; @@ -178,6 +334,15 @@ hook OnGangLoad( gangid ) return 1; } +hook OnGangUnload( gangid, bool: deleted ) +{ + foreach ( new slotid : gangvehicles< gangid > ) { + RemoveGangVehicle( gangid, slotid ); + Iter_SafeRemove( gangvehicles< gangid >, slotid, slotid ); + } + return 1; +} + hook OnPlayerEndModelPreview( playerid, handleid ) { if ( handleid == PREVIEW_MODEL_GVEHICLE ) @@ -189,11 +354,131 @@ hook OnPlayerEndModelPreview( playerid, handleid ) return 1; } -CMD:car( playerid ) +hook OnEnterExitModShop( playerid, enterexit, interiorid ) { - new Float: X, Float: Y, Float: Z; - GetPlayerPos( playerid, X, Y, Z ); - CreateGangVehicle( GetPlayerGang( playerid ), 560 ); + if ( enterexit == 0 ) + { + new + vehicleid = GetPlayerVehicleID( playerid ); + + if ( IsValidVehicle( vehicleid ) ) + { + if ( g_gangVehicle{ vehicleid } ) + { + new + gangid, slotid; + + GetGangVehicleData( vehicleid, gangid, slotid ); + + printf("%d %d", gangid, slotid ); + + if ( IsValidGangID( gangid ) && IsValidGangVehicle( gangid, slotid ) ) + { + new + szMods[ MAX_CAR_MODS * 10 ]; + + // save vehicle mods to variable + for ( new i = 0; i < MAX_CAR_MODS; i ++ ) + { + // check if valid mod + if ( ( g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] = GetVehicleComponentInSlot( vehicleid, i ) ) < 1000 ) { + g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] = 0; + } + + // save as a sql delimited string + format( szMods, sizeof( szMods ), "%s%d.", szMods, g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] ); + } + + // update sql + mysql_format( dbHandle, szBigString, sizeof( szBigString ), "UPDATE `GANG_VEHICLES` SET `MODS`='%e' WHERE `ID`=%d", szMods, g_gangVehicleData[ gangid ] [ slotid ] [ E_SQL_ID ] ); + mysql_single_query( szBigString ); + print( szBigString ); + } + } + } + } + return 1; +} + +hook OnVehicleSpawn( vehicleid ) +{ + if ( g_gangVehicle{ vehicleid } ) + { + new + gangid, slotid; + + GetGangVehicleData( vehicleid, gangid, slotid ); + + if ( IsValidGangID( gangid ) && IsValidGangVehicle( gangid, slotid ) ) { + RemoveGangVehicle( gangid, slotid ); + } + } + return 1; +} + +hook OnVehiclePaintjob( playerid, vehicleid, paintjobid ) +{ + if ( g_gangVehicle{ vehicleid } ) + { + new + gangid, slotid; + + GetGangVehicleData( vehicleid, gangid, slotid ); + + if ( IsValidGangID( gangid ) && IsValidGangVehicle( gangid, slotid ) ) + { + g_gangVehicleData[ gangid ] [ slotid ] [ E_PAINTJOB ] = paintjobid; + mysql_single_query( sprintf( "UPDATE `GANG_VEHICLES` SET `PAINTJOB` = %d WHERE `ID` = %d", paintjobid, g_gangVehicleData[ gangid ] [ slotid ] [ E_SQL_ID ] ) ); + } + } + return 1; +} + +hook OnVehicleRespray( playerid, vehicleid, color1, color2 ) +{ + if ( g_gangVehicle{ vehicleid } ) + { + new + gangid, slotid; + + GetGangVehicleData( vehicleid, gangid, slotid ); + + if ( IsValidGangID( gangid ) && IsValidGangVehicle( gangid, slotid ) ) + { + g_gangVehicleData[ gangid ] [ slotid ] [ E_COLOR ] [ 0 ] = color1; + g_gangVehicleData[ gangid ] [ slotid ] [ E_COLOR ] [ 1 ] = color2; + mysql_single_query( sprintf( "UPDATE `GANG_VEHICLES` SET `COLOR1` = %d, `COLOR2` = %d WHERE `ID` = %d", color1, color2, g_gangVehicleData[ gangid ] [ slotid ] [ E_SQL_ID ] ) ); + } + } + return 1; +} + +hook OnPlayerDriveVehicle( playerid, vehicleid ) +{ + if ( g_gangVehicle{ vehicleid } ) + { + new + gangid, slotid; + + GetGangVehicleData( vehicleid, gangid, slotid ); + + if ( IsValidGangID( gangid ) && IsValidGangVehicle( gangid, slotid ) ) + { + new + player_gang = GetPlayerGang( playerid ); + + if ( player_gang == gangid ) + { + SendClientMessageFormatted( playerid, g_gangData[ gangid ] [ E_COLOR ], "[GANG VEHICLE]"COL_WHITE" Welcome to %s's vehicle.", g_gangData[ gangid ] [ E_NAME ] ); + Beep( playerid ); + } + else if ( ! IsPlayerAdminOnDuty( playerid ) ) + { + SyncObject( playerid, 1 ); // Just sets the players position where the vehicle is. + SendError( playerid, "This vehicle is restricted to gang members of %s.", g_gangData[ gangid ] [ E_NAME ] ); + } + } + } return 1; } @@ -215,7 +500,8 @@ thread GangVehicles_LoadVehicles( gangid ) cache_get_field_content_int( row, "MODEL_ID" ), cache_get_field_content_int( row, "COLOR1" ), cache_get_field_content_int( row, "COLOR2" ), - cache_get_field_content_int( row, "PAINTJOB" ) + cache_get_field_content_int( row, "PAINTJOB" ), + cache_get_field_content_int( row, "ID" ) ); // load the paintjobs in @@ -228,8 +514,13 @@ thread GangVehicles_LoadVehicles( gangid ) return 1; } +thread GangVehicles_InsertVehicle( gangid, slotid ) { + g_gangVehicleData[ gangid ] [ slotid ] [ E_SQL_ID ] = cache_insert_id( ); + return 1; +} + /* ** Functions ** */ -stock CreateGangVehicle( gangid, modelid, color1 = -1, color2 = -1, paintjob = 3 ) +stock CreateGangVehicle( gangid, modelid, color1 = -1, color2 = -1, paintjob = 3, sql_id = -1 ) { new slotid = Iter_Free( gangvehicles< gangid > ); @@ -241,13 +532,85 @@ stock CreateGangVehicle( gangid, modelid, color1 = -1, color2 = -1, paintjob = 3 g_gangVehicleData[ gangid ] [ slotid ] [ E_COLOR ] [ 1 ] = color2; g_gangVehicleData[ gangid ] [ slotid ] [ E_PAINTJOB ] = paintjob; g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] = modelid; - ResetGangVehicleMods( gangid, slotid ); + g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ] = -1; + // insert if not exists + if ( sql_id != -1 ) { + g_gangVehicleData[ gangid ] [ slotid ] [ E_SQL_ID ] = sql_id; + } else { + mysql_format( dbHandle, szBigString, sizeof( szBigString ), "INSERT INTO `GANG_VEHICLES` (`GANG_ID`,`MODEL_ID`,`COLOR1`,`COLOR2`,`PAINTJOB`,`MODS`) VALUES (%d,%d,%d,%d,%d,'0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.')", GetGangSqlID( gangid ), modelid, color1, color2, paintjob ); + mysql_tquery( dbHandle, szBigString, "GangVehicles_InsertVehicle", "dd", gangid, slotid ); + } + + ResetGangVehicleMods( gangid, slotid ); Iter_Add( gangvehicles< gangid >, slotid ); } return slotid; } +stock DestroyGangVehicle( gangid, slotid ) +{ + if ( Iter_Contains( gangvehicles< gangid >, slotid ) ) { + RemoveGangVehicle( gangid, slotid ); + mysql_single_query( sprintf( "DELETE FROM `GANG_VEHICLES` WHERE `ID` = %d", g_gangVehicleData[ gangid ] [ slotid ] [ E_SQL_ID ] ) ); + Iter_Remove( gangvehicles< gangid >, slotid ); + } + return 0; +} + +stock RemoveGangVehicle( gangid, slotid ) +{ + if ( Iter_Contains( gangvehicles< gangid >, slotid ) ) { + if ( g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ] != -1 ) { + g_gangVehicle{ g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ] } = false; + } + DestroyVehicle( g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ] ); + g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ] = -1; + } + return 0; +} + +stock SpawnGangVehicle( gangid, slotid, Float: X, Float: Y, Float: Z, Float: RZ ) +{ + new + vehicleid = 0; + + if ( Iter_Contains( gangvehicles< gangid >, slotid ) ) + { + // reset special data + ResetVehicleMethlabData( g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ], true ); + + // make sure vehicle does not exist + RemoveGangVehicle( gangid, slotid ); + + // create vehicle + if ( IsValidVehicle( ( vehicleid = CreateVehicle( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ], X, Y, Z, RZ, g_gangVehicleData[ gangid ] [ slotid ] [ E_COLOR ] [ 0 ], g_gangVehicleData[ gangid ] [ slotid ] [ E_COLOR ] [ 1 ], GANG_VEHICLE_SPAWN_COOLDOWN, .addsiren = 1 ) ) ) ) + { + // set vehicle id + g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ] = vehicleid; + g_gangVehicleData[ gangid ] [ slotid ] [ E_ACTIVATION_TIME ] = GetServerTime( ) + GANG_VEHICLE_SPAWN_COOLDOWN; + g_gangVehicle{ vehicleid } = true; + + // restore data + SetVehicleNumberPlate( g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ], g_gangData[ gangid ] [ E_NAME ] ); + ChangeVehiclePaintjob( g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ], g_gangVehicleData[ gangid ] [ slotid ] [ E_PAINTJOB ] ); + + // restore car mods + for ( new i = 0; i < MAX_CAR_MODS; i ++ ) { + if ( g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] >= 1000 && g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] < 1193 ) { + if ( CarMod_IsLegalCarMod( GetVehicleModel( g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ] ), g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] ) ) { + AddVehicleComponent( g_gangVehicleData[ gangid ] [ slotid ] [ E_VEHICLE_ID ], g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] ); + } else { + g_gangVehicleModifications[ gangid ] [ slotid ] [ i ] = 0; + } + } + } + return vehicleid; + } + } + return 0; +} + stock ResetGangVehicleMods( gangid, slotid, fordestroy=1 ) { if ( ! IsValidGangVehicle( gangid, slotid ) ) @@ -267,27 +630,52 @@ stock ResetGangVehicleMods( gangid, slotid, fordestroy=1 ) mysql_single_query( szNormalString ); } -stock ShowPlayerGangVehicleMenu( playerid, gangid ) +stock ShowPlayerGangVehicleMenu( playerid, facilityid ) { - SetPVarInt( playerid, "gang_vehicle_gang", gangid ); - ShowPlayerDialog( playerid, DIALOG_GANG_VEHICLE_MENU, DIALOG_STYLE_LIST, ""COL_WHITE"Gang Vehicles", "Spawn Gang Vehicle\nBuy Gang Vehicle", "Select", "Close" ); + SetPVarInt( playerid, "gang_vehicle_facility", facilityid ); + SetPVarInt( playerid, "gang_vehicle_gang", GetGangIDFromFacilityID( facilityid ) ); + ShowPlayerDialog( playerid, DIALOG_GANG_VEHICLE_MENU, DIALOG_STYLE_LIST, ""COL_WHITE"Gang Vehicles", "Spawn Gang Vehicle\nBuy Gang Vehicle\nSell Gang Vehicle", "Select", "Close" ); return 1; } static stock GangVehicles_ShowBuyableList( playerid, type_id ) { static - szBuyableVehicles[ 1400 ]; + buyable_vehicles[ 1400 ], i; - if ( szBuyableVehicles[ 0 ] != '\0' ) { - for ( new i = 0; i < sizeof( g_BuyableVehicleData ); i ++ ) if ( g_BuyableVehicleData[ i ] [ E_TYPE ] == type_id ) { - format( szBuyableVehicles, sizeof( szBuyableVehicles ), "%s"COL_GOLD"%s%s%s\t%s\n", szBuyableVehicles, cash_format( g_BuyableVehicleData[ i ] [ E_PRICE ] * GANG_VEHICLE_PRICE_FACTOR ), g_BuyableVehicleData[ i ] [ E_VIP ] ? ( "" ) : ( #COL_WHITE ), g_BuyableVehicleData[ i ] [ E_PRICE ] < 100000 ? ( "\t" ) : ( "" ), g_BuyableVehicleData[ i ] [ E_NAME ] ); - } + for ( i = 0, buyable_vehicles[ 0 ] = '\0'; i < sizeof( g_BuyableVehicleData ); i ++ ) if ( g_BuyableVehicleData[ i ] [ E_TYPE ] == type_id ) { + format( buyable_vehicles, sizeof( buyable_vehicles ), "%s"COL_GOLD"%s%s%s\t%s\n", buyable_vehicles, cash_format( g_BuyableVehicleData[ i ] [ E_PRICE ] * GANG_VEHICLE_PRICE_FACTOR ), g_BuyableVehicleData[ i ] [ E_VIP ] ? ( "" ) : ( #COL_WHITE ), g_BuyableVehicleData[ i ] [ E_PRICE ] < 100000 ? ( "\t" ) : ( "" ), g_BuyableVehicleData[ i ] [ E_NAME ] ); } + SetPVarInt( playerid, "vehicle_preview", type_id ); - return ShowPlayerDialog( playerid, DIALOG_GANG_VD_BUY, DIALOG_STYLE_LIST, "{FFFFFF}Vehicle Dealership", szBuyableVehicles, "Options", "Cancel" ); + return ShowPlayerDialog( playerid, DIALOG_GANG_VD_BUY, DIALOG_STYLE_LIST, "{FFFFFF}Vehicle Dealership", buyable_vehicles, "Select", "Back" ); } +stock GetGangVehicleData( vehicleid, &gangid, &slotid ) { + foreach ( new g : gangs ) { + foreach ( new v : gangvehicles< g > ) if ( g_gangVehicleData[ g ] [ v ] [ E_VEHICLE_ID ] == vehicleid ) { + gangid = g; + slotid = v; + break; + } + } +} + +static stock GangVehicles_ShowSpawnList( playerid, gangid ) { + new + current_time = GetServerTime( ); + + szBigString = ""COL_WHITE"Vehicle\t"COL_WHITE"Availablity\n"; + + foreach ( new slotid : gangvehicles< gangid > ) + { + format( szBigString, sizeof( szBigString ), "%s%s\t%s\n", szBigString, + GetVehicleName( g_gangVehicleData[ gangid ] [ slotid ] [ E_MODEL ] ), + g_gangVehicleData[ gangid ] [ slotid ] [ E_ACTIVATION_TIME ] > current_time ? ( secondstotime( g_gangVehicleData[ gangid ] [ slotid ] [ E_ACTIVATION_TIME ] - current_time ) ) : ( COL_GREEN # "Available" ) + ); + } + return ShowPlayerDialog( playerid, DIALOG_GANG_VEHICLE_SPAWN, DIALOG_STYLE_TABLIST_HEADERS, ""COL_WHITE"Gang Vehicles - Spawn", szBigString, "Select", "Close" ); +} /* ** Migrations ** */ /* CREATE TABLE IF NOT EXISTS `GANG_VEHICLES` ( @@ -297,6 +685,7 @@ static stock GangVehicles_ShowBuyableList( playerid, type_id ) `COLOR1` int(4), `COLOR2` int(4), `PAINTJOB` tinyint(2), - `MODS` varchar(90) + `MODS` varchar(90), + FOREIGN KEY (GANG_ID) REFERENCES GANGS (ID) ON DELETE CASCADE ); */ diff --git a/gamemodes/irresistible/cnr/features/vehicles/vdealership.pwn b/gamemodes/irresistible/cnr/features/vehicles/vdealership.pwn index 0279af4..1d9c6b3 100644 --- a/gamemodes/irresistible/cnr/features/vehicles/vdealership.pwn +++ b/gamemodes/irresistible/cnr/features/vehicles/vdealership.pwn @@ -427,3 +427,43 @@ stock ShowBuyableVehiclesTypeDialog( playerid, type_id ) SetPVarInt( playerid, "vehicle_preview", type_id ); return 1; } + +stock GetBuyableVehiclePrice( modelid ) { + for ( new i = 0; i < sizeof ( g_BuyableVehicleData ); i ++ ) if ( g_BuyableVehicleData[ i ] [ E_MODEL ] == modelid ) { + return g_BuyableVehicleData[ i ] [ E_PRICE ]; + } + return 0; +} + +stock GetClosestBoatPort( Float: current_x, Float: current_y, Float: current_z, &Float: dest_x, &Float: dest_y, &Float: dest_z, &Float: distance = FLOAT_INFINITY ) +{ + static const + Float: g_boatSpawnLocations[ ] [ 3 ] = + { + { 2950.59080, -2000.382, -0.4033 }, { 1986.55710, -75.03830, -0.1938 }, + { 2238.51780, 498.92970, 0.02490 }, { -626.54060, 832.18100, -0.1432 }, + { -1448.5302, 679.33510, -0.2547 }, { -1710.0466, 241.71960, -0.3029 }, + { -2181.0417, 2488.8093, -0.3036 }, { -2940.6545, 1238.2001, 0.11180 }, + { -2974.5994, 543.54410, 0.44440 }, { -1341.1674, -2989.101, -0.1943 } + } + ; + + new + final_port = 0; + + // get the closest port based off coordinates + for ( new i = 0, Float: fTmp = 0.0; i < sizeof ( g_boatSpawnLocations ); i ++ ) + { + if ( 0.0 < ( fTmp = GetDistanceBetweenPoints( current_x, current_y, current_z, g_boatSpawnLocations[ i ] [ 0 ], g_boatSpawnLocations[ i ] [ 1 ], g_boatSpawnLocations[ i ] [ 2 ] ) ) < distance ) + { + distance = fTmp; + final_port = i; + } + } + + // store the destination coordinates + dest_x = g_boatSpawnLocations[ final_port ] [ 0 ]; + dest_y = g_boatSpawnLocations[ final_port ] [ 1 ]; + dest_z = g_boatSpawnLocations[ final_port ] [ 2 ]; + return 1; +} diff --git a/gamemodes/irresistible/cnr/features/vehicles/vehicles.pwn b/gamemodes/irresistible/cnr/features/vehicles/vehicles.pwn index 1b92edd..0f00a0a 100644 --- a/gamemodes/irresistible/cnr/features/vehicles/vehicles.pwn +++ b/gamemodes/irresistible/cnr/features/vehicles/vehicles.pwn @@ -801,7 +801,6 @@ stock RespawnBuyableVehicle( samp_veh_id, occupantid = INVALID_PLAYER_ID ) GetVehicleParamsEx( g_vehicleData[ playerid ] [ id ] [ E_VEHICLE_ID ], engine, lights, alarm, doors, bonnet, boot, objective ); SetVehicleParamsEx( g_vehicleData[ playerid ] [ id ] [ E_VEHICLE_ID ], VEHICLE_PARAMS_OFF, lights, alarm, doors, bonnet, boot, objective ); } - return g_vehicleData[ playerid ] [ id ] [ E_VEHICLE_ID ]; }