Adding in discovery zone modifications
This commit is contained in:
parent
8746c23518
commit
2c1ff2473d
21 changed files with 423 additions and 58 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "src/assets/server-grid-editor"]
|
||||
path = src/assets/server-grid-editor
|
||||
url = https://github.com/GrapeshotGames/ServerGridEditor.git
|
||||
3
.idea/dictionaries/Tom.xml
generated
3
.idea/dictionaries/Tom.xml
generated
|
|
@ -4,6 +4,9 @@
|
|||
<w>deparse</w>
|
||||
<w>gameplay</w>
|
||||
<w>pegjs</w>
|
||||
<w>powerstones</w>
|
||||
<w>sublevel</w>
|
||||
<w>sublevels</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
||||
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
|
|
@ -2,5 +2,6 @@
|
|||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/src/assets/server-grid-editor" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
20
package-lock.json
generated
20
package-lock.json
generated
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
34
src/app/models/atlasData/discovery-zone.model.ts
Normal file
34
src/app/models/atlasData/discovery-zone.model.ts
Normal file
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
<button class="btn btn-primary btn-block" [routerLink]="['dbs']">DB Settings</button>
|
||||
<button class="btn btn-primary btn-block" [routerLink]="['quests']">Quest Settings</button>
|
||||
<button class="btn btn-primary btn-block" [routerLink]="['servers']">Server Settings</button>
|
||||
<button class="btn btn-primary btn-block" [routerLink]="['map']">Map</button>
|
||||
</div>
|
||||
<div class="col-10"><router-outlet></router-outlet></div>
|
||||
</div>
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
<div style="height: 400px;"
|
||||
<div style="height: 600px;"
|
||||
leaflet
|
||||
[leafletOptions]="options"
|
||||
[(leafletCenter)]="center"
|
||||
[(leafletZoom)]="zoom">
|
||||
<div *ngFor="let l of layers" [leafletLayer]="l"></div>
|
||||
</div>
|
||||
<p>Zoom: {{ zoom }}</p>
|
||||
<p>Center lat: {{ center.lat }} Center long: {{ center.lng }}</p>
|
||||
[leafletOptions]="options">
|
||||
<div *ngFor="let s of serverLayers" [leafletLayer]="s"></div>
|
||||
<div *ngFor="let i of islandLayers" [leafletLayer]="i"></div>
|
||||
<div *ngFor="let d of discoveryLayers" [leafletLayer]="d"></div>
|
||||
</div>
|
||||
|
|
@ -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)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
<div class="mt-3">
|
||||
<h2>{{ discovery.name }}
|
||||
<button class="btn btn-primary btn-sm" [routerLink]="['/config', 'server', cellIndex]">Back to Cell</button>
|
||||
</h2>
|
||||
<p>{{ discovery.sizeX }} by {{ discovery.sizeY }} by {{ discovery.sizeZ }}</p>
|
||||
<ngb-accordion>
|
||||
<ngb-panel title="General Settings">
|
||||
<ng-template ngbPanelContent>
|
||||
<app-text id="name" label="Name" [(text)]="discovery.name"></app-text>
|
||||
<app-number id="worldX" label="World X" [(number)]="discovery.worldX"></app-number>
|
||||
<app-number id="worldY" label="World Y" [(number)]="discovery.worldY"></app-number>
|
||||
<app-number id="rotation" label="Rotation" [(number)]="discovery.rotation" step="0.000001"
|
||||
min="{{ minRot }}" max="{{ maxRot }}"></app-number>
|
||||
<h4>Zone Size</h4>
|
||||
<app-number id="sizeX" label="Size X" [(number)]="discovery.sizeX"></app-number>
|
||||
<app-number id="sizeY" label="Size Y" [(number)]="discovery.sizeY"></app-number>
|
||||
<app-number id="sizeZ" label="Size Z" [(number)]="discovery.sizeZ"
|
||||
help="If the discovery zone has any size, this is normally 40,000"></app-number>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
<ngb-panel title="Discovery Settings">
|
||||
<ng-template ngbPanelContent>
|
||||
<app-number id="xp" label="XP" [(number)]="discovery.xp"
|
||||
help="XP Gained for discovering this zone. Note this also alters the max XP you can gain by levelling"></app-number>
|
||||
<app-checkbox id="allowSea" label="Allow Sea Discovery" [(checkbox)]="discovery.allowSea"
|
||||
help="May not do what you think - Always false on Official Server"></app-checkbox>
|
||||
<app-select-object id="explorerNoteIndex" label="Explorer Note" [optionObject]="explorerNotes"
|
||||
[option]="discovery.explorerNoteIndex" (optionChange)="setExplorerNote($event)"
|
||||
help="Opens a page in the players Discoveries menu on unlocking"></app-select-object>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
<ngb-panel title="Manual Volumes">
|
||||
<ng-template ngbPanelContent>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>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.</p>
|
||||
<p>Note as well, the location of a Manual Volume discovery doesnt really matter, however it defaults to
|
||||
the center of the cell.</p>
|
||||
<app-checkbox id="bIsManuallyPlaced" label="Enable Manual Volume"
|
||||
[(checkbox)]="discovery.bIsManuallyPlaced"></app-checkbox>
|
||||
<app-select-list id="ManualVolumeName" label="Manual Volume Name" *ngIf="discovery.bIsManuallyPlaced"
|
||||
[optionList]="discoveryVolumeNameOptions"
|
||||
[(option)]="discovery.ManualVolumeName"></app-select-list>
|
||||
<button class="btn btn-warning" (click)="setLocationCenterOfCell()">Set Center to Cell Center</button>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
</div>
|
||||
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -50,11 +50,55 @@
|
|||
<ngb-panel title="Island Settings">
|
||||
<ng-template ngbPanelContent>
|
||||
<p><em>Note that Sublevel settings are sorted in the background</em></p>
|
||||
<div *ngFor="let island of cell.islandInstances; let i = index">
|
||||
<h4>Island Instance {{ i }} - ID {{ island.id }} <button class="btn btn-sm btn-primary" [routerLink]="['island', i]">Edit</button></h4>
|
||||
<app-select-object id="{{ i }}-island-name" label="Island Model" [optionObject]="islandOptions"
|
||||
[option]="island.name" (optionChange)="changeIslandModel(i, $event)"></app-select-object>
|
||||
</div>
|
||||
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name & Model</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<app-select-object id="new-island" label="New Island" [optionObject]="islandOptions" [withEmptyOption]="true"
|
||||
[(option)]="newIslandName"></app-select-object>
|
||||
</td>
|
||||
<td><button class="btn btn-warning" (click)="addNewIsland()" [disabled]="!newIslandName">Add</button></td>
|
||||
</tr>
|
||||
<tr *ngFor="let island of cell.islandInstances; let i = index">
|
||||
<td>
|
||||
<app-select-object id="{{ i }}-island-name" label="{{ island.name }}" [optionObject]="islandOptions"
|
||||
[option]="island.name" (optionChange)="changeIslandModel(i, $event)"></app-select-object>
|
||||
</td>
|
||||
<td><button class="btn btn-primary" [routerLink]="['island', i]">Edit</button></td>
|
||||
<td><button class="btn btn-danger" (click)="deleteIsland(i)">Delete</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
<ngb-panel title="Discovery Zone Settings">
|
||||
<ng-template ngbPanelContent>
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Discovery Type</th>
|
||||
<th><button class="btn btn-sm btn-warning" (click)="addNewDiscovery()">Add</button></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let disco of cell.discoZones; let i = index">
|
||||
<th>{{ disco.name }}</th>
|
||||
<td>{{ disco.bIsManuallyPlaced ? "Location" : "Island" }}</td>
|
||||
<td><button class="btn btn-sm btn-primary" [routerLink]="['discovery', i]">Edit</button></td>
|
||||
<td><button class="btn btn-sm btn-danger" (click)="deleteDiscovery(i)">Delete</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</ng-template>
|
||||
</ngb-panel>
|
||||
</ngb-accordion>
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
src/assets/server-grid-editor
Submodule
1
src/assets/server-grid-editor
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit cffac3d0dff6391908bde5d2180efb6bbc76a101
|
||||
30
src/data/explorer-notes.json
Normal file
30
src/data/explorer-notes.json
Normal file
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ export class IslandDataModel implements Deserialize {
|
|||
imagePath: string;
|
||||
landscapeMaterialOverride: number;
|
||||
sublevelNames: string[];
|
||||
discoveryVolumeNames: string[];
|
||||
spawnerOverrides: object;
|
||||
extraSublevels: string[];
|
||||
treasureMapSpawnPoints: string[];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue