MCCodes - Chapter 3: Crime System

MCCodes Walkthrough Tutorial

Welcome to Chapter 3! In Chapter 2: Global Setup & Session Management, we learned how MCCodes sets everything up when you load a page, including figuring out who you are ($ir) and connecting to the game's brain (the database $db). Now that the stage is set, let's dive into one of the first things you might do in the game: committing crimes!

The Problem: Earning Your Keep (The Risky Way)

In many online text-based games, you need ways to earn money, experience points (XP), and maybe find useful items without necessarily fighting other players. How can the game provide a solo activity where players can take risks for potential rewards?

The Solution: MCCodes uses a Crime System. This system lets players attempt various criminal activities. Each crime has a cost, a chance of success based on the player's abilities, and different outcomes depending on whether they succeed or fail. It's a core Player vs. Environment (PVE) feature -- you're challenging the game's rules, not another player.

What are Crimes? The Risk vs. Reward Game

Think of crimes as mini-games of chance. You choose an action, like "Search the Streets" or "Rob a Convenience Store".

How to Use the Crime System (As a Player)

Let's see how you'd actually commit a crime in the game.

  1. Navigate to the Crime Page: You'll typically find a link in the main menu (set up by header.php as we saw in Chapter 1: Page Rendering & Structure) that takes you to criminal.php.

  2. See the List: The criminal.php page shows you a list of available crimes. These are usually grouped by category or difficulty.

    • Analogy: Imagine a bulletin board in a shady part of town, listing various "opportunities".

      Here's a simplified example of what you might see:

      Criminal Centre
      
      Petty Crimes
      -------------------------------------------
      Crime           | Cost      | Do
      -------------------------------------------
      Search the streets | 2 Brave   | [Do]
      Pickpocket someone | 3 Brave   | [Do]
      
      Minor Offenses
      -------------------------------------------
      Crime           | Cost      | Do
      -------------------------------------------
      Rob a hobo      | 5 Brave   | [Do]
      Steal hubcaps   | 6 Brave   | [Do]
      
  3. Choose Your Crime: You look at the list, check the Brave cost, and decide which crime you want to attempt.

  4. Click "Do": Clicking the "[Do]" link next to a crime sends your request to the server. This link actually points to another file, docrime.php, and tells it which crime you chose (using a number, the Crime ID, in the web address). For example, clicking "Do" for "Search the streets" might go to docrime.php?c=1.

  5. See the Outcome: The docrime.php script processes your attempt. After a moment, the page will reload or update, showing you the result:

    • Success: "You search the streets and find $50!" (You gain money, XP, etc.)
    • Failure: "You search the streets but find nothing useful." (You lose the Brave you spent).
    • Jail: "A police officer spots you trying to pickpocket and arrests you! You're sent to jail for 5 minutes." (You lose Brave and are put in jail, unable to play normally for a while).

How it Works Under the Hood

Let's trace what happens when you click that "Do" link for a crime.

Step-by-Step Walkthrough:

  1. Request: Your browser sends a request to docrime.php, including the Crime ID (e.g., ?c=1).
  2. Setup: docrime.php includes globals.php. This sets up your session, connects to the database ($db), loads your player data ($ir), etc. (as seen in Chapter 2).
  3. Checks: It checks if you're already in jail or the hospital ($ir['jail'] > 0). If so, it stops you.
  4. Get Crime Details: It uses the Crime ID ($_GET['c']) to look up the crime's details in the crimes database table (cost, formula, rewards, texts, jail time).
  5. Check Brave: It checks if you have enough Brave ($ir['brave']) to pay the crime's cost (crimeBRAVE). If not, it stops you.
  6. Deduct Brave: If you have enough, it subtracts the Brave cost from your character. This updates your $ir['brave'] value and saves it back to the users table in the database.
  7. Calculate Success: This is the tricky part! The crime has a crimePERCFORM (Percent Formula) stored in the database, like '((WILL*0.8)/2.5)+(LEVEL/4)'. The script replaces WILL and LEVEL with your actual stats from $ir and calculates a success percentage ($sucrate).
    • (Caution:* MCCodes uses a PHP function called eval() here. While powerful, eval() can be a security risk if not used very carefully, as it executes code stored as text. Modern development often avoids eval().)*
  8. Roll the Dice: The script generates a random number (e.g., between 1 and 100).
  9. Determine Outcome:
    • If the random number is less than or equal to your calculated $sucrate, you succeed!
    • Otherwise, you fail. The script might also have a chance to send you to jail on failure (often another random roll).
  10. Apply Results:
    • Success: Adds rewards (money, crystals, XP, Crime XP) to your $ir data and updates the users table. If the crime gives an item, it calls a function to add it to your inventory (we'll see this in Chapter 4: Item Management).
    • Failure: No rewards, just Brave lost.
    • Jail: Sets your $ir['jail'] time and $ir['jail_reason'] and updates the users table.
  11. Show Message: Displays the appropriate text message for success, failure, or jail (stored in the crimes table).
  12. Finish Page: Calls $h->endpage() to complete the HTML page.

Sequence Diagram:

sequenceDiagram
    participant B as Browser
    participant CP as criminal.php
    participant DP as docrime.php
    participant G as globals.php
    participant DB as Database

    B->>CP: Request criminal.php
    CP->>G: require 'globals.php' (loads $ir, $h, etc.)
    G-->>CP: Setup complete
    CP->>DB: Fetch crime groups & crimes
    DB-->>CP: Return crime list data
    CP-->>B: Display list of crimes with "Do" links (to docrime.php?c=ID)

    B->>DP: Click "Do" (Request docrime.php?c=ID)
    DP->>G: require 'globals.php' (loads $ir, $h, etc.)
    G-->>DP: Setup complete
    DP->>DP: Check if user jailed/hospitalized (using $ir)
    DP->>DB: Fetch details for crime ID from `crimes` table
    DB-->>DP: Return crime details (cost, formula, rewards...)
    DP->>DP: Check if $ir['brave'] >= crime cost
    DP->>DB: Update user's brave (deduct cost)
    DP->>DP: Calculate success rate (using formula & $ir stats)
    DP->>DP: Roll random number, compare to success rate
    alt Success
        DP->>DB: Update user's money, xp, crimexp, crystals
        opt Crime gives item
            DP->>DP: Call item_add() function
        end
        DP-->>B: Display success message
    else Failure
        alt Jail
             DP->>DB: Update user's jail time and reason
             DP-->>B: Display jail message
        else Simple Fail
             DP-->>B: Display failure message
        end
    end
    DP->>H: $h->endpage()

Diving into the Code

Let's look at simplified snippets of the key files.

1. criminal.php (Displaying the List)

This file mainly fetches data and displays it in an HTML table.

<?php
// File: criminal.php (Simplified)
require_once('globals.php'); // Setup session, user data ($ir), etc.

// Check if player can access this page
if ($ir['jail'] || $ir['hospital']) {
    die('This page cannot be accessed while in jail or hospital.');
}

echo "<h3>Criminal Centre</h3>";
echo "<table width='75%' cellspacing='1' class='table'>
        <tr><th>Crime</th><th>Cost</th><th>Do</th></tr>";

// Get crime groups (e.g., "Petty Crimes", "Minor Offenses")
$q_groups = $db->query("SELECT cgID, cgNAME FROM crimegroups ORDER BY cgORDER ASC");

// Get all crimes
$crimes_data = [];
$q_crimes = $db->query("SELECT crimeGROUP, crimeNAME, crimeBRAVE, crimeID FROM crimes ORDER BY crimeBRAVE ASC");
while ($row = $db->fetch_row($q_crimes)) {
    $crimes_data[] = $row;
}
$db->free_result($q_crimes);

// Loop through groups and display crimes within each group
while ($group = $db->fetch_row($q_groups)) {
    echo "<tr><td colspan='3' class='h'>{$group['cgNAME']}</td></tr>"; // Group header

    foreach ($crimes_data as $crime) {
        if ($crime['crimeGROUP'] == $group['cgID']) {
            // Display one row for each crime in this group
            echo "<tr>
                    <td>{$crime['crimeNAME']}</td>
                    <td>{$crime['crimeBRAVE']} Brave</td>
                    <td><a href='docrime.php?c={$crime['crimeID']}'>Do</a></td>
                  </tr>";
        }
    }
}
$db->free_result($q_groups);

echo '</table>';
$h->endpage(); // Finish the HTML page structure
?>

2. docrime.php (Processing the Attempt)

This is where the core logic happens.

<?php
// File: docrime.php (Simplified)
require_once('globals.php'); // Setup session, user data ($ir), etc.

// Get the chosen crime ID from the URL (?c=ID)
$crime_id = isset($_GET['c']) ? abs((int)$_GET['c']) : 0;

if ($crime_id <= 0) {
    die("Invalid Crime ID.");
}

// Check if player can access
if ($ir['jail'] > 0 || $ir['hospital'] > 0) {
    die('This page cannot be accessed while in jail or hospital.');
}

// Fetch crime details from the database
$q = $db->query("SELECT * FROM crimes WHERE crimeID = {$crime_id} LIMIT 1");
if ($db->num_rows($q) == 0) {
    die("Invalid Crime.");
}
$crime_data = $db->fetch_row($q);
$db->free_result($q);

// Check if player has enough Brave
if ($ir['brave'] < $crime_data['crimeBRAVE']) {
    die("You do not have enough Brave to perform this crime.");
}

// --- Action Starts ---
echo $crime_data['crimeITEXT']; // Display initial text ("You attempt to...")

// Deduct Brave
$ir['brave'] -= $crime_data['crimeBRAVE'];
$db->query("UPDATE users SET brave = {$ir['brave']} WHERE userid = $userid");

// Calculate Success Rate using the formula
$sucrate = 0;
$formula = str_replace(
    ['LEVEL', 'CRIMEXP', 'WILL', 'IQ' /* ... other stats ... */],
    [$ir['level'], $ir['crimexp'], $ir['will'], $ir['IQ'] /* ... */],
    $crime_data['crimePERCFORM'] // Get formula text from DB
);
// WARNING: eval() is used here. Be cautious with this function!
eval('$sucrate = ' . $formula . ';');
$sucrate = max(5, min(95, (int)$sucrate)); // Keep rate between 5% and 95%

// Roll the dice!
$roll = rand(1, 100);

if ($roll <= $sucrate) {
    // --- SUCCESS ---
    echo "<br />" . str_replace('{money}', $crime_data['crimeSUCCESSMUNY'], $crime_data['crimeSTEXT']);

    // Calculate rewards
    $gain_money = $crime_data['crimeSUCCESSMUNY'];
    $gain_crys = $crime_data['crimeSUCCESSCRYS'];
    $gain_xp = (int) ($gain_money / 8); // Example XP calculation
    $gain_crimexp = $crime_data['crimeXP'];

    // Update user in database
    $db->query("UPDATE users
                SET money = money + {$gain_money},
                    crystals = crystals + {$gain_crys},
                    exp = exp + {$gain_xp},
                    crimexp = crimexp + {$gain_crimexp}
                WHERE userid = $userid");

    // Give item if applicable
    if ($crime_data['crimeSUCCESSITEM'] > 0) {
        // item_add() will be covered in Chapter 4
        item_add($userid, $crime_data['crimeSUCCESSITEM'], 1);
        echo "<br />You also found an item!";
    }

} elseif (rand(1, 3) == 1 && $crime_data['crimeJAILTIME'] > 0) {
    // --- JAILED (Example: 1 in 3 chance on failure, if crime can jail) ---
    echo "<br />" . $crime_data['crimeJTEXT'];
    $db->query("UPDATE users
                SET jail = {$crime_data['crimeJAILTIME']},
                    jail_reason = '{$db->escape($crime_data['crimeJREASON'])}'
                WHERE userid = $userid");

} else {
    // --- FAILURE ---
    echo "<br />" . $crime_data['crimeFTEXT'];
    // Only Brave was lost (already deducted)
}

echo "<br /><br /><a href='docrime.php?c={$crime_id}'>Try Again</a>";
echo "<br /><a href='criminal.php'>Back to Crimes</a>";

$h->endpage(); // Finish the page
?>

3. Database (crimes Table)

This table, defined in dbdata.sql, stores all the information about each crime. Key columns include:

Admins can add, edit, or delete crimes and crime groups using the Staff Panel (staff_crimes.php), which modifies this database table.

Conclusion

You've now learned about the Crime System, a fundamental PVE (Player vs Environment) activity in MCCodes!

This system provides a core gameplay loop where players can risk resources (Brave) to gain rewards and improve their character, driven by their stats and a little luck.

Speaking of rewards, many crimes can award items. But how are items managed, stored, and used? Let's find out!


Next Up: Chapter 4: Item Management

Previously: Chapter 2: Global Setup & Session Management


First published April 21, 2025

Tags: MCCodes Walkthrough Tutorial