• Automation
    Backend Management
    Bot Development

  • I believe in

    code

  • generateBuilding(
                      definition: ReifiableDef,
                      position: Vector,
                      orientation?: Orientation
                  ): Building {
                      definition = Buildings.reify(definition);
                      orientation ??= Map.getRandomBuildingOrientation(definition.rotationMode);
              
                      const building = new Building(this.game, definition, Vec.clone(position), orientation);
              
                      for (const obstacleData of definition.obstacles) {
                            const obstacleDef = Obstacles.fromString(getRandomIDString(obstacleData.idString));
                            let obstacleRotation = obstacleData.rotation ?? Map.getRandomRotation(obstacleDef.rotationMode);
                
                                if (obstacleDef.rotationMode === RotationMode.Limited) {
                                    obstacleRotation = Numeric.addOrientations(orientation, obstacleRotation as Orientation);
                                }
                    
                                let lootSpawnOffset: Vector | undefined;
                    
                                if (obstacleData.lootSpawnOffset) lootSpawnOffset = Vec.addAdjust(Vec.create(0, 0), obstacleData.lootSpawnOffset, orientation);
                    
                                    const obstacle = this.generateObstacle(
                                        obstacleDef,
                                        Vec.addAdjust(position, obstacleData.position, orientation),
                                        obstacleRotation,
                                        obstacleData.scale ?? 1,
                                        obstacleData.variation,
                                        lootSpawnOffset,
                                        building,
                                        obstacleData.puzzlePiece
                                    );
                        
                            if (obstacleDef.role === ObstacleSpecialRoles.Activatable ||
                                obstacleDef.role === ObstacleSpecialRoles.Door) {
                                building.interactableObstacles.add(obstacle);
                            }
                      }
              
                              for (const lootData of definition.lootSpawners) {
                                  const table = LootTables[lootData.table];
                                  const drops = table.loot;
                      
                                      for (
                                          const item of Array.from(
                                              { length: random(table.min, table.max) },
                                              () => getLootTableLoot(drops as WeightedItem[]) // fixme This will break if multiple tables are specified
                                          ).flat()
                                      ) {
                                          this.game.addLoot(
                                              item.idString,
                                              Vec.addAdjust(position, lootData.position, orientation),
                                              item.count
                                          );
                                      }
                              }
              
                      for (const subBuilding of definition.subBuildings) {
                          const finalOrientation = Numeric.addOrientations(orientation, subBuilding.orientation ?? 0);
                          this.generateBuilding(
                              getRandomIDString(subBuilding.idString),
                              Vec.addAdjust(position, subBuilding.position, finalOrientation),
                              finalOrientation
                          );
                      }
              
                          for (const floor of definition.floors) {
                              this.terrain.addFloor(floor.type, floor.hitbox.transform(position, 1, orientation));
                          }
                  
                      for (const decal of definition.decals) {
                          this.game.grid.addObject(new Decal(this.game, Decals.reify(decal.idString), Vec.addAdjust(position, decal.position, orientation), Numeric.addOrientations(orientation, decal.orientation ?? 0)));
                      }
              
                      if (!definition.hideOnMap) this.packet.objects.push(building);
                      this.game.grid.addObject(building);
                      return building;
                  }
                  advanceGasStage(): void {
                    if (Config.gas.mode === GasMode.Disabled) return;
                    const currentStage = GasStages[this.stage + 1];
                    if (currentStage === undefined) return;
            
                    const duration = Config.gas.mode === GasMode.Debug && Config.gas.overrideDuration !== undefined && currentStage.duration !== 0
                        ? Config.gas.overrideDuration
                        : currentStage.duration;
            
                    this.stage++;
                    this.state = currentStage.state;
                    this.currentDuration = duration;
                    this.completionRatio = 1;
                    this.countdownStart = this.game.now;
            
                    if (currentStage.state === GasState.Waiting) {
                        this.oldPosition = Vec.clone(this.newPosition);
                        if (currentStage.newRadius !== 0) {
                            const { width, height } = this.game.map;
                            if (Config.gas.mode === GasMode.Debug && Config.gas.overridePosition) {
                                this.newPosition = Vec.create(width / 2, height / 2);
                            } else {
                                const maxDistance = (currentStage.oldRadius - currentStage.newRadius) * this.mapSize;
                                const maxDistanceSquared = maxDistance ** 2;
            
                                this.newPosition = randomPointInsideCircle(this.oldPosition, maxDistance);
            
                                let quadCoord = Gas._genQuadCoord(this.newPosition, width, height);
                                let foundPosition = false;
                                for (let attempts = 0; attempts < 100; attempts++) {
                                    quadCoord = Gas._genQuadCoord(this.newPosition, width, height);
                                    if (Geometry.distanceSquared(quadCoord, this.oldPosition) <= maxDistanceSquared) {
                                        foundPosition = true;
                                        break;
                                    }
                                }
            
                                if (foundPosition) this.newPosition = quadCoord;
                            }
                        } else {
                            this.newPosition = Vec.clone(this.oldPosition);
                        }
                        this.currentPosition = Vec.clone(this.oldPosition);
                        this.currentRadius = currentStage.oldRadius * this.mapSize;
                    }
            
                    this.oldRadius = currentStage.oldRadius * this.mapSize;
                    this.newRadius = currentStage.newRadius * this.mapSize;
                    this.dps = currentStage.dps;
                    this.dirty = true;
                    this.completionRatioDirty = true;
            
                    if (currentStage.summonAirdrop) {
                        this.game.summonAirdrop(
                            this.game.map.getRandomPosition(
                                new CircleHitbox(15),
                                {
                                    maxAttempts: 500,
                                    spawnMode: MapObjectSpawnMode.GrassAndSand,
                                    collides: position => Geometry.distanceSquared(position, this.currentPosition) >= this.newRadius ** 2
                                }
                            ) ?? this.newPosition
                        );
                    }
            
                    // Start the next stage
                    if (duration !== 0) {
                        this.game.addTimeout(() => this.advanceGasStage(), duration * 1000);
                    }
                }
                
                
  • Email me about...