Adding in discovery zone modifications

This commit is contained in:
Tom Bloor 2020-01-13 21:43:36 +00:00
parent 8746c23518
commit 2c1ff2473d
Signed by: TBSliver
GPG key ID: 4657C7EBE42CC5CC
21 changed files with 423 additions and 58 deletions

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "src/assets/server-grid-editor"]
path = src/assets/server-grid-editor
url = https://github.com/GrapeshotGames/ServerGridEditor.git

View file

@ -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
View file

@ -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
View file

@ -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",

View file

@ -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",

View file

@ -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}
]
}

View file

@ -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,

View 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;
}
}

View file

@ -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;
}
}

View file

@ -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>

View file

@ -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>
[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>
<p>Zoom: {{ zoom }}</p>
<p>Center lat: {{ center.lat }} Center long: {{ center.lng }}</p>

View file

@ -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)
];
}
}

View file

@ -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>

View file

@ -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 );
}
}

View file

@ -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) {

View file

@ -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"
<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>
</div>
</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>

View file

@ -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);
}
}

@ -0,0 +1 @@
Subproject commit cffac3d0dff6391908bde5d2180efb6bbc76a101

View 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"
}

View file

@ -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",

View file

@ -8,6 +8,7 @@ export class IslandDataModel implements Deserialize {
imagePath: string;
landscapeMaterialOverride: number;
sublevelNames: string[];
discoveryVolumeNames: string[];
spawnerOverrides: object;
extraSublevels: string[];
treasureMapSpawnPoints: string[];