Files
starruler-linux/scripts/shared/designs.as
T
2018-07-17 14:15:37 +02:00

260 lines
7.4 KiB
ActionScript 3

bool checkCoreFacingBackwards(Design& design, Subsystem& sys) {
if(!design.hull.active.valid(sys.core, HEX_UpLeft) || design.hull.isExteriorInDirection(sys.core, HEX_UpLeft))
return false;
if(!design.hull.active.valid(sys.core, HEX_DownLeft) || design.hull.isExteriorInDirection(sys.core, HEX_DownLeft))
return false;
design.addError(true, format(locale::ERROR_FACE_BACKWARDS, sys.type.name), sys, null, sys.core);
return true;
}
vec2u getTargetGridSize(const Design@ dsg) {
return vec2u(max(1, uint(dsg.total(SV_GridWidth))), max(1, uint(dsg.total(SV_GridHeight))));
}
const vec2u FLAGSHIP_GRID_SIZE(28, 23);
const vec2u SUPPORT_GRID_SIZE(19, 16);
const vec2u SATELLITE_GRID_SIZE(21, 17);
vec2u getDesignGridSize(const Hull@ hull, double size) {
if(hull.hasTag("Support"))
return SUPPORT_GRID_SIZE;
if(hull.hasTag("Satellite"))
return SATELLITE_GRID_SIZE;
return FLAGSHIP_GRID_SIZE;
}
vec2u getDesignGridSize(const string& type, double size) {
if(type == "Support")
return SUPPORT_GRID_SIZE;
if(type == "Satellite")
return SATELLITE_GRID_SIZE;
return FLAGSHIP_GRID_SIZE;
}
bool checkGlobalDesign(Design& design, Subsystem& sys) {
//Check for the correct grid size
vec2u target = getTargetGridSize(design);
if(design.hull.gridSize.x > int(target.x) || design.hull.gridSize.y > int(target.y)) {
design.addError(true, locale::ERROR_GRID_SIZE, null, null, vec2u());
return true;
}
return false;
}
bool checkCoversAllDirections(Design& design, Subsystem& sys) {
auto gridSize = design.hull.gridSize;
//Top & Bottom Lines
for(uint i = 0, cnt = gridSize.x; i < cnt; ++i) {
if(checkCovers(sys.type, design, vec2u(i, 0), HEX_DownLeft))
return true;
if(checkCovers(sys.type, design, vec2u(i, 0), HEX_Down))
return true;
if(checkCovers(sys.type, design, vec2u(i, 0), HEX_DownRight))
return true;
if(checkCovers(sys.type, design, vec2u(i, gridSize.y-1), HEX_UpLeft))
return true;
if(checkCovers(sys.type, design, vec2u(i, gridSize.y-1), HEX_Up))
return true;
if(checkCovers(sys.type, design, vec2u(i, gridSize.y-1), HEX_UpRight))
return true;
}
//Right & Left Lines
for(uint i = 0, cnt = gridSize.y; i < cnt; ++i) {
if(checkCovers(sys.type, design, vec2u(0, i), HEX_DownRight))
return true;
if(checkCovers(sys.type, design, vec2u(0, i), HEX_UpRight))
return true;
if(checkCovers(sys.type, design, vec2u(gridSize.x-1, i), HEX_DownLeft))
return true;
if(checkCovers(sys.type, design, vec2u(gridSize.x-1, i), HEX_UpLeft))
return true;
}
return false;
}
bool checkCovers(const SubsystemDef@ def, Design& design, vec2u& pos, HexGridAdjacency direction) {
while(design.hull.active.valid(pos)) {
auto@ sys = design.subsystem(pos);
if(sys !is null) {
if(sys.type is def)
return false;
design.addError(true, format(locale::ERROR_MUST_COVER, def.name), null, null, vec2u());
return true;
}
if(!design.hull.active.advance(pos, direction))
break;
}
return false;
}
bool checkAdjacentToEverything(Design& design, Subsystem& checkSys) {
bool failed = false;
for(uint i = 0, cnt = design.subsystemCount; i < cnt; ++i) {
auto@ sys = design.subsystems[i];
if(sys is checkSys)
continue;
if(sys.type.hasTag(ST_Ephemeral))
continue;
for(uint n = 0, ncnt = sys.hexCount; n < ncnt; ++n) {
vec2u hex = sys.hexagon(n);
if(!design.hull.active.valid(hex))
continue;
bool found = false;
for(uint d = 0; d < 6; ++d) {
vec2u other = hex;
if(design.hull.active.advance(other, HexGridAdjacency(d))) {
auto@ otherSys = design.subsystem(other);
if(otherSys !is null && otherSys is checkSys) {
found = true;
break;
}
}
}
if(!found) {
if(!failed) {
design.addError(true, format(locale::ERROR_MUST_ADJACENT, checkSys.type.name), null, null, vec2u());
failed = true;
}
design.addErrorHex(hex);
}
}
}
return failed;
}
bool checkAdjacentToAllInterior(Design& design, Subsystem& checkSys) {
bool failed = false;
for(uint i = 0, cnt = design.subsystemCount; i < cnt; ++i) {
auto@ sys = design.subsystems[i];
if(sys is checkSys)
continue;
if(sys.type.hasTag(ST_Ephemeral))
continue;
if(sys.type.hasTag(ST_ExternalSpace))
continue;
for(uint n = 0, ncnt = sys.hexCount; n < ncnt; ++n) {
vec2u hex = sys.hexagon(n);
if(!design.hull.active.valid(hex))
continue;
bool found = false;
for(uint d = 0; d < 6; ++d) {
vec2u other = hex;
if(design.hull.active.advance(other, HexGridAdjacency(d))) {
auto@ otherSys = design.subsystem(other);
if(otherSys !is null && otherSys is checkSys) {
found = true;
break;
}
}
}
if(!found) {
if(!failed) {
design.addError(true, format(locale::ERROR_MUST_ADJACENT_INTERIOR, checkSys.type.name), null, null, vec2u());
failed = true;
}
design.addErrorHex(hex);
}
}
}
return failed;
}
bool checkContiguous(Design& design, Subsystem& sys) {
HexGridb checked(design.hull.active.width, design.hull.active.height);
checked.clear(false);
if(sys.hexCount > 0)
markContiguous(design, sys, checked, sys.hexagon(0));
for(uint i = 0, cnt = sys.hexCount; i < cnt; ++i) {
if(!checked[sys.hexagon(i)]) {
design.addError(true, format(locale::ERROR_CONTIGUOUS, sys.type.name), null, null, vec2u());
return true;
}
}
return false;
}
void markContiguous(Design& design, Subsystem& sys, HexGridb& grid, const vec2u& hex) {
if(grid[hex])
return;
grid[hex] = true;
for(uint d = 0; d < 6; ++d) {
vec2u other = hex;
if(design.hull.active.advance(other, HexGridAdjacency(d))) {
auto@ otherSys = design.subsystem(other);
if(otherSys is sys)
markContiguous(design, sys, grid, other);
}
}
}
bool checkSinew(Design& design, Subsystem& sys) {
bool errors = false;
if(checkAdjacentToAllInterior(design, sys))
errors = true;
if(checkContiguous(design, sys))
errors = true;
return errors;
}
bool checkExposedLeftRight(Design& design, Subsystem& sys) {
array<bool> hasExposed(6, false);
for(uint i = 0, cnt = sys.hexCount; i < cnt; ++i) {
vec2u hex = sys.hexagon(i);
for(uint n = 0; n < 6; ++n) {
if(design.hull.isExteriorInDirection(hex, HexGridAdjacency(n)))
hasExposed[n] = true;
}
}
if(!hasExposed[HEX_UpLeft] && !hasExposed[HEX_DownLeft]) {
design.addError(true, format(locale::ERROR_EXPOSE_LEFT_RIGHT, sys.type.name), sys, null, vec2u());
return true;
}
if(!hasExposed[HEX_UpRight] && !hasExposed[HEX_DownRight]) {
design.addError(true, format(locale::ERROR_EXPOSE_LEFT_RIGHT, sys.type.name), sys, null, vec2u());
return true;
}
return false;
}
#section server-side
void getDesignMesh(Empire@ owner, const Design& design, MeshDesc& mesh) {
const Shipset@ ss;
const ShipSkin@ skin;
if(owner !is null)
@ss = owner.shipset;
if(ss !is null) {
bool isCivilian = !design.hasTag(ST_Weapon) && !design.hasTag(ST_SupportCap);
if(isCivilian) {
if(design.hasSubsystem(subsystem::TractorBeam))
@skin = ss.getSkin("Tractor");
else if(design.hasSubsystem(subsystem::MiningLaser))
@skin = ss.getSkin("Miner");
}
if(design.hasTag(ST_Gate) && design.hasTag(ST_Station))
@skin = ss.getSkin("Gate");
}
if(skin !is null) {
@mesh.model = skin.model;
@mesh.material = skin.material;
}
else if(design.hasTag(ST_Gate) && design.hasTag(ST_Station)) {
@mesh.model = model::Warpgate;
@mesh.material = material::GenericPBR_Gate;
}
else {
@mesh.model = design.hull.model;
@mesh.material = design.hull.material;
}
@mesh.iconSheet = design.distantIcon.sheet;
mesh.iconIndex = design.distantIcon.index;
}