sfcnr/gamemodes/irresistible/cnr/features/gangs/gangs.pwn
Cloudy 65df9ffaf3 Fixes a bug in gangs
Leader isn't shown in the gang members list, because his current gang wasn't being set to his new gang ID.

Upon gang creation, added an SQL query that updates the player's gang ID with the new gang created.
2019-06-09 19:12:44 +03:00

1186 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 visit "COL_GREY"donate.sfcnr.com" );
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 ) );
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;
}