Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/helpers/Commands.js
Show First 20 Lines • Show All 1,190 Lines • ▼ Show 20 Lines | function TryConstructWall(player, cmpPlayer, controlAllUnits, cmd) | ||||
// "autorepair": true, // whether to automatically start constructing/repairing the new foundation | // "autorepair": true, // whether to automatically start constructing/repairing the new foundation | ||||
// "autocontinue": true, // whether to automatically gather/build/etc after finishing this | // "autocontinue": true, // whether to automatically gather/build/etc after finishing this | ||||
// "queued": true, // whether to add the construction/repairing of this wall's pieces to entities' queue (if applicable) | // "queued": true, // whether to add the construction/repairing of this wall's pieces to entities' queue (if applicable) | ||||
// } | // } | ||||
if (cmd.pieces.length <= 0) | if (cmd.pieces.length <= 0) | ||||
return; | return; | ||||
if (cmd.startSnappedEntity && cmd.pieces[0].template == cmd.wallSet.templates.tower) | if (!cmd.rebuildStartTower && cmd.startSnappedEntity && cmd.pieces[0].template == cmd.wallSet.templates.tower) | ||||
{ | { | ||||
error(cmd.startSnappedEntity); | |||||
error("[TryConstructWall] Starting wall piece cannot be a tower (" + cmd.wallSet.templates.tower + ") when snapping at the starting side"); | error("[TryConstructWall] Starting wall piece cannot be a tower (" + cmd.wallSet.templates.tower + ") when snapping at the starting side"); | ||||
return; | return; | ||||
} | } | ||||
if (cmd.endSnappedEntity && cmd.pieces[cmd.pieces.length - 1].template == cmd.wallSet.templates.tower) | if (!cmd.rebuildEndTower && cmd.endSnappedEntity && cmd.pieces[cmd.pieces.length - 1].template == cmd.wallSet.templates.tower) | ||||
{ | { | ||||
error("[TryConstructWall] Ending wall piece cannot be a tower (" + cmd.wallSet.templates.tower + ") when snapping at the ending side"); | error("[TryConstructWall] Ending wall piece cannot be a tower (" + cmd.wallSet.templates.tower + ") when snapping at the ending side"); | ||||
return; | return; | ||||
} | } | ||||
// Assign obstruction control groups to allow the wall pieces to mutually overlap during foundation placement | // Assign obstruction control groups to allow the wall pieces to mutually overlap during foundation placement | ||||
// and during construction. The scheme here is that whatever wall pieces are inbetween two towers inherit the control | // and during construction. The scheme here is that whatever wall pieces are inbetween two towers inherit the control | ||||
// groups of both of the towers they are connected to (either newly constructed ones as part of the wall, or existing | // groups of both of the towers they are connected to (either newly constructed ones as part of the wall, or existing | ||||
Show All 19 Lines | function TryConstructWall(player, cmpPlayer, controlAllUnits, cmd) | ||||
// to be placed while overlapping the previous piece. | // to be placed while overlapping the previous piece. | ||||
// | // | ||||
// SECOND PASS: | // SECOND PASS: | ||||
// - Go end to start from the last successfully placed wall piece (which might be a tower we backtracked to), this | // - Go end to start from the last successfully placed wall piece (which might be a tower we backtracked to), this | ||||
// time registering the right neighbouring tower in each non-tower piece. | // time registering the right neighbouring tower in each non-tower piece. | ||||
// first pass; L -> R | // first pass; L -> R | ||||
var lastTowerIndex = -1; // index of the last tower we've encountered in cmd.pieces | let lastTowerIndex = -1; // index of the last tower we've encountered in cmd.pieces | ||||
var lastTowerControlGroup = null; // control group of the last tower we've encountered, to assign to non-tower pieces | let lastTowerControlGroup = null; // control group of the last tower we've encountered, to assign to non-tower pieces | ||||
// If we're snapping to an existing entity at the starting end, set lastTowerControlGroup to its control group ID so that | // If we're snapping to an existing entity at the starting end, set lastTowerControlGroup to its control group ID so that | ||||
// the first wall piece can be built while overlapping it. | // the first wall piece can be built while overlapping it. | ||||
if (cmd.startSnappedEntity) | if (cmd.startSnappedEntity) | ||||
{ | { | ||||
var cmpSnappedStartObstruction = Engine.QueryInterface(cmd.startSnappedEntity, IID_Obstruction); | let cmpSnappedStartObstruction = Engine.QueryInterface(cmd.startSnappedEntity, IID_Obstruction); | ||||
if (!cmpSnappedStartObstruction) | if (!cmpSnappedStartObstruction) | ||||
{ | { | ||||
error("[TryConstructWall] Snapped entity on starting side does not have an obstruction component"); | error("[TryConstructWall] Snapped entity on starting side does not have an obstruction component"); | ||||
return; | return; | ||||
} | } | ||||
lastTowerControlGroup = cmpSnappedStartObstruction.GetControlGroup(); | lastTowerControlGroup = cmpSnappedStartObstruction.GetControlGroup(); | ||||
// set different control group to delete upon construction | |||||
if (cmd.rebuildStartTower) { | |||||
cmpSnappedStartObstruction.SetControlGroup(0); | |||||
} | |||||
//warn("setting lastTowerControlGroup to control group of start snapped entity " + cmd.startSnappedEntity + ": " + lastTowerControlGroup); | // warn("setting lastTowerControlGroup to control group of start snapped entity " + cmd.startSnappedEntity + ": " + lastTowerControlGroup); | ||||
Stan: Nuke. | |||||
} | } | ||||
var i = 0; | let i = 0; | ||||
var queued = cmd.queued; | let queued = cmd.queued; | ||||
var pieces = clone(cmd.pieces); | let pieces = clone(cmd.pieces); | ||||
for (; i < pieces.length; ++i) | for (; i < pieces.length; ++i) | ||||
{ | { | ||||
var piece = pieces[i]; | let piece = pieces[i]; | ||||
// All wall pieces after the first must be queued. | // All wall pieces after the first must be queued. | ||||
if (i > 0 && !queued) | if (i > 0 && !queued) | ||||
queued = true; | queued = true; | ||||
// 'lastTowerControlGroup' must always be defined and valid here, except if we're at the first piece and we didn't do | // 'lastTowerControlGroup' must always be defined and valid here, except if we're at the first piece and we didn't do | ||||
// start position snapping (implying that the first entity we build must be a tower) | // start position snapping (implying that the first entity we build must be a tower) | ||||
if (lastTowerControlGroup === null || lastTowerControlGroup == INVALID_ENTITY) | if (lastTowerControlGroup === null || lastTowerControlGroup == INVALID_ENTITY) | ||||
{ | { | ||||
if (!(i == 0 && piece.template == cmd.wallSet.templates.tower && !cmd.startSnappedEntity)) | if (!(i == 0 && piece.template == cmd.wallSet.templates.tower && !cmd.startSnappedEntity)) | ||||
{ | { | ||||
error("[TryConstructWall] Expected last tower control group to be available, none found (1st pass, iteration " + i + ")"); | error("[TryConstructWall] Expected last tower control group to be available, none found (1st pass, iteration " + i + ")"); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
var constructPieceCmd = { | let constructPieceCmd = { | ||||
"type": "construct", | "type": "construct", | ||||
"entities": cmd.entities, | "entities": cmd.entities, | ||||
"template": piece.template, | "template": piece.template, | ||||
"x": piece.x, | "x": piece.x, | ||||
"z": piece.z, | "z": piece.z, | ||||
"angle": piece.angle, | "angle": piece.angle, | ||||
"autorepair": cmd.autorepair, | "autorepair": cmd.autorepair, | ||||
"autocontinue": cmd.autocontinue, | "autocontinue": cmd.autocontinue, | ||||
"queued": queued, | "queued": queued, | ||||
// Regardless of whether we're building a tower or an intermediate wall piece, it is always (first) constructed | // Regardless of whether we're building a tower or an intermediate wall piece, it is always (first) constructed | ||||
// using the control group of the last tower (see comments above). | // using the control group of the last tower (see comments above). | ||||
"obstructionControlGroup": lastTowerControlGroup, | "obstructionControlGroup": lastTowerControlGroup, | ||||
}; | }; | ||||
// If we're building the last piece and we're attaching to a snapped entity, we need to add in the snapped entity's | // If we're building the last piece and we're attaching to a snapped entity, we need to add in the snapped entity's | ||||
// control group directly at construction time (instead of setting it in the second pass) to allow it to be built | // control group directly at construction time (instead of setting it in the second pass) to allow it to be built | ||||
// while overlapping the snapped entity. | // while overlapping the snapped entity. | ||||
if (i == pieces.length - 1 && cmd.endSnappedEntity) | if (i == pieces.length - 1 && cmd.endSnappedEntity) | ||||
{ | { | ||||
var cmpEndSnappedObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction); | let cmpEndSnappedObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction); | ||||
if (cmpEndSnappedObstruction) | if (cmpEndSnappedObstruction) | ||||
constructPieceCmd.obstructionControlGroup2 = cmpEndSnappedObstruction.GetControlGroup(); | constructPieceCmd.obstructionControlGroup2 = cmpEndSnappedObstruction.GetControlGroup(); | ||||
} | } | ||||
var pieceEntityId = TryConstructBuilding(player, cmpPlayer, controlAllUnits, constructPieceCmd); | let pieceEntityId = TryConstructBuilding(player, cmpPlayer, controlAllUnits, constructPieceCmd); | ||||
if (pieceEntityId) | if (pieceEntityId) | ||||
{ | { | ||||
// wall piece foundation successfully built, save the entity ID in the piece info object so we can reference it later | // wall piece foundation successfully built, save the entity ID in the piece info object so we can reference it later | ||||
piece.ent = pieceEntityId; | piece.ent = pieceEntityId; | ||||
// if we built a tower, do the control group dance (see outline above) and update lastTowerControlGroup and lastTowerIndex | // if we built a tower, do the control group dance (see outline above) and update lastTowerControlGroup and lastTowerIndex | ||||
if (piece.template == cmd.wallSet.templates.tower) | if (piece.template == cmd.wallSet.templates.tower) | ||||
{ | { | ||||
var cmpTowerObstruction = Engine.QueryInterface(pieceEntityId, IID_Obstruction); | let cmpTowerObstruction = Engine.QueryInterface(pieceEntityId, IID_Obstruction); | ||||
var newTowerControlGroup = pieceEntityId; | let newTowerControlGroup = pieceEntityId; | ||||
if (i > 0) | if (i > 0) | ||||
{ | { | ||||
//warn(" updating previous wall piece's secondary control group to " + newTowerControlGroup); | // warn(" updating previous wall piece's secondary control group to " + newTowerControlGroup); | ||||
var cmpPreviousObstruction = Engine.QueryInterface(pieces[i-1].ent, IID_Obstruction); | let cmpPreviousObstruction = Engine.QueryInterface(pieces[i-1].ent, IID_Obstruction); | ||||
// TODO: ensure that cmpPreviousObstruction exists | if(cmpPreviousObstruction) | ||||
// TODO: ensure that the previous obstruction does not yet have a secondary control group set | // TODO: ensure that the previous obstruction does not yet have a secondary control group set | ||||
cmpPreviousObstruction.SetControlGroup2(newTowerControlGroup); | cmpPreviousObstruction.SetControlGroup2(newTowerControlGroup); | ||||
} | } | ||||
// TODO: ensure that cmpTowerObstruction exists | // give the tower its unique control group if not rebuildings | ||||
cmpTowerObstruction.SetControlGroup(newTowerControlGroup); // give the tower its own unique control group | if (!cmd.rebuildStartTower && cmpTowerObstruction) { | ||||
cmpTowerObstruction.SetControlGroup(newTowerControlGroup); | |||||
} | |||||
elexisUnsubmitted Done Inline Actionsno braces for oneliners elexis: no braces for oneliners | |||||
lastTowerIndex = i; | lastTowerIndex = i; | ||||
lastTowerControlGroup = newTowerControlGroup; | lastTowerControlGroup = newTowerControlGroup; | ||||
} | } | ||||
} | } | ||||
else // failed to build wall piece, abort | else // failed to build wall piece, abort | ||||
break; | break; | ||||
} | } | ||||
var lastBuiltPieceIndex = i - 1; | let lastBuiltPieceIndex = i - 1; | ||||
var wallComplete = (lastBuiltPieceIndex == pieces.length - 1); | let wallComplete = (lastBuiltPieceIndex == pieces.length - 1); | ||||
// At this point, 'i' is the index of the last wall piece that was successfully constructed (which may or may not be a tower). | // At this point, 'i' is the index of the last wall piece that was successfully constructed (which may or may not be a tower). | ||||
// Now do the second pass going right-to-left, registering the control groups of the towers to the right of each piece (if any) | // Now do the second pass going right-to-left, registering the control groups of the towers to the right of each piece (if any) | ||||
// as their secondary control groups. | // as their secondary control groups. | ||||
lastTowerControlGroup = null; // control group of the last tower we've encountered, to assign to non-tower pieces | lastTowerControlGroup = null; // control group of the last tower we've encountered, to assign to non-tower pieces | ||||
// only start off with the ending side's snapped tower's control group if we were able to build the entire wall | // only start off with the ending side's snapped tower's control group if we were able to build the entire wall | ||||
if (cmd.endSnappedEntity && wallComplete) | if (cmd.endSnappedEntity && wallComplete) | ||||
{ | { | ||||
var cmpSnappedEndObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction); | let cmpSnappedEndObstruction = Engine.QueryInterface(cmd.endSnappedEntity, IID_Obstruction); | ||||
if (!cmpSnappedEndObstruction) | if (!cmpSnappedEndObstruction) | ||||
{ | { | ||||
error("[TryConstructWall] Snapped entity on ending side does not have an obstruction component"); | error("[TryConstructWall] Snapped entity on ending side does not have an obstruction component"); | ||||
return; | return; | ||||
} | } | ||||
lastTowerControlGroup = cmpSnappedEndObstruction.GetControlGroup(); | lastTowerControlGroup = cmpSnappedEndObstruction.GetControlGroup(); | ||||
} | } | ||||
for (var j = lastBuiltPieceIndex; j >= 0; --j) | for (let j = lastBuiltPieceIndex; j >= 0; --j) | ||||
{ | { | ||||
var piece = pieces[j]; | let piece = pieces[j]; | ||||
if (!piece.ent) | if (!piece.ent) | ||||
{ | { | ||||
error("[TryConstructWall] No entity ID set for constructed entity of template '" + piece.template + "'"); | error("[TryConstructWall] No entity ID set for constructed entity of template '" + piece.template + "'"); | ||||
continue; | continue; | ||||
} | } | ||||
var cmpPieceObstruction = Engine.QueryInterface(piece.ent, IID_Obstruction); | let cmpPieceObstruction = Engine.QueryInterface(piece.ent, IID_Obstruction); | ||||
if (!cmpPieceObstruction) | if (!cmpPieceObstruction) | ||||
{ | { | ||||
error("[TryConstructWall] Wall piece of template '" + piece.template + "' has no Obstruction component"); | error("[TryConstructWall] Wall piece of template '" + piece.template + "' has no Obstruction component"); | ||||
continue; | continue; | ||||
} | } | ||||
if (piece.template == cmd.wallSet.templates.tower) | if (piece.template == cmd.wallSet.templates.tower) | ||||
{ | { | ||||
// encountered a tower entity, update the last tower control group | // encountered a tower entity, update the last tower control group | ||||
lastTowerControlGroup = cmpPieceObstruction.GetControlGroup(); | lastTowerControlGroup = cmpPieceObstruction.GetControlGroup(); | ||||
} | } | ||||
else | else | ||||
{ | { | ||||
// Encountered a non-tower entity, update its secondary control group to 'lastTowerControlGroup'. | // Encountered a non-tower entity, update its secondary control group to 'lastTowerControlGroup'. | ||||
// Note that the wall piece may already have its secondary control group set to the tower's entity ID from a control group | // Note that the wall piece may already have its secondary control group set to the tower's entity ID from a control group | ||||
// dance during the first pass, in which case we should validate it against 'lastTowerControlGroup'. | // dance during the first pass, in which case we should validate it against 'lastTowerControlGroup'. | ||||
var existingSecondaryControlGroup = cmpPieceObstruction.GetControlGroup2(); | let existingSecondaryControlGroup = cmpPieceObstruction.GetControlGroup2(); | ||||
if (existingSecondaryControlGroup == INVALID_ENTITY) | if (existingSecondaryControlGroup == INVALID_ENTITY) | ||||
{ | { | ||||
if (lastTowerControlGroup != null && lastTowerControlGroup != INVALID_ENTITY) | if (lastTowerControlGroup != null && lastTowerControlGroup != INVALID_ENTITY) | ||||
{ | { | ||||
cmpPieceObstruction.SetControlGroup2(lastTowerControlGroup); | cmpPieceObstruction.SetControlGroup2(lastTowerControlGroup); | ||||
} | } | ||||
} | } | ||||
else if (existingSecondaryControlGroup != lastTowerControlGroup) | else if (existingSecondaryControlGroup != lastTowerControlGroup) | ||||
▲ Show 20 Lines • Show All 331 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
Nuke.