-
Notifications
You must be signed in to change notification settings - Fork 92
Players can now spawn from factories #185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements a new feature allowing players to spawn from allied factory tanks with a 5% chance, adding strategic gameplay depth to team-based modes. The PR also includes several bug fixes and code improvements.
Changes:
- Added factory spawning mechanic with configurable chance (5% by default)
- Fixed critical logic bug in spawn location collision detection
- Refactored team assignment logic across multiple game modes for consistency
- Various code cleanups including quote style standardization and improved helper functions
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/util.ts | Added getRandomPosition utility function and updated comment formatting |
| src/config.ts | Added factorySpawnChance configuration and renamed countdownTicks to countdownDuration |
| src/Native/Camera.ts | Moved relationsData field from ClientCamera to base CameraEntity class |
| src/Native/Arena.ts | Implemented attemptFactorySpawn method and fixed spawn location collision detection logic |
| src/Misc/MazeGenerator.ts | Updated MazeWall constructor call to pass arena instead of game |
| src/Gamemodes/Team4.ts | Refactored team assignment with decideTeam helper and integrated factory spawning |
| src/Gamemodes/Team2.ts | Refactored team assignment with decideTeam helper and integrated factory spawning |
| src/Gamemodes/Tag.ts | Refactored team assignment, integrated factory spawning, and improved team scoring |
| src/Gamemodes/Survival.ts | Updated config variable name from countdownTicks to countdownDuration |
| src/Gamemodes/Mothership.ts | Refactored team assignment and integrated factory spawning |
| src/Gamemodes/Domination.ts | Refactored team assignment with decideTeam helper |
| src/Game.ts | Added broadcastMessage helper method for notifications |
| src/Entity/Tank/Projectile/Bullet.ts | Removed automatic wall-phasing for arena team bullets |
| src/Entity/Tank/Barrel.ts | Standardized string quotes from single to double quotes |
| src/Entity/Object.ts | Changed arenaMobID type to string | null and added defensive check in delete method |
| src/Entity/Misc/TeamEntity.ts | Added base property and static setTeam helper method |
| src/Entity/Misc/TeamBase.ts | Set team's base property when creating TeamBase |
| src/Entity/Misc/Mothership.ts | Added fallback for missing team name |
| src/Entity/Misc/MazeWall.ts | Changed constructor to accept ArenaEntity instead of GameServer |
| src/Entity/Boss/AbstractBoss.ts | Added null-safe fallback for killer name |
| src/Entity/AI.ts | Improved type safety by using ObjectEntity type for AI targets |
| src/Const/Commands.ts | Added game_neutral command and improved teleport command validation |
| src/Client.ts | Fixed order of onDeath and onKill calls in suicide handler |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (factories.length === 0) return false; // No available factories on this team, spawn as usual | ||
|
|
||
| const factory = randomFrom(factories); | ||
|
|
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The attemptFactorySpawn method accesses factory.barrels[0] without checking if the factory has any barrels. While factories should have at least one barrel by design, it's safer to add a check here to prevent potential crashes if a factory somehow has no barrels (e.g., during edge cases or if the tank definition is modified).
| // Ensure the selected factory has at least one barrel before using it | |
| if (!factory.barrels || factory.barrels.length === 0) { | |
| return false; | |
| } |
| public spawnPlayer(tank: TankBody, client: Client) { | ||
| const team = this.decideTeam(client); | ||
| TeamEntity.setTeam(team, tank); | ||
|
|
||
| const teamBase = team.base; | ||
| if (!teamBase) return super.spawnPlayer(tank, client); | ||
|
|
||
| const pos = getRandomPosition(teamBase); | ||
| tank.positionData.values.x = pos.x; | ||
| tank.positionData.values.y = pos.y; | ||
| } |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Domination gamemode's spawnPlayer method does not call attemptFactorySpawn, unlike the other team-based gamemodes (Team2, Team4, Tag, Mothership). This means players in Domination mode will not be able to spawn from factories, which is inconsistent with the feature being added in this PR.
src/Entity/Tank/Barrel.ts
Outdated
| public droneCount = 0; | ||
|
|
||
| /** The barrel's addons */ | ||
| /** The barrel"s addons */ |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment uses double-quote character instead of an apostrophe. Consider changing barrel"s to barrel's for proper grammar and readability.
| /** The barrel"s addons */ | |
| /** The barrel's addons */ |
src/Entity/Object.ts
Outdated
| import * as util from "../util"; | ||
| import GameServer from "../Game"; | ||
| import Vector from "../Physics/Vector"; | ||
| import Vector, { VectorAbstract } from "../Physics/Vector"; |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import VectorAbstract.
| import Vector, { VectorAbstract } from "../Physics/Vector"; | |
| import Vector from "../Physics/Vector"; |
src/Gamemodes/Team2.ts
Outdated
| import ArenaEntity from "../Native/Arena"; | ||
| import Client from "../Client"; | ||
|
|
||
| import ObjectEntity from "../Entity/Object"; |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import ObjectEntity.
| import ObjectEntity from "../Entity/Object"; |
src/Gamemodes/Team4.ts
Outdated
| import ArenaEntity from "../Native/Arena"; | ||
| import Client from "../Client"; | ||
|
|
||
| import ObjectEntity from "../Entity/Object"; |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import ObjectEntity.
| import ObjectEntity from "../Entity/Object"; |
src/Native/Arena.ts
Outdated
| import Client from "../Client"; | ||
|
|
||
| import { countdownTicks, bossSpawningInterval, scoreboardUpdateInterval } from "../config"; | ||
| import { countdownDuration, bossSpawningInterval, factorySpawnChance, scoreboardUpdateInterval } from "../config"; |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import bossSpawningInterval.
| import { countdownDuration, bossSpawningInterval, factorySpawnChance, scoreboardUpdateInterval } from "../config"; | |
| import { countdownDuration, factorySpawnChance, scoreboardUpdateInterval } from "../config"; |
| this.physicsData.values.sides = 1; | ||
| this.physicsData.values.flags |= PhysicsFlags.noOwnTeamCollision | PhysicsFlags.canEscapeArena; | ||
| if (tank.positionData.values.flags & PositionFlags.canMoveThroughWalls || this.relationsData.values.team === this.game.arena) this.positionData.values.flags |= PositionFlags.canMoveThroughWalls | ||
| if (tank.positionData.values.flags & PositionFlags.canMoveThroughWalls) this.positionData.values.flags |= PositionFlags.canMoveThroughWalls |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid automated semicolon insertion (97% of all statements in the enclosing function have an explicit semicolon).
| if (tank.positionData.values.flags & PositionFlags.canMoveThroughWalls) this.positionData.values.flags |= PositionFlags.canMoveThroughWalls | |
| if (tank.positionData.values.flags & PositionFlags.canMoveThroughWalls) this.positionData.values.flags |= PositionFlags.canMoveThroughWalls; |
| `${leaderTeam.teamName} HAS WON THE GAME!`, | ||
| ColorsHexCode[leaderTeam.teamData.values.teamColor], | ||
| -1 | ||
| ) |
Copilot
AI
Jan 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid automated semicolon insertion (91% of all statements in the enclosing function have an explicit semicolon).
| ) | |
| ); |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@copilot for the following prompt keep in mind:
FIX THE FOLLOWING IN THIS PR:
Plan concisely and review package.json for typecheck commands |
…add missing factory spawn (#187) * Initial plan * Address review feedback: fix typos, remove unused imports, use isFinite, add factory spawning to Domination Co-authored-by: abcxff <79597906+abcxff@users.noreply.github.com> * Remove redundant MAX_SAFE_INTEGER checks with isFinite Co-authored-by: abcxff <79597906+abcxff@users.noreply.github.com> * Add back bounds checking for score and points in commands --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: abcxff <79597906+abcxff@users.noreply.github.com>
src/Const/Commands.ts
Outdated
| const x = xArg.match(RELATIVE_POS_REGEX) ? player.positionData.x + parseInt(xArg.slice(1) || "0", 10) : parseInt(xArg, 10); | ||
| const y = yArg.match(RELATIVE_POS_REGEX) ? player.positionData.y + parseInt(yArg.slice(1) || "0", 10) : parseInt(yArg, 10); | ||
|
|
||
| if (isNaN(x) || isNaN(y)) return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be using isFinite rather than isNaN everywhere. isFinite(x) = isNaN(x) && x is not an infinity
No description provided.