mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Improve pipette
This commit is contained in:
parent
5b2df00cc7
commit
d907dbb191
@ -76,7 +76,6 @@ export class GameHUD {
|
||||
shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()),
|
||||
notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()),
|
||||
buildingsSelectedForCopy: /** @type {TypedSignal<[Array<number>]>} */ (new Signal()),
|
||||
pipetteExecuted: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
||||
pasteBlueprintRequested: new Signal(),
|
||||
};
|
||||
|
||||
|
@ -1,16 +1,15 @@
|
||||
import { DrawParameters } from "../../../core/draw_parameters";
|
||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||
import { TrackedState } from "../../../core/tracked_state";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { Vector } from "../../../core/vector";
|
||||
import { T } from "../../../translations";
|
||||
import { enumMouseButton } from "../../camera";
|
||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { Blueprint } from "./blueprint";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { blueprintShape } from "../../upgrades";
|
||||
import { T } from "../../../translations";
|
||||
import { PipetteBlueprint } from "./pipette_blueprint";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { Blueprint } from "./blueprint";
|
||||
|
||||
export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
createElements(parent) {
|
||||
@ -37,7 +36,6 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this);
|
||||
|
||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
||||
@ -56,37 +54,6 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the pipette function
|
||||
*/
|
||||
startPipette() {
|
||||
// Disable in overview
|
||||
if (this.root.camera.getIsMapOverlayActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mousePosition = this.root.app.mousePosition;
|
||||
if (!mousePosition) {
|
||||
// Not on screen
|
||||
return;
|
||||
}
|
||||
|
||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||
const tile = worldPos.toTileSpace();
|
||||
const contents = this.root.map.getTileContent(tile);
|
||||
|
||||
// Make sure we selected something, and also make sure it's not a special entity
|
||||
if (contents && !contents.components.Unremovable && !contents.components.Belt) {
|
||||
const blueprint = PipetteBlueprint.fromEntity(contents);
|
||||
|
||||
// Notice: Order here matters, since pipetteExecuted clears the blueprint
|
||||
this.root.hud.signals.pipetteExecuted.dispatch(contents);
|
||||
this.currentBlueprint.set(blueprint);
|
||||
} else {
|
||||
this.root.hud.signals.pipetteExecuted.dispatch(null);
|
||||
}
|
||||
}
|
||||
|
||||
onCanAffordChanged(canAfford) {
|
||||
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Math_abs, Math_degrees, Math_round } from "../../../core/builtins";
|
||||
import { globalConfig } from "../../../core/config";
|
||||
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||
import { Signal, STOP_PROPAGATION } from "../../../core/signal";
|
||||
import { TrackedState } from "../../../core/tracked_state";
|
||||
import { Vector } from "../../../core/vector";
|
||||
@ -9,7 +10,6 @@ import { Entity } from "../../entity";
|
||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||
import { defaultBuildingVariant, MetaBuilding } from "../../meta_building";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { lerp } from "../../../core/utils";
|
||||
|
||||
/**
|
||||
* Contains all logic for the building placer - this doesn't include the rendering
|
||||
@ -98,12 +98,12 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
.getBinding(KEYMAPPINGS.placement.switchDirectionLockSide)
|
||||
.add(this.switchDirectionLockSide, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this);
|
||||
this.root.gameState.inputReciever.keyup.add(this.checkForDirectionLockSwitch, this);
|
||||
|
||||
// BINDINGS TO GAME EVENTS
|
||||
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
|
||||
this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this);
|
||||
this.root.hud.signals.pipetteExecuted.add(this.abortPlacement, this);
|
||||
this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch());
|
||||
this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch());
|
||||
|
||||
@ -218,6 +218,125 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the pipette function
|
||||
*/
|
||||
startPipette() {
|
||||
// Disable in overview
|
||||
if (this.root.camera.getIsMapOverlayActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mousePosition = this.root.app.mousePosition;
|
||||
if (!mousePosition) {
|
||||
// Not on screen
|
||||
return;
|
||||
}
|
||||
|
||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||
const tile = worldPos.toTileSpace();
|
||||
const contents = this.root.map.getTileContent(tile);
|
||||
|
||||
if (!contents) {
|
||||
this.currentMetaBuilding.set(null);
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to extract the building
|
||||
const extracted = this.hack_reconstructMetaBuildingAndVariantFromBuilding(contents);
|
||||
if (!extracted) {
|
||||
this.currentMetaBuilding.set(null);
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentMetaBuilding.set(extracted.metaBuilding);
|
||||
this.currentVariant.set(extracted.variant);
|
||||
this.currentBaseRotation = contents.components.StaticMapEntity.rotation;
|
||||
|
||||
// Make sure we selected something, and also make sure it's not a special entity
|
||||
// if (contents && !contents.components.Unremovable) {
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
* HACK!
|
||||
*
|
||||
* This attempts to reconstruct the meta building and its variant from a given entity
|
||||
* @param {Entity} entity
|
||||
* @returns {{ metaBuilding: MetaBuilding, variant: string }}
|
||||
*/
|
||||
hack_reconstructMetaBuildingAndVariantFromBuilding(entity) {
|
||||
if (entity.components.Hub) {
|
||||
// Hub is not copyable
|
||||
return null;
|
||||
}
|
||||
|
||||
const matches = [];
|
||||
const metaBuildings = gMetaBuildingRegistry.entries;
|
||||
for (let i = 0; i < metaBuildings.length; ++i) {
|
||||
const metaBuilding = metaBuildings[i];
|
||||
const availableVariants = metaBuilding.getAvailableVariants(this.root);
|
||||
checkVariant: for (let k = 0; k < availableVariants.length; ++k) {
|
||||
const variant = availableVariants[k];
|
||||
let unplaced = metaBuilding.createEntity({
|
||||
root: this.root,
|
||||
variant,
|
||||
origin: new Vector(0, 0),
|
||||
rotation: 0,
|
||||
originalRotation: 0,
|
||||
rotationVariant: 0,
|
||||
});
|
||||
|
||||
// Compare if both entities share the same components
|
||||
for (let component in entity.components) {
|
||||
if ((entity.components[component] == null) !== (unplaced.components[component] == null)) {
|
||||
continue checkVariant;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for same item processor
|
||||
if (
|
||||
entity.components.ItemProcessor &&
|
||||
entity.components.ItemProcessor.type != unplaced.components.ItemProcessor.type
|
||||
) {
|
||||
continue checkVariant;
|
||||
}
|
||||
|
||||
// Check for underground belt
|
||||
if (
|
||||
entity.components.UndergroundBelt &&
|
||||
entity.components.UndergroundBelt.tier != unplaced.components.UndergroundBelt.tier
|
||||
) {
|
||||
continue checkVariant;
|
||||
}
|
||||
|
||||
// Check for same sprite key - except for underground belts
|
||||
// since the sprite may vary here
|
||||
if (
|
||||
!entity.components.UndergroundBelt &&
|
||||
entity.components.StaticMapEntity.spriteKey !=
|
||||
unplaced.components.StaticMapEntity.spriteKey
|
||||
) {
|
||||
continue checkVariant;
|
||||
}
|
||||
matches.push({ metaBuilding, variant });
|
||||
}
|
||||
}
|
||||
|
||||
if (matches.length == 1) {
|
||||
const staticEntity = entity.components.StaticMapEntity;
|
||||
const key = staticEntity.spriteKey || staticEntity.blueprintSpriteKey;
|
||||
assert(
|
||||
key &&
|
||||
key.includes(matches[0].metaBuilding.id) &&
|
||||
(matches[0].variant === defaultBuildingVariant || key.includes(matches[0].variant))
|
||||
);
|
||||
return matches[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
switchDirectionLockSide() {
|
||||
this.currentDirectionLockSide = 1 - this.currentDirectionLockSide;
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
import { Vector } from "../../../core/vector";
|
||||
import { Entity } from "../../entity";
|
||||
import { Blueprint } from "./blueprint";
|
||||
|
||||
export class PipetteBlueprint extends Blueprint {
|
||||
/**
|
||||
* @see Blueprint.getCost
|
||||
*/
|
||||
getCost() {
|
||||
// Its free
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new pipetted blueprint from a given entity
|
||||
* @param {Entity} entity
|
||||
*/
|
||||
static fromEntity(entity) {
|
||||
const clone = entity.duplicateWithoutContents();
|
||||
clone.components.StaticMapEntity.origin = new Vector(0, 0);
|
||||
return new PipetteBlueprint([clone]);
|
||||
}
|
||||
}
|
@ -147,10 +147,32 @@ export class MetaBuilding {
|
||||
* @param {string} param0.variant
|
||||
*/
|
||||
createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||
const entity = this.createEntity({
|
||||
root,
|
||||
origin,
|
||||
rotation,
|
||||
originalRotation,
|
||||
rotationVariant,
|
||||
variant,
|
||||
});
|
||||
root.map.placeStaticEntity(entity);
|
||||
root.entityMgr.registerEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the entity without placing it
|
||||
* @param {object} param0
|
||||
* @param {GameRoot} param0.root
|
||||
* @param {Vector} param0.origin Origin tile
|
||||
* @param {number=} param0.rotation Rotation
|
||||
* @param {number} param0.originalRotation Original Rotation
|
||||
* @param {number} param0.rotationVariant Rotation variant
|
||||
* @param {string} param0.variant
|
||||
*/
|
||||
createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||
const entity = new Entity(root);
|
||||
|
||||
const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant);
|
||||
|
||||
entity.addComponent(
|
||||
new StaticMapEntityComponent({
|
||||
spriteKey:
|
||||
@ -166,12 +188,8 @@ export class MetaBuilding {
|
||||
blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "",
|
||||
})
|
||||
);
|
||||
|
||||
this.setupEntityComponents(entity, root);
|
||||
this.updateVariants(entity, rotationVariant, variant);
|
||||
|
||||
root.map.placeStaticEntity(entity);
|
||||
root.entityMgr.registerEntity(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user