How Player Teams Function in PHPDTS: Data Fields and Membership Logic

Player teams in PHPDTS are defined by four database fields—teamID, teamPass, teamMate, and teamIcon—and managed through dedicated functions in include/game/team.func.php that handle creation, joining, and quitting with stamina cost validation.

PHPDTS is an open-source PHP-based duel tournament system where players can form alliances to coordinate strategy and private communication. Understanding how player teams function requires examining both the database schema that stores membership data and the helper functions that enforce team logic. This article analyzes the amarillonmc/phpdts source code to reveal exactly which data fields define team membership and how the game mechanics utilize this information.

Database Fields That Define Team Membership

Team affiliation is stored directly in the players table, with the schema defined in install/bra.sql at lines 128-132. Four specific columns control every aspect of team identity and access control.

teamID serves as the primary identifier—a string containing the team name (e.g., 'RedDragons'). When empty, the player has no team affiliation. This field appears on player profiles and drives the team chat filtering system.

teamPass stores the password required to join the team, remaining empty when no password protection is active. The teamjoin() function verifies this value before admitting new members, ensuring only authorized players can enter private teams.

teamMate maintains a dynamic "+"-separated list of all member names, including the team owner. Whenever a player joins or quits, the system updates this field across all existing members to keep the roster synchronized. For example, a three-person team might store 'Alice+Bob+Charlie' in each member's record.

teamIcon specifies a small integer (defaulting to 0) that selects the visual emblem displayed next to the team name in the alive list and on winner pages.

Core Team Management Functions

All team-related logic is centralized in include/game/team.func.php. These functions handle the complete lifecycle of player teams while enforcing stamina costs and validation rules.

Validating Actions with teamcheck()

Before processing any team command, the system calls teamcheck() (lines 10-19) to enforce prerequisites. This function rejects actions if the player already belongs to a team and verifies that the player has sufficient stamina ($sp) to cover the operation costs. Creation requires $team_sp stamina points, while joining consumes $teamj_sp points—both constants defined in config.inc.php.

Formation via teammake()

The teammake($tID, $tPass, $tIcon) function (lines 27-85) handles team creation. After passing the teamcheck() validation, it establishes the new team by setting the caller's teamID, teamPass, and teamIcon fields. The function deducts the creation stamina cost and registers the founder as the first member in their own teamMate field.

Recruitment via teamjoin()

To join an existing team, players invoke teamjoin($tID, $tPass) (lines 101-119). This function verifies that the target team exists and that the provided password matches the stored teamPass value. After confirming the player has enough stamina ($teamj_sp), it appends the new member's name to the teamMate field of every existing team member and updates the joiner's teamID to complete the association.

Departure via teamquit()

When a player leaves, teamquit() (lines 176-190) removes their name from the teamMate lists of all current members. It then clears the departing player's teamID, teamPass, and teamIcon fields, effectively dissolving their membership. The function handles edge cases where teams become empty by simply clearing the owner’s records without additional database cleanup.

Gameplay Systems Integrating Team Data

Team membership influences multiple gameplay mechanics beyond simple grouping, affecting communication, victory recording, and interface rendering.

Restricted Communication Channels

The chat system implements team privacy through the getchat() function in include/global.func.php (lines 382-385). Messages sent by players with a non-empty teamID are stored with type='1' and the recv field set to the team name. The global chat fetcher filters messages using this field, ensuring only teammates see the communications.

Victory Recording and Display

Upon player death, the battle logic stores team information in the winners table, including teamID, teamMate, and teamIcon. The winner.php script (lines 101-115) retrieves this data to render team banners on the victory page, displaying the full roster of surviving teammates who contributed to the win.

Profile and Alive List Rendering

Templates read team fields to visualize membership status. The templates/nouveau/profile.htm file (lines 175-177) displays the current teamID and icon on player profiles, while templates/default/alivelist.htm (lines 28-29) renders team icons next to player names in the survival rankings, allowing quick identification of allied players.

Implementation Example

The following pseudo-code demonstrates the function calls triggered by player commands:

// Player creates a new team with ID 'RedDragons', password 'secret', and icon 3
if ($cmd == 'team' && $subcmd == 'teammake') {
    teammake('RedDragons', 'secret', 3);
}

// Player joins an existing team
if ($cmd == 'team' && $subcmd == 'teamjoin') {
    teamjoin('RedDragons', 'secret');
}

// Player leaves their current team
if ($cmd == 'team' && $subcmd == 'teamquit') {
    teamquit();
}

Behind these calls, the system manipulates the four core database columns and synchronizes the teamMate rosters across all affected members.

Summary

  • Four database fields define team membership: teamID (team name), teamPass (access password), teamMate (roster list), and teamIcon (visual identifier), all stored in the players table per install/bra.sql.
  • Stamina-gated operations prevent abuse: teamcheck() validates that players have sufficient $sp to cover $team_sp (creation) or $teamj_sp (joining) costs before executing commands.
  • Centralized logic in include/game/team.func.php handles creation via teammake(), joining via teamjoin(), and quitting via teamquit(), maintaining synchronized teamMate strings across all members.
  • Cross-system integration enables team-only chat filtering (include/global.func.php), winner page banners (winner.php), and profile icons (templates/nouveau/profile.htm).

Frequently Asked Questions

What database columns store team membership in PHPDTS?

The players table contains four columns defined in install/bra.sql (lines 128-132): teamID stores the team name string, teamPass holds the optional join password, teamMate contains a "+"-delimited list of all member names, and teamIcon specifies the emblem integer. These fields work together to define complete membership status.

How does the game prevent players from joining multiple teams?

The teamcheck() function in include/game/team.func.php (lines 10-19) explicitly rejects any team command if the player's teamID field is non-empty. This validation occurs before teammake() or teamjoin() executes, ensuring players must quit their current team before forming or entering a new one.

What stamina costs are associated with team management?

Two constants defined in config.inc.php govern stamina consumption: $team_sp is deducted when creating a team via teammake(), and $teamj_sp is consumed when joining via teamjoin(). The teamcheck() function verifies the player has sufficient $sp stamina points before allowing either operation to proceed.

How is team-only chat implemented in the codebase?

Team chat privacy is implemented in include/global.func.php (lines 382-385) by filtering on the recv database field. When a player with a non-empty teamID sends a message, the system stores it with type='1' and recv set to their team name. The getchat() function retrieves only messages where recv matches the requesting player's teamID, effectively isolating communications to teammates only.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →