diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..14d4dab --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/assets/server-grid-editor"] + path = src/assets/server-grid-editor + url = https://github.com/GrapeshotGames/ServerGridEditor.git diff --git a/.idea/dictionaries/Tom.xml b/.idea/dictionaries/Tom.xml index 084fc1d..745f7b5 100644 --- a/.idea/dictionaries/Tom.xml +++ b/.idea/dictionaries/Tom.xml @@ -4,6 +4,9 @@ deparse gameplay pegjs + powerstones + sublevel + sublevels \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..64afc6a 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 6a689a8..e888f96 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1886,8 +1886,7 @@ "@types/geojson": { "version": "7946.0.7", "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.7.tgz", - "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==", - "dev": true + "integrity": "sha512-wE2v81i4C4Ol09RtsWFAqg3BUitWbHSpSlIo+bNdsCJijO9sjme+zm+73ZMCa/qMC8UEERxzGbvmr1cffo2SiQ==" }, "@types/glob": { "version": "7.1.1", @@ -1919,11 +1918,18 @@ "version": "1.5.7", "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.5.7.tgz", "integrity": "sha512-FiPU4NQwH+jQ2wc3IjD7+9hgNZ95m4ry8qILO+eS6L4eUUVSXr+472+k4SRVEW+8j18QwqY7PFqudDQzfpRXTQ==", - "dev": true, "requires": { "@types/geojson": "*" } }, + "@types/leaflet-imageoverlay-rotated": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@types/leaflet-imageoverlay-rotated/-/leaflet-imageoverlay-rotated-0.1.4.tgz", + "integrity": "sha512-b5Q2h1D4APy/hsYfqU1D1WGzsg7/jcxaezZk52R6V0VicqS9Lno72+ok0VNYTkdWmAWHhRFuwJOU1TldznYBqQ==", + "requires": { + "@types/leaflet": "*" + } + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -7340,6 +7346,14 @@ "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.6.0.tgz", "integrity": "sha512-CPkhyqWUKZKFJ6K8umN5/D2wrJ2+/8UIpXppY7QDnUZW5bZL5+SEI2J7GBpwh4LIupOKqbNSQXgqmrEJopHVNQ==" }, + "leaflet-imageoverlay-rotated": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/leaflet-imageoverlay-rotated/-/leaflet-imageoverlay-rotated-0.2.1.tgz", + "integrity": "sha512-8MsrIuW/aXI0EjDXgJSJJ67nqVNQJsP/glmND9g6yc6t+zQgdPUbTRHC65jSs/IBwzwyhggnDgDuydalcEX+ew==", + "requires": { + "leaflet": "^1.0.0" + } + }, "less": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/less/-/less-3.9.0.tgz", diff --git a/package.json b/package.json index 3e976ba..a606d5d 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,12 @@ "@angular/router": "~8.2.11", "@asymmetrik/ngx-leaflet": "^6.0.1", "@ng-bootstrap/ng-bootstrap": "^5.1.1", + "@types/leaflet-imageoverlay-rotated": "^0.1.4", "@types/pegjs": "^0.10.1", "ace-builds": "^1.4.7", "bootstrap": "^4.3.1", "leaflet": "^1.6.0", + "leaflet-imageoverlay-rotated": "^0.2.1", "rxjs": "~6.4.0", "ts-pegjs": "^0.2.6", "tslib": "^1.10.0", diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index a9042e9..8191716 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -9,6 +9,7 @@ import { ServersComponent } from "./pages/config/servers/servers.component"; import { ServerComponent } from "./pages/config/servers/server/server.component"; import { IslandInstanceComponent } from "./pages/config/servers/island-instance/island-instance.component"; import { MapComponent } from "./pages/config/map/map.component"; +import { DiscoveryZoneComponent } from "./pages/config/servers/discovery-zone/discovery-zone.component"; const routes: Routes = [ @@ -22,6 +23,7 @@ const routes: Routes = [ {path: 'servers', component: ServersComponent}, {path: 'server/:index', component: ServerComponent}, {path: 'server/:index/island/:islandIndex', component: IslandInstanceComponent}, + {path: 'server/:index/discovery/:discoIndex', component: DiscoveryZoneComponent}, {path: 'map', component: MapComponent} ] } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index bdc1989..3d9d4c8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -25,6 +25,7 @@ import { SelectObjectComponent } from './components/form/select-object/select-ob import { IslandInstanceComponent } from './pages/config/servers/island-instance/island-instance.component'; import { LeafletModule } from "@asymmetrik/ngx-leaflet"; import { MapComponent } from './pages/config/map/map.component'; +import { DiscoveryZoneComponent } from './pages/config/servers/discovery-zone/discovery-zone.component'; @NgModule({ declarations: [ @@ -45,7 +46,8 @@ import { MapComponent } from './pages/config/map/map.component'; SelectListComponent, SelectObjectComponent, IslandInstanceComponent, - MapComponent + MapComponent, + DiscoveryZoneComponent ], imports: [ BrowserModule, diff --git a/src/app/models/atlasData/discovery-zone.model.ts b/src/app/models/atlasData/discovery-zone.model.ts new file mode 100644 index 0000000..dc035be --- /dev/null +++ b/src/app/models/atlasData/discovery-zone.model.ts @@ -0,0 +1,34 @@ +import { Deserialize } from "../util/deserialize.model"; + +export class DiscoveryZoneModel implements Deserialize { + id: number; + name: string; + + sizeX: number = 0; + sizeY: number = 0; + sizeZ: number = 0; + + worldX: number = 0; + worldY: number = 0; + rotation: number = 0; + + xp: number = 0; + + allowSea: boolean = false; + explorerNoteIndex: number = 0; + + bIsManuallyPlaced: boolean = false; + ManualVolumeName: string; + + deserialize(input: any): this { + Object.assign(this, input); + return this; + } + + toJSON(): object { + let json = Object.assign({}, this); + // Key not shown at all if manually placed. + if (!json.bIsManuallyPlaced) delete json.ManualVolumeName; + return json; + } +} \ No newline at end of file diff --git a/src/app/models/atlasData/server.model.ts b/src/app/models/atlasData/server.model.ts index 7d1f701..f0c694a 100644 --- a/src/app/models/atlasData/server.model.ts +++ b/src/app/models/atlasData/server.model.ts @@ -1,6 +1,7 @@ import { Deserialize } from "../util/deserialize.model"; import { ServerSublevelModel } from "./serverSublevel.model"; import { IslandInstanceModel } from "./island-instance.model"; +import { DiscoveryZoneModel } from "./discovery-zone.model"; export class ServerModel implements Deserialize { // General Settings @@ -46,7 +47,7 @@ export class ServerModel implements Deserialize { extraSublevels: string[]; totalExtraSublevels: string[]; islandInstances: IslandInstanceModel[]; - discoZones; + discoZones: DiscoveryZoneModel[]; spawnRegions; // Dont render if default/empty @@ -72,6 +73,7 @@ export class ServerModel implements Deserialize { Object.assign(this, input); this.sublevels = this.sublevels.map(i => new ServerSublevelModel().deserialize(i)); this.islandInstances = this.islandInstances.map(i => new IslandInstanceModel().deserialize(i)); + this.discoZones = this.discoZones.map(i => new DiscoveryZoneModel().deserialize(i)); return this; } } \ No newline at end of file diff --git a/src/app/pages/config/config.component.html b/src/app/pages/config/config.component.html index 2f5021a..526c189 100644 --- a/src/app/pages/config/config.component.html +++ b/src/app/pages/config/config.component.html @@ -4,6 +4,7 @@ +
\ No newline at end of file diff --git a/src/app/pages/config/map/map.component.html b/src/app/pages/config/map/map.component.html index 715a6db..d4e8506 100644 --- a/src/app/pages/config/map/map.component.html +++ b/src/app/pages/config/map/map.component.html @@ -1,9 +1,7 @@ -
-
-
-

Zoom: {{ zoom }}

-

Center lat: {{ center.lat }} Center long: {{ center.lng }}

\ No newline at end of file + [leafletOptions]="options"> +
+
+
+ \ No newline at end of file diff --git a/src/app/pages/config/map/map.component.ts b/src/app/pages/config/map/map.component.ts index d1dca20..a3f7de1 100644 --- a/src/app/pages/config/map/map.component.ts +++ b/src/app/pages/config/map/map.component.ts @@ -1,8 +1,11 @@ import { Component, OnInit } from '@angular/core'; -import { CRS, LatLng, latLng, LatLngBounds, latLngBounds, Rectangle, tileLayer } from "leaflet"; +import { Circle, CRS, ImageOverlay, LatLng, LatLngBounds, Rectangle } from "leaflet"; import { Server } from "../../../server"; +import { IslandInstanceModel } from "../../../models/atlasData/island-instance.model"; +import * as L from 'leaflet'; +import 'leaflet-imageoverlay-rotated'; -const SIZE_SCALE = 100_000; +const RADIAN_RATIO = Math.PI / 180; @Component({ selector: 'app-map', @@ -13,16 +16,20 @@ export class MapComponent implements OnInit { options = { crs: CRS.Simple, - zoom: 0, + zoom: -16, maxBounds: undefined, maxBoundsViscosity: 0.5, center: undefined, - layers: [] + layers: [], + minZoom: -16, }; - center: LatLng; - zoom: number; - layers = []; + serverLayers = []; + islandLayers = []; + discoveryLayers = []; + + maxX: number; + maxY: number; constructor(private server: Server) { } @@ -30,28 +37,83 @@ export class MapComponent implements OnInit { ngOnInit() { // all in Y X format. Also, upside down! (0,0 is bottom left instead of top left) // Also, due to insanely large sizes, divide by 100_000 - const maxX = (this.server.serverGrid.gridSize * this.server.serverGrid.totalGridsX) / SIZE_SCALE; - const maxY = (this.server.serverGrid.gridSize * this.server.serverGrid.totalGridsY) / SIZE_SCALE; - const northEast = new LatLng(0, maxX); - const southWest = new LatLng(maxY, 0); + this.maxX = this.server.serverGrid.gridSize * this.server.serverGrid.totalGridsX; + this.maxY = this.server.serverGrid.gridSize * this.server.serverGrid.totalGridsY; + const northEast = new LatLng(0, this.maxX); + const southWest = new LatLng(this.maxY, 0); this.options.maxBounds = new LatLngBounds(southWest, northEast); this.options.center = new LatLng(0, 0); - this.options.layers[0] = new Rectangle(this.options.maxBounds, { - color: '#3c3c00', - weight: 5, - fillColor: 'lightblue', - fill: true - }); + this.options.layers.push(new ImageOverlay('./assets/server-grid-editor/WaterTiles/instinctworld-autoscaling.png', this.options.maxBounds)); - this.server.serverGrid.servers.forEach(i => { - const servMinX = (this.server.serverGrid.gridSize * i.gridX) / SIZE_SCALE; - const servMaxX = servMinX + (this.server.serverGrid.gridSize / SIZE_SCALE); - const servMinY = (this.server.serverGrid.gridSize * i.gridY) / SIZE_SCALE; - const servMaxY = servMinY + (this.server.serverGrid.gridSize / SIZE_SCALE); + this.server.serverGrid.servers.forEach(s => { + // Server Layer + const servMinX = this.server.serverGrid.gridSize * s.gridX; + const servMaxX = servMinX + this.server.serverGrid.gridSize; + const servMinY = this.server.serverGrid.gridSize * s.gridY; + const servMaxY = servMinY + this.server.serverGrid.gridSize; const servNE = new LatLng(servMinY, servMaxX); const servSW = new LatLng(servMaxY, servMinX); const servBounds = new LatLngBounds(servSW, servNE); - this.layers.push(new Rectangle(servBounds,{color: 'pink', weight: 5})); + this.serverLayers.push(new Rectangle(servBounds,{color: 'black', weight: 1})); + + s.islandInstances.forEach(i => { + const imgUrl = './assets/server-grid-editor/' + this.server.islands[i.name].imagePath.substring(2); + const islandLocation = this.islandToImageRotation(i); + this.islandLayers.push(L.imageOverlay.rotated(imgUrl, islandLocation[0], islandLocation[1], islandLocation[2])); + }); + + s.discoZones.forEach(d => { + if (d.ManualVolumeName !== undefined) return; + const imgUrl = './assets/server-grid-editor/Resources/discoZoneBox.png'; + const discoLocation = this.discoveryZoneToImageRotation(d); + this.discoveryLayers.push(L.imageOverlay.rotated(imgUrl, discoLocation[0], discoLocation[1], discoLocation[2])); + }); }) } + + gridCoordinateToMapLatLng(gridX: number, gridY: number): LatLng { + // Need to invert gridY for the Latitude. + const newY = this.maxY - gridY; + return new LatLng(newY, gridX); + } + + islandToImageRotation(island: IslandInstanceModel): LatLng[] { + return this.gridCoordinateToImageRotation(island.worldX, island.worldY, island.rotation, island.islandWidth, island.islandHeight); + } + + discoveryZoneToImageRotation(disco): LatLng[] { + return this.gridCoordinateToImageRotation(disco.worldX, disco.worldY, disco.rotation, disco.sizeX, disco.sizeY); + } + + gridCoordinateToImageRotation(worldX, worldY, rotation, width, height): LatLng[] { + const halfWidth = width / 2; + const halfHeight = height / 2; + + const radians = (rotation + 90) * RADIAN_RATIO; + + const cosR = Math.cos(radians); + const sinR = Math.sin(radians); + + // https://gamedev.stackexchange.com/questions/86755/how-to-calculate-corner-positions-marks-of-a-rotated-tilted-rectangle + // Rotate any point around + // Nx = x * cos(a) - y * sin(a) + // Ny = x * sin(a) + y * cos(a) + + // REMEMBER everything is upside down + // Top Left -1, 1 + const topLeftX = worldX + (-halfWidth * cosR) - (halfHeight * sinR); + const topLeftY = worldY + (-halfWidth * sinR) + (halfHeight * cosR); + // Bottom Left -1, -1 BUT mirrored for some reason so 1, 1 + const botLeftX = worldX + (halfWidth * cosR) - (halfHeight * sinR); + const botLeftY = worldY + (halfWidth * sinR) + (halfHeight * cosR); + // Top Right 1, 1 BUT mirrored for some reason so -1, -1 + const topRightX = worldX + (-halfWidth * cosR) - (-halfHeight * sinR); + const topRightY = worldY + (-halfWidth * sinR) + (-halfHeight * cosR); + + return [ + this.gridCoordinateToMapLatLng(topLeftX, topLeftY), + this.gridCoordinateToMapLatLng(topRightX, topRightY), + this.gridCoordinateToMapLatLng(botLeftX, botLeftY) + ]; + } } diff --git a/src/app/pages/config/servers/discovery-zone/discovery-zone.component.html b/src/app/pages/config/servers/discovery-zone/discovery-zone.component.html new file mode 100644 index 0000000..fb62b8a --- /dev/null +++ b/src/app/pages/config/servers/discovery-zone/discovery-zone.component.html @@ -0,0 +1,55 @@ +
+

{{ discovery.name }} + +

+

{{ discovery.sizeX }} by {{ discovery.sizeY }} by {{ discovery.sizeZ }}

+ + + + + + + +

Zone Size

+ + + +
+
+ + + + + + + + + +

Manual Volumes are either specific points on a map, or a particular 'discovery' available in a + cell. For example, certain Forests and Pools on an island are discovery zones in the official + server. Also the Powerstone locations are a discovery point, however the names for these aren't tied + to a specific island.

+

When a player enters the area of the 'Volume' or otherwise triggers it (in the case of Powerstones), + the discovery zone will be unlocked. This happens whether the player is on land, gliding, or + swimming. This only happens with these Manual Volume Discoveries - Normal discovery zones require + you to set foot on the area.

+

If the Zone size (under general settings) is set to 0 for XYZ, then no shimmer will show around the + discovery. Any other size will show a shimmer of that set size, and location, in game.

+

Note as well, the location of a Manual Volume discovery doesnt really matter, however it defaults to + the center of the cell.

+ + + +
+
+
+
\ No newline at end of file diff --git a/src/app/pages/config/servers/discovery-zone/discovery-zone.component.ts b/src/app/pages/config/servers/discovery-zone/discovery-zone.component.ts new file mode 100644 index 0000000..61021f7 --- /dev/null +++ b/src/app/pages/config/servers/discovery-zone/discovery-zone.component.ts @@ -0,0 +1,78 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from "@angular/router"; +import { Server } from "../../../../server"; +import { ServerModel } from "../../../../models/atlasData/server.model"; +import { DiscoveryZoneModel } from "../../../../models/atlasData/discovery-zone.model"; +import * as ExplorerNotes from '../../../../../data/explorer-notes.json'; + +@Component({ + selector: 'app-discovery-zone', + templateUrl: './discovery-zone.component.html' +}) +export class DiscoveryZoneComponent implements OnInit { + private cell: ServerModel; + private cellIndex; + private discovery: DiscoveryZoneModel; + private discoIndex; + + private minX: number; + private maxX: number; + private minY: number; + private maxY: number; + private minRot: number = 0; + private maxRot: number = 360; + + private explorerNotes; + + private discoveryVolumeNameOptions: string[] = [ + "PowerStone1", + "PowerStone2", + "PowerStone3", + "PowerStone4", + "PowerStone5", + "PowerStone6", + "PowerStone7", + "PowerStone8", + "PowerStone9", + "SecondaryStone1", + "SecondaryStone2", + "SecondaryStone3", + "SecondaryStone4", + "SecondaryStone5", + "SecondaryStone6", + "SecondaryStone7", + "SecondaryStone8", + "SecondaryStone9", + ]; + + constructor(private server: Server, private route: ActivatedRoute) { + } + + ngOnInit() { + this.cellIndex = this.route.snapshot.paramMap.get('index'); + this.discoIndex = this.route.snapshot.paramMap.get('discoIndex'); + this.cell = this.server.serverGrid.servers[this.cellIndex]; + this.discovery = this.cell.discoZones[this.discoIndex]; + this.minX = this.cell.gridX * this.server.serverGrid.gridSize; + this.maxX = this.minX + this.server.serverGrid.gridSize; + this.minY = this.cell.gridY * this.server.serverGrid.gridSize; + this.maxY = this.minY + this.server.serverGrid.gridSize; + this.explorerNotes = (ExplorerNotes as any).default; + + this.cell.islandInstances.forEach(i => { + const islandData = this.server.islands[i.name]; + if (islandData.discoveryVolumeNames === undefined ) return; + this.discoveryVolumeNameOptions = this.discoveryVolumeNameOptions.concat(islandData.discoveryVolumeNames); + }); + console.log(this.discoveryVolumeNameOptions); + } + + private setExplorerNote(option: string) { + this.discovery.explorerNoteIndex = parseInt(option); + } + + private setLocationCenterOfCell() { + this.discovery.worldX = this.minX + ( this.server.serverGrid.gridSize / 2 ); + this.discovery.worldY = this.minY + ( this.server.serverGrid.gridSize / 2 ); + } +} diff --git a/src/app/pages/config/servers/island-instance/island-instance.component.ts b/src/app/pages/config/servers/island-instance/island-instance.component.ts index 78655aa..b54ce60 100644 --- a/src/app/pages/config/servers/island-instance/island-instance.component.ts +++ b/src/app/pages/config/servers/island-instance/island-instance.component.ts @@ -34,6 +34,7 @@ export class IslandInstanceComponent implements OnInit { this.minY = this.cell.gridY * this.server.serverGrid.gridSize; this.maxY = this.minY + this.server.serverGrid.gridSize; } + // TODO Need to update subLevels in parent Cell when updating X and Y... // Issue with text arrays and editing jumps on each change. trackByFn(index: any, item: any) { diff --git a/src/app/pages/config/servers/server/server.component.html b/src/app/pages/config/servers/server/server.component.html index 977e248..10cd6d9 100644 --- a/src/app/pages/config/servers/server/server.component.html +++ b/src/app/pages/config/servers/server/server.component.html @@ -50,11 +50,55 @@

Note that Sublevel settings are sorted in the background

-
-

Island Instance {{ i }} - ID {{ island.id }}

- -
+ + + + + + + + + + + + + + + + + + + + +
Name & Model
+ +
+ +
+
+
+ + + + + + + + + + + + + + + + + + + +
NameDiscovery Type
{{ disco.name }}{{ disco.bIsManuallyPlaced ? "Location" : "Island" }}
diff --git a/src/app/pages/config/servers/server/server.component.ts b/src/app/pages/config/servers/server/server.component.ts index 38494c5..2610d77 100644 --- a/src/app/pages/config/servers/server/server.component.ts +++ b/src/app/pages/config/servers/server/server.component.ts @@ -5,6 +5,7 @@ import { ServerModel } from "../../../../models/atlasData/server.model"; import { IslandDataModel } from "../../../../../data/models/island-data.model"; import { IslandInstanceModel } from "../../../../models/atlasData/island-instance.model"; import { ServerSublevelModel } from "../../../../models/atlasData/serverSublevel.model"; +import { DiscoveryZoneModel } from "../../../../models/atlasData/discovery-zone.model"; @Component({ selector: 'app-server', @@ -14,6 +15,7 @@ export class ServerComponent implements OnInit { private cell: ServerModel; private templateOptions: string[]; private islandOptions: object = {}; + private newIslandName: string; constructor(private server: Server, private route: ActivatedRoute) { } @@ -27,38 +29,38 @@ export class ServerComponent implements OnInit { private changeIslandModel(index: number, name: string) { let oldIsland = this.cell.islandInstances[index]; - const newIslandData = this.server.islands[name]; - const oldIslandData = this.server.islands[oldIsland.name]; - - let newIsland = IslandInstanceModel.fromIslandData(newIslandData); + let newIsland = IslandInstanceModel.fromIslandData(this.server.islands[name]); + newIsland.id = this.server.serverGrid.getNextId(); // keep X, Y and Rotation the same newIsland.worldX = oldIsland.worldX; newIsland.worldY = oldIsland.worldY; newIsland.rotation = oldIsland.rotation; - // Remove old Sublevels - oldIslandData.sublevelNames.forEach(i => { + this.removeSublevelsForIsland(oldIsland); + this.addSublevelsForIsland(newIsland); + this.cell.islandInstances[index] = newIsland; + this.updateExtraSublevels(); + } + + private removeSublevelsForIsland(island: IslandInstanceModel) { + const islandData = this.server.islands[island.name]; + islandData.sublevelNames.forEach(i => { const j = this.cell.sublevels.findIndex(sublevel => sublevel.name === i); if (j > -1) { this.cell.sublevels.splice(j, 1); } }); + } - // Get new unique ID - newIsland.id = this.server.serverGrid.getNextId(); - - // Add new Sublevels - newIslandData.sublevelNames.forEach(i => { + private addSublevelsForIsland(island: IslandInstanceModel) { + const islandData = this.server.islands[island.name]; + islandData.sublevelNames.forEach(i => { let newSublevel = new ServerSublevelModel(); newSublevel.name = i; - newSublevel.setupFromIsland(newIsland, newIslandData, this.cell, this.server.serverGrid); + newSublevel.setupFromIsland(island, islandData, this.cell, this.server.serverGrid); this.cell.sublevels.push(newSublevel); }); - - this.cell.islandInstances[index] = newIsland; - - this.updateExtraSublevels(); } private updateExtraSublevels() { @@ -75,4 +77,30 @@ export class ServerComponent implements OnInit { }); }); } + + addNewIsland() { + const newIslandData = this.server.islands[this.newIslandName]; + let newIsland = IslandInstanceModel.fromIslandData(newIslandData); + newIsland.id = this.server.serverGrid.getNextId(); + this.addSublevelsForIsland(newIsland); + this.cell.islandInstances.push(newIsland); + this.updateExtraSublevels(); + } + + deleteIsland(index: number) { + let oldIsland = this.cell.islandInstances[index]; + this.removeSublevelsForIsland(oldIsland); + this.cell.islandInstances.splice(index, 1); + this.updateExtraSublevels(); + } + + addNewDiscovery() { + let newDisco = new DiscoveryZoneModel(); + newDisco.id = this.server.serverGrid.getNextId(); + this.cell.discoZones.push(newDisco); + } + + deleteDiscovery(index: number) { + this.cell.discoZones.splice(index, 1); + } } diff --git a/src/assets/server-grid-editor b/src/assets/server-grid-editor new file mode 160000 index 0000000..cffac3d --- /dev/null +++ b/src/assets/server-grid-editor @@ -0,0 +1 @@ +Subproject commit cffac3d0dff6391908bde5d2180efb6bbc76a101 diff --git a/src/data/explorer-notes.json b/src/data/explorer-notes.json new file mode 100644 index 0000000..1d4b434 --- /dev/null +++ b/src/data/explorer-notes.json @@ -0,0 +1,30 @@ +{ + "0": "None Set", + "1": "The Ladle of Life", + "2": "Gorgon's Perch", + "3": "The Fish's Mouth", + "4": "The Slender Gate", + "5": "Widowmaker's Claw", + "6": "Faceplant!", + "8": "Horseshoe of Eternity", + "9": "The Rainless Reef", + "11": "Hawthorn's Trap", + "12": "Giant's Crown", + "13": "Eagle's Eye", + "14": "Twin Tales", + "15": "Unknown Temple", + "16": "The Prancing Lady", + "17": "The Great and Angry Warrior", + "18": "Shattered Castle", + "19": "Eye of the Wolf", + "20": "The Demon of the Deep", + "21": "PowerStone 1", + "22": "PowerStone 2", + "23": "PowerStone 3", + "24": "PowerStone 4", + "25": "PowerStone 5", + "26": "PowerStone 6", + "27": "PowerStone 7", + "28": "PowerStone 8", + "29": "PowerStone 9" +} \ No newline at end of file diff --git a/src/data/islands.json b/src/data/islands.json index 41591f7..d2f8751 100644 --- a/src/data/islands.json +++ b/src/data/islands.json @@ -127,7 +127,7 @@ "name": "Mnt_B_WF", "x": 306000.0, "y": 306000.0, - "imagePath": "./IslandImages/Mnt_B_WF_img.png", + "imagePath": "./IslandImages/MNT_B_WF_img.png", "landscapeMaterialOverride": 5, "sublevelNames": [ "Mnt_B", @@ -12472,6 +12472,9 @@ "Mnt_H_Marine_Cold_Near", "Mnt_H_PO" ], + "discoveryVolumeNames": [ + "Mnt_H_Near_08B-BarricadeofIce" + ], "spawnerOverrides": {}, "extraSublevels": [ "MasterIBL_CaveEntrance_Polar", diff --git a/src/data/models/island-data.model.ts b/src/data/models/island-data.model.ts index 6232a1f..099d7dc 100644 --- a/src/data/models/island-data.model.ts +++ b/src/data/models/island-data.model.ts @@ -8,6 +8,7 @@ export class IslandDataModel implements Deserialize { imagePath: string; landscapeMaterialOverride: number; sublevelNames: string[]; + discoveryVolumeNames: string[]; spawnerOverrides: object; extraSublevels: string[]; treasureMapSpawnPoints: string[];