construction-mod/scripts/saveBuilding.cs
2025-06-05 12:37:16 +02:00

842 lines
34 KiB
C#

// SaveBuilding.cs
//
// This script made possible by a joint effort of DynaBlade and JackTL
//
// Functions:
//
// saveBuilding(clientId,radius,file[$],quiet[1/0])
// saveBuildingCentered(clientId,radius,file[$],quiet[1/0],centerAtMinZ[1/0])
// delBuildingWaypoint()
// loadBuilding(file[$])
// saveBuildingTimer(time in seconds,globalEcho[1/0],file[$],useMultipleFiles[1/0]) // No limit on multiple files yet. Beware
// saveBuildingTimerOn() // <-- for restarting timed saves, does not initialize like saveBuildingTimer()
// saveBuildingTimerOff()
// delDupPieces(clientId,radius,quiet[1/0]) // NOTE: There are issues with calling this function a second time before the previous call's deconstruction has finished
//
// See functions for (some) comments
if ($SaveBuilding::SaveFolder $= "")
$SaveBuilding::SaveFolder = "Buildings/";
if ($SaveBuilding::AutoSaveFolder $= "")
$SaveBuilding::AutoSaveFolder = "Buildings/AutoSave/";
if ($SaveBuilding::TimerDefaultTime $= "")
$SaveBuilding::TimerDefaultTime = 5 * 60 * 1000; // 5 minutes. Saving may cause stutter on low-end servers with high number of pieces
if ($SaveBuilding::QuickDelete $= "")
$SaveBuilding::QuickDelete = 1;
// See if we want to save the piece
function saveBuildingCheck(%obj) {
%save = false;
%dataBlockName = %obj.getDatablock().getName();
switch$ (%dataBlockName) {
case "DeployedSpine":
%save = true;
case "DeployedWoodSpine":
%save = true;
case "DeployedMSpine":
%save = true;
case "DeployedMSpineRing":
%save = true;
case "DeployedFloor":
%save = true;
case "DeployedWall":
%save = true;
case "DeployedwWall":
%save = true;
case "DeployedEnergizer":
%save = true;
case "DeployedStationInventory":
%save = true;
case "DeployedJumpad":
%save = true;
case "DeployedEscapePod":
%save = true;
case "TelePadDeployedBase":
%save = true;
case "TelePadBeam":
%save = true;
case "DeployedLTarget":
%save = true;
case "DeployedLogoProjector":
%save = true;
case "DeployedSwitch":
%save = true;
case "DeployedPulseSensor":
%save = true;
case "DeployedMotionSensor":
%save = true;
case "TurretDeployedBase":
%save = true;
case "TurretDeployedFloorIndoor":
%save = true;
case "TurretDeployedWallIndoor":
%save = true;
case "TurretDeployedCeilingIndoor":
%save = true;
case "TurretDeployedOutdoor":
%save = true;
case "LaserDeployed":
%save = true;
case "MissileRackTurretDeployed":
%save = true;
case "DiscTurretDeployed":
%save = true;
case "TurretDeployedCamera":
%save = true;
case "DeployedLightBase":
%save = true;
case "DeployedTripwire":
%save = true;
case "DispenserDep":
%save = true;
case "AudioDep":
%save = true;
case "EmitterDep":
%save = true;
}
if (%dataBlockName $= "StationInventory" && %obj.deployed == true)
%save = true;
if (%dataBlockName $= "GeneratorLarge" && %obj.deployed == true)
%save = true;
if (%dataBlockName $= "SolarPanel" && %obj.deployed == true)
%save = true;
if (%dataBlockName $= "SensorMediumPulse" && %obj.deployed == true)
%save = true;
if (%dataBlockName $= "SensorLargePulse" && %obj.deployed == true)
%save = true;
if (getSubStr(%dataBlockName,0,18) $= "DeployedForceField")
%save = true;
if (getSubStr(%dataBlockName,0,20) $= "DeployedGravityField")
%save = true;
if (getSubStr(%dataBlockName,0,12) $= "DeployedTree")
%save = true;
if (getSubStr(%dataBlockName,0,13) $= "DeployedCrate")
%save = true;
if (getSubStr(%dataBlockName,0,18) $= "DeployedDecoration")
%save = true;
return %save;
}
// This function saves a building and its position in the map
function saveBuilding(%cl,%rad,%file,%quiet,%isAutoSave) {
if (%quiet == true) {
$SaveBuilding::Quiet = true;
}
else {
$SaveBuilding::Quiet = false; // Overwrite
}
%origCl = %cl;
if (!isObject(%cl)) {
if (isObject(nameToID(LocalClientConnection))) {
%cl = nameToID(LocalClientConnection);
}
else {
if ($CurrentClientId) {
%cl = $CurrentClientId;
}
}
}
if (%rad < 1) {
%rad = 100000;
}
%buildingCount = 0;
if (%file $= "" || %file $= "0") {
for(%found = true; %found; %buildingCount++ ) {
%suffix = %buildingCount;
while (strLen(%suffix) < 5) %suffix = "0" @ %suffix;
if (%isAutoSave)
%file = $SaveBuilding::AutoSaveFolder @ $MissionName @ "-" @ %suffix @ ".cs";
else
%file = $SaveBuilding::SaveFolder @ %cl.nameBase @ "-" @ $MissionName @ "-" @ %suffix @ ".cs";
%found = isFile(%file);
}
}
else {
if (%isAutoSave)
%file = $SaveBuilding::AutoSaveFolder @ %file;
else
%file = $SaveBuilding::SaveFolder @ %file;
}
if (isObject(%cl.getControlObject())) {
%pos = %cl.getControlObject().getPosition();
}
if (!%pos) {
%pos = "0 0 0";
}
if (%isAutoSave && (%origCl $= "" || %origCl $= "0"))
%pos = "0 0 0";
new fileObject("Building");
if (!$SaveBuilding::Quiet) {
warn("Saving to file: \"" @ %file @ "\"");
}
Building.openForWrite(%file);
Building.writeLine("// CONSTRUCTION MOD SAVE FILE");
Building.writeLine("// Saved by \"" @ getField(%cl.nameBase,0) @ "\"");
Building.writeLine("// Created in mission \"" @ $MissionName @ "\"");
Building.writeLine("// Construction " @ $ModVersion);
Building.writeLine("");
$SaveBuilding::Saved = 0;
$SaveBuilding::Skipped = 0;
initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType);
while((%obj = containerSearchNext()) != 0) {
%cmp = writeBuildingComponent(%obj);
if (%cmp !$= "") {
Building.writeLine(%cmp);
}
}
if (!$SaveBuilding::Quiet) {
warn("Saved to file: \"" @ %file @ "\"");
warn("Saved pieces: " @ $SaveBuilding::Saved);
warn("Skipped pieces: " @ $SaveBuilding::Skipped);
}
$SaveBuilding::LastFile = %file;
Building.close();
Building.delete();
return %file;
}
function writeBuildingComponent(%obj) {
%dataBlockName = %obj.getDatablock().getName();
%save = false;
%save = saveBuildingCheck(%obj);
if (%save == true) {
if (%dataBlockName $= "DeployedMSpineRing") // Handled by DeployedMSpine
return;
if (%dataBlockName $= "TelePadBeam") // Handled by TelePadDeployedBase
return;
if (%dataBlockName $= "DeployedLTarget") // Handled by parent object
return;
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %obj @ " Name: " @ %dataBlockName);
%buildingPiece = "%building = new (" @ %obj.getClassName() @ ") () {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %dataBlockName @ "\";";
if (%obj.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %obj.position @ "\";";
if (%obj.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %obj.rotation @ "\";";
if (%obj.realScale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.realScale @ "\";";
else {if (%obj.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.scale @ "\";";}
if (%obj.team !$= "") %buildingPiece = %buildingPiece @ "team = \"" @ %obj.team @ "\";";
if (%obj.ownerGUID !$= "") %buildingPiece = %buildingPiece @ "ownerGUID = \"" @ %obj.ownerGUID @ "\";";
if (%obj.needsFit) %buildingPiece = %buildingPiece @ "needsfit = \"" @ %obj.needsFit @ "\";";
if (%obj.grounded) %buildingPiece = %buildingPiece @ "grounded = \"" @ %obj.grounded @ "\";";
if (%obj.deployed !$= "") %buildingPiece = %buildingPiece @ "deployed = \"" @ %obj.deployed @ "\";";
if (%obj.impulse !$= "") %buildingPiece = %buildingPiece @ "impulse = \"" @ %obj.impulse @ "\";";
if (%obj.velocityMod !$= "") %buildingPiece = %buildingPiece @ "velocityMod = \"" @ %obj.velocityMod @ "\";";
if (%obj.gravityMod !$= "") %buildingPiece = %buildingPiece @ "gravityMod = \"" @ %obj.gravityMod @ "\";";
if (%obj.appliedForce !$= "") %buildingPiece = %buildingPiece @ "appliedForce = \"" @ %obj.appliedForce @ "\";";
if (%obj.powerFreq !$= "") %buildingPiece = %buildingPiece @ "powerFreq = \"" @ %obj.powerFreq @ "\";";
if (%obj.isSwitchedOff !$= "") %buildingPiece = %buildingPiece @ "isSwitchedOff = \"" @ %obj.isSwitchedOff @ "\";";
if (%obj.switchRadius !$= "") %buildingPiece = %buildingPiece @ "switchRadius = \"" @ %obj.switchRadius @ "\";";
if (%obj.holoBlock !$= "") %buildingPiece = %buildingPiece @ "holoBlock = \"" @ %obj.holoBlock @ "\";";
if (%obj.noSlow !$= "") %buildingPiece = %buildingPiece @ "noSlow = \"" @ %obj.noSlow @ "\";";
if (%obj.static !$= "") %buildingPiece = %buildingPiece @ "static = \"" @ %obj.static @ "\";";
if (%obj.timed !$= "") %buildingPiece = %buildingPiece @ "timed = \"" @ %obj.timed @ "\";";
if (%obj.beamRange !$= "") %buildingPiece = %buildingPiece @ "beamRange = \"" @ %obj.beamRange @ "\";";
if (%obj.tripMode !$= "") %buildingPiece = %buildingPiece @ "tripMode = \"" @ %obj.tripMode @ "\";";
if (%obj.fieldMode !$= "") %buildingPiece = %buildingPiece @ "fieldMode = \"" @ %obj.fieldMode @ "\";";
if (%dataBlockName $= "TelePadDeployedBase") {
if (%obj.frequency !$= "") %buildingPiece = %buildingPiece @ "frequency = \"" @ %obj.frequency @ "\";";
if (%obj.teleMode !$= "") %buildingPiece = %buildingPiece @ "teleMode = \"" @ %obj.teleMode @ "\";";
}
if (%obj.getType() & $TypeMasks::TurretObjectType) {
if (%obj.isSeeker !$= "") %buildingPiece = %buildingPiece @ "isSeeker = \"" @ %obj.isSeeker @ "\";";
%barrel = %obj.getMountedImage(0);
if (%barrel > 0)
%buildingPiece = %buildingPiece @ "initialBarrel = \"" @ %barrel.getName() @ "\";";
}
%buildingPiece = %buildingPiece @ "};";
if (%obj.getTarget() != -1) %buildingPiece = %buildingPiece @ "setTargetSensorGroup(%building.getTarget()," @ mAbs(%obj.team) @ ");";
%buildingPiece = %buildingPiece @ "addToDeployGroup(%building);";
if (%obj.noSlow !$= "") %buildingPiece = %buildingPiece @ "%building.pzone.delete();%building.pzone = \"\";";
if (%dataBlockName $= "DeployedEnergizer" || %dataBlockName $= "DeployedStationInventory" || %dataBlockName $= "StationInventory"
|| %dataBlockName $= "TurretDeployedFloorIndoor" || %dataBlockName $= "TurretDeployedWallIndoor" || %dataBlockName $= "TurretDeployedCeilingIndoor"
|| %dataBlockName $= "TurretDeployedOutdoor" || %dataBlockName $= "DeployedPulseSensor"
|| %dataBlockName $= "LaserDeployed" || %dataBlockName $= "MissileRackTurretDeployed" || %dataBlockName $= "DiscTurretDeployed") {
%buildingPiece = %buildingPiece @ "%building.deploy();";
if (%dataBlockName $= "StationInventory")
%buildingPiece = %buildingPiece @ "adjustTrigger(%building);";
}
if (%obj.getDatablock().rechargeRate > 0 && !%obj.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();";
if (%obj.getType() & $TypeMasks::TurretObjectType)
%buildingPiece = %buildingPiece @ "%building.setRechargeRate(%building.getDatablock().rechargeRate);";
if (%obj.getDataBlock().className $= "Generator" || %obj.getDataBlock().className $= "Switch") {
if (%obj.isSwitchedOff)
%buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Disabled Frequency\" SPC %building.powerFreq));";
else
%buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Frequency\" SPC %building.powerFreq));";
if (%dataBlockName $= "DeployedSwitch")
%buildingPiece = %buildingPiece @ "setTargetSkin(%building.target,'" @ getTaggedString(getTargetSkin(%obj.target)) @ "');";
if (!%obj.isSwitchedOff)
%buildingPiece = %buildingPiece @ "%building.playThread($AmbientThread,\"ambient\");";
else {
if (%obj.isSwitchedOff)
// nb: doubles no. of power switches done, when loading switched off gens
%buildingPiece = %buildingPiece @ "%building.lastState = \"\";%building.getDataBlock().losePower(%building);";
}
}
$SaveBuilding::Saved++;
// Ugly, but it works. May be cleaned up later.
if (isObject(%obj.lTarget)) { // We assume none of the later saved sub-objects need decon targets, could make this a subroutine
%target = %obj.lTarget;
%targetDataBlock = %target.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %target @ " Name: " @ %targetDataBlock);
%buildingPiece = %buildingPiece @ "%target = new StaticShape() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %targetDataBlock @ "\";";
if (%target.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %target.position @ "\";";
if (%target.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %target.rotation @ "\";";
if (%target.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %target.scale @ "\";";
if (%target.team) %buildingPiece = %buildingPiece @ "team = \"" @ %target.team @ "\";";
%buildingPiece = %buildingPiece @ "lMain = %building;";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.lTarget = %target;";
%buildingPiece = %buildingPiece @ "addToDeployGroup(%target);";
if (%target.getDatablock().rechargeRate > 0 && !%target.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();";
}
if (%dataBlockName $= "DeployedMSpine") {
%left = %obj.left;
%right = %obj.right;
if (isObject(%left)) {
%leftDataBlock = %left.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %left @ " Name: " @ %leftDataBlock);
%buildingPiece = %buildingPiece @ "%left = new StaticShape() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %leftDataBlock @ "\";";
if (%left.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %left.position @ "\";";
if (%left.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %left.rotation @ "\";";
if (%left.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %left.scale @ "\";";
if (%left.team) %buildingPiece = %buildingPiece @ "team = \"" @ %left.team @ "\";";
if (%left.needsFit) %buildingPiece = %buildingPiece @ "needsfit = \"" @ %left.needsFit @ "\";";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.left = %left;";
%buildingPiece = %buildingPiece @ "addToDeployGroup(%left);";
if (%left.getDatablock().rechargeRate > 0 && !%left.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();";
$SaveBuilding::Saved++;
}
if (isObject(%right)) {
%rightDataBlock = %right.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %right @ " Name: " @ %rightDataBlock);
%buildingPiece = %buildingPiece @ "%right = new StaticShape() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %rightDataBlock @ "\";";
if (%right.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %right.position @ "\";";
if (%right.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %right.rotation @ "\";";
if (%right.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %right.scale @ "\";";
if (%right.team) %buildingPiece = %buildingPiece @ "team = \"" @ %right.team @ "\";";
if (%right.needsFit) %buildingPiece = %buildingPiece @ "needsfit = \"" @ %right.needsFit @ "\";";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.right = %right;";
%buildingPiece = %buildingPiece @ "addToDeployGroup(%right);";
if (%right.getDatablock().rechargeRate > 0 && !%right.getDatablock().needsPower) %buildingPiece = %buildingPiece @ "%building.setSelfPowered();";
$SaveBuilding::Saved++;
}
}
else if (%dataBlockName $= "TelePadDeployedBase") {
%beam = %obj.beam;
if (isObject(%beam)) {
%beamDataBlock = %beam.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %beam @ " Name: " @ %beamDataBlock);
%buildingPiece = %buildingPiece @ "%beam = new StaticShape() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %beamDataBlock @ "\";";
if (%beam.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %beam.position @ "\";";
if (%beam.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %beam.rotation @ "\";";
if (%beam.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %beam.scale @ "\";";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.beam = %beam;";
%buildingPiece = %buildingPiece @ "%beam.playThread(0,\"ambient\");";
%buildingPiece = %buildingPiece @ "%beam.setThreadDir(0,true);";
%buildingPiece = %buildingPiece @ "%beam.flashThreadDir = true;";
%buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Frequency\" SPC %building.frequency));";
}
}
else if (%dataBlockName $= "DeployedLogoProjector") {
%holo = %obj.holo;
if (isObject(%holo)) {
%holoDataBlock = %holo.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %holo @ " Name: " @ %holoDataBlock);
%buildingPiece = %buildingPiece @ "%holo = new StaticShape() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %holoDataBlock @ "\";";
if (%holo.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %holo.position @ "\";";
if (%holo.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %holo.rotation @ "\";";
if (%holo.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %holo.scale @ "\";";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.holo = %holo;";
%buildingPiece = %buildingPiece @ "%holo.projector = %building;";
}
}
else if (%dataBlockName $= "DeployedLightBase") {
%light = %obj.light;
if (isObject(%light)) {
%lightDataBlock = %light.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %light @ " Name: " @ %lightDataBlock);
%buildingPiece = %buildingPiece @ "%light = new Item() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %lightDataBlock @ "\";";
%buildingPiece = %buildingPiece @ "static = true;";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.light = %light;";
%buildingPiece = %buildingPiece @ "%light.lightBase = %building;";
%buildingPiece = %buildingPiece @ "adjustLight(%building);";
}
}
else if (%dataBlockName $= "DeployedTripwire") {
%tripField = %obj.tripField;
if (isObject(%tripField)) {
%tripFieldDataBlock = %tripField.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %tripField @ " Name: " @ %tripFieldDataBlock);
%buildingPiece = %buildingPiece @ "%tripField = new ForceFieldBare() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %tripFieldDataBlock @ "\";";
if (%tripField.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %tripField.scale @ "\";";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.tripField = %tripField;";
%buildingPiece = %buildingPiece @ "%tripField.pzone.delete();%building.pzone = \"\";";
}
%tripTrigger = %obj.tripTrigger;
if (isObject(%tripTrigger)) {
%tripTriggerDataBlock = %tripTrigger.getDatablock().getName();
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %tripTrigger @ " Name: " @ %tripTriggerDataBlock);
%buildingPiece = %buildingPiece @ "%tripTrigger = new Trigger() {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %tripTriggerDataBlock @ "\";";
if (%tripTrigger.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %tripTrigger.scale @ "\";";
if (%tripTrigger.polyhedron !$= "") %buildingPiece = %buildingPiece @ "polyhedron = \"" @ %tripTrigger.polyhedron @ "\";";
%buildingPiece = %buildingPiece @ "};";
%buildingPiece = %buildingPiece @ "%building.tripTrigger = %tripTrigger;";
%buildingPiece = %buildingPiece @ "%tripTrigger.baseObj = %building;";
}
%buildingPiece = %buildingPiece @ "setTargetName(%building.target,addTaggedString(\"Frequency\" SPC %building.powerFreq));";
%buildingPiece = %buildingPiece @ "%building.deploy();";
%buildingPiece = %buildingPiece @ "adjustTripwire(%building);";
}
else if (%dataBlockName $= "DeployedEscapePod") {
%buildingPiece = %buildingPiece @ "adjustEscapePod(%building);";
%buildingPiece = %buildingPiece @ "escapePodLoop(%building);";
}
}
else {
if (!$SaveBuilding::Quiet) {
// warn("Skipping: " @ %obj @ " Name: " @ %dataBlockName);
}
%buildingPiece = "";
$SaveBuilding::Skipped++;
}
return %buildingPiece;
}
// This function saves a building and relocates it to the center of the 'map'
// Optional switch to put center at lowest part of building
//
// NB: Position of objects (such as support beams) is their attachment point,
// not their actual center. This may give some 'strange' results when centering
// small buildings
function saveBuildingCentered(%cl,%rad,%file,%quiet,%centerAtMinZ) {
if (%quiet == true) {
$SaveBuilding::Quiet = true;
}
else {
$SaveBuilding::Quiet = false; // Overwrite
}
if (!isObject(%cl)) {
if (isObject(nameToID(LocalClientConnection))) {
%cl = nameToID(LocalClientConnection);
}
else {
if ($CurrentClientId) {
%cl = $CurrentClientId;
}
}
}
if (%rad < 1) {
%rad = 100000;
}
%buildingCount = 0;
if (%file $= "") {
for(%found = true; %found; %buildingCount++ ) {
%suffix = %buildingCount;
while (strLen(%suffix) < 5) %suffix = "0" @ %suffix;
%file = $SaveBuilding::SaveFolder @ %cl.nameBase @ "-" @ $MissionName @ "-" @ %suffix @ ".cs";
%found = isFile(%file);
}
}
else {
%file = $SaveBuilding::SaveFolder @ %file;
}
if (isObject(%cl.getControlObject())) {
%pos = %cl.getControlObject().getPosition();
}
if (!%pos) {
%pos = "0 0 0";
}
new fileObject("Building");
if (!$SaveBuilding::Quiet) {
warn("Saving to file: \"" @ %file @ "\"");
}
Building.openForWrite(%file);
Building.writeLine("// CONSTRUCTION MOD SAVE FILE");
Building.writeLine("// This building was saved by \"" @ getField(%cl.nameBase,0) @ "\"");
Building.writeLine("// This building was created in mission \"" @ $MissionName @ "\"");
Building.writeLine("");
$SaveBuilding::Saved = 0;
$SaveBuilding::Skipped = 0;
$SaveBuilding::MaxX = 0;
$SaveBuilding::MaxY = 0;
$SaveBuilding::MaxZ = 0;
$SaveBuilding::MinX = 0;
$SaveBuilding::MinY = 0;
$SaveBuilding::MinZ = 0;
%firstObj = true;
initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType);
while((%obj = containerSearchNext()) != 0) {
%compPos = checkBuildingComponentCentered(%obj);
if (%compPos) {
%x = getWord(%compPos,0);
%y = getWord(%compPos,1);
%z = getWord(%compPos,2);
if (%x > $SaveBuilding::MaxX || %firstObj) {$SaveBuilding::MaxX = %x;}
if (%y > $SaveBuilding::MaxY || %firstObj) {$SaveBuilding::MaxY = %y;}
if (%z > $SaveBuilding::MaxZ || %firstObj) {$SaveBuilding::MaxZ = %z;}
if (%x < $SaveBuilding::MinX || %firstObj) {$SaveBuilding::MinX = %x;}
if (%y < $SaveBuilding::MinY || %firstObj) {$SaveBuilding::MinY = %y;}
if (%z < $SaveBuilding::MinZ || %firstObj) {$SaveBuilding::MinZ = %z;}
%firstObj = false;
}
}
$SaveBuilding::SizeX = $SaveBuilding::MaxX - $SaveBuilding::MinX;
$SaveBuilding::SizeY = $SaveBuilding::MaxY - $SaveBuilding::MinY;
$SaveBuilding::SizeZ = $SaveBuilding::MaxZ - $SaveBuilding::MinZ;
$SaveBuilding::CenterX = $SaveBuilding::MinX + ($SaveBuilding::SizeX / 2);
$SaveBuilding::CenterY = $SaveBuilding::MinY + ($SaveBuilding::SizeY / 2);
if (!%centerAtMinZ) {$SaveBuilding::CenterZ = $SaveBuilding::MinZ + ($SaveBuilding::SizeZ / 2);}
else {$SaveBuilding::CenterZ = $SaveBuilding::MinZ;}
if (isObject($SaveBuilding::TestWaypoint))
$SaveBuilding::TestWaypoint.delete();
$SaveBuilding::TestWaypoint = new WayPoint(SaveBuildingWaypoint) {
position = $SaveBuilding::CenterX SPC $SaveBuilding::CenterY SPC $SaveBuilding::CenterZ;
rotation = "1 0 0 0";
scale = "1 1 1";
dataBlock = "WayPointMarker";
team = 0;
name = "Saved Building Center";
};
MissionCleanup.add($SaveBuilding::TestWaypoint);
initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType);
while((%obj = containerSearchNext()) != 0) {
%cmp = writeBuildingComponentCentered(%obj);
if (%cmp !$= "") {
Building.writeLine(%cmp);
}
}
if (!$SaveBuilding::Quiet) {
warn("Saved to file: \"" @ %file @ "\"");
warn("Saved pieces: " @ $SaveBuilding::Saved);
warn("Skipped pieces: " @ $SaveBuilding::Skipped);
}
$SaveBuilding::LastFile = %file;
Building.close();
Building.delete();
return %file;
}
function checkBuildingComponentCentered(%obj) {
%save = false;
%save = saveBuildingCheck(%obj);
if (%save == true) {
%pos = %obj.position;
%x = getWord(%pos,0);
%y = getWord(%pos,1);
%z = getWord(%pos,2);
%obj.saveBuilding = true;
return %x SPC %y SPC %z;
}
else {
%obj.saveBuilding = false;
return;
}
}
function writeBuildingComponentCentered(%obj) {
%dataBlockName = %obj.getDatablock().getName();
%save = false;
%save = saveBuildingCheck(%obj);
if (%save == true) {
if (!$SaveBuilding::Quiet)
echo("Saving: " @ %obj @ " Name: " @ %dataBlockName);
%buildingPiece = "%building = new (" @ %obj.getClassName() @ ") () {";
%buildingPiece = %buildingPiece @ "datablock = \"" @ %dataBlockName @ "\";";
%pos = %obj.position;
%x = getWord(%pos,0)-$SaveBuilding::CenterX;
%y = getWord(%pos,1)-$SaveBuilding::CenterY;
%z = getWord(%pos,2)-$SaveBuilding::CenterZ;
%savePos = %x SPC %y SPC %z;
if (%obj.position !$= "") %buildingPiece = %buildingPiece @ "position = \"" @ %savePos @ "\";";
if (%obj.rotation !$= "") %buildingPiece = %buildingPiece @ "rotation = \"" @ %obj.rotation @ "\";";
if (%obj.realScale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.realScale @ "\";";
else {if (%obj.scale !$= "") %buildingPiece = %buildingPiece @ "scale = \"" @ %obj.scale @ "\";";}
if (%obj.impulse !$= "") %buildingPiece = %buildingPiece @ "impulse = \"" @ %obj.impulse @ "\";";
if (%obj.frequency !$= "") %buildingPiece = %buildingPiece @ "frequency = \"" @ %obj.frequency @ "\";";
%buildingPiece = %buildingPiece @ "};";
$SaveBuilding::Saved++;
}
else {
if (!$SaveBuilding::Quiet) {
// warn("Skipping: " @ %obj @ " Name: " @ %dataBlockName);
}
%buildingPiece = "";
$SaveBuilding::Skipped++;
}
return %buildingPiece;
}
function delBuildingWaypoint() {
if (isObject($SaveBuilding::TestWaypoint))
$SaveBuilding::TestWaypoint.delete();
}
function loadBuilding(%file) {
compile($SaveBuilding::SaveFolder @ %file); // Just in case it bombs out
exec($SaveBuilding::SaveFolder @ %file);
}
function saveBuildingTimer(%timeInSeconds,%globalEcho,%file,%useMultipleFiles,%isScheduled,%threadCount) {
if (!%isScheduled) {
$SaveBuilding::TimerCount++;
$SaveBuilding::TimerTime = %timeInSeconds * 1000;
if ($SaveBuilding::TimerTime < 1)
$SaveBuilding::TimerTime = $SaveBuilding::TimerDefaultTime;
$SaveBuilding::TimerFile = %file;
if ($SaveBuilding::TimerFile $= "" || $SaveBuilding::TimerFile $= "0")
$SaveBuilding::TimerFile = "SaveBuildingTimer.cs";
if (%useMultipleFiles)
$SaveBuilding::TimerFile = "";
$SaveBuilding::TimerGlobalChatEcho = %globalEcho;
$SaveBuilding::TimerEnabled = true;
%threadCount = $SaveBuilding::TimerCount;
}
if ($SaveBuilding::TimerEnabled == true && $SaveBuilding::TimerCount == %threadCount && isObject("MissionCleanup/Deployables")) {
%file = saveBuilding(0,0,$SaveBuilding::TimerFile,true,true);
%timeToNextSave = mFloatLength($SaveBuilding::TimerTime / 60 / 1000,2);
%timeToNextSaveMinutes = mFloor(%timeToNextSave);
%timeToNextSaveSeconds = mFloor((%timeToNextSave - %timeToNextSaveMinutes) * 60);
%timeToNextSave = %timeToNextSaveMinutes @ "m, " @ %timeToNextSaveSeconds @ "s";
%filespec = "\"" @ %file @ "\"";
if ($SaveBuilding::TimerFile $= "")
%filespec = %filespec @ " (using multiple files)";
warn("-SaveBuildingTimer- Saved to: " @ %filespec @ " - Timer: " @ %timeToNextSave);
if ($SaveBuilding::TimerGlobalChatEcho)
MessageAll('msgClient',"\c2Buildings saved. Next save in " @ %timeToNextSave);
if ($SaveBuilding::TimerTime > 0) // Extra safety
schedule($SaveBuilding::TimerTime,0,saveBuildingTimer,0,0,0,0,true,%threadCount);
}
else {
warn("-SaveBuildingTimer- Thread " @ %threadCount @ " disabled. Last active thread: " @ $SaveBuilding::TimerCount);
}
}
// NB: This function does not setup default parameters
function saveBuildingTimerOn() {
if ($SaveBuilding::TimerTime < 1) {
$SaveBuilding::TimerTime = $SaveBuilding::TimerDefaultTime;
}
$SaveBuilding::TimerCount++;
$SaveBuilding::TimerEnabled = true;
saveBuildingTimer(0,0,0,0,true,$SaveBuilding::TimerCount);
}
function saveBuildingTimerOff() {
$SaveBuilding::TimerEnabled = false;
}
function delDupPieces(%cl,%rad,%quiet) {
%randomTime = 10000;
if (%quiet == true) {
$SaveBuilding::Quiet = true;
}
else {
$SaveBuilding::Quiet = false; // Overwrite
}
if (!isObject(%cl)) {
if (isObject(nameToID(LocalClientConnection))) {
%cl = nameToID(LocalClientConnection);
}
else {
if ($CurrentClientId) {
%cl = $CurrentClientId;
}
}
}
if (%rad < 1) {
%rad = 100000;
}
if (isObject(%cl.getControlObject())) {
%pos = %cl.getControlObject().getPosition();
}
if (!%pos) {
%pos = "0 0 0";
}
%oldChk = "";
initContainerRadiusSearch(%pos,%rad,$TypeMasks::StaticShapeObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::ItemObjectType);
while((%obj = containerSearchNext()) != 0) {
%dataBlockName = %obj.getDatablock().getName();
%save = saveBuildingCheck(%obj);
if (%save) {
// Round down a bit
%objPos = mFloatLength(getWord(%obj.getPosition(),0),2) SPC mFloatLength(getWord(%obj.getPosition(),1),2) SPC mFloatLength(getWord(%obj.getPosition(),2),2);
%objRot = mFloatLength(getWord(%obj.rotation,0),2) SPC mFloatLength(getWord(%obj.rotation,1),2) SPC mFloatLength(getWord(%obj.rotation,2),2) SPC mFloatLength(getWord(%obj.rotation,3),2);
if (%obj.realScale)
%objScale = %obj.realScale;
else
%objScale = %obj.scale;
if (%dataBlockName $= "DeployedFloor" || %dataBlockName $= "DeployedwWall")
// This doesn't handle all wWalls, but it helps
%chk = %dataBlockName SPC %objPos SPC %objScale;
else
%chk = %dataBlockName SPC %objPos SPC %objRot SPC %objScale;
if (%chk $= %oldChk) {
%deleted++;
if (!$SaveBuilding::Quiet && %dataBlockName !$= "DeployedMSpineRing")
warn("Deleting: " @ %oldObj @ " Name: " @ %dataBlockName);
// from inventoryHud.cs, modified
%random = getRandom() * %randomTime;
// Not the best way of doing this..
if ($SaveBuilding::QuickDelete == true) {
// Handle special cases
if (%dataBlockName $= "DeployedMSpine") {
if (isObject(%oldObj.left)) {
if (!$SaveBuilding::Quiet)
warn("Deleting: " @ %oldObj.left @ " Name: " @ %oldObj.left.getDatablock().getName());
%deleted++;
remDSurface(%oldObj.left);
%oldObj.left.delete();
}
if (isObject(%oldObj.right)) {
if (!$SaveBuilding::Quiet)
warn("Deleting: " @ %oldObj.right @ " Name: " @ %oldObj.right.getDatablock().getName());
%deleted++;
remDSurface(%oldObj.right);
%oldObj.right.delete();
}
remDSurface(%oldObj);
%oldObj.delete();
}
else if (%dataBlockName $= "DeployedEscapePod") {
if (isObject(%oldObj.lTarget)) {
if (!$SaveBuilding::Quiet)
warn("Deleting: " @ %oldObj.lTarget @ " Name: " @ %oldObj.lTarget.getDatablock().getName());
%deleted++;
remDSurface(%oldObj.lTarget);
%oldObj.lTarget.delete();
}
if (isObject(%oldObj.podVehicle)) {
if (!$SaveBuilding::Quiet)
warn("Deleting: " @ %oldObj.podVehicle @ " Name: " @ %oldObj.podVehicle.getDatablock().getName());
%deleted++;
%oldObj.podVehicle.delete();
}
%oldObj.delete();
}
else if (%dataBlockName $= "DeployedMSpineRing") {
// Nil. Handled by DeployedMSpine
%deleted--;
}
else if (%dataBlockName $= "TelePadBeam") {
// Nil. Handled by TelePadDeployedBase
%deleted--;
}
else if (%dataBlockName $= "DeployedLTarget") {
// Nil. Handled by parent object
%deleted--;
}
else {
if (%oldObj.beam)
%oldObj.beam.delete();
if (%oldObj.pzone)
%oldObj.pzone.delete();
if (%oldObj.trigger)
%oldObj.trigger.delete();
if (%oldObj.lTarget)
%oldObj.lTarget.delete();
if (%oldObj.holo)
%oldObj.holo.delete();
if (%oldObj.light)
%oldObj.light.delete();
if (%oldObj.tripField)
%oldObj.tripField.delete();
if (%oldObj.tripTrigger)
%oldObj.tripTrigger.delete();
remDSurface(%oldObj);
%oldObj.delete();
}
}
else {
// Handle special cases
if (%dataBlockName $= "DeployedMSpineRing") {
// Nil. Handled by DeployedMSpine
}
else if (%dataBlockName $= "TelePadBeam") {
// Nil. Handled by TelePadDeployedBase
}
else if (%dataBlockName $= "DeployedLTarget") {
// Nil. Handled by parent object
}
else {
%oldObj.getDataBlock().schedule(%random,"disassemble",0, %oldObj); // Run Item Specific code.
}
}
}
else {
%checked++;
// if (!$SaveBuilding::Quiet)
// echo("Checking: " @ %obj @ " Name: " @ %dataBlockName);
}
%oldChk = %chk;
%oldObj = %obj;
}
else {
%skipped++;
// if (!$SaveBuilding::Quiet)
// warn("Skipping: " @ %obj @ " Name: " @ %dataBlockName);
}
}
if (!$SaveBuilding::Quiet) {
warn("Checked pieces: " @ %checked);
warn("Skipped pieces: " @ %skipped);
warn("Deleted pieces: " @ %deleted);
}
return %randomTime;
}
function updateDeployedCount() {
Game.clearDeployableMaxes();
%group = nameToID("MissionCleanup/Deployables");
%count = %group.getCount();
for(%i=0;%i<%count;%i++) {
%obj = %group.getObject(%i);
%revItem = $ReverseDeployItem[%obj.getDataBlock().getName()];
if (getWord(%revItem,0) $= "poof")
%revItem = getWord(%revItem,1);
if (%revItem !$= "")
$TeamDeployedCount[%obj.team,%revItem]++;
}
}