1818
1919import GameServer from "../Game" ;
2020import ShapeManager from "../Misc/ShapeManager" ;
21+ import BossManager from "../Misc/BossManager" ;
2122import TankBody from "../Entity/Tank/TankBody" ;
2223import ArenaCloser from "../Entity/Misc/ArenaCloser" ;
24+ import AbstractBoss from "../Entity/Boss/AbstractBoss" ;
2325
2426import { VectorAbstract } from "../Physics/Vector" ;
2527import { ArenaGroup , TeamGroup } from "./FieldGroups" ;
@@ -30,13 +32,6 @@ import { TeamGroupEntity } from "../Entity/Misc/TeamEntity";
3032
3133import Client from "../Client" ;
3234
33- import AbstractBoss from "../Entity/Boss/AbstractBoss" ;
34- import Guardian from "../Entity/Boss/Guardian" ;
35- import Summoner from "../Entity/Boss/Summoner" ;
36- import FallenOverlord from "../Entity/Boss/FallenOverlord" ;
37- import FallenBooster from "../Entity/Boss/FallenBooster" ;
38- import Defender from "../Entity/Boss/Defender" ;
39-
4035import { countdownTicks , bossSpawningInterval , scoreboardUpdateInterval } from "../config" ;
4136
4237export const enum ArenaState {
@@ -76,11 +71,8 @@ export default class ArenaEntity extends Entity implements TeamGroupEntity {
7671
7772 public shapeScoreRewardMultiplier : number = 1 ;
7873
79- /** Enable or disable natural boss spawning */
80- public allowBoss : boolean = true ;
81-
82- /** The current boss spawned into the game */
83- public boss : AbstractBoss | null = null ;
74+ /** The boss spawner. Set to null in gamemode file to disable boss spawning. */
75+ public bossManager : BossManager | null = new BossManager ( this ) ;
8476
8577 /** Scoreboard leader */
8678 public leader : TankBody | null = null ;
@@ -134,21 +126,18 @@ export default class ArenaEntity extends Entity implements TeamGroupEntity {
134126 }
135127
136128 /**
137- * Finds a spawnable location on the map.
129+ * Finds a spawnable location on the map within the given width and height .
138130 */
139- public findSpawnLocation ( isPlayer : boolean = false ) : VectorAbstract {
131+ public findSpawnLocation ( width : number = this . width , height : number = this . height ) : VectorAbstract {
140132 const pos = {
141- x : ~ ~ ( Math . random ( ) * this . width - this . width / 2 ) ,
142- y : ~ ~ ( Math . random ( ) * this . height - this . height / 2 ) ,
133+ x : ~ ~ ( Math . random ( ) * width - width / 2 ) ,
134+ y : ~ ~ ( Math . random ( ) * height - height / 2 ) ,
143135 }
144136
145137 for ( let i = 0 ; i < 20 ; ++ i ) {
146- if (
147- ! this . isValidSpawnLocation ( pos . x , pos . y ) ||
148- isPlayer && Math . max ( pos . x , pos . y ) < this . arenaData . values . rightX / 2 && Math . min ( pos . x , pos . y ) > this . arenaData . values . leftX / 2
149- ) {
150- pos . x = ~ ~ ( Math . random ( ) * this . width - this . width / 2 ) ;
151- pos . y = ~ ~ ( Math . random ( ) * this . height - this . height / 2 ) ;
138+ if ( ! this . isValidSpawnLocation ( pos . x , pos . y ) ) {
139+ pos . x = ~ ~ ( Math . random ( ) * width - width / 2 ) ;
140+ pos . y = ~ ~ ( Math . random ( ) * height - height / 2 ) ;
152141 continue ;
153142 }
154143
@@ -163,8 +152,8 @@ export default class ArenaEntity extends Entity implements TeamGroupEntity {
163152 } ) ;
164153
165154 if ( entity ) {
166- pos . x = ~ ~ ( Math . random ( ) * this . width - this . width / 2 ) ;
167- pos . y = ~ ~ ( Math . random ( ) * this . height - this . height / 2 ) ;
155+ pos . x = ~ ~ ( Math . random ( ) * width - width / 2 ) ;
156+ pos . y = ~ ~ ( Math . random ( ) * height - height / 2 ) ;
168157 continue ;
169158 }
170159
@@ -174,6 +163,21 @@ export default class ArenaEntity extends Entity implements TeamGroupEntity {
174163 return pos ;
175164 }
176165
166+ public findPlayerSpawnLocation ( ) : VectorAbstract {
167+ let pos = this . findSpawnLocation ( ) ;
168+ for ( let i = 0 ; i < 20 ; ++ i ) {
169+ if (
170+ Math . max ( pos . x , pos . y ) < this . arenaData . values . rightX / 2 &&
171+ Math . min ( pos . x , pos . y ) > this . arenaData . values . leftX / 2
172+ ) {
173+ pos = this . findSpawnLocation ( ) ; // Players spawn away from the center
174+ continue ;
175+ }
176+ break ;
177+ }
178+ return pos ;
179+ }
180+
177181 /** Checks if players or shapes can spawn at the given coordinates. */
178182 public isValidSpawnLocation ( x : number , y : number ) : boolean {
179183 // Override in gamemode files
@@ -301,7 +305,7 @@ export default class ArenaEntity extends Entity implements TeamGroupEntity {
301305 * Allows the arena to decide how players are spawned into the game.
302306 */
303307 public spawnPlayer ( tank : TankBody , client : Client ) {
304- const { x, y } = this . findSpawnLocation ( true ) ;
308+ const { x, y } = this . findPlayerSpawnLocation ( ) ;
305309
306310 tank . positionData . values . x = x ;
307311 tank . positionData . values . y = y ;
@@ -337,18 +341,6 @@ export default class ArenaEntity extends Entity implements TeamGroupEntity {
337341 this . state = ArenaState . OPEN ;
338342 }
339343
340- /** Spawns the boss into the arena */
341- protected spawnBoss ( ) {
342- const TBoss = [ Guardian , Summoner , FallenOverlord , FallenBooster , Defender ]
343- [ ~ ~ ( Math . random ( ) * 5 ) ] ;
344-
345- this . boss = new TBoss ( this . game ) ;
346-
347- const { x, y } = this . game . arena . findSpawnLocation ( ) ;
348- this . boss . positionData . values . x = x ;
349- this . boss . positionData . values . y = y ;
350- }
351-
352344 public tick ( tick : number ) {
353345 this . shapes . tick ( ) ;
354346 this . updateArenaState ( ) ;
@@ -359,8 +351,6 @@ export default class ArenaEntity extends Entity implements TeamGroupEntity {
359351 this . arenaData . leaderY = this . leader . positionData . values . y ;
360352 }
361353
362- if ( this . allowBoss && this . game . tick >= 1 && ( this . game . tick % bossSpawningInterval ) === 0 && ! this . boss ) {
363- this . spawnBoss ( ) ;
364- }
354+ this . bossManager ?. tick ( tick ) ;
365355 }
366356}
0 commit comments