Skip to content

Commit

Permalink
v2.0.4: fix problems with object list and search & replace
Browse files Browse the repository at this point in the history
  • Loading branch information
Sadret committed Jul 5, 2023
1 parent eb55c22 commit 114d938
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 39 deletions.
5 changes: 5 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2.0.4 (2023-07-05)
------------------------------------------------------------------------
- Improved: Handling of objects that are loaded twice.
- Fix: Delete / replace message now displays the correct number of elements.

2.0.3 (2023-07-05)
------------------------------------------------------------------------
- Fix: [#39] New track elements now copy and mirror properly.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "openrct2-scenery-manager",
"version": "2.0.3",
"version": "2.0.4",
"description": "OpenRCT2 Scenery Manager Plug-In",
"author": "Sadret",
"license": "GPL-3.0",
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ An OpenRCT2 plug-in to copy and paste scenery, with many more features.
## Installation

1. Make sure that your OpenRCT2 version is up-to-date. You need at least version `0.4.0` or a recent development version.
2. Go to the [releases](#https://github.com/Sadret/openrct2-scenery-manager/releases) page and download the `scenery-manager-2.0.3.js` file from the latest release. Save it in the `plugin` subfolder of your OpenRCT2 user directory.\
2. Go to the [releases](#https://github.com/Sadret/openrct2-scenery-manager/releases) page and download the `scenery-manager-2.0.4.js` file from the latest release. Save it in the `plugin` subfolder of your OpenRCT2 user directory.\
On Windows, this is usually at `C:Users\{User}\Documents\OpenRCT2\plugin`.\
If you had a previous version of the Scenery Manager installed, make sure to delete its file from the `plugin` folder.
3. Start OpenRCT2 and open a scenario. If this is the first time that you use this plug-in, it should show a welcome message.
Expand Down
21 changes: 14 additions & 7 deletions src/core/Map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as Arrays from "../utils/Arrays";
import * as Context from "./Context";
import * as Coordinates from "../utils/Coordinates";
import * as Footpath from "../template/Footpath";
import * as SmallScenery from "../template/SmallScenery";
import * as Objects from "../utils/Objects";

import Template from "../template/Template";
Expand Down Expand Up @@ -170,13 +171,19 @@ export function remove(
data => Context.queryExecuteActionCallback(data, callback)
);
else
Template.getRemoveActionData(
tile,
Template.copyFrom(element),
element.isGhost ? 72 : 0,
).forEach(
data => Context.queryExecuteActionCallback(data, callback)
);
// workaround to handle objects that are loaded twice: use the correct index
(element.type === "small_scenery"
? SmallScenery.getRemoveActionData(
Coordinates.toWorldCoords(tile),
element,
element.isGhost ? 72 : 0,
) : Template.getRemoveActionData(
tile,
Template.copyFrom(element),
element.isGhost ? 72 : 0,
)).forEach(
data => Context.queryExecuteActionCallback(data, callback)
);
else {
removeElement(tile, element, additionOnly);
callback && callback({ error: 0 });
Expand Down
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import MainWindow from "./window/MainWindow";

registerPlugin({
name: "scenery-manager",
version: "2.0.3",
version: "2.0.4",
authors: ["Sadret"],
type: "local",
licence: "GPL-3.0",
Expand Down
14 changes: 10 additions & 4 deletions src/template/SmallScenery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ export function getPlaceActionData(

export function getRemoveActionData(
coords: CoordsXY,
element: SmallSceneryData,
element: SmallSceneryData | SmallSceneryElement,
flags: number,
): RemoveActionData[] {
const object = ObjectIndex.getObject("small_scenery", element.qualifier);
if (object === null)
const object = getObject(element);
if (object === undefined)
return [];
return [{
type: "smallsceneryremove",
Expand All @@ -102,11 +102,17 @@ export function getRemoveActionData(
...coords,
z: element.baseZ,
flags: flags,
object: object.index,
object: object,
},
}];
}

function getObject(element: SmallSceneryData | SmallSceneryElement): number | undefined {
if ("object" in element) return element.object;
else return ObjectIndex.getObject("small_scenery", element.qualifier) ?.index;

}

export function setQuadrant(element: SmallSceneryData, quadrant: number): SmallSceneryData {
return isFullTile(element) ? element : {
...element,
Expand Down
4 changes: 2 additions & 2 deletions src/utils/Jumper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ export default class Jumper {
"Reached end of map!",
);
} else {
const tile = data[0];
const [tile, element] = data;
if (inParkOnly && !Map.hasOwnership(tile))
return this.jump();
ui.mainViewport.scrollTo({
x: tile.x * 32,
y: tile.y * 32,
z: data[1].baseZ,
z: element.baseZ,
});
}
this.button.setText(this.btnLabel);
Expand Down
9 changes: 5 additions & 4 deletions src/window/ObjectDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,21 @@ import BooleanProperty from "../config/BooleanProperty";
import GUI from "../gui/GUI";
import Jumper from "../utils/Jumper";
import MainWindow from "./MainWindow";
import ObjectIndex from "../core/ObjectIndex";

function match(element: TileElement, object: SceneryObject): boolean {
switch (object.type) {
case "wall":
case "small_scenery":
case "large_scenery":
case "footpath":
return element.type === object.type && element.object === object.index;
return element.type === object.type && ObjectIndex.getQualifier(object.type, element.object) === object.qualifier;
case "footpath_surface":
return element.type === "footpath" && element.surfaceObject === object.index;
return element.type === "footpath" && ObjectIndex.getQualifier(object.type, element.surfaceObject) === object.qualifier;
case "footpath_railings":
return element.type === "footpath" && element.railingsObject === object.index;
return element.type === "footpath" && ObjectIndex.getQualifier(object.type, element.railingsObject) === object.qualifier;
case "footpath_addition":
return element.type === "footpath" && element.addition === object.index;
return element.type === "footpath" && ObjectIndex.getQualifier(object.type, element.addition) === object.qualifier;
}
}

Expand Down
42 changes: 30 additions & 12 deletions src/window/tabs/Replace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,33 +59,53 @@ function findAndDelete(replace: boolean): void {
overlay.setIsVisible(true);
const mode = Configuration.tools.placeMode.getValue();
const inParkOnly = inParkOnlyProp.getValue();
let count = 0;
let pending = 0;
let ok = 0;
let err = 0;
let shouldReport = false;
// does not actually report the number of <replaced> elements
let report = () => {
if (shouldReport)
Dialogs.showAlert({
title: "Elements replaced",
message: [`${replace ? "Replaced" : "Deleted"} ${ok} element${ok === 1 ? "" : "s"} (${err} error${err === 1 ? "" : "s"}).`],
width: 192,
});
shouldReport = false;
};

new MapIterator(
getTileSelection()
).forEach(
coords => {
const tile = Map.getTile(coords);
if (inParkOnly && !Map.hasOwnership(tile))
return;
if (mode === "raw" && replace)
if (mode === "raw" && replace) {
tile.elements.forEach(
element => {
if (findGroup.match(element)) {
count++;
replaceGroup.replace(element);
ok++;
}
},
);
else {
report();
} else {
const elements = Map.read(tile);
elements.forEach(
element => {
if (findGroup.match(element)) {
pending++;
const callback = (result: GameActionResult) => {
pending--;
if (result.error)
return;
count++;
if (!replace)
err++;
else
ok++;
if (shouldReport && pending === 0)
report();
if (!replace || result.error)
return;
// safe only
replaceGroup.replace(element);
Expand All @@ -106,11 +126,9 @@ function findAndDelete(replace: boolean): void {
if (done) {
overlay.setIsVisible(false);
overlay.setProgress(undefined);
Dialogs.showAlert({
title: "Elements replaced",
message: [`${replace ? "Replaced" : "Deleted"} ${count} elements.`],
width: 192,
})
shouldReport = true;
if (shouldReport && pending === 0)
report();
}
},
);
Expand Down
3 changes: 2 additions & 1 deletion src/window/tabs/Research.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ export default new GUI.Tab({
padding: 8,
margin: GUI.Margin.uniform(8),
}).add(
new GUI.Label({ text: "Version: 2.0.3 (2023-07-05)", }),
new GUI.Label({ text: "Version: 2.0.4 (2023-07-05)", }),
new GUI.GroupBox({ text: "Latest changes" }).add(
new GUI.Label({ text: "- Fix problems with object list and search & replace." }),
new GUI.Label({ text: "- Fix copy & paste for new track elements." }),
new GUI.Label({ text: "- Fix footpath addition place in safe mode." }),
new GUI.Label({ text: "- Tertiary colours for large scenery." }),
Expand Down
14 changes: 8 additions & 6 deletions src/window/widgets/SceneryFilterGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,12 @@ export default class SceneryFilterGroup extends GUI.GroupBox {

public match(element: TileElement): boolean {
if (element.type !== this.type.getValue()) return false;
if (!this.matchObject(this.qualifier, element.object)) return false;
if (!this.matchObject(this.qualifier, element.type, element.object)) return false;
switch (element.type) {
case "footpath":
if (!this.matchObject(this.surface, element.surfaceObject)) return false;
if (!this.matchObject(this.railings, element.railingsObject)) return false;
if (!this.matchObject(this.surface, "footpath_surface", element.surfaceObject)) return false;
if (!this.matchObject(this.railings, "footpath_railings", element.railingsObject)) return false;
if (!this.matchObject(this.addition, "footpath_addition", element.addition)) return false;
return true;
case "wall":
case "large_scenery":
Expand All @@ -178,13 +179,14 @@ export default class SceneryFilterGroup extends GUI.GroupBox {
}
}

private matchObject(property: Property<IndexedObject>, index: number | null): boolean {
private matchObject(property: Property<IndexedObject>, type: ObjectType, objIdx: number | null): boolean {
const object = property.getValue();
if (object === this.any)
return true;
const qualifier = ObjectIndex.getQualifier(type, objIdx);
if (object === this.none)
return index === null;
return object.index === index;
return qualifier === null;
return object.qualifier === qualifier;
}

private matchColour(property: Property<number | null>, colour: number): boolean {
Expand Down

0 comments on commit 114d938

Please sign in to comment.