MCCodes - Chapter 6: Gang System
Welcome to Chapter 6! In Chapter 5: Attacking System, we saw how you can use your stats and items to fight other players. But sometimes, strength comes in numbers! What if you want to team up with other players, work together, share resources, and maybe even fight other teams? That's where the Gang System comes in.
The Problem: Teaming Up for Fun and Profit
Playing solo is fine, but many games are more fun with friends or teammates. How can players form persistent groups, manage their membership, share resources like money, communicate privately, participate in group activities, and even engage in conflicts with other groups?
The Solution: MCCodes provides a robust Gang System. Think of it like a virtual clubhouse or team management system. It allows players to create or join groups called "gangs". Once inside, members can:
- Socialize: Chat privately in gang forums.
- Collaborate: Participate in large-scale Organized Crimes (OCs) that require multiple members.
- Share: Donate money and items to a shared gang vault.
- Compete: Engage in Gang Wars against other gangs.
- Organize: Have leaders (President, Vice-President) who can manage members, applications, and gang settings.
It adds a whole layer of social interaction and cooperative gameplay to the game.
How Gangs Work: A Clubhouse Tour
Let's explore the different parts of the Gang System from a player's perspective.
1. Finding a Clubhouse (gangcentral.php
)
Just like looking for clubs in a town, you need a place to see which gangs exist. This is handled by gangcentral.php
.
- Analogy: This is the town's Club Directory board.
When you visit this page, you'll typically see a list of all the gangs in the game:
Gang Central
> Create A Gang Here
Gang Listings
--------------------------------------------------
Gang | Members | President | Respect
--------------------------------------------------
The Sharks | 15 | Big Tuna | 1500
The Jets | 12 | Riff | 1200
... more gangs ...
--------------------------------------------------
This page shows you the basic info and provides links to view each gang in more detail or to start your own gang (if you meet the requirements, like having enough money - see creategang.php
).
2. Looking Inside a Clubhouse (gangs.php
)
Clicking on a gang's name (like "The Sharks") in the Gang Central list takes you to gangs.php?action=view&ID=GangID
. This page shows you the public profile of that specific gang.
- Analogy: This is like looking at the front entrance and reading the public notice board of a specific clubhouse.
Here you might see:
- Gang Name and Description
- President and Vice-President names (with links to their profiles)
- Number of Members
- Gang Respect Level
- Links to view the Member List or Apply to join.
3. Joining the Club (Applying via gangs.php
)
If you're not already in a gang and you like what you see, you can click the "Apply" link on the gang's profile page (gangs.php?action=apply&ID=GangID
).
- Analogy: Filling out a membership application form.
This usually presents a form where you can write a short message explaining why you want to join. Clicking "Submit" sends your application to the gang's leaders.
4. Inside the Clubhouse (yourgang.php
) - The Member Hub
Once your application is accepted (or if you created the gang), you gain access to the members-only area: yourgang.php
. This is the main hub for everything related to your gang.
- Analogy: This is the actual inside of the clubhouse, only accessible to members.
yourgang.php
typically has several sections or links:
- Summary: Basic info about your gang (like the public view, but maybe with more details).
- Members: A list of all current members, their levels, and how long they've been in the gang. (Staff might see a "Kick" button here).
- Donate: A place to contribute your personal money or crystals to the shared gang vault.
- Forums: Access to the private gang forum for discussions.
- Crimes: Information about any ongoing Organized Crime the gang is planning.
- Staff Room (for President/VP): Access to management functions like handling applications, managing the vault, starting wars, changing settings, etc.
- Announcement: A message board displaying announcements from the gang leaders.
- Events: A log of recent gang activities (donations, members joining/leaving, OCs started, etc.).
- Leave: A button to leave the gang (usually disabled for President/VP).
5. Clubhouse Management (Staff Roles)
Gangs have a hierarchy:
- President: The top leader. Can do everything: manage members, applications, vault, settings, wars, OCs, change VP, and even transfer presidency.
- Vice-President (VP): Second in command. Can usually do most management tasks like handling applications, managing the vault, kicking members (except the President), and starting OCs, but typically cannot declare wars or change the President.
These roles allow for organized management of the gang's affairs.
How It Works Under the Hood
Let's trace the flow of viewing gangs and applying to join.
Step-by-Step Walkthrough:
- Visit Central: You click the "Gang Central" link, requesting
gangcentral.php
. - Setup:
gangcentral.php
includesglobals.php
(Chapter 2: Global Setup & Session Management) to set up your session, connect to the DB ($db
), load your info ($ir
), etc. - Fetch Gangs: It queries the
gangs
table, possibly joining withusers
to get the President's name. - Display List: It loops through the results and displays the HTML table of gangs, including links to
gangs.php?action=view&ID=...
for each. - View Specific Gang: You click a link, requesting
gangs.php?action=view&ID=GangID
. - Setup:
gangs.php
includesglobals.php
. - Fetch Details: It uses the
GangID
from the URL ($_GET['ID']
) to query thegangs
table for that specific gang's details (name, desc, president ID, VP ID, respect). It also queriesusers
to get the President/VP names and counts members. - Display Profile: It shows the gang's profile information and provides links like "Apply" (
gangs.php?action=apply&ID=...
). - Click Apply: You click the apply link, requesting
gangs.php?action=apply&ID=GangID
. - Show Form: If you're not already in a gang (
$ir['gang'] == 0
), it displays the application text area and a submit button (pointing togangs.php?action=applys&ID=...
). It includes a CSRF token for security (Chapter 9: Security Functions (CSRF/Password/Validation)). - Submit Application: You fill out the form and submit it. The request goes to
gangs.php?action=applys&ID=GangID
with your text ($_POST['application']
) and the CSRF token. - Process Application:
-
gangs.php
includesglobals.php
. - It verifies the CSRF token.
- It checks again if you're already in a gang.
- If all checks pass, it inserts a new row into the
applications
table containing your User ID, the Gang ID, and your application text. - It also inserts a record into the
gangevents
table to notify the gang leaders that a new application arrived. - It displays a success message "Application Sent".
-
- Approval (Later): A gang leader (President/VP) logs in, goes to
yourgang.php
, navigates to the Staff > Applications section. They see your application, read your text, and click "Accept" or "Decline". Accepting adds your$userid
to the gang (UPDATE users SET gang = GangID WHERE userid = $userid
) and deletes the application record. Declining just deletes the application record. You get an event notification either way.
Sequence Diagram (Viewing & Applying):
sequenceDiagram participant B as Browser participant GC as gangcentral.php participant GP as gangs.php participant DB as Database participant YG as yourgang.php (Staff) B->>GC: Request gangcentral.php GC->>DB: Fetch list of gangs DB-->>GC: Gang data GC-->>B: Display gang list (links to gangs.php) B->>GP: Request gangs.php?action=view&ID=X GP->>DB: Fetch details for Gang X DB-->>GP: Gang profile data GP-->>B: Display Gang X profile (with Apply link) B->>GP: Click Apply link (gangs.php?action=apply&ID=X) GP-->>B: Display application form (if not in gang) B->>GP: Submit Application (gangs.php?action=applys&ID=X + text) GP->>GP: Verify CSRF, check if already in gang GP->>DB: INSERT into `applications` table (userID, gangID, text) GP->>DB: INSERT into `gangevents` table (notify leaders) DB-->>GP: Inserts successful GP-->>B: Display "Application Sent" Note over B, YG: Later... Gang Leader logs in B->>YG: Request yourgang.php?action=staff&act2=apps YG->>DB: Fetch applications for Gang X DB-->>YG: List of applications (including yours) YG-->>B: Display application list with Accept/Decline buttons B->>YG: Leader clicks Accept (POST to yourgang.php) YG->>YG: Verify CSRF YG->>DB: UPDATE users SET gang = X WHERE userid = YourID YG->>DB: DELETE from `applications` table YG->>DB: INSERT into `gangevents` (notify members) YG->>DB: INSERT into `events` (notify applicant) DB-->>YG: Updates successful YG-->>B: Display "Application Accepted"
This shows the journey from discovering a gang to submitting an application and how it gets processed by the gang's staff later via yourgang.php
.
Diving into the Code
Let's look at simplified code snippets.
(Note:* MCCodes often uses global $db, $ir, $userid, $h;
at the start of functions to access variables defined in globals.php
. While functional, modern PHP often encourages passing these as arguments or using object properties instead.)*
1. gangcentral.php
(Listing Gangs)
<?php
// File: gangcentral.php (Simplified)
require_once('globals.php'); // Setup $ir, $db, $h
echo "<h3>Gang Central</h3>";
// Link to create a gang (checks money/gang status inside creategang.php)
echo "<a href='creategang.php'>> Create A Gang Here</a><br />";
echo "<hr /><u>Gang Listings</u><br />";
echo "<table cellspacing=1 class='table'>
<tr><th>Gang</th><th>Members</th><th>President</th><th>Respect</th></tr>";
// Query to get all gangs and their presidents' names
$gq = $db->query(
"SELECT g.gangID, g.gangNAME, g.gangRESPECT, u.userid, u.username
FROM gangs AS g
LEFT JOIN users AS u ON g.gangPRESIDENT = u.userid
ORDER BY g.gangID ASC"
);
while ($gangdata = $db->fetch_row($gq)) {
// Count members for this gang
$count_query = $db->query(
"SELECT COUNT(userid) FROM users WHERE gang = {$gangdata['gangID']}"
);
$member_count = $db->fetch_single($count_query);
$db->free_result($count_query);
// Display row
echo "<tr>
<td><a href='gangs.php?action=view&ID={$gangdata['gangID']}'>{$gangdata['gangNAME']}</a></td>
<td>{$member_count}</td>
<td><a href='viewuser.php?u={$gangdata['userid']}'>{$gangdata['username']}</a></td>
<td>{$gangdata['gangRESPECT']}</td>
</tr>";
}
$db->free_result($gq); // Free the main query result
echo '</table>';
$h->endpage();
?>
- Includes
globals.php
: Standard setup. - Database Query: Selects gang info and joins with
users
to get the president's username. - Loop & Count: Goes through each gang, performs another query inside the loop to count members (this isn't super efficient, but common in older code).
- Display: Creates an HTML table row for each gang with links to view the gang profile (
gangs.php
) and the president's profile (viewuser.php
).
2. gangs.php
(Viewing a Gang Profile & Applying)
<?php
// File: gangs.php (Simplified)
require_once('globals.php'); // Setup $ir, $db, $h
// Get Gang ID from URL, ensure it's a positive number
$_GET['ID'] = isset($_GET['ID']) ? abs((int)$_GET['ID']) : 0;
if (!$_GET['ID']) { die("Invalid Gang ID."); }
$gang_id = $_GET['ID'];
// Fetch this specific gang's data
$gq = $db->query(
"SELECT gangPRESIDENT, gangVICEPRES, gangNAME, gangID, gangRESPECT, gangDESC
FROM gangs
WHERE gangID = {$gang_id}"
);
if ($db->num_rows($gq) == 0) { die("Gang not found."); }
$gangdata = $db->fetch_row($gq);
$db->free_result($gq);
// Default action is 'view'
$action = $_GET['action'] ?? 'view';
// --- VIEW ACTION ---
if ($action == 'view') {
echo "<h3><u>{$gangdata['gangNAME']} Gang</u></h3><hr />";
// Fetch President Name
$pres_q = $db->query("SELECT username FROM users WHERE userid = {$gangdata['gangPRESIDENT']}");
$pres_name = ($db->num_rows($pres_q) > 0) ? $db->fetch_single($pres_q) : 'N/A';
$db->free_result($pres_q);
echo "President: {$pres_name}<br />";
// Fetch Vice-President Name (similar query)
// ... code to get VP name ...
echo "Vice-President: {$vp_name}<hr />";
// Count Members
$count_q = $db->query("SELECT COUNT(userid) FROM users WHERE gang = {$gang_id}");
$member_count = $db->fetch_single($count_q);
$db->free_result($count_q);
echo "Members: {$member_count}<br />";
echo "Description: {$gangdata['gangDESC']}<br />";
echo "Respect Level: {$gangdata['gangRESPECT']}<br />";
// Links
echo "> <a href='gangs.php?action=userlist&ID={$gang_id}'>User List</a><br />";
if ($ir['gang'] == 0) { // Only show Apply link if user is not in a gang
echo "> <a href='gangs.php?action=apply&ID={$gang_id}'>Apply</a>";
}
}
// --- APPLY FORM ACTION ---
elseif ($action == 'apply') {
if ($ir['gang'] == 0) {
$apply_csrf = request_csrf_code('gang_apply'); // Generate CSRF token
echo "<h3>Apply to {$gangdata['gangNAME']}</h3>";
echo "<form action='gangs.php?action=applys&ID={$gang_id}' method='post'>
Why should you be accepted?<br />
<textarea name='application' rows='7' cols='40'></textarea><br />
<input type='hidden' name='verf' value='{$apply_csrf}' />
<input type='submit' value='Send Application' />
</form>";
} else {
echo 'You are already in a gang.';
}
}
// --- SUBMIT APPLICATION ACTION ---
elseif ($action == 'applys') {
if (!$ir['gang']) {
// Verify CSRF token
if (!isset($_POST['verf']) || !verify_csrf_code('gang_apply', stripslashes($_POST['verf']))) {
die("CSRF validation failed. Please try applying again.");
}
$application_text = $db->escape(htmlentities(stripslashes($_POST['application'] ?? ''), ENT_QUOTES, 'ISO-8859-1'));
// Insert into applications table
$db->query(
"INSERT INTO applications (appUSER, appGANG, appTEXT)
VALUES($userid, {$gang_id}, '{$application_text}')"
);
// Add gang event
$gang_event_text = $db->escape("<a href='viewuser.php?u={$userid}'>{$ir['username']}</a> applied.");
$db->query(
"INSERT INTO gangevents (gevGANG, gevTIME, gevTEXT)
VALUES({$gang_id}, " . time() . ", '{$gang_event_text}')"
);
echo "Application sent to {$gangdata['gangNAME']}!";
} else {
echo 'You are already in a gang.';
}
}
// ... other actions like userlist ...
$h->endpage();
?>
- Gets ID & Data: Fetches the specific gang's details based on
$_GET['ID']
. - Action Handling: Uses
if/elseif
to handle different actions (view
,apply
,applys
). - View: Shows gang details and links. Crucially, it only shows the "Apply" link if the viewing player isn't already in a gang (
$ir['gang'] == 0
). - Apply Form: If the action is
apply
and the player isn't in a gang, it shows the text area and includes a CSRF token (request_csrf_code
). - Apply Submit: If the action is
applys
, it first verifies the CSRF token (verify_csrf_code
). If valid and the player isn't in a gang, it sanitizes the input ($db->escape
,htmlentities
) and inserts the application into theapplications
table and logs an event ingangevents
.
3. yourgang.php
(The Member Hub - Simplified Index & Donate)
<?php
// File: yourgang.php (Simplified Index/Donate)
require_once('globals.php'); // Setup $ir, $db, $h
// Check if user is actually in a gang
if (!$ir['gang']) {
die("You're not in a gang.");
}
// Fetch data for the user's gang
$gq = $db->query("SELECT * FROM gangs WHERE gangID = {$ir['gang']}");
if ($db->num_rows($gq) == 0) { die("Your gang seems to have been deleted."); }
$gangdata = $db->fetch_row($gq);
$db->free_result($gq);
echo "<h3><u>Your Gang - {$gangdata['gangNAME']}</u></h3>";
// --- Determine Action ---
$action = $_GET['action'] ?? 'index'; // Default to index view
// --- INDEX ACTION ---
if ($action == 'index') {
echo "<table cellspacing=1 class='table'>
<tr><td><a href='yourgang.php?action=summary'>Summary</a></td>
<td><a href='yourgang.php?action=donate'>Donate</a></td></tr>
<tr><td><a href='yourgang.php?action=members'>Members</a></td>
<td><a href='yourgang.php?action=crimes'>Crimes</a></td></tr>
<tr><td><a href='yourgang.php?action=forums'>Forums</a></td>
<td><a href='yourgang.php?action=leave'>Leave</a></td></tr>";
// Show Staff link only if President or VP
if ($gangdata['gangPRESIDENT'] == $userid || $gangdata['gangVICEPRES'] == $userid) {
echo "<tr><td colspan='2'><a href='yourgang.php?action=staff&act2=idx'>Staff Room</a></td></tr>";
}
echo "</table><br />";
echo "<b>Gang Announcement:</b><br /><div>{$gangdata['gangAMENT']}</div><br />";
// Show last 10 events (query gangevents table, loop and display)
// ... code to fetch and display last 10 events ...
}
// --- DONATE FORM ACTION ---
elseif ($action == 'donate') {
$donate_csrf = request_csrf_code('yourgang_donate');
echo "<b>Donate to the Vault</b><br />";
echo "Vault has: " . money_formatter($gangdata['gangMONEY']) . " and {$gangdata['gangCRYSTALS']} crystals.<br />";
echo "You have: " . money_formatter($ir['money']) . " and {$ir['crystals']} crystals.<br />";
echo "<form action='yourgang.php?action=donate2' method='post'>
Money: <input type='text' name='money' value='0' /><br />
Crystals: <input type='text' name='crystals' value='0' /><br />
<input type='hidden' name='verf' value='{$donate_csrf}' />
<input type='submit' value='Donate' />
</form>";
}
// --- DONATE SUBMIT ACTION ---
elseif ($action == 'donate2') {
// Verify CSRF
if (!isset($_POST['verf']) || !verify_csrf_code('yourgang_donate', stripslashes($_POST['verf']))) {
die("CSRF validation failed. Please try donating again.");
}
$money_to_donate = isset($_POST['money']) ? abs((int)$_POST['money']) : 0;
$crystals_to_donate = isset($_POST['crystals']) ? abs((int)$_POST['crystals']) : 0;
// Check if player has enough
if ($money_to_donate > $ir['money'] || $crystals_to_donate > $ir['crystals']) {
die("You don't have enough to donate that amount.");
}
if ($money_to_donate == 0 && $crystals_to_donate == 0) {
die("You didn't specify an amount to donate.");
}
// Update player's balance
$db->query("UPDATE users SET money = money - {$money_to_donate}, crystals = crystals - {$crystals_to_donate} WHERE userid = $userid");
// Update gang vault
$db->query("UPDATE gangs SET gangMONEY = gangMONEY + {$money_to_donate}, gangCRYSTALS = gangCRYSTALS + {$crystals_to_donate} WHERE gangID = {$ir['gang']}");
// Log gang event
$donate_event_text = $db->escape("<a href='viewuser.php?u={$userid}'>{$ir['username']}</a> donated.");
$db->query("INSERT INTO gangevents (gevGANG, gevTIME, gevTEXT) VALUES({$ir['gang']}, " . time() . ", '{$donate_event_text}')");
echo "Donation successful!";
}
// --- STAFF ACTIONS (Example: Apps) ---
elseif ($action == 'staff' && ($gangdata['gangPRESIDENT'] == $userid || $gangdata['gangVICEPRES'] == $userid)) {
$staff_action = $_GET['act2'] ?? 'idx';
if ($staff_action == 'apps') {
// Check if accepting/declining
$app_id = isset($_POST['app']) ? abs((int)$_POST['app']) : 0;
$app_what = isset($_POST['what']) ? $_POST['what'] : ''; // 'accept' or 'decline'
if ($app_id > 0 && ($app_what == 'accept' || $app_what == 'decline')) {
// Verify CSRF for the specific app action form
// ... CSRF check ...
// Fetch application details (appUSER, username)
// ... DB query for application ...
if ($app_what == 'accept') {
// Check gang capacity
// ... DB query to count members ...
// if (member_count >= gangdata['gangCAPACITY']) { die("Gang is full."); }
// Add user to gang
// ... UPDATE users SET gang = gangID WHERE userid = appUSER ...
// ... DELETE from applications ...
// ... Add events (user event, gang event) ...
echo "Application accepted.";
} else { // Decline
// ... DELETE from applications ...
// ... Add events (user event, gang event) ...
echo "Application declined.";
}
} else {
// Display list of applications
echo "<b>Applications</b><br />";
// ... Query applications table ...
// ... Loop and display each application with Accept/Decline forms (including CSRF tokens per form) ...
}
}
// ... other staff actions (vault, upgrades, wars etc.) ...
}
$h->endpage();
?>
- Checks Gang Membership: Verifies
$ir['gang']
is set. - Fetches Gang Data: Loads details for the player's current gang.
- Action Router: Uses
$_GET['action']
to decide what to show. - Index: Displays the main navigation links, announcement, and recent events. Shows the "Staff Room" link only if the user is President or VP.
- Donate Form: Shows current vault/player balances and a form to enter donation amounts, including a CSRF token.
- Donate Submit: Verifies CSRF, checks if the player has enough funds, updates both the
users
andgangs
tables, and logs agangevents
entry. - Staff Section: Further routes based on
$_GET['act2']
. The simplified 'apps' section shows the logic: display list, or process accept/decline (including CSRF checks, capacity checks, DB updates, and event logging).
Key Files and Tables
- Core Files:
-
gangcentral.php
: Lists all gangs. -
gangs.php
: Shows public profile for a specific gang, handles applying. -
yourgang.php
: The main hub for gang members, handles donations, member lists, staff actions (apps, vault, wars, OCs, etc.). -
creategang.php
: Handles the creation of a new gang. -
gangwars.php
: Publicly lists active gang wars. -
oclog.php
: Shows details of a past organized crime attempt. -
staff_gangs.php
: Staff Panel tool for managing gangs externally.
-
- Database Tables:
-
gangs
: Stores core gang information (name, desc, vault, respect, president/VP IDs, capacity, current OC). -
users
: Links users to gangs via thegang
column, storesdaysingang
. -
applications
: Temporarily stores pending applications to join gangs. -
gangevents
: Logs significant events within a gang (joins, leaves, donations, apps, OCs, etc.). -
gangwars
: Stores currently active wars between gangs. -
surrenders
: Stores surrender requests related to gang wars. -
orgcrimes
: Defines the available organized crimes gangs can attempt. -
oclogs
: Logs the results of past organized crime attempts. -
forum_forums
,forum_topics
,forum_posts
: Used for gang-specific forums (filtered byff_auth='gang'
andff_owner=gangID
).
-
Conclusion
You've now learned about the Gang System in MCCodes! It's like a comprehensive clubhouse management system built into the game.
- Players can find gangs (
gangcentral.php
), view their profiles (gangs.php
), and apply to join. - Members use
yourgang.php
as their hub for donations, communication (forums), and participating in group activities like Organized Crimes. - Leaders (President/VP) use the Staff section of
yourgang.php
to manage applications, the vault, members, settings, and initiate conflicts (wars) or cooperative actions (OCs). - Various tables (
gangs
,applications
,gangevents
,gangwars
, etc.) track all the data related to these player groups.
This system adds a significant social and cooperative dimension, allowing players to form alliances, share resources, and achieve goals together.
Many game systems need things to happen automatically on a schedule -- like refilling energy, ending jail sentences, or processing gang crime results. How does MCCodes handle these timed events?
Next Up: Chapter 7: Cron Job System
Previously: Chapter 5: Attacking System
First published April 21, 2025
Tags: MCCodes Walkthrough Tutorial