Changeset View
Standalone View
binaries/data/mods/public/simulation/helpers/Commands.js
// Setting this to true will display some warnings when commands | // Setting this to true will display some warnings when commands | ||||
// are likely to fail, which may be useful for debugging AIs | // are likely to fail, which may be useful for debugging AIs | ||||
var g_DebugCommands = false; | var g_DebugCommands = false; | ||||
function ProcessCommand(player, cmd) | function ProcessCommand(player, cmd) | ||||
{ | { | ||||
let cmpPlayer = QueryPlayerIDInterface(player); | let cmpPlayer = QueryPlayerIDInterface(player); | ||||
if (!cmpPlayer) | if (!cmpPlayer) | ||||
return; | return; | ||||
let data = { | let data = { | ||||
"cmpPlayer": cmpPlayer, | "cmpPlayer": cmpPlayer, | ||||
"controlAllUnits": cmpPlayer.CanControlAllUnits() | "controlAllUnits": cmpPlayer.CanControlAllUnits() | ||||
}; | }; | ||||
if (cmd.entities) | if (cmd.entities) | ||||
data.entities = FilterEntityList(cmd.entities, player, data.controlAllUnits); | data.entities = FilterEntityList(cmd.entities, player, data.controlAllUnits); | ||||
Freagarach: The entities are filtered here. (Introduced in rP13367 where the warnings below were not… | |||||
// Allow focusing the camera on recent commands | // Allow focusing the camera on recent commands | ||||
let commandData = { | let commandData = { | ||||
"type": "playercommand", | "type": "playercommand", | ||||
"players": [player], | "players": [player], | ||||
"cmd": cmd | "cmd": cmd | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | for (let ent of data.entities) | ||||
queue.AddBatch(cmd.template, "unit", +cmd.count, cmd.metadata); | queue.AddBatch(cmd.template, "unit", +cmd.count, cmd.metadata); | ||||
else | else | ||||
queue.AddBatch(cmd.template, "unit", +cmd.count); | queue.AddBatch(cmd.template, "unit", +cmd.count); | ||||
} | } | ||||
}, | }, | ||||
"research": function(player, cmd, data) | "research": function(player, cmd, data) | ||||
{ | { | ||||
if (!CanControlUnit(cmd.entity, player, data.controlAllUnits)) | if (!CanControlUnit(cmd.entity, player, data.controlAllUnits)) | ||||
Done Inline ActionsDuplicated with L17. Freagarach: Duplicated with L17. | |||||
{ | { | ||||
if (g_DebugCommands) | if (g_DebugCommands) | ||||
warn("Invalid command: research building cannot be controlled by player "+player+": "+uneval(cmd)); | warn("Invalid command: research building cannot be controlled by player "+player+": "+uneval(cmd)); | ||||
return; | return; | ||||
} | } | ||||
var cmpTechnologyManager = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); | var cmpTechnologyManager = QueryOwnerInterface(cmd.entity, IID_TechnologyManager); | ||||
if (!cmpTechnologyManager.CanResearch(cmd.template)) | if (!cmpTechnologyManager.CanResearch(cmd.template)) | ||||
{ | { | ||||
if (g_DebugCommands) | if (g_DebugCommands) | ||||
warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd)); | warn("Invalid command: Requirements to research technology are not met: " + uneval(cmd)); | ||||
return; | return; | ||||
} | } | ||||
var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); | var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); | ||||
if (queue) | if (queue) | ||||
queue.AddBatch(cmd.template, "technology"); | queue.AddBatch(cmd.template, "technology"); | ||||
}, | }, | ||||
"stop-production": function(player, cmd, data) | "stop-production": function(player, cmd, data) | ||||
{ | { | ||||
if (!CanControlUnit(cmd.entity, player, data.controlAllUnits)) | if (!CanControlUnit(cmd.entity, player, data.controlAllUnits)) | ||||
Done Inline ActionsDuplicated with L17. Freagarach: Duplicated with L17. | |||||
{ | { | ||||
if (g_DebugCommands) | if (g_DebugCommands) | ||||
warn("Invalid command: production building cannot be controlled by player "+player+": "+uneval(cmd)); | warn("Invalid command: production building cannot be controlled by player "+player+": "+uneval(cmd)); | ||||
return; | return; | ||||
} | } | ||||
Done Inline ActionsWhy did you delete these two? wraitii: Why did you delete these two? | |||||
Done Inline ActionsBecause it is checked earlier now, so we won't be able to arrive here, IIRC. Freagarach: Because it is checked earlier now, so we won't be able to arrive here, IIRC. | |||||
Done Inline Actionsbb: However that is in unit_actions.js, hence in the gui, which is only ran for one client. NOT for… | |||||
Done Inline ActionsI should have more explicit that I meant not that it was changed in this diff. Freagarach: I should have more explicit that I meant not that it was changed in this diff.
If you want I… | |||||
Done Inline ActionsSo what this means is that the L17 check makes this redundant. wraitii: So what this means is that the L17 check makes this redundant. | |||||
var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); | var queue = Engine.QueryInterface(cmd.entity, IID_ProductionQueue); | ||||
if (queue) | if (queue) | ||||
queue.RemoveBatch(cmd.id); | queue.RemoveBatch(cmd.id); | ||||
}, | }, | ||||
"construct": function(player, cmd, data) | "construct": function(player, cmd, data) | ||||
{ | { | ||||
TryConstructBuilding(player, data.cmpPlayer, data.controlAllUnits, cmd); | TryConstructBuilding(player, data.cmpPlayer, data.controlAllUnits, cmd); | ||||
▲ Show 20 Lines • Show All 482 Lines • ▼ Show 20 Lines | cmpGUIInterface.PushNotification({ | ||||
"type": "text", | "type": "text", | ||||
"players": [player], | "players": [player], | ||||
"message": markForTranslation("Some unit(s) can't go back to work"), | "message": markForTranslation("Some unit(s) can't go back to work"), | ||||
"translateMessage": true | "translateMessage": true | ||||
}); | }); | ||||
} | } | ||||
/** | /** | ||||
* Sends a GUI notification about entities that can't be controlled. | |||||
* @param {} player - The player-ID of the player that needs to recieve this message. | |||||
StanUnsubmitted Done Inline Actionsrecieve → receive Stan: recieve → receive
I believe player is a number ? | |||||
FreagarachAuthorUnsubmitted Done Inline ActionsO wow, 2x aye. Freagarach: O wow, 2x aye. | |||||
*/ | |||||
function notifyOrderFailure(player) | |||||
Not Done Inline ActionsWhy is this in the sim? IMO the player should be notified immediately from the gui, not a few turn later (in MP) when the order is tried being processed. bb: Why is this in the sim? IMO the player should be notified immediately from the gui, not a few… | |||||
Not Done Inline ActionsThere is an instant notification in the GUI -> the icons don't appear / something tells you it's not working. This is a fallback for the case where something unexpected happens, such as a player selecting controllable and uncontrollable units and ordering them to move. I'm not sure with our current design that we can really improve a ton on this. wraitii: There is an instant notification in the GUI -> the icons don't appear / something tells you… | |||||
{ | |||||
let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); | |||||
Done Inline ActionsCheck ? Stan: Check ? | |||||
cmpGUIInterface.PushNotification({ | |||||
"type": "text", | |||||
"players": [player], | |||||
"message": markForTranslation("Some unit(s) can't be controlled."), | |||||
Done Inline ActionsI would prefer to fetch the name of the entity there instead of a generic message like that. wraitii: I would prefer to fetch the name of the entity there instead of a generic message like that. | |||||
"translateMessage": true | |||||
Not Done Inline ActionsI'm not sure whether this gets translated properly, markForTranslation was not in the lesson by @elexis ;) Freagarach: I'm not sure whether this gets translated properly, `markForTranslation` was not in the lesson… | |||||
}); | |||||
} | |||||
Done Inline ActionsThe 'some' seems completely redundant. wraitii: The 'some' seems completely redundant. | |||||
/** | |||||
* Get some information about the formations used by entities. | * Get some information about the formations used by entities. | ||||
* The entities must have a UnitAI component. | * The entities must have a UnitAI component. | ||||
*/ | */ | ||||
function ExtractFormations(ents) | function ExtractFormations(ents) | ||||
{ | { | ||||
var entities = []; // subset of ents that have UnitAI | var entities = []; // subset of ents that have UnitAI | ||||
var members = {}; // { formationentity: [ent, ent, ...], ... } | var members = {}; // { formationentity: [ent, ent, ...], ... } | ||||
for (let ent of ents) | for (let ent of ents) | ||||
▲ Show 20 Lines • Show All 767 Lines • ▼ Show 20 Lines | for (let ent of ents) | ||||
++count; | ++count; | ||||
} | } | ||||
return count >= requirements.minCount; | return count >= requirements.minCount; | ||||
} | } | ||||
/** | /** | ||||
* Check if player can control this entity | * Check if player can control this entity | ||||
* returns: true if the entity is valid and owned by the player | * @param {number} entity - The ID of the entity. | ||||
* or control all units is activated, else false | * @param {number} player - The ID of the player. | ||||
* @param {boolean} controlAll - Whether the controlAll-cheat is enabled. | |||||
* @return {boolean} - Whether the entity can be controlled. | |||||
*/ | */ | ||||
function CanControlUnit(entity, player, controlAll) | function CanControlUnit(entity, player, controlAll) | ||||
{ | { | ||||
return IsOwnedByPlayer(player, entity) || controlAll; | let cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); | ||||
let CanBeControlled = IsOwnedByPlayer(player, entity) && (cmpUnitAI ? !cmpUnitAI.IsUncontrollable() : true) || controlAll; | |||||
StanUnsubmitted Done Inline Actions(cmpUnitAI ? !cmpUnitAI.IsUncontrollable() : true) → cmpUnitAI && !cmpUnitAI.IsUncontrollable() || !cmpUnitAI I guess whatever the value of cmpUnitAi doesn't change the outcome. Maybe it could be written differently ? Stan: (cmpUnitAI ? !cmpUnitAI.IsUncontrollable() : true) → cmpUnitAI && !cmpUnitAI.IsUncontrollable()… | |||||
if (!CanBeControlled) | |||||
notifyOrderFailure(player); | |||||
StanUnsubmitted Done Inline ActionsWhat happens if someone selects all units on the wall ? Stan: What happens if someone selects all units on the wall ? | |||||
FreagarachAuthorUnsubmitted Done Inline ActionsIf one orders many units which are not controllable, many messages are sent. Freagarach: If one orders many units which are not controllable, many messages are sent. | |||||
StanUnsubmitted Done Inline ActionsMissing parenthesis ? (operator precedence) Stan: Missing parenthesis ? (operator precedence) | |||||
return CanBeControlled; | |||||
Done Inline ActionsEarly return, no component, notcontrollable? Stan: Early return, no component, notcontrollable? | |||||
Done Inline ActionsBut when controlAll is true, we want any unit to be controllable. Freagarach: But when `controlAll` is true, we want any unit to be controllable. | |||||
} | } | ||||
Done Inline ActionsI guess that sends the message you removed above? Stan: I guess that sends the message you removed above? | |||||
Done Inline ActionsIt actualy sends it also when g_debug is false. Freagarach: It actualy sends it also when g_debug is false. | |||||
/** | /** | ||||
* Check if player can control this entity | * Check if player can control this entity | ||||
* returns: true if the entity is valid and owned by the player | * returns: true if the entity is valid and owned by the player | ||||
* or the entity is owned by an mutualAlly | * or the entity is owned by an mutualAlly | ||||
* or control all units is activated, else false | * or control all units is activated, else false | ||||
*/ | */ | ||||
function CanControlUnitOrIsAlly(entity, player, controlAll) | function CanControlUnitOrIsAlly(entity, player, controlAll) | ||||
Done Inline ActionsI think CanPlayerOrAllyControlUnit would be a better name, I parse this as "Can I Control the Unit or can I ally the Unit" wraitii: I think `CanPlayerOrAllyControlUnit` would be a better name, I parse this as "Can I Control the… | |||||
{ | { | ||||
return IsOwnedByPlayer(player, entity) || IsOwnedByMutualAllyOfPlayer(player, entity) || controlAll; | return IsOwnedByPlayer(player, entity) || IsOwnedByMutualAllyOfPlayer(player, entity) || controlAll; | ||||
Done Inline Actionsso I can control a unit owned by ally which is not controllable? bb: so I can control a unit owned by ally which is not controllable? | |||||
Done Inline ActionsAh yes, this function is not used how it should when reading its name ^^ Freagarach: Ah yes, this function is not used how it should when reading its name ^^ | |||||
} | } | ||||
/** | /** | ||||
* Filter entities which the player can control | * Filter entities which the player can control | ||||
*/ | */ | ||||
function FilterEntityList(entities, player, controlAll) | function FilterEntityList(entities, player, controlAll) | ||||
{ | { | ||||
return entities.filter(ent => CanControlUnit(ent, player, controlAll)); | return entities.filter(ent => CanControlUnit(ent, player, controlAll)); | ||||
Show All 39 Lines |
The entities are filtered here. (Introduced in rP13367 where the warnings below were not removed.)