civ7-modding-tools
Version:
Mod generation tool for Civilization 7.
223 lines (204 loc) • 9.12 kB
text/typescript
import * as lodash from "lodash";
import { TClassProperties, TObjectValues, TPartialRequired } from "../types";
import {
BuildingNode,
ConstructibleMaintenanceNode,
ConstructibleNode,
ConstructiblePlunderNode,
ConstructibleValidBiomeNode,
ConstructibleValidDistrictNode,
ConstructibleValidFeatureNode,
ConstructibleValidResourceNode,
ConstructibleValidTerrainNode,
ConstructibleYieldChangeNode,
DatabaseNode,
DistrictFreeConstructibleNode,
IconDefinitionNode,
ImprovementNode,
TBuildingNode,
TConstructibleMaintenanceNode,
TConstructibleNode,
TConstructibleValidResourceNode,
TConstructibleYieldChangeNode,
TDistrictFreeConstructibleNode,
TIconDefinitionNode,
TImprovementNode,
TypeNode,
TypeTagNode
} from "../nodes";
import { ACTION_GROUP_ACTION, BIOME, CONSTRUCTIBLE_TYPE_TAG, DISTRICT, FEATURE, KIND, TERRAIN } from "../constants";
import { XmlFile } from "../files";
import { ConstructibleLocalization, TConstructibleLocalization } from "../localizations";
import { locale, trim } from "../utils";
import { BaseBuilder } from "./BaseBuilder";
import { AdjacencyYieldChangeNode, TAdjacencyYieldChangeNode } from "../nodes/AdjacencyYieldChangeNode";
import { ConstructibleAdjacencyNode } from "../nodes/ConstructibleAdjacencyNode";
type TConstructibleBuilder = TClassProperties<ConstructibleBuilder>
export class ConstructibleBuilder extends BaseBuilder<TConstructibleBuilder> {
_always: DatabaseNode = new DatabaseNode();
_localizations: DatabaseNode = new DatabaseNode();
_icons: DatabaseNode = new DatabaseNode();
typeTags: TObjectValues<typeof CONSTRUCTIBLE_TYPE_TAG>[] = [];
constructibleValidDistricts: TObjectValues<typeof DISTRICT>[] = [];
constructibleValidBiomes: TObjectValues<typeof BIOME>[] = [];
constructibleValidFeatures: TObjectValues<typeof FEATURE>[] = [];
constructibleValidTerrains: TObjectValues<typeof TERRAIN>[] = [];
constructibleValidResources: TPartialRequired<TConstructibleValidResourceNode, 'resourceType'>[] = [];
constructiblePlunders: TPartialRequired<ConstructiblePlunderNode, 'plunderType'>[] = [];
building: Partial<TBuildingNode> | null = null;
improvement: Partial<TImprovementNode> | null = null;
constructible: TPartialRequired<TConstructibleNode, 'constructibleType'> = {
constructibleType: 'BUILDING_CUSTOM',
}
constructibleYieldChanges: Partial<TConstructibleYieldChangeNode>[] = [];
constructibleMaintenances: Partial<TConstructibleMaintenanceNode>[] = [];
adjacencyYieldChanges: Partial<TAdjacencyYieldChangeNode>[] = [];
icon: TPartialRequired<TIconDefinitionNode, 'path'> = {
path: 'fs://game/civ_sym_han'
}
districtFreeConstructibles: TPartialRequired<TDistrictFreeConstructibleNode, 'districtType'>[] = [];
localizations: TConstructibleLocalization[] = [];
constructor(payload: Partial<TConstructibleBuilder> = {}) {
super();
this.fill(payload);
}
migrate() {
if(!this.improvement && !this.building) {
if(this.constructible.constructibleType.startsWith('BUILDING_')){
this.building = {};
}
if(this.constructible.constructibleType.startsWith('IMPROVEMENT_')) {
this.improvement = {};
}
}
this._always.fill({
types: [new TypeNode({
type: this.constructible.constructibleType,
kind: KIND.CONSTRUCTIBLE
})],
buildings: this.building ? [new BuildingNode({
...this.constructible,
...this.building
})] : [],
improvements: this.improvement ? [new ImprovementNode({
...this.constructible,
...this.improvement
})] : [],
typeTags: this.typeTags.map(item => new TypeTagNode({
type: this.constructible.constructibleType,
tag: item
})),
constructibles: [new ConstructibleNode({
name: locale(this.constructible.constructibleType, 'name'),
description: locale(this.constructible.constructibleType, 'description'),
tooltip: locale(this.constructible.constructibleType, 'tooltip'),
...this.constructible
})],
constructibleValidDistricts: this.constructibleValidDistricts.map(item => {
return new ConstructibleValidDistrictNode({
...this.constructible,
districtType: item
})
}),
constructibleValidBiomes: this.constructibleValidBiomes.map(item => {
return new ConstructibleValidBiomeNode({
...this.constructible,
biomeType: item
})
}),
constructibleValidFeatures: this.constructibleValidFeatures.map(item => {
return new ConstructibleValidFeatureNode({
...this.constructible,
featureType: item
})
}),
constructibleValidTerrains: this.constructibleValidTerrains.map(item => {
return new ConstructibleValidTerrainNode({
...this.constructible,
terrainType: item
})
}),
constructibleValidResources: this.constructibleValidResources.map(item => {
return new ConstructibleValidResourceNode({
...this.constructible,
...item
})
}),
constructiblePlunders: this.constructiblePlunders.map(item => {
return new ConstructiblePlunderNode({
...this.constructible,
...item
})
}),
constructibleMaintenances: this.constructibleMaintenances.map(item => {
return new ConstructibleMaintenanceNode({
...this.constructible,
...item
})
}),
constructibleYieldChanges: this.constructibleYieldChanges.map(item => {
return new ConstructibleYieldChangeNode({
...this.constructible,
...item
})
}),
districtFreeConstructibles: this.districtFreeConstructibles.map(item => {
return new DistrictFreeConstructibleNode({
constructibleType: this.constructible.constructibleType,
...item
})
}),
});
if (this.adjacencyYieldChanges.length) {
this.adjacencyYieldChanges.forEach(item => {
const adjacencyYieldChange = new AdjacencyYieldChangeNode(item);
this._always.constructibleAdjacencies.push(new ConstructibleAdjacencyNode({
constructibleType: this.constructible.constructibleType,
yieldChangeId: adjacencyYieldChange.id,
}))
this._always.adjacencyYieldChanges.push(adjacencyYieldChange);
});
}
this._icons.fill({
iconDefinitions: [new IconDefinitionNode({
id: this.constructible.constructibleType,
...this.icon,
})]
})
this._localizations.fill({
englishText: this.localizations.map(item => {
return new ConstructibleLocalization({
prefix: this.constructible.constructibleType,
...item
});
}).flatMap(item => item.getNodes())
});
return this;
}
build() {
const path = `/constructibles/${lodash.kebabCase(trim(this.constructible.constructibleType))}/`;
return [
new XmlFile({
path,
name: 'always.xml',
content: this._always.toXmlElement(),
actionGroups: [this.actionGroupBundle.always],
actionGroupActions: [ACTION_GROUP_ACTION.UPDATE_DATABASE]
}),
new XmlFile({
path,
name: 'localization.xml',
content: this._localizations.toXmlElement(),
actionGroups: [this.actionGroupBundle.shell, this.actionGroupBundle.always],
actionGroupActions: [ACTION_GROUP_ACTION.UPDATE_TEXT]
}),
new XmlFile({
path,
name: 'icons.xml',
content: this._icons.toXmlElement(),
actionGroups: [this.actionGroupBundle.shell, this.actionGroupBundle.always],
actionGroupActions: [ACTION_GROUP_ACTION.UPDATE_ICONS]
}),
]
}
}