sfcnr/gamemodes/irresistible/cnr/features/gangs/gangs.pwn
2023-12-29 02:47:25 +03:00

1190 lines
46 KiB
Plaintext

/*
* Irresistible Gaming (c) 2018
* Developed by Lorenc
* Module: gangs.inc
* Purpose: gang system
*/
/* ** Includes ** */
#include < YSI\y_hooks >
/* ** Definitions ** */
#define MAX_GANGS ( MAX_PLAYERS ) // safest is MAX_PLAYERS
#define INVALID_GANG_ID ( -1 )
#define MAX_COLEADERS ( 3 )
/* ** Macros ** */
#define IsGangPrivate(%0) ( g_gangData[ %0 ] [ E_INVITE_ONLY ] )
#define GetGangSqlID(%0) ( g_gangData[ %0 ] [ E_SQL_ID ] )
#define GetPlayerGang(%0) ( p_GangID[ %0 ] )
#define IsValidGangID(%0) ( 0 <= %0 < MAX_GANGS && Iter_Contains( gangs, %0 ) )
#define IsPlayerInPlayerGang(%0,%1) ( p_Class[ %0 ] == p_Class[ %1 ] && p_Class[ %0 ] == CLASS_CIVILIAN && p_GangID[ %0 ] == p_GangID[ %1 ] && p_GangID[ %0 ] != INVALID_GANG_ID )
/* ** Variables ** */
enum e_gang_data
{
E_SQL_ID, E_NAME[ 30 ], E_LEADER,
E_COLOR, E_SOFT_DELETE_TS,
E_BANK, E_KILLS, E_DEATHS,
E_SCORE, E_RESPECT,
E_COLEADER[ MAX_COLEADERS ], bool: E_INVITE_ONLY, E_JOIN_MSG[ 96 ],
bool: E_HAS_FACILITY
};
enum E_GANG_LEAVE_REASON
{
GANG_LEAVE_QUIT,
GANG_LEAVE_KICK,
GANG_LEAVE_UNKNOWN
};
new
g_gangColors[ ] = { 0x99FF00FF, 0x00CC00FF, 0x009999FF, 0x0033CCFF, 0x330099FF, 0x660099FF, 0xCC0099FF },
g_gangData [ MAX_GANGS ] [ e_gang_data ],
g_sortedGangData [ MAX_GANGS ] [ e_gang_data ], // used for sorting only
p_GangID [ MAX_PLAYERS ],
bool: p_gangInvited [ MAX_PLAYERS ] [ MAX_GANGS ],
p_gangInviteTick [ MAX_PLAYERS ],
Iterator:gangs<MAX_GANGS>
;
/* ** Forwards ** */
forward OnPlayerLeaveGang( playerid, gangid, reason );
forward ZoneTimer( );
/* ** Hooks ** */
/*hook OnGameModeInit( )
{
#if !defined DEBUG_MODE
// Remove inactive gang members
// mysql_single_query( "UPDATE `USERS` SET `GANG_ID`=-1 WHERE UNIX_TIMESTAMP()-`USERS`.`LASTLOGGED` > 1209600" );
// Remove gangs with a non existant gang leader / unmatched player gang id to gang leader id (***broken query***)
// mysql_single_query( "DELETE g FROM GANGS g LEFT JOIN USERS u ON g.LEADER = u.ID WHERE (u.GANG_ID != g.ID OR u.ID IS NULL) AND g.LEADER >= 0" );
#endif
return 1;
}*/
hook OnServerUpdate( )
{
// Soft delete gang
foreach (new gangid : gangs) if ( g_gangData[ gangid ] [ E_SOFT_DELETE_TS ] != 0 && g_iTime > g_gangData[ gangid ] [ E_SOFT_DELETE_TS ] )
{
new
members = GetOnlineGangMembers( gangid );
if ( members <= 0 )
{
new
cur = gangid;
printf("Removed Gang From Cache Gang Id %d Since No Ppl", g_gangData[ gangid ] [ E_SQL_ID ] );
DestroyGang( gangid, true, .iter_remove = false );
Iter_SafeRemove( gangs, cur, gangid );
}
else g_gangData[ gangid ] [ E_SOFT_DELETE_TS ] = 0;
}
return 1;
}
hook OnDialogResponse( playerid, dialogid, response, listitem, inputtext[ ] )
{
if ( dialogid == DIALOG_GANG_COLOR && response )
{
if ( listitem != 0 )
{
listitem -= 1; // So it starts from 0...
g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ] = g_gangColors[ listitem ];
SendClientMessageToGang( p_GangID[ playerid ], g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has changed the gang color to %s", ReturnPlayerName( playerid ), playerid, ReturnGangNameColor( listitem ) );
SetGangColorsToGang( p_GangID[ playerid ] );
}
else {
if ( p_VIPLevel[ playerid ] < VIP_REGULAR ) return SendError( playerid, "You are not a V.I.P, to become one please discuss with admins" );
ShowPlayerDialog( playerid, DIALOG_GANG_COLOR_INPUT, DIALOG_STYLE_INPUT, "{FFFFFF}Gang Colors", "{FFFFFF}Write a hexidecimal color within the textbox", "Submit", "Cancel" );
}
}
else if ( dialogid == DIALOG_GANG_COLOR_INPUT && response )
{
if ( !strlen( inputtext ) || !isHex( inputtext ) )
return ShowPlayerDialog( playerid, DIALOG_GANG_COLOR_INPUT, DIALOG_STYLE_INPUT, "{FFFFFF}Gang Colors", "{FFFFFF}Write a hexidecimal color within the textbox\n\n{ff0000}Invalid HEX color.", "Submit", "Cancel" );
new gangid = p_GangID[ playerid ];
new hex_to_int = HexToInt( inputtext );
g_gangData[ gangid ] [ E_COLOR ] = setAlpha( hex_to_int, 0xFF );
SendClientMessageToGang( gangid, g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has changed the gang color to %06x", ReturnPlayerName( playerid ), playerid, hex_to_int >>> 8 );
SetGangColorsToGang( gangid );
}
else if ( dialogid == DIALOG_GANG_LIST && response )
{
new
x = 0;
for ( new g = 0; g < sizeof( g_sortedGangData ); g ++ ) if ( g_sortedGangData[ g ] [ E_SQL_ID ] != 0 )
{
if ( x == listitem )
{
new curr_gang = p_GangID[ playerid ];
new curr_gang_sql = 0;
if ( Iter_Contains( gangs, curr_gang ) )
curr_gang_sql = g_gangData[ curr_gang ] [ E_SQL_ID ];
SetPVarInt( playerid, "viewing_gang_sql", g_sortedGangData[ g ] [ E_SQL_ID ] );
ShowPlayerDialog( playerid, DIALOG_GANG_LIST_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Options", sprintf( "%sJoin Gang\nView Statistics\nView Gang Members", curr_gang_sql != g_sortedGangData[ g ] [ E_SQL_ID ] && ! g_sortedGangData[ g ] [ E_INVITE_ONLY ] ? ( COL_WHITE ) : ( COL_BLACK ) ), "Select", "Back" );
break;
}
x ++;
}
}
else if ( dialogid == DIALOG_GANG_LIST_OPTIONS )
{
if ( !response )
return cmd_gangs( playerid, "" );
new gang_sql = GetPVarInt( playerid, "viewing_gang_sql" );
new g;
// search sql, just incase someone searchs the gangs and doesnt find what they want
foreach (g : gangs) if ( g_gangData[ g ] [ E_SQL_ID ] == gang_sql ) {
break;
}
if ( ! ( 0 <= g < MAX_GANGS ) || ! Iter_Contains( gangs, g ) )
return SendError( playerid, "Unable to discover gang information as it no longer is loaded, please try again. (0x7D)" );
switch( listitem )
{
case 0: // Join gang
{
if ( p_Class[ playerid ] != CLASS_CIVILIAN ) {
SendError( playerid, "You must be a civilian to switch gangs." );
} else if ( p_GangID[ playerid ] == g ) {
SendError( playerid, "You are already in this gang." );
} else if ( IsGangPrivate( g ) ) {
SendError( playerid, "You can no longer join this gang as it is private." );
} else if ( ! SetPlayerGang( playerid, g ) ) {
SendError( playerid, "You can no longer join this gang." );
}
ShowPlayerDialog( playerid, DIALOG_GANG_LIST_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Options", sprintf( "%sJoin Gang\nView Statistics\nView Gang Members", p_GangID[ playerid ] != g && ! g_gangData[ g ] [ E_INVITE_ONLY ] ? ( COL_WHITE ) : ( COL_BLACK ) ), "Select", "Back" );
}
case 1: // View statistics
{
new iPlayers = GetOnlineGangMembers( g );
SetPVarInt( playerid, "gang_members_id", g );
format( szLargeString, 350, ""COL_GREY"Gang ID:"COL_WHITE" %d\n"COL_GREY"Online Members:"COL_WHITE" %d\n"COL_GREY"Score:"COL_WHITE" %d\n"COL_GREY"Kills:"COL_WHITE" %d\n"COL_GREY"Deaths:"COL_WHITE" %d\n"COL_GREY"K/D Ratio:"COL_WHITE" %0.2f\n", g_gangData[ g ] [ E_SQL_ID ], iPlayers, g_gangData[ g ] [ E_SCORE ], g_gangData[ g ] [ E_KILLS ], g_gangData[ g ] [ E_DEATHS ], floatdiv( g_gangData[ g ] [ E_KILLS ], g_gangData[ g ] [ E_DEATHS ] ) );
format( szLargeString, 350, "%s"COL_GREY"Bank:"COL_WHITE" %s\n"COL_GREY"Zones Captured:"COL_WHITE" %d", szLargeString, cash_format( g_gangData[ g ] [ E_BANK ] ), GetGangCapturedTurfs( g ) );
ShowPlayerDialog( playerid, DIALOG_GANG_LIST_RESPONSE, DIALOG_STYLE_MSGBOX, "{FFFFFF}Gang Statistics", szLargeString, "Close", "Back" );
}
case 2:
{
// View gang members
mysql_tquery( dbHandle,
sprintf( "SELECT `NAME`,`ONLINE` FROM `USERS` WHERE `GANG_ID`=%d ORDER BY `ONLINE` DESC LIMIT 20 OFFSET 0", g_gangData[ g ] [ E_SQL_ID ] ),
"OnListGangMembers", "ddd", playerid, g, 0
);
}
}
return 1;
}
else if ( dialogid == DIALOG_GANG_LIST_RESPONSE )
{
new g = GetPVarInt( playerid, "gang_members_id" );
if ( ! Iter_Contains( gangs, g ) )
return SendError( playerid, "Could not find gang. Try again." );
return ShowPlayerDialog( playerid, DIALOG_GANG_LIST_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Options", sprintf( "%sJoin Gang\nView Statistics\nView Gang Members", p_GangID[ playerid ] != g && ! g_gangData[ g ] [ E_INVITE_ONLY ] ? ( COL_WHITE ) : ( COL_BLACK ) ), "Select", "Back" );
}
else if ( dialogid == DIALOG_GANG_LIST_MEMBERS )
{
new g = GetPVarInt( playerid, "gang_members_id" );
new members_shown = GetPVarInt( playerid, "gang_members_results" );
new page = GetPVarInt( playerid, "gang_members_page" );
if ( ! Iter_Contains( gangs, g ) )
return SendError( playerid, "Could not find gang. Try again." );
if ( ! response && page == 0 )
return ShowPlayerDialog( playerid, DIALOG_GANG_LIST_OPTIONS, DIALOG_STYLE_LIST, "{FFFFFF}Gang Options", sprintf( "%sJoin Gang\nView Statistics\nView Gang Members", p_GangID[ playerid ] != g && ! g_gangData[ g ] [ E_INVITE_ONLY ] ? ( COL_WHITE ) : ( COL_BLACK ) ), "Select", "Back" );
if ( members_shown < 20 && response )
return 1;
// if response, add a page, otherwise previous
page += response ? 1 : -1;
// find page result
mysql_tquery( dbHandle,
sprintf( "SELECT `NAME`,`ONLINE` FROM `USERS` WHERE `GANG_ID`=%d ORDER BY `ONLINE` DESC LIMIT 20 OFFSET %d", g_gangData[ g ] [ E_SQL_ID ], page * 20 ),
"OnListGangMembers", "ddd", playerid, g, page
);
return 1;
}
return 1;
}
/* ** Callbacks ** */
public OnPlayerLeaveGang( playerid, gangid, reason )
{
switch( reason )
{
case GANG_LEAVE_KICK:
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has left the gang (KICKED)", ReturnPlayerName( playerid ), playerid );
case GANG_LEAVE_QUIT:
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has left the gang (LEFT)", ReturnPlayerName( playerid ), playerid );
case GANG_LEAVE_UNKNOWN:
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has left the gang (UNKNOWN)", ReturnPlayerName( playerid ), playerid );
}
return 1;
}
/* ** Commands ** */
CMD:clans( playerid, params[ ] )
{
mysql_function_query( dbHandle, "SELECT * FROM `GANGS` WHERE `CLAN_TAG` IS NOT NULL ORDER BY `SCORE` DESC", true, "OnListClans", "d", playerid );
return 1;
}
CMD:gangs( playerid, params[ ] )
{
if ( !Iter_Count(gangs) )
return SendError( playerid, "There are no gangs to list." );
// store current sort into gangs & sort by respect
g_sortedGangData = g_gangData;
SortDeepArray( g_sortedGangData, E_RESPECT, .order = SORT_DESC );
// create dialog
szHugeString = ""COL_WHITE"Gang\t"COL_WHITE"Respect\n";
for ( new g = 0; g < sizeof( g_sortedGangData ); g ++ ) if ( g_sortedGangData[ g ] [ E_SQL_ID ] != 0 ) {
format( szHugeString, sizeof( szHugeString ), "%s{%06x}%s\t%d\n", szHugeString, g_sortedGangData[ g ] [ E_COLOR ] >>> 8, g_sortedGangData[ g ] [ E_NAME ], g_sortedGangData[ g ] [ E_RESPECT ] );
}
return ShowPlayerDialog( playerid, DIALOG_GANG_LIST, DIALOG_STYLE_TABLIST_HEADERS, "Gangs List", szHugeString, "Select", "Cancel" );
}
CMD:getgang( playerid, params[ ] )
{
new
pID
;
if ( sscanf( params, "u", pID ) ) return SendUsage( playerid, "/getgang [PLAYER_ID]" );
else if ( !IsPlayerConnected( pID ) || IsPlayerNPC( pID ) ) return SendError( playerid, "Invalid Player ID." );
else if ( p_PlayerLogged{ pID } == false ) return SendError( playerid, "This player is not logged in." );
else
{
if (p_GangID[ pID ] == INVALID_GANG_ID) {
SendServerMessage( playerid, ""COL_GREY"%s(%d) is not in a gang.", ReturnPlayerName( pID ), pID );
}
else {
SendServerMessage( playerid, ""COL_GREY"%s(%d) is in {%06x}%s", ReturnPlayerName( pID ), pID, g_gangData[ p_GangID[ pID ] ] [ E_COLOR ] >>> 8, g_gangData[ p_GangID[ pID ] ][ E_NAME ] );
}
}
return 1;
}
CMD:gang( playerid, params[ ] )
{
if ( p_Class[ playerid ] != CLASS_CIVILIAN ) return SendError( playerid, "This is restricted to civilians only." );
if ( !strcmp( params, "offlinekick", false, 11 ) )
{
new
iGang = p_GangID[ playerid ],
p_Name[ MAX_PLAYER_NAME ];
if ( ! IsPlayerGangLeader( playerid, p_GangID[ playerid ] ) )
return SendError( playerid, "You are not the gang leader." );
if ( sscanf( params[ 12 ], "s[24]", p_Name ) )
return SendUsage( playerid, "/gang offlinekick [PLAYER_NAME]" );
trimString( p_Name );
mysql_format( dbHandle, szNormalString, 128, "SELECT `ID`, `NAME`, `GANG_ID` FROM `USERS` WHERE `NAME`='%e' AND `GANG_ID`=%d", p_Name, g_gangData[ iGang ][ E_SQL_ID ] );
mysql_tquery( dbHandle, szNormalString, "OnGangKickOffline", "dd", playerid, g_gangData[ iGang ][ E_SQL_ID ] );
return 1;
}
else if ( !strcmp( params, "leader", false, 6 ) )
{
new
pID
;
if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not inside a gang." );
else if ( !IsPlayerGangLeader( playerid, p_GangID[ playerid ], .only_leader = 1 ) ) return SendError( playerid, "You are not the gang leader." );
else if ( sscanf( params[ 7 ], "u", pID ) ) return SendUsage( playerid, "/gang leader [PLAYER_ID]" );
else if ( !IsPlayerConnected( pID ) || IsPlayerNPC( pID ) ) return SendError( playerid, "Invalid Player ID." );
else if ( pID == playerid ) return SendError( playerid, "You cannot apply this action to yourself." );
else if ( p_GangID[ pID ] != p_GangID[ playerid ] ) return SendError( playerid, "This player isn't in your gang." );
else
{
g_gangData[ p_GangID[ playerid ] ] [ E_LEADER ] = p_AccountID[ pID ];
SendClientMessageToGang( p_GangID[ playerid ], g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) is the new gang leader.", ReturnPlayerName( pID ), pID );
SaveGangData( p_GangID[ playerid ] );
}
return 1;
}
else if ( !strcmp( params, "coleader", false, 8 ) )
{
new
gangid = p_GangID[ playerid ], pID;
if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not inside a gang." );
else if ( !IsPlayerGangLeader( playerid, p_GangID[ playerid ], .only_leader = 1 ) ) return SendError( playerid, "You are not the gang leader." );
else if ( sscanf( params[ 9 ], "u", pID ) ) return SendUsage( playerid, "/gang coleader [PLAYER_ID]" );
else if ( !IsPlayerConnected( pID ) || IsPlayerNPC( pID ) ) return SendError( playerid, "Invalid Player ID." );
else if ( pID == playerid ) return SendError( playerid, "You cannot apply this action to yourself." );
else if ( p_GangID[ pID ] != p_GangID[ playerid ] ) return SendError( playerid, "This player isn't in your gang." );
else
{
new
slotid = -1;
for ( new i = 0; i < MAX_COLEADERS; i ++ )
{
// check for dupes
if ( g_gangData[ gangid ] [ E_COLEADER ] [ i ] == p_AccountID[ pID ] )
return SendError( playerid, "This player is already a coleader of your gang." );
// find slot
if ( ! g_gangData[ gangid ] [ E_COLEADER ] [ i ] ) {
slotid = i;
break;
}
}
if ( slotid != -1 )
{
g_gangData[ gangid ] [ E_COLEADER ] [ slotid ] = p_AccountID[ pID ];
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) is the #%d co-leader.", ReturnPlayerName( pID ), pID, slotid + 1 );
mysql_single_query( sprintf( "INSERT INTO `GANG_COLEADERS` (`GANG_ID`,`USER_ID`) VALUES (%d, %d)", g_gangData[ gangid ] [ E_SQL_ID ], p_AccountID[ pID ] ) );
}
else SendError( playerid, "There can only be a maximum of %d gang co-leaders. Kick one of them first.", MAX_COLEADERS );
}
return 1;
}
else if ( !strcmp( params, "kick", false, 4 ) )
{
new
pID
;
if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not inside a gang." );
else if ( !IsPlayerGangLeader( playerid, p_GangID[ playerid ] ) ) return SendError( playerid, "You are not the gang leader." );
else if ( sscanf( params[ 5 ], "u", pID ) ) return SendUsage( playerid, "/gang kick [PLAYER_ID]" );
else if ( !IsPlayerConnected( pID ) || IsPlayerNPC( pID ) ) return SendError( playerid, "Invalid Player ID." );
else if ( p_GangID[ pID ] != p_GangID[ playerid ] ) return SendError( playerid, "This player isn't in your gang." );
else if ( IsPlayerGangLeader( pID, p_GangID[ playerid ], .only_leader = 1 ) ) return SendError( playerid, "This person is the gang leader." );
else
{
RemovePlayerFromGang( pID, GANG_LEAVE_KICK, playerid );
}
return 1;
}
else if ( !strcmp( params, "name", false, 4 ) )
{
new
szName[ 30 ]
;
if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not inside a gang." );
else if ( !IsPlayerGangLeader( playerid, p_GangID[ playerid ] ) ) return SendError( playerid, "You are not the gang leader." );
else if ( sscanf( params[ 5 ], "s[30]", szName ) ) return SendUsage( playerid, "/gang name [GANG_NAME]" );
else if ( textContainsIP( szName ) || textContainsBadTextdrawLetters( szName ) ) return SendError( playerid, "Invalid Gang Name." );
else if ( gangNameExists( szName ) ) return SendError( playerid, "This gang already exists, try another name." );
else
{
trimString( szName );
format( g_gangData[ p_GangID[ playerid ] ] [ E_NAME ], 30, "%s", szName );
SendClientMessageToGang( p_GangID[ playerid ], g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has changed the gang's name to {%06x}%s"COL_WHITE".", ReturnPlayerName( playerid ), playerid, g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ] >>> 8, szName );
SaveGangData( p_GangID[ playerid ] );
}
return 1;
}
else if ( !strcmp( params, "color", false, 5 ) )
{
if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not inside a gang." );
if ( !IsPlayerGangLeader( playerid, p_GangID[ playerid ] ) ) return SendError( playerid, "You are not the gang leader." );
return ShowPlayerDialog( playerid, DIALOG_GANG_COLOR, DIALOG_STYLE_LIST, "Gang Colors", ""COL_GREY"Custom Hex Code "COL_GOLD"[V.I.P]\n{99FF00}Yellow Green\n{00CC00}Green\n{009999}Blue Green\n{0033CC}Blue\n{330099}Blue Violet\n{660099}Violet\n{CC0099}Red Violet", "Select", "Cancel" );
}
else if ( !strcmp( params, "create", false, 5 ) )
{
new
szName[ 30 ]
;
if ( sscanf( params[ 6 ], "s[30]", szName ) ) return SendUsage( playerid, "/gang create [GANG_NAME]" );
else if ( p_GangID[ playerid ] != INVALID_GANG_ID ) return SendError( playerid, "To make a gang, you must leave your current gang with /gang leave" );
else if ( textContainsIP( szName ) || textContainsBadTextdrawLetters( szName ) ) return SendError( playerid, "Invalid Gang Name." );
else if ( gangNameExists( szName ) ) return SendError( playerid, "This gang already exists, try another name." );
else
{
new
handle = CreateGang( .gang_name = szName, .leader = p_AccountID[ playerid ], .gang_color = g_gangColors[ random( sizeof( g_gangColors ) ) ] );
if ( handle != INVALID_GANG_ID )
{
p_GangID[ playerid ] = handle; // set it anyway here just incase of cache taking a bit
if ( p_WantedLevel[ playerid ] == 0 && p_AdminOnDuty{ playerid } == false )
SetPlayerColor( playerid, g_gangData[ handle ] [ E_COLOR ] );
mysql_single_query( sprintf( "UPDATE `USERS` SET `GANG_ID`=%d WHERE `ID`=%d", g_gangData[ handle ] [ E_SQL_ID ], p_AccountID[ playerid ] ) );
SendClientMessageToGang( handle, g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]{FFFFFF} You have created the gang: %s (%d)", szName, g_gangData[ handle ] [ E_SQL_ID ] );
}
else SendError( playerid, "There are no available slots to create a gang." );
}
return 1;
}
else if ( !strcmp( params, "joinmsg", false, 7 ) )
{
new
gangid = p_GangID[ playerid ];
if ( gangid == INVALID_GANG_ID ) return SendError( playerid, "You are not inside any gang." );
if ( !IsPlayerGangLeader( playerid, gangid ) ) return SendError( playerid, "You are not the gang leader." );
if ( sscanf( params[ 8 ], "s[96]", g_gangData[ gangid ] [ E_JOIN_MSG ] ) )
{
mysql_single_query( sprintf( "UPDATE `GANGS` SET `JOIN_MSG`=NULL WHERE `ID`=%d", g_gangData[ gangid ] [ E_SQL_ID ] ) );
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) removed the gang's join message.", ReturnPlayerName( playerid ), playerid );
}
else
{
format( szBigString, sizeof( szBigString ), "UPDATE `GANGS` SET `JOIN_MSG`='%s' WHERE `ID`=%d", mysql_escape( g_gangData[ gangid ] [ E_JOIN_MSG ] ), g_gangData[ gangid ] [ E_SQL_ID ] );
mysql_single_query( szBigString );
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) set the gang's join message:", ReturnPlayerName( playerid ), playerid );
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]"COL_GREY" %s", g_gangData[ gangid ] [ E_JOIN_MSG ] );
}
return 1;
}
else if ( !strcmp( params, "join", false, 4 ) )
{
new
gID
;
if ( sscanf( params[ 5 ], "d", gID ) ) return SendUsage( playerid, "/gang join [GANG_ID]" );
else if ( gID < 0 || gID >= MAX_GANGS ) return SendError( playerid, "Invalid Gang ID." );
else if ( !Iter_Contains( gangs, gID ) ) return SendError( playerid, "Invalid Gang ID." );
else if ( p_gangInvited[ playerid ] [ gID ] == false ) return SendError( playerid, "You haven't been invited to this gang." );
else if ( g_iTime > p_gangInviteTick[ playerid ] ) return p_gangInvited[ playerid ] [ gID ] = false, SendError( playerid, "This invite has expired, each invite only lasts for 2 minutes." );
else if ( p_GangID[ playerid ] != INVALID_GANG_ID ) return SendError( playerid, "You are already inside a gang." );
else
{
p_gangInvited[ playerid ] [ gID ] = false;
SetPlayerGang( playerid, gID );
}
return 1;
}
else if ( !strcmp( params, "invite", false, 6 ) )
{
new
pID
;
if ( sscanf( params[ 7 ], "u", pID ) ) return SendUsage( playerid, "/gang invite [PLAYER_ID]" );
else if ( !IsPlayerConnected( pID ) ) return SendError( playerid, "This player is not connected." );
else if ( p_Class[ pID ] != CLASS_CIVILIAN ) return SendError( playerid, "You cannot invite people from non-civilian classes." );
else if ( IsPlayerSettingToggled( pID, SETTING_GANG_INVITES ) ) return SendError( playerid, "This player has disabled gang invites." );
else if ( pID == playerid ) return SendError( playerid, "You cannot use this on yourself." );
else if ( p_GangID[ pID ] != INVALID_GANG_ID ) return SendError( playerid, "This player is already inside a gang." );
else if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not inside any gang." );
else if ( p_GangID[ pID ] == p_GangID[ playerid ] ) return SendError( playerid, "This player is in your gang." );
else
{
if ( g_gangData[ p_GangID[ playerid ] ] [ E_INVITE_ONLY ] && !IsPlayerGangLeader( playerid, p_GangID[ playerid ] ) )
return SendError( playerid, "You are not the gang leader." );
p_gangInvited[ pID ] [ p_GangID[ playerid ] ] = true;
p_gangInviteTick[ pID ] = g_iTime + 120;
GameTextForPlayer( pID, sprintf( "~n~~y~~h~/gang join %d", p_GangID[ playerid ] ), 2000, 4 );
format( szNormalString, sizeof( szNormalString ), "[GANG]{FFFFFF} %s(%d) has invited you to join %s, to join type \"/gang join %d\"", ReturnPlayerName( playerid ), playerid, g_gangData[ p_GangID[ playerid ] ] [ E_NAME ], p_GangID[ playerid ] );
SendClientMessage( pID, g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], szNormalString );
format( szNormalString, sizeof( szNormalString ), "[GANG]{FFFFFF} You have invited %s(%d) to join your gang.", ReturnPlayerName( pID ), pID );
SendClientMessage( playerid, g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], szNormalString );
}
return 1;
}
else if ( !strcmp( params, "leave", false, 5 ) )
{
if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not in any gang." );
RemovePlayerFromGang( playerid, GANG_LEAVE_QUIT );
return SendServerMessage( playerid, "You have left your previous gang." );
}
else if ( !strcmp( params, "splitprofit", false, 11 ) )
{
new
fProfitSplit;
if ( sscanf( params[ 12 ], "d", fProfitSplit ) ) SendUsage( playerid, "/gang splitprofit [PERCENTAGE]" );
else if ( p_GangID[ playerid ] == INVALID_GANG_ID ) SendError( playerid, "You are not inside any gang." );
else if ( fProfitSplit == 0 && p_GangSplitProfits[ playerid ] == 0 ) SendError( playerid, "You are already not splitting any profit among your gang bank." );
else if ( fProfitSplit == 0 )
{
p_GangSplitProfits[ playerid ] = 0;
SendClientMessageToGang( p_GangID[ playerid ], g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has decided to no longer split his profits to the gang.", ReturnPlayerName( playerid ), playerid );
}
else if ( fProfitSplit == p_GangSplitProfits[ playerid ] && fProfitSplit != 0 ) SendError( playerid, "Your current profit split is the same as the percentage you specified." );
else if ( 0 < fProfitSplit > 100 ) SendError( playerid, "Choose a percentage between 0 and 100." );
else if ( fProfitSplit > 99999999 || fProfitSplit < 0 ) SendError( playerid, "Choose a percentage between 0 and 100." ); // Going over billions
else
{
p_GangSplitProfits[ playerid ] = fProfitSplit;
SendClientMessageToGang( p_GangID[ playerid ], g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has decided to split %d%s of his profit into the gang bank.", ReturnPlayerName( playerid ), playerid, fProfitSplit, "%%" );
}
return 1;
}
else if ( !strcmp( params, "private", false, 6 ) )
{
new
gangid = p_GangID[ playerid ];
if ( gangid == INVALID_GANG_ID ) return SendError( playerid, "You are not inside any gang." );
else if ( ! IsPlayerGangLeader( playerid, gangid ) ) return SendError( playerid, "You are not a gang leader." );
else
{
// Reset all gang invites
for( new i = 0; i < MAX_PLAYERS; i++ ) {
p_gangInvited[ i ] [ gangid ] = false;
}
// Update private status
mysql_single_query( sprintf( "UPDATE `GANGS` SET `INVITE_ONLY`=%d WHERE `ID`=%d", ( g_gangData[ gangid ] [ E_INVITE_ONLY ] = !g_gangData[ gangid ] [ E_INVITE_ONLY ] ), g_gangData[ gangid ] [ E_SQL_ID ] ) );
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) %s made the gang private.", ReturnPlayerName( playerid ), playerid, g_gangData[ gangid ] [ E_INVITE_ONLY ] ? ( "has" ) : ( "has not" ) );
}
return 1;
}
return SendUsage( playerid, "/gang [CREATE/LEAVE/INVITE/JOIN/KICK/NAME/LEADER/COLEADER/COLOR/SPLITPROFIT/PRIVATE/JOINMSG]" );
}
CMD:g( playerid, params[ ] )
{
new
msg[ 90 ]
;
if ( p_Class[ playerid ] != CLASS_CIVILIAN ) return SendError( playerid, "Civilians can use this command only." );
else if ( p_GangID[ playerid ] == INVALID_GANG_ID ) return SendError( playerid, "You are not in any gang." );
else if ( sscanf( params, "s[90]", msg ) ) return SendUsage( playerid, "/g [MESSAGE]" );
else
{
SendClientMessageToGang( p_GangID[ playerid ], g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "<Gang Chat> %s(%d):{FFFFFF} %s", ReturnPlayerName( playerid ), playerid, msg );
}
return 1;
}
/* ** SQL Threads ** */
thread OnPlayerGangLoaded( playerid )
{
new rows, fields;
cache_get_data( rows, fields );
if ( rows )
{
new gang_name[ 30 ], join_msg[ 96 ];
new gang_sql_id = cache_get_field_content_int( 0, "ID" );
// Check again if the gang exists
foreach (new g : gangs) if ( gang_sql_id == g_gangData[ g ] [ E_SQL_ID ] ) {
p_GangID[ playerid ] = g;
printf( "[gang debug] found duplicate gang for gang id %d (User : %s)", g, ReturnPlayerName( playerid ) );
return 1;
}
// reset name and join message appropriately
cache_get_field_content( 0, "NAME", gang_name, dbHandle, sizeof( gang_name ) );
cache_get_field_content( 0, "JOIN_MSG", join_msg, dbHandle, sizeof( join_msg ) );
// create gang
new handle = CreateGang( gang_name,
cache_get_field_content_int( 0, "LEADER", dbHandle ),
cache_get_field_content_int( 0, "COLOR", dbHandle ),
cache_get_field_content_int( 0, "KILLS", dbHandle ),
cache_get_field_content_int( 0, "DEATHS", dbHandle ),
cache_get_field_content_int( 0, "BANK", dbHandle ),
cache_get_field_content_int( 0, "SCORE", dbHandle ),
cache_get_field_content_int( 0, "RESPECT", dbHandle ),
!! cache_get_field_content_int( 0, "INVITE_ONLY", dbHandle ),
join_msg, false, gang_sql_id
);
// message player
if ( handle != ITER_NONE )
{
p_GangID[ playerid ] = handle;
InformGangConnectMessage( playerid, handle );
printf("[%s] Added gangid %d as gang slot %d", ReturnPlayerName( playerid ), gang_sql_id, handle );
}
else
{
p_GangID[ playerid ] = -1;
SendServerMessage( playerid, "Had an issue loading your gang. Contact " SERVER_OPERATOR " (0x92F)." );
printf("[GANG] [ERROR] Had an issue loading a gang row id %d", gang_sql_id );
}
}
else
{
p_GangID[ playerid ] = -1;
}
return 1;
}
thread OnGangAdded( gangid )
{
g_gangData[ gangid ] [ E_SQL_ID ] = cache_insert_id( );
mysql_single_query( sprintf( "UPDATE `USERS` SET `GANG_ID`=%d WHERE `ID`=%d", g_gangData[ gangid ] [ E_SQL_ID ], g_gangData[ gangid ][ E_LEADER ] ) );
return 1;
}
thread OnGangColeaderLoad( gangid ) {
new
rows, fields;
cache_get_data( rows, fields );
if ( rows ) {
for( new i = 0; i < rows; i ++ ) {
if ( i >= MAX_COLEADERS ) break;
g_gangData[ gangid ] [ E_COLEADER ] [ i ] = cache_get_field_content_int( i, "USER_ID", dbHandle );
}
}
}
thread OnListGangMembers( playerid, gangid, page )
{
new
rows, i;
cache_get_data( rows, tmpVariable );
if ( rows )
{
static
userName[ MAX_PLAYER_NAME ];
for( i = 0, szLargeString[ 0 ] = '\0'; i < rows; i++ )
{
cache_get_field_content( i, "NAME", userName );
format( szLargeString, sizeof( szLargeString ), "%s%s%s\n", szLargeString, cache_get_field_content_int( i, "ONLINE", dbHandle ) ? ( #COL_GREEN ) : ( #COL_WHITE ), userName );
}
SetPVarInt( playerid, "gang_members_id", gangid );
SetPVarInt( playerid, "gang_members_results", rows );
SetPVarInt( playerid, "gang_members_page", page );
ShowPlayerDialog( playerid, DIALOG_GANG_LIST_MEMBERS, DIALOG_STYLE_LIST, sprintf( ""COL_WHITE"Gang Members - Page %d", page + 1 ), szLargeString, rows >= 20 ? ( "Next" ) : ( "Close" ), "Back" );
}
else
{
// Notify user
SendError( playerid, "This gang no longer has any members." );
}
return 1;
}
thread OnListClans( playerid )
{
new
rows, fields
;
cache_get_data( rows, fields );
if ( rows )
{
new
szTag[ 8 ],
szName[ 30 ],
iScore, iColor
;
szLargeString = ""COL_WHITE"Tag\t"COL_WHITE"Name\t"COL_WHITE"Score\n";
for( new i = 0; i < rows; i++ )
{
cache_get_field_content( i, "CLAN_TAG", szTag );
cache_get_field_content( i, "NAME", szName );
iScore = cache_get_field_content_int( i, "SCORE", dbHandle );
iColor = cache_get_field_content_int( i, "COLOR", dbHandle );
format( szLargeString, sizeof( szLargeString ), "%s[%s]\t{%06x}%s\t%d\n", szLargeString, szTag, iColor >>> 8, szName, iScore );
}
return ShowPlayerDialog( playerid, DIALOG_NULL, DIALOG_STYLE_TABLIST_HEADERS, "Clan List", szLargeString, "Close", "" ), 1;
}
SendError( playerid, "There are no clans to show." );
return 1;
}
thread OnGangKickOffline( playerid, gangid )
{
new
static_gangid = p_GangID[ playerid ],
rows = cache_get_row_count( );
if ( rows )
{
new player_name[ MAX_PLAYER_NAME ];
new scan_name[ MAX_PLAYER_NAME ];
cache_get_field_content( 0, "NAME", player_name );
// scan if player is online
new player_accid = cache_get_field_content_int( 0, "ID", dbHandle );
foreach ( new scanid : Player ) {
GetPlayerName( scanid, scan_name, sizeof( scan_name ) );
if ( strmatch( player_name, scan_name ) ) {
return SendError( playerid, "You cannot use this command on a online player." ), 1;
}
}
// verify player is in gang
new player_gangid = cache_get_field_content_int( 0, "GANG_ID", dbHandle );
if ( IsPlayerGangLeader( playerid, player_gangid, .only_leader = 1 ) ) {
return SendError( playerid, "You cannot kick this player from the gang." );
}
if ( player_gangid != gangid ) {
return SendError( playerid, "This player is not in your gang." );
}
// remove as coleader
mysql_single_query( sprintf( "DELETE FROM `GANG_COLEADERS` WHERE `USER_ID`=%d", player_accid ) );
mysql_single_query( sprintf( "UPDATE `USERS` SET `GANG_ID`=-1 WHERE `ID`=%d", player_accid ) );
for ( new i = 0; i < MAX_COLEADERS; i++ ) if ( g_gangData[ gangid ] [ E_COLEADER ] [ i ] == player_accid ) {
g_gangData[ gangid ] [ E_COLEADER ] [ i ] = 0;
}
SendClientMessageToGang( static_gangid, g_gangData[ static_gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s has left the gang (KICKED)", player_name );
}
else
{
SendError( playerid, "It seems like this player isn't in your gang!" );
}
return 1;
}
/* ** Functions ** */
stock CreateGang( const gang_name[ 30 ], leader, gang_color, kills = 1, deaths = 1, bank = 0, score = 0, respect = 0, bool: invite_only = false, const join_message[ 96 ] = "NULL", bool: has_facility = false, sql_id = 0 )
{
new handle = Iter_Free( gangs );
if ( handle != ITER_NONE )
{
// Insert into iterator
Iter_Add( gangs, handle );
// insert gang into database, if no sql found
if ( ! sql_id )
{
// insert gang and fetch sql id
mysql_format( dbHandle, szBigString, sizeof( szBigString ), "INSERT INTO `GANGS`(`NAME`,`LEADER`,`COLOR`) VALUES ('%e', %d, %d)", gang_name, leader, gang_color );
mysql_function_query( dbHandle, szBigString, true, "OnGangAdded", "d", handle );
// reset coleaders in this case
for ( new i = 0; i < MAX_COLEADERS; i ++ ) {
g_gangData[ handle ] [ E_COLEADER ] [ i ] = 0;
}
}
else
{
// set gang sql id
g_gangData[ handle ] [ E_SQL_ID ] = sql_id;
// load coleaders
format( szNormalString, sizeof( szNormalString ), "SELECT `USER_ID` FROM `GANG_COLEADERS` WHERE `GANG_ID`=%d LIMIT 0,%d", g_gangData[ handle ] [ E_SQL_ID ], MAX_COLEADERS );
mysql_function_query( dbHandle, szNormalString, true, "OnGangColeaderLoad", "d", handle );
}
// Check for null join message
if ( ismysqlnull( join_message ) ) g_gangData[ handle ] [ E_JOIN_MSG ] [ 0 ] = '\0';
else format( g_gangData[ handle ] [ E_JOIN_MSG ], 96, "%s", join_message );
// format name
format( g_gangData[ handle ] [ E_NAME ], 30, "%s", gang_name );
trimString( g_gangData[ handle ] [ E_NAME ] );
// default variables
g_gangData[ handle ] [ E_LEADER ] = leader;
g_gangData[ handle ] [ E_KILLS ] = kills;
g_gangData[ handle ] [ E_DEATHS ] = deaths;
g_gangData[ handle ] [ E_SCORE ] = score;
g_gangData[ handle ] [ E_BANK ] = bank;
g_gangData[ handle ] [ E_COLOR ] = gang_color;
g_gangData[ handle ] [ E_RESPECT ] = respect;
g_gangData[ handle ] [ E_INVITE_ONLY ] = invite_only;
g_gangData[ handle ] [ E_HAS_FACILITY ] = has_facility;
// callback
CallLocalFunction( "OnGangLoad", "d", handle );
}
return handle;
}
stock DestroyGang( gangid, bool: soft_delete, bool: iter_remove = true )
{
if ( !Iter_Contains( gangs, gangid ) )
return;
if ( ! soft_delete )
{
// Do SQL operations
mysql_single_query( sprintf( "DELETE FROM `GANGS` WHERE `ID`=%d", g_gangData[ gangid ] [ E_SQL_ID ] ) );
mysql_single_query( sprintf( "DELETE FROM `GANG_COLEADERS` WHERE `GANG_ID`=%d", g_gangData[ gangid ] [ E_SQL_ID ] ) );
mysql_single_query( sprintf( "UPDATE `USERS` SET `GANG_ID`=-1 WHERE `GANG_ID`=%d", g_gangData[ gangid ] [ E_SQL_ID ] ) );
}
// Disconnect current users
foreach(new i : Player) if ( p_GangID[ i ] == gangid ) {
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;
g_gangData[ gangid ] [ E_SOFT_DELETE_TS ] = 0;
g_gangData[ gangid ] [ E_COLOR ] = g_gangColors[ random( sizeof( g_gangColors ) ) ];
g_gangData[ gangid ] [ E_NAME ] [ 0 ] = '\0';
g_gangData[ gangid ] [ E_BANK ] = 0;
g_gangData[ gangid ] [ E_RESPECT ] = 0;
g_gangData[ gangid ] [ E_INVITE_ONLY ] = false;
g_gangData[ gangid ] [ E_JOIN_MSG ] [ 0 ] = '\0';
// Reset coleaders
for ( new i = 0; i < MAX_COLEADERS; i ++ )
g_gangData[ gangid ] [ E_COLEADER ] [ i ] = 0;
// Free iterator id
if ( iter_remove ) {
Iter_Remove( gangs, gangid );
}
// Empty out the turfs
// Turf_ResetGangTurfs( gangid );
}
stock SaveGangData( gangid )
{
if ( gangid == INVALID_GANG_ID )
return;
mysql_format( dbHandle, szLargeString, sizeof( szLargeString ), "UPDATE `GANGS` SET `NAME`='%e',`LEADER`=%d,`COLOR`=%d,`KILLS`=%d,`DEATHS`=%d,`SCORE`=%d,`BANK`=%d,`RESPECT`=%d WHERE `ID`=%d",
g_gangData[ gangid ] [ E_NAME ], g_gangData[ gangid ] [ E_LEADER ], g_gangData[ gangid ] [ E_COLOR ], g_gangData[ gangid ] [ E_KILLS ], g_gangData[ gangid ] [ E_DEATHS ], g_gangData[ gangid ] [ E_SCORE ], g_gangData[ gangid ] [ E_BANK ], g_gangData[ gangid ] [ E_RESPECT ], g_gangData[ gangid ] [ E_SQL_ID ] );
mysql_single_query( szLargeString );
}
stock SetPlayerFindOrCreateGang( playerid, gang_sql )
{
new bool: foundGang = false;
// Reset gang id just incase
p_GangID[ playerid ] = INVALID_GANG_ID;
// Search all gangs for the SQL
printf("[%s] Reading gang id %d", ReturnPlayerName( playerid ), gang_sql );
if ( gang_sql ) {
foreach (new g : gangs) if( gang_sql == g_gangData[ g ] [ E_SQL_ID ] ) {
p_GangID[ playerid ] = g, foundGang = true;
break;
}
}
printf("[%s] Found gang ? %s , id %d, gangid %d", ReturnPlayerName( playerid ), foundGang ? ("YES") : ("NO"), p_GangID[ playerid ], gang_sql );
if ( ! foundGang ) {
format( szNormalString, sizeof( szNormalString ), "SELECT * FROM `GANGS` WHERE `LEADER`=%d OR `ID`=%d LIMIT 0,1", p_AccountID[ playerid ], gang_sql );
mysql_function_query( dbHandle, szNormalString, true, "OnPlayerGangLoaded", "d", playerid );
}
// Send gang join message
if ( p_GangID[ playerid ] != INVALID_GANG_ID && strlen( g_gangData[ p_GangID[ playerid ] ] [ E_JOIN_MSG ] ) ) {
SendClientMessageFormatted( playerid, g_gangData[ p_GangID[ playerid ] ] [ E_COLOR ], "[GANG]"COL_GREY" %s", g_gangData[ p_GangID[ playerid ] ] [ E_JOIN_MSG ] );
}
}
stock InformGangConnectMessage( playerid, gangid )
{
if ( ! strlen( g_gangData[ gangid ] [ E_JOIN_MSG ] ) ) {
SendClientMessageFormatted( playerid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]"COL_GREY" %s has been loaded into the server.", g_gangData[ gangid ] [ E_NAME ] );
} else {
SendClientMessageFormatted( playerid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]"COL_GREY" %s", g_gangData[ gangid ] [ E_JOIN_MSG ] );
}
return 1;
}
stock IsPlayerGangLeader( playerid, gangid, only_leader = 0 ) {
if ( g_gangData[ gangid ] [ E_LEADER ] == p_AccountID[ playerid ] )
return true;
// Reset coleaders
if ( only_leader == 0 ) {
for ( new i = 0; i < MAX_COLEADERS; i ++ ) {
if ( g_gangData[ gangid ] [ E_COLEADER ] [ i ] == p_AccountID[ playerid ] )
return true;
}
}
return false;
}
stock DisconnectFromGang( playerid )
{
new
gangid = p_GangID[ playerid ];
if ( gangid == INVALID_GANG_ID )
return 0;
p_GangID[ playerid ] = INVALID_GANG_ID;
if ( ! Iter_Contains( gangs, gangid ) )
return 0;
if ( g_gangData[ gangid ] [ E_HAS_FACILITY ] ) // we will not soft delete gangs with facilities
return 1;
new
members = GetOnlineGangMembers( gangid );
printf("Gang id %d has currently %d members online", g_gangData[ gangid ] [ E_SQL_ID ], members );
if ( members <= 0 ) {
g_gangData[ gangid ] [ E_SOFT_DELETE_TS ] = g_iTime + 60;
printf("[GANG DEBUG] Begin soft delete Id %d Since No Ppl", g_gangData[ gangid ] [ E_SQL_ID ] );
}
return 1;
}
stock RemovePlayerFromGang( playerid, E_GANG_LEAVE_REASON: reason = GANG_LEAVE_UNKNOWN, otherid = INVALID_PLAYER_ID )
{
new
gangid = p_GangID[ playerid ];
p_GangID[ playerid ] = INVALID_GANG_ID;
if ( !Iter_Contains( gangs, gangid ) )
return 0;
SetPlayerColorToTeam( playerid );
if ( g_gangData[ gangid ] [ E_LEADER ] == p_AccountID[ playerid ] )
{
new
selected_coleader = -1;
for ( new i = 0; i < MAX_COLEADERS; i ++ ) if ( g_gangData[ gangid ] [ E_COLEADER ] [ i ] ) {
selected_coleader = i;
break;
}
// Coleader exists?
if ( selected_coleader != -1 )
{
g_gangData[ gangid ] [ E_LEADER ] = g_gangData[ gangid ] [ E_COLEADER ] [ selected_coleader ];
g_gangData[ gangid ] [ E_COLEADER ] [ selected_coleader ] = 0;
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} The co-leader of the gang has been selected as the gang leader (acc id %d).", selected_coleader );
}
else
{
// Set invalid player to allow for check
g_gangData[ gangid ] [ E_LEADER ] = -1;
// Look for leader substitute
foreach(new memberid : Player)
{
if ( p_GangID[ memberid ] == gangid )
{
// Update color gang
SetGangColorsToGang( gangid );
g_gangData[ gangid ] [ E_LEADER ] = p_AccountID[ memberid ];
SendClientMessageToGang( gangid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has been selected as the gang leader.", ReturnPlayerName( memberid ), memberid );
break;
}
}
// Cannot find any leader, so destroy
if ( g_gangData[ gangid ] [ E_LEADER ] == -1 )
{
// Warn gang owner about gang
SendClientMessage( playerid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} There was nobody online that could be a leader for this gang therefore it has been deleted from the server." );
// Destroy gang internally
DestroyGang( gangid, false );
return 1;
}
}
}
// reset the coleader
for ( new i = 0; i < MAX_COLEADERS; i++ ) if ( g_gangData[ gangid ] [ E_COLEADER ] [ i ] == p_AccountID[ playerid ] ) {
g_gangData[ gangid ] [ E_COLEADER ] [ i ] = 0;
}
// wouldn't make sense to keep the coleader in any gang
mysql_single_query( sprintf( "DELETE FROM `GANG_COLEADERS` WHERE `USER_ID`=%d", p_AccountID[ playerid ] ) );
mysql_single_query( sprintf( "UPDATE `USERS` SET `GANG_ID`=-1 WHERE `ID`=%d", p_AccountID[ playerid ] ) );
printf("[%s] Gang ID after leaving is %d", ReturnPlayerName( playerid ), p_GangID[ playerid ] );
// Alter the gang & players
if ( Iter_Contains( gangs, gangid ) )
{
SaveGangData( gangid );
CallLocalFunction( "OnPlayerLeaveGang", "ddd", playerid, gangid, _: reason );
switch( reason )
{
case GANG_LEAVE_KICK:
SendClientMessageFormatted( playerid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has been kicked from the gang by %s(%d)!", ReturnPlayerName( playerid ), playerid, ReturnPlayerName( otherid ), otherid );
case GANG_LEAVE_UNKNOWN, GANG_LEAVE_QUIT:
SendClientMessageFormatted( playerid, g_gangData[ gangid ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has left the gang!", ReturnPlayerName( playerid ), playerid );
}
}
return 1;
}
stock SetPlayerGang( playerid, joining_gang )
{
if ( ! Iter_Contains( gangs, joining_gang ) )
return 0;
// remove from existing gang
if ( p_GangID[ playerid ] != INVALID_GANG_ID ) {
RemovePlayerFromGang( playerid, GANG_LEAVE_QUIT );
}
p_GangID[ playerid ] = joining_gang;
if ( GetPlayerWantedLevel( playerid ) < 1 ) SetPlayerColor( playerid, g_gangData[ joining_gang ] [ E_COLOR ] );
mysql_single_query( sprintf( "UPDATE `USERS` SET `GANG_ID`=%d WHERE `ID`=%d", g_gangData[ joining_gang ] [ E_SQL_ID ], GetPlayerAccountID( playerid ) ) );
SendClientMessageToGang( joining_gang, g_gangData[ joining_gang ] [ E_COLOR ], "[GANG]{FFFFFF} %s(%d) has joined the gang.", ReturnPlayerName( playerid ), playerid );
CallLocalFunction( "OnPlayerJoinGang", "dd", playerid, joining_gang );
return 1;
}
stock GetGangCash( gangid ) return g_gangData[ gangid ] [ E_BANK ];
stock GiveGangCash( gangid, cash ) {
g_gangData[ gangid ] [ E_BANK ] += cash;
}
stock gangNameExists( szName[ ] )
{
foreach(new i : gangs)
{
if ( strmatch( g_gangData[ i ] [ E_NAME ], szName ) ) return true;
}
return false;
}
stock SetGangColorsToGang( gangid )
{
foreach ( new i : Player )
{
// refresh player turfs
CallLocalFunction( "OnPlayerGangChangeColor", "dd", i, gangid );
// set new colour of player
if ( p_GangID[ i ] == gangid && p_WantedLevel[ i ] <= 0 && p_Class[ i ] == CLASS_CIVILIAN ) {
SetPlayerColor( i, g_gangData[ gangid ] [ E_COLOR ] );
}
}
}
stock ReturnGangName( i )
{
new
szGang[ 30 ] = "Unknown";
if ( IsValidGangID( i ) ) {
format( szGang, sizeof( szGang ), "%s", g_gangData[ i ] [ E_NAME ] );
}
return szGang;
}
stock SplitPlayerCashForGang( playerid, Float: cashRobbed )
{
new
bGangProfitSplit = ( p_GangID[ playerid ] != INVALID_GANG_ID && p_GangSplitProfits[ playerid ] ), Float: cashBanked = 0;
if ( bGangProfitSplit )
{
new
Float: keepOnHand = cashRobbed;
cashRobbed = ( keepOnHand * float( 100 - p_GangSplitProfits[ playerid ] ) ) / 100.0;
cashBanked = ( keepOnHand * float( p_GangSplitProfits[ playerid ] ) ) / 100.0;
new
iRoundedBanked = floatround( cashBanked, floatround_floor );
SendServerMessage( playerid, "You've split %s (%d%s) towards your gang's bank balance.", cash_format( iRoundedBanked ), p_GangSplitProfits[ playerid ], "%%" );
/*if ( -1 < iRoundedBanked > 50000 )
{
printf( "[EXPLOIT] [0xC1] %s has tried to store %s to gang %d", ReturnPlayerName( playerid ), cash_format( iRoundedBanked ), p_GangID[ playerid ] );
return SendError( playerid, "An exploit (0xC2) had occured, therefore this robbery was denied. Please report this to Lorenc!" );
}*/
g_gangData[ p_GangID[ playerid ] ] [ E_BANK ] += iRoundedBanked;
}
new
iRoundedRobbed = floatround( cashRobbed, floatround_floor );
if ( iRoundedRobbed != 0 )
{
/*if ( -1 < iRoundedRobbed > 50000 )
{
printf( "[EXPLOIT] [0xC1] %s has robbed %s", ReturnPlayerName( playerid ), cash_format( iRoundedRobbed ) );
return SendError( playerid, "An exploit (0xC1) had occured, therefore this robbery was denied. Please report this to Lorenc!" );
}*/
GivePlayerCash( playerid, iRoundedRobbed );
}
return 1;
}
stock GetOnlineGangMembers( gangid, &afk_members = 0 )
{
if ( gangid == INVALID_GANG_ID )
return 0;
new
iPlayers = 0;
foreach ( new playerid : Player ) if ( p_GangID[ playerid ] == gangid ) {
if ( IsPlayerAFK( playerid ) ) afk_members ++;
iPlayers ++;
}
return iPlayers;
}
CMD:gangiter( playerid, params[] )
{
if ( !IsPlayerAdmin( playerid ) ) return false;
SendClientMessageFormatted( playerid, -1, "Gang Iter Count: %i", Iter_Count( gangs ) );
return true;
}