Page MenuHomeWildfire Games

Fix formations not queueing orders properly.
ClosedPublic

Authored by wraitii on Apr 16 2020, 8:38 AM.

Details

Summary

When giving a queued order to a formation that was tasked to do some task from >10 m distance, the entities are first informed that they are kept busy by the formation (ResetFinishedOrder) in the walking state. When given the order within 10 m, that function is not called, thus the formation in the MEMBER-state thinks that all of its entities have finished their orders, thus going idle instead of waiting to finish their jobs.

This diff puts a ResetFinishedOrder-call in the enter-function of the MEMBER-state such that all orders causing the formation to enter this state will wait for its members to finish their tasks.

Test Plan

Verify that:

  • When two entities in formation tasked within 10 m from a task finish that task before reacting to a queued order (see ticket).
  • No other, negative, change in behaviour is observed.

It might be that this is just symptom fighting, so please check whether this is the right place to make a change.

Event Timeline

Freagarach created this revision.Apr 16 2020, 8:38 AM
Freagarach retitled this revision from Summary: When giving a queued order to a formation that was tasked to do some task from >10 m distance, the entities are first informed that they are kept busy by the formation (`ResetFinishedOrder`) in the walking state. When given the order... to Fix formations not queueing orders properly..Apr 16 2020, 8:40 AM
Freagarach edited the summary of this revision. (Show Details)

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
| 788| 788| 					this.FinishOrder();
| 789| 789| 					return;
| 790| 790| 				}
| 791|    |-				else
| 792|    |-				{
|    | 791|+				
| 793| 792| 					this.SetNextState("GARRISON.APPROACHING");
| 794| 793| 					return;
| 795|    |-				}
|    | 794|+				
| 796| 795| 			}
| 797| 796| 
| 798| 797| 			this.SetNextState("GARRISON.GARRISONING");
|    | [NORMAL] ESLintBear (key-spacing):
|    | Missing space before value for key 'GARRISON'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|1060|1060| 			},
|1061|1061| 		},
|1062|1062| 
|1063|    |-		"GARRISON":{
|    |1063|+		"GARRISON": {
|1064|1064| 			"APPROACHING": {
|1065|1065| 				"enter": function() {
|1066|1066| 					if (!this.MoveToGarrisonRange(this.order.data.target))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2043|2043| 
|2044|2044| 				"Attacked": function(msg) {
|2045|2045| 					// If we are capturing and are attacked by something that we would not capture, attack that entity instead
|2046|    |-					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force)
|2047|    |-						&& this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|    |2046|+					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force) &&
|    |2047|+						this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|2048|2048| 						this.RespondToTargetedEntities([msg.data.attacker]);
|2049|2049| 				},
|2050|2050| 			},
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2202|2202| 					"MovementUpdate": function(msg) {
|2203|2203| 						// If it looks like the path is failing, and we are close enough (3 tiles) from wanted range
|2204|2204| 						// stop anyways. This avoids pathing for an unreachable goal and reduces lag considerably.
|2205|    |-						if (msg.likelyFailure || 
|    |2205|+						if (msg.likelyFailure ||
|2206|2206| 							msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.order.data.max + this.DefaultRelaxedMaxRange) ||
|2207|2207| 							!msg.obstructed && this.CheckRange(this.order.data))
|2208|2208| 							this.FinishOrder();
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2844|2844| 					{
|2845|2845| 						// The building was already finished/fully repaired before we arrived;
|2846|2846| 						// let the ConstructionFinished handler handle this.
|2847|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2847|+						this.OnGlobalConstructionFinished({ "entity": this.repairTarget, "newentity": this.repairTarget});
|2848|2848| 						return true;
|2849|2849| 					}
|2850|2850| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2844|2844| 					{
|2845|2845| 						// The building was already finished/fully repaired before we arrived;
|2846|2846| 						// let the ConstructionFinished handler handle this.
|2847|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2847|+						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget });
|2848|2848| 						return true;
|2849|2849| 					}
|2850|2850| 
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3142|3142| 				this.StopTimer();
|3143|3143| 				this.ResetAnimation();
|3144|3144| 				if (this.formationAnimationVariant)
|3145|    |-					this.SetAnimationVariant(this.formationAnimationVariant)
|    |3145|+					this.SetAnimationVariant(this.formationAnimationVariant);
|3146|3146| 				else
|3147|3147| 					this.SetDefaultAnimationVariant();
|3148|3148| 				var cmpResistance = Engine.QueryInterface(this.entity, IID_Resistance);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3368|3368| 		"COMBAT": "INDIVIDUAL.COMBAT", // reuse the same combat behaviour for animals
|3369|3369| 
|3370|3370| 		"WALKING": "INDIVIDUAL.WALKING",	// reuse the same walking behaviour for animals
|3371|    |-							// only used for domestic animals
|    |3371|+		// only used for domestic animals
|3372|3372| 
|3373|3373| 		// Reuse the same garrison behaviour for animals.
|3374|3374| 		"GARRISON": "INDIVIDUAL.GARRISON",
|    | [NORMAL] ESLintBear (no-unneeded-ternary):
|    | Unnecessary use of boolean literals in conditional expression.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3430|3430| 
|3431|3431| UnitAI.prototype.IsAnimal = function()
|3432|3432| {
|3433|    |-	return (this.template.NaturalBehaviour ? true : false);
|    |3433|+	return (!!this.template.NaturalBehaviour);
|3434|3434| };
|3435|3435| 
|3436|3436| UnitAI.prototype.IsDangerousAnimal = function()
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3546|3546| 		{
|3547|3547| 			let index = this.GetCurrentState().indexOf(".");
|3548|3548| 			if (index != -1)
|3549|    |-				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index));
|    |3549|+				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0, index));
|3550|3550| 			this.Stop(false);
|3551|3551| 		}
|3552|3552| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3602|3602| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3603|3603| 			continue;
|3604|3604| 		if (i == 0)
|3605|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3605|+			this.UnitFsm.ProcessMessage(this, { "type": "PickupCanceled", "data": msg});
|3606|3606| 		else
|3607|3607| 			this.orderQueue.splice(i, 1);
|3608|3608| 		Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3602|3602| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3603|3603| 			continue;
|3604|3604| 		if (i == 0)
|3605|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3605|+			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg });
|3606|3606| 		else
|3607|3607| 			this.orderQueue.splice(i, 1);
|3608|3608| 		Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3689|3689| };
|3690|3690| 
|3691|3691| 
|3692|    |-//// FSM linkage functions ////
|    |3692|+// // FSM linkage functions ////
|3693|3693| 
|3694|3694| // Setting the next state to the current state will leave/re-enter the top-most substate.
|3695|3695| UnitAI.prototype.SetNextState = function(state)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3860|3860| 				continue;
|3861|3861| 			if (this.orderQueue[i].type == type)
|3862|3862| 				continue;
|3863|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3863|+			this.orderQueue.splice(i, 0, { "type": type, "data": data});
|3864|3864| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3865|3865| 			return;
|3866|3866| 		}
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3860|3860| 				continue;
|3861|3861| 			if (this.orderQueue[i].type == type)
|3862|3862| 				continue;
|3863|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3863|+			this.orderQueue.splice(i, 0, {"type": type, "data": data });
|3864|3864| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3865|3865| 			return;
|3866|3866| 		}
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4102|4102| 	if (data.timerRepeat === undefined)
|4103|4103| 		this.timer = undefined;
|4104|4104| 
|4105|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |4105|+	this.UnitFsm.ProcessMessage(this, { "type": "Timer", "data": data, "lateness": lateness});
|4106|4106| };
|4107|4107| 
|4108|4108| /**
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4102|4102| 	if (data.timerRepeat === undefined)
|4103|4103| 		this.timer = undefined;
|4104|4104| 
|4105|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |4105|+	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness });
|4106|4106| };
|4107|4107| 
|4108|4108| /**
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4147|4147| 	// TODO: This is a bit inefficient since every unit listens to every
|4148|4148| 	// construction message - ideally we could scope it to only the one we're building
|4149|4149| 
|4150|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |4150|+	this.UnitFsm.ProcessMessage(this, { "type": "ConstructionFinished", "data": msg});
|4151|4151| };
|4152|4152| 
|4153|4153| UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4147|4147| 	// TODO: This is a bit inefficient since every unit listens to every
|4148|4148| 	// construction message - ideally we could scope it to only the one we're building
|4149|4149| 
|4150|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |4150|+	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg });
|4151|4151| };
|4152|4152| 
|4153|4153| UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4178|4178| 	if (msg.fromStatusEffect)
|4179|4179| 		return;
|4180|4180| 
|4181|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |4181|+	this.UnitFsm.ProcessMessage(this, { "type": "Attacked", "data": msg});
|4182|4182| };
|4183|4183| 
|4184|4184| UnitAI.prototype.OnGuardedAttacked = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4178|4178| 	if (msg.fromStatusEffect)
|4179|4179| 		return;
|4180|4180| 
|4181|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |4181|+	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg });
|4182|4182| };
|4183|4183| 
|4184|4184| UnitAI.prototype.OnGuardedAttacked = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4183|4183| 
|4184|4184| UnitAI.prototype.OnGuardedAttacked = function(msg)
|4185|4185| {
|4186|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |4186|+	this.UnitFsm.ProcessMessage(this, { "type": "GuardedAttacked", "data": msg.data});
|4187|4187| };
|4188|4188| 
|4189|4189| UnitAI.prototype.OnHealthChanged = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4183|4183| 
|4184|4184| UnitAI.prototype.OnGuardedAttacked = function(msg)
|4185|4185| {
|4186|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |4186|+	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data });
|4187|4187| };
|4188|4188| 
|4189|4189| UnitAI.prototype.OnHealthChanged = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4188|4188| 
|4189|4189| UnitAI.prototype.OnHealthChanged = function(msg)
|4190|4190| {
|4191|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |4191|+	this.UnitFsm.ProcessMessage(this, { "type": "HealthChanged", "from": msg.from, "to": msg.to});
|4192|4192| };
|4193|4193| 
|4194|4194| UnitAI.prototype.OnRangeUpdate = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4188|4188| 
|4189|4189| UnitAI.prototype.OnHealthChanged = function(msg)
|4190|4190| {
|4191|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |4191|+	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to });
|4192|4192| };
|4193|4193| 
|4194|4194| UnitAI.prototype.OnRangeUpdate = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4194|4194| UnitAI.prototype.OnRangeUpdate = function(msg)
|4195|4195| {
|4196|4196| 	if (msg.tag == this.losRangeQuery)
|4197|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |4197|+		this.UnitFsm.ProcessMessage(this, { "type": "LosRangeUpdate", "data": msg});
|4198|4198| 	else if (msg.tag == this.losHealRangeQuery)
|4199|4199| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|4200|4200| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4194|4194| UnitAI.prototype.OnRangeUpdate = function(msg)
|4195|4195| {
|4196|4196| 	if (msg.tag == this.losRangeQuery)
|4197|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |4197|+		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg });
|4198|4198| 	else if (msg.tag == this.losHealRangeQuery)
|4199|4199| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|4200|4200| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4196|4196| 	if (msg.tag == this.losRangeQuery)
|4197|4197| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|4198|4198| 	else if (msg.tag == this.losHealRangeQuery)
|4199|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |4199|+		this.UnitFsm.ProcessMessage(this, { "type": "LosHealRangeUpdate", "data": msg});
|4200|4200| };
|4201|4201| 
|4202|4202| UnitAI.prototype.OnPackFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4196|4196| 	if (msg.tag == this.losRangeQuery)
|4197|4197| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|4198|4198| 	else if (msg.tag == this.losHealRangeQuery)
|4199|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |4199|+		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg });
|4200|4200| };
|4201|4201| 
|4202|4202| UnitAI.prototype.OnPackFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4201|4201| 
|4202|4202| UnitAI.prototype.OnPackFinished = function(msg)
|4203|4203| {
|4204|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |4204|+	this.UnitFsm.ProcessMessage(this, { "type": "PackFinished", "packed": msg.packed});
|4205|4205| };
|4206|4206| 
|4207|4207| //// Helper functions to be called by the FSM ////
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4201|4201| 
|4202|4202| UnitAI.prototype.OnPackFinished = function(msg)
|4203|4203| {
|4204|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |4204|+	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed });
|4205|4205| };
|4206|4206| 
|4207|4207| //// Helper functions to be called by the FSM ////
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4204|4204| 	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|4205|4205| };
|4206|4206| 
|4207|    |-//// Helper functions to be called by the FSM ////
|    |4207|+// // Helper functions to be called by the FSM ////
|4208|4208| 
|4209|4209| UnitAI.prototype.GetWalkSpeed = function()
|4210|4210| {
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4916|4916| UnitAI.prototype.AttackEntityInZone = function(ents)
|4917|4917| {
|4918|4918| 	var target = ents.find(target =>
|4919|    |-		this.CanAttack(target)
|4920|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|    |4919|+		this.CanAttack(target) &&
|    |4920|+		this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4921|4921| 		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4922|4922| 	);
|4923|4923| 	if (!target)
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4917|4917| {
|4918|4918| 	var target = ents.find(target =>
|4919|4919| 		this.CanAttack(target)
|4920|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4921|    |-		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|    |4920|+		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) &&
|    |4921|+		(this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4922|4922| 	);
|4923|4923| 	if (!target)
|4924|4924| 		return false;
|    | [NORMAL] ESLintBear (no-multi-spaces):
|    | Multiple spaces found before 'Engine'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4981|4981| 	// If we are guarding/escorting, don't abandon as long as the guarded unit is in target range of the attacker
|4982|4982| 	if (this.isGuardOf)
|4983|4983| 	{
|4984|    |-		var cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |4984|+		var cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|4985|4985| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4986|4986| 		if (cmpUnitAI && cmpAttack &&
|4987|4987| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4985|4985| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4986|4986| 		if (cmpUnitAI && cmpAttack &&
|4987|4987| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|4988|    |-				return false;
|    |4988|+			return false;
|4989|4989| 	}
|4990|4990| 
|4991|4991| 	// Stop if we're in hold-ground mode and it's too far from the holding point
|    | [NORMAL] ESLintBear (no-multi-spaces):
|    | Multiple spaces found before 'Engine'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5023|5023| 	// If we are guarding/escorting, chase at least as long as the guarded unit is in target range of the attacker
|5024|5024| 	if (this.isGuardOf)
|5025|5025| 	{
|5026|    |-		let cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |5026|+		let cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|5027|5027| 		let cmpAttack = Engine.QueryInterface(target, IID_Attack);
|5028|5028| 		if (cmpUnitAI && cmpAttack &&
|5029|5029| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5036|5036| 	return false;
|5037|5037| };
|5038|5038| 
|5039|    |-//// External interface functions ////
|    |5039|+// // External interface functions ////
|5040|5040| 
|5041|5041| UnitAI.prototype.SetFormationController = function(ent)
|5042|5042| {
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5192|5192| 	{
|5193|5193| 		if (this.isGuardOf == target && this.order && this.order.type == "Guard")
|5194|5194| 			return;
|5195|    |-		else
|5196|    |-			this.RemoveGuard();
|    |5195|+		this.RemoveGuard();
|5197|5196| 	}
|5198|5197| 
|5199|5198| 	this.AddOrder("Guard", { "target": target, "force": false }, queued);
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5523|5523| 
|5524|5524| 	if (this.IsFormationController())
|5525|5525| 		this.CallMemberFunction("CancelSetupTradeRoute", [target]);
|5526|    |-}
|    |5526|+};
|5527|5527| /**
|5528|5528|  * Adds trade order to the queue. Either walk to the first market, or
|5529|5529|  * start a new route. Not forced, so it can be interrupted by attacks.
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5544|5544| 	    this.workOrders.length && this.workOrders[0].type == "Trade")
|5545|5545| 	{
|5546|5546| 		let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader);
|5547|    |-		if (cmpTrader.HasBothMarkets() && 
|    |5547|+		if (cmpTrader.HasBothMarkets() &&
|5548|5548| 		   (cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source ||
|5549|5549| 		    cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target))
|5550|5550| 		{
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5825|5825| 				{
|5826|5826| 					var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5827|5827| 					var targetClasses = this.order.data.targetClasses;
|5828|    |-					if (targetClasses.attack && cmpIdentity
|5829|    |-						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5828|+					if (targetClasses.attack && cmpIdentity &&
|    |5829|+						!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5830|5830| 						continue;
|5831|5831| 					if (targetClasses.avoid && cmpIdentity
|5832|5832| 						&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5828|5828| 					if (targetClasses.attack && cmpIdentity
|5829|5829| 						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5830|5830| 						continue;
|5831|    |-					if (targetClasses.avoid && cmpIdentity
|5832|    |-						&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5831|+					if (targetClasses.avoid && cmpIdentity &&
|    |5832|+						MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5833|5833| 						continue;
|5834|5834| 					// Only used by the AIs to prevent some choices of targets
|5835|5835| 					if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ])
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5851|5851| 		{
|5852|5852| 			var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5853|5853| 			var targetClasses = this.order.data.targetClasses;
|5854|    |-			if (cmpIdentity && targetClasses.attack
|5855|    |-				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5854|+			if (cmpIdentity && targetClasses.attack &&
|    |5855|+				!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5856|5856| 				continue;
|5857|5857| 			if (cmpIdentity && targetClasses.avoid
|5858|5858| 				&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5854|5854| 			if (cmpIdentity && targetClasses.attack
|5855|5855| 				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5856|5856| 				continue;
|5857|    |-			if (cmpIdentity && targetClasses.avoid
|5858|    |-				&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5857|+			if (cmpIdentity && targetClasses.avoid &&
|    |5858|+				MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5859|5859| 				continue;
|5860|5860| 			// Only used by the AIs to prevent some choices of targets
|5861|5861| 			if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ])
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5997|5997| 
|5998|5998| UnitAI.prototype.SetHeldPosition = function(x, z)
|5999|5999| {
|6000|    |-	this.heldPosition = {"x": x, "z": z};
|    |6000|+	this.heldPosition = { "x": x, "z": z};
|6001|6001| };
|6002|6002| 
|6003|6003| UnitAI.prototype.SetHeldPositionOnEntity = function(entity)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5997|5997| 
|5998|5998| UnitAI.prototype.SetHeldPosition = function(x, z)
|5999|5999| {
|6000|    |-	this.heldPosition = {"x": x, "z": z};
|    |6000|+	this.heldPosition = {"x": x, "z": z };
|6001|6001| };
|6002|6002| 
|6003|6003| UnitAI.prototype.SetHeldPositionOnEntity = function(entity)
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6024|6024| 	return false;
|6025|6025| };
|6026|6026| 
|6027|    |-//// Helper functions ////
|    |6027|+// // Helper functions ////
|6028|6028| 
|6029|6029| /**
|6030|6030|  * General getter for ranges.
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6043|6043| 		return undefined;
|6044|6044| 
|6045|6045| 	return component.GetRange(type);
|6046|    |-}
|    |6046|+};
|6047|6047| 
|6048|6048| UnitAI.prototype.CanAttack = function(target)
|6049|6049| {
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6241|6241| 	return cmpPack && cmpPack.IsPacking();
|6242|6242| };
|6243|6243| 
|6244|    |-//// Formation specific functions ////
|    |6244|+// // Formation specific functions ////
|6245|6245| 
|6246|6246| UnitAI.prototype.IsAttackingAsFormation = function()
|6247|6247| {
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6246|6246| UnitAI.prototype.IsAttackingAsFormation = function()
|6247|6247| {
|6248|6248| 	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|6249|    |-	return cmpAttack && cmpAttack.CanAttackAsFormation()
|6250|    |-		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|    |6249|+	return cmpAttack && cmpAttack.CanAttackAsFormation() &&
|    |6250|+		this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|6251|6251| };
|6252|6252| 
|6253|6253| //// Animal specific functions ////
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6250|6250| 		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|6251|6251| };
|6252|6252| 
|6253|    |-//// Animal specific functions ////
|    |6253|+// // Animal specific functions ////
|6254|6254| 
|6255|6255| UnitAI.prototype.MoveRandomly = function(distance)
|6256|6256| {

binaries/data/mods/public/simulation/components/UnitAI.js
| 338| »   »   »   return·true;
|    | [NORMAL] ESLintBear (consistent-return):
|    | Method 'Order.WalkToTarget' expected no return value.

binaries/data/mods/public/simulation/components/UnitAI.js
|1253| »   »   »   »   return·false;
|    | [NORMAL] ESLintBear (consistent-return):
|    | Method 'Timer' expected no return value.

binaries/data/mods/public/simulation/components/UnitAI.js
|4007| »   var·isWorkType·=·type·=>·type·==·"Gather"·||·type·==·"Trade"·||·type·==·"Repair"·||·type·==·"ReturnResource";
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'type' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4903| »   var·target·=·ents.find(target·=>·this.CanAttack(target));
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'target' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4918| »   var·target·=·ents.find(target·=>
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'target' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4964| »   var·ent·=·ents.find(ent·=>·this.CanHeal(ent));
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'ent' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4987| »   »   ····cmpAttack.GetAttackTypes().some(type·=>·cmpUnitAI.CheckTargetAttackRange(this.isGuardOf,·type)))
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'type' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2047| »   »   »   »   »   »   &&·this.order.data.target·!=·msg.data.attacker·&&·this.GetBestAttackAgainst(msg.data.attacker,·true)·!=·"Capture")
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|3145| »   »   »   »   »   this.SetAnimationVariant(this.formationAnimationVariant)
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/UnitAI.js
|3954| »   »   var·order·=·{·"type":·type,·"data":·data·};
|    | [NORMAL] JSHintBear:
|    | 'order' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|4038| »   for·(var·i·=·0;·i·<·this.orderQueue.length;·++i)
|    | [NORMAL] JSHintBear:
|    | 'i' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|4920| »   »   &&·this.CheckTargetDistanceFromHeldPosition(target,·IID_Attack,·this.GetBestAttackAgainst(target,·true))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|4921| »   »   &&·(this.GetStance().respondChaseBeyondVision·||·this.CheckTargetIsInVisionRange(target))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5526| }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/UnitAI.js
|5829| »   »   »   »   »   »   &&·!MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.attack))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5832| »   »   »   »   »   »   &&·MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.avoid))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5845| »   var·targets·=·this.GetTargetsFromUnit();
|    | [NORMAL] JSHintBear:
|    | 'targets' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5846| »   for·(var·targ·of·targets)
|    | [NORMAL] JSHintBear:
|    | 'targ' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5852| »   »   »   var·cmpIdentity·=·Engine.QueryInterface(targ,·IID_Identity);
|    | [NORMAL] JSHintBear:
|    | 'cmpIdentity' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5853| »   »   »   var·targetClasses·=·this.order.data.targetClasses;
|    | [NORMAL] JSHintBear:
|    | 'targetClasses' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5855| »   »   »   »   &&·!MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.attack))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5858| »   »   »   »   &&·MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.avoid))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|6046| }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/UnitAI.js
|6250| »   »   &&·this.GetCurrentState()·==·"FORMATIONCONTROLLER.COMBAT.ATTACKING";
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.
Executing section cli...

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2006/display/redirect

Silier requested changes to this revision.Apr 19 2020, 2:26 PM

I can still break it.

This revision now requires changes to proceed.Apr 19 2020, 2:26 PM

ok, blame my shift

One issue, what if member calls finishorder when he gets order by refusing for example or not being able to start the order.
Then formation controller will stuck in Member state forever.

Whenever FinishOrder is called, this.finishedOrder is set to true. So I'm not sure how that would keep the controller in MEMBER?

Freagarach requested review of this revision.May 21 2020, 10:04 AM
wraitii requested changes to this revision.May 22 2020, 10:54 PM
wraitii added a subscriber: wraitii.

This feels like putting a patch on gruyère and hoping it won't leak :P

What Angen means is a scenario like the following:

  1. Make a formation with 4 dudes and 1 doggo.
  2. Order them to gather something
  3. Shift-queue a construction

You'd have

  1. CallMemberFunction
  2. Doggo refuses the order (something calls FinishOrder) immediately, goes to IDLE
  3. Controller enters member, resets Finished Order
  4. Doggo is now stuck in IDLE with a false finishedOrder and the controller will never move on.

Now the funny thing is I can't actually find any case in the current UnitAI where this actually happens. The example above works, because the dog doesn't actually refuse the order, it walks to target instead. Heal is handled correctly too. There might be an edge case somewhere, but for now this would have seemed fine.

I think a better fix is to always call ResetFinishOrder right before calling a regular callmemberfunction. Then you're sure that finisher order will be set to whatever is the output of that.

Then I think (not sure but I think) that you can remove most of the existing ResetFinishOrder calls.

Also I feel like the regular "walk" orders should also have a MEMBER appended after them, so that we wait for units to finish moving, but that could probably be a separate patch.

This revision now requires changes to proceed.May 22 2020, 10:54 PM
wraitii commandeered this revision.May 23 2020, 10:02 AM
wraitii edited reviewers, added: Freagarach; removed: wraitii.
This revision now requires review to proceed.May 23 2020, 10:02 AM
wraitii updated this revision to Diff 11989.May 23 2020, 10:04 AM

(commandeering as Freagarach is busy this WE and I want to work on formations).


Here's a better fix based on what's described above: the point of ResetFinishOrder is to reset before waiting on members to finish an order. The place where this makes the most sense is right before giving that order.
We can then remove all current calls to ResetFinishOrder, which seems to be there because this wasn't done in "MEMBER" entry.
Unlike the change above, this makes us fall into a "Pit of success", where you'd have to go out of your way to write non-working code in the common case.

Successful build - Chance fights ever on the side of the prudent.

Linter detected issues:
Executing section Source...
Executing section JS...
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
| 788| 788| 					this.FinishOrder();
| 789| 789| 					return;
| 790| 790| 				}
| 791|    |-				else
| 792|    |-				{
|    | 791|+				
| 793| 792| 					this.SetNextState("GARRISON.APPROACHING");
| 794| 793| 					return;
| 795|    |-				}
|    | 794|+				
| 796| 795| 			}
| 797| 796| 
| 798| 797| 			this.SetNextState("GARRISON.GARRISONING");
|    | [NORMAL] ESLintBear (key-spacing):
|    | Missing space before value for key 'GARRISON'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|1054|1054| 			},
|1055|1055| 		},
|1056|1056| 
|1057|    |-		"GARRISON":{
|    |1057|+		"GARRISON": {
|1058|1058| 			"APPROACHING": {
|1059|1059| 				"enter": function() {
|1060|1060| 					if (!this.MoveToGarrisonRange(this.order.data.target))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2023|2023| 
|2024|2024| 				"Attacked": function(msg) {
|2025|2025| 					// If we are capturing and are attacked by something that we would not capture, attack that entity instead
|2026|    |-					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force)
|2027|    |-						&& this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|    |2026|+					if (this.order.data.attackType == "Capture" && (this.GetStance().targetAttackersAlways || !this.order.data.force) &&
|    |2027|+						this.order.data.target != msg.data.attacker && this.GetBestAttackAgainst(msg.data.attacker, true) != "Capture")
|2028|2028| 						this.RespondToTargetedEntities([msg.data.attacker]);
|2029|2029| 				},
|2030|2030| 			},
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2182|2182| 					"MovementUpdate": function(msg) {
|2183|2183| 						// If it looks like the path is failing, and we are close enough (3 tiles) from wanted range
|2184|2184| 						// stop anyways. This avoids pathing for an unreachable goal and reduces lag considerably.
|2185|    |-						if (msg.likelyFailure || 
|    |2185|+						if (msg.likelyFailure ||
|2186|2186| 							msg.obstructed && this.RelaxedMaxRangeCheck(this.order.data, this.order.data.max + this.DefaultRelaxedMaxRange) ||
|2187|2187| 							!msg.obstructed && this.CheckRange(this.order.data))
|2188|2188| 							this.FinishOrder();
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2824|2824| 					{
|2825|2825| 						// The building was already finished/fully repaired before we arrived;
|2826|2826| 						// let the ConstructionFinished handler handle this.
|2827|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2827|+						this.OnGlobalConstructionFinished({ "entity": this.repairTarget, "newentity": this.repairTarget});
|2828|2828| 						return true;
|2829|2829| 					}
|2830|2830| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|2824|2824| 					{
|2825|2825| 						// The building was already finished/fully repaired before we arrived;
|2826|2826| 						// let the ConstructionFinished handler handle this.
|2827|    |-						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget});
|    |2827|+						this.OnGlobalConstructionFinished({"entity": this.repairTarget, "newentity": this.repairTarget });
|2828|2828| 						return true;
|2829|2829| 					}
|2830|2830| 
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3122|3122| 				this.StopTimer();
|3123|3123| 				this.ResetAnimation();
|3124|3124| 				if (this.formationAnimationVariant)
|3125|    |-					this.SetAnimationVariant(this.formationAnimationVariant)
|    |3125|+					this.SetAnimationVariant(this.formationAnimationVariant);
|3126|3126| 				else
|3127|3127| 					this.SetDefaultAnimationVariant();
|3128|3128| 				var cmpResistance = Engine.QueryInterface(this.entity, IID_Resistance);
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 2 tabs but found 7.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3348|3348| 		"COMBAT": "INDIVIDUAL.COMBAT", // reuse the same combat behaviour for animals
|3349|3349| 
|3350|3350| 		"WALKING": "INDIVIDUAL.WALKING",	// reuse the same walking behaviour for animals
|3351|    |-							// only used for domestic animals
|    |3351|+		// only used for domestic animals
|3352|3352| 
|3353|3353| 		// Reuse the same garrison behaviour for animals.
|3354|3354| 		"GARRISON": "INDIVIDUAL.GARRISON",
|    | [NORMAL] ESLintBear (no-unneeded-ternary):
|    | Unnecessary use of boolean literals in conditional expression.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3410|3410| 
|3411|3411| UnitAI.prototype.IsAnimal = function()
|3412|3412| {
|3413|    |-	return (this.template.NaturalBehaviour ? true : false);
|    |3413|+	return (!!this.template.NaturalBehaviour);
|3414|3414| };
|3415|3415| 
|3416|3416| UnitAI.prototype.IsDangerousAnimal = function()
|    | [NORMAL] ESLintBear (comma-spacing):
|    | A space is required after ','.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3526|3526| 		{
|3527|3527| 			let index = this.GetCurrentState().indexOf(".");
|3528|3528| 			if (index != -1)
|3529|    |-				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0,index));
|    |3529|+				this.UnitFsm.SwitchToNextState(this, this.GetCurrentState().slice(0, index));
|3530|3530| 			this.Stop(false);
|3531|3531| 		}
|3532|3532| 
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3582|3582| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3583|3583| 			continue;
|3584|3584| 		if (i == 0)
|3585|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3585|+			this.UnitFsm.ProcessMessage(this, { "type": "PickupCanceled", "data": msg});
|3586|3586| 		else
|3587|3587| 			this.orderQueue.splice(i, 1);
|3588|3588| 		Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3582|3582| 		if (this.orderQueue[i].type != "PickupUnit" || this.orderQueue[i].data.target != msg.entity)
|3583|3583| 			continue;
|3584|3584| 		if (i == 0)
|3585|    |-			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg});
|    |3585|+			this.UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg });
|3586|3586| 		else
|3587|3587| 			this.orderQueue.splice(i, 1);
|3588|3588| 		Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3669|3669| };
|3670|3670| 
|3671|3671| 
|3672|    |-//// FSM linkage functions ////
|    |3672|+// // FSM linkage functions ////
|3673|3673| 
|3674|3674| // Setting the next state to the current state will leave/re-enter the top-most substate.
|3675|3675| UnitAI.prototype.SetNextState = function(state)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3840|3840| 				continue;
|3841|3841| 			if (this.orderQueue[i].type == type)
|3842|3842| 				continue;
|3843|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3843|+			this.orderQueue.splice(i, 0, { "type": type, "data": data});
|3844|3844| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3845|3845| 			return;
|3846|3846| 		}
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|3840|3840| 				continue;
|3841|3841| 			if (this.orderQueue[i].type == type)
|3842|3842| 				continue;
|3843|    |-			this.orderQueue.splice(i, 0, {"type": type, "data": data});
|    |3843|+			this.orderQueue.splice(i, 0, {"type": type, "data": data });
|3844|3844| 			Engine.PostMessage(this.entity, MT_UnitAIOrderDataChanged, { "to": this.GetOrderData() });
|3845|3845| 			return;
|3846|3846| 		}
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4082|4082| 	if (data.timerRepeat === undefined)
|4083|4083| 		this.timer = undefined;
|4084|4084| 
|4085|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |4085|+	this.UnitFsm.ProcessMessage(this, { "type": "Timer", "data": data, "lateness": lateness});
|4086|4086| };
|4087|4087| 
|4088|4088| /**
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4082|4082| 	if (data.timerRepeat === undefined)
|4083|4083| 		this.timer = undefined;
|4084|4084| 
|4085|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness});
|    |4085|+	this.UnitFsm.ProcessMessage(this, {"type": "Timer", "data": data, "lateness": lateness });
|4086|4086| };
|4087|4087| 
|4088|4088| /**
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4127|4127| 	// TODO: This is a bit inefficient since every unit listens to every
|4128|4128| 	// construction message - ideally we could scope it to only the one we're building
|4129|4129| 
|4130|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |4130|+	this.UnitFsm.ProcessMessage(this, { "type": "ConstructionFinished", "data": msg});
|4131|4131| };
|4132|4132| 
|4133|4133| UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4127|4127| 	// TODO: This is a bit inefficient since every unit listens to every
|4128|4128| 	// construction message - ideally we could scope it to only the one we're building
|4129|4129| 
|4130|    |-	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg});
|    |4130|+	this.UnitFsm.ProcessMessage(this, {"type": "ConstructionFinished", "data": msg });
|4131|4131| };
|4132|4132| 
|4133|4133| UnitAI.prototype.OnGlobalEntityRenamed = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4158|4158| 	if (msg.fromStatusEffect)
|4159|4159| 		return;
|4160|4160| 
|4161|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |4161|+	this.UnitFsm.ProcessMessage(this, { "type": "Attacked", "data": msg});
|4162|4162| };
|4163|4163| 
|4164|4164| UnitAI.prototype.OnGuardedAttacked = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4158|4158| 	if (msg.fromStatusEffect)
|4159|4159| 		return;
|4160|4160| 
|4161|    |-	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
|    |4161|+	this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg });
|4162|4162| };
|4163|4163| 
|4164|4164| UnitAI.prototype.OnGuardedAttacked = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4163|4163| 
|4164|4164| UnitAI.prototype.OnGuardedAttacked = function(msg)
|4165|4165| {
|4166|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |4166|+	this.UnitFsm.ProcessMessage(this, { "type": "GuardedAttacked", "data": msg.data});
|4167|4167| };
|4168|4168| 
|4169|4169| UnitAI.prototype.OnHealthChanged = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4163|4163| 
|4164|4164| UnitAI.prototype.OnGuardedAttacked = function(msg)
|4165|4165| {
|4166|    |-	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data});
|    |4166|+	this.UnitFsm.ProcessMessage(this, {"type": "GuardedAttacked", "data": msg.data });
|4167|4167| };
|4168|4168| 
|4169|4169| UnitAI.prototype.OnHealthChanged = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4168|4168| 
|4169|4169| UnitAI.prototype.OnHealthChanged = function(msg)
|4170|4170| {
|4171|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |4171|+	this.UnitFsm.ProcessMessage(this, { "type": "HealthChanged", "from": msg.from, "to": msg.to});
|4172|4172| };
|4173|4173| 
|4174|4174| UnitAI.prototype.OnRangeUpdate = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4168|4168| 
|4169|4169| UnitAI.prototype.OnHealthChanged = function(msg)
|4170|4170| {
|4171|    |-	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to});
|    |4171|+	this.UnitFsm.ProcessMessage(this, {"type": "HealthChanged", "from": msg.from, "to": msg.to });
|4172|4172| };
|4173|4173| 
|4174|4174| UnitAI.prototype.OnRangeUpdate = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4174|4174| UnitAI.prototype.OnRangeUpdate = function(msg)
|4175|4175| {
|4176|4176| 	if (msg.tag == this.losRangeQuery)
|4177|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |4177|+		this.UnitFsm.ProcessMessage(this, { "type": "LosRangeUpdate", "data": msg});
|4178|4178| 	else if (msg.tag == this.losHealRangeQuery)
|4179|4179| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|4180|4180| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4174|4174| UnitAI.prototype.OnRangeUpdate = function(msg)
|4175|4175| {
|4176|4176| 	if (msg.tag == this.losRangeQuery)
|4177|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|    |4177|+		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg });
|4178|4178| 	else if (msg.tag == this.losHealRangeQuery)
|4179|4179| 		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|4180|4180| };
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4176|4176| 	if (msg.tag == this.losRangeQuery)
|4177|4177| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|4178|4178| 	else if (msg.tag == this.losHealRangeQuery)
|4179|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |4179|+		this.UnitFsm.ProcessMessage(this, { "type": "LosHealRangeUpdate", "data": msg});
|4180|4180| };
|4181|4181| 
|4182|4182| UnitAI.prototype.OnPackFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4176|4176| 	if (msg.tag == this.losRangeQuery)
|4177|4177| 		this.UnitFsm.ProcessMessage(this, {"type": "LosRangeUpdate", "data": msg});
|4178|4178| 	else if (msg.tag == this.losHealRangeQuery)
|4179|    |-		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg});
|    |4179|+		this.UnitFsm.ProcessMessage(this, {"type": "LosHealRangeUpdate", "data": msg });
|4180|4180| };
|4181|4181| 
|4182|4182| UnitAI.prototype.OnPackFinished = function(msg)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4181|4181| 
|4182|4182| UnitAI.prototype.OnPackFinished = function(msg)
|4183|4183| {
|4184|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |4184|+	this.UnitFsm.ProcessMessage(this, { "type": "PackFinished", "packed": msg.packed});
|4185|4185| };
|4186|4186| 
|4187|4187| //// Helper functions to be called by the FSM ////
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4181|4181| 
|4182|4182| UnitAI.prototype.OnPackFinished = function(msg)
|4183|4183| {
|4184|    |-	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|    |4184|+	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed });
|4185|4185| };
|4186|4186| 
|4187|4187| //// Helper functions to be called by the FSM ////
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4184|4184| 	this.UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
|4185|4185| };
|4186|4186| 
|4187|    |-//// Helper functions to be called by the FSM ////
|    |4187|+// // Helper functions to be called by the FSM ////
|4188|4188| 
|4189|4189| UnitAI.prototype.GetWalkSpeed = function()
|4190|4190| {
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4896|4896| UnitAI.prototype.AttackEntityInZone = function(ents)
|4897|4897| {
|4898|4898| 	var target = ents.find(target =>
|4899|    |-		this.CanAttack(target)
|4900|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|    |4899|+		this.CanAttack(target) &&
|    |4900|+		this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4901|4901| 		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4902|4902| 	);
|4903|4903| 	if (!target)
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4897|4897| {
|4898|4898| 	var target = ents.find(target =>
|4899|4899| 		this.CanAttack(target)
|4900|    |-		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true))
|4901|    |-		&& (this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|    |4900|+		&& this.CheckTargetDistanceFromHeldPosition(target, IID_Attack, this.GetBestAttackAgainst(target, true)) &&
|    |4901|+		(this.GetStance().respondChaseBeyondVision || this.CheckTargetIsInVisionRange(target))
|4902|4902| 	);
|4903|4903| 	if (!target)
|4904|4904| 		return false;
|    | [NORMAL] ESLintBear (no-multi-spaces):
|    | Multiple spaces found before 'Engine'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4963|4963| 	// If we are guarding/escorting, don't abandon as long as the guarded unit is in target range of the attacker
|4964|4964| 	if (this.isGuardOf)
|4965|4965| 	{
|4966|    |-		var cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |4966|+		var cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|4967|4967| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4968|4968| 		if (cmpUnitAI && cmpAttack &&
|4969|4969| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|    | [NORMAL] ESLintBear (indent):
|    | Expected indentation of 3 tabs but found 4.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|4967|4967| 		var cmpAttack = Engine.QueryInterface(target, IID_Attack);
|4968|4968| 		if (cmpUnitAI && cmpAttack &&
|4969|4969| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|4970|    |-				return false;
|    |4970|+			return false;
|4971|4971| 	}
|4972|4972| 
|4973|4973| 	// Stop if we're in hold-ground mode and it's too far from the holding point
|    | [NORMAL] ESLintBear (no-multi-spaces):
|    | Multiple spaces found before 'Engine'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5005|5005| 	// If we are guarding/escorting, chase at least as long as the guarded unit is in target range of the attacker
|5006|5006| 	if (this.isGuardOf)
|5007|5007| 	{
|5008|    |-		let cmpUnitAI =  Engine.QueryInterface(target, IID_UnitAI);
|    |5008|+		let cmpUnitAI = Engine.QueryInterface(target, IID_UnitAI);
|5009|5009| 		let cmpAttack = Engine.QueryInterface(target, IID_Attack);
|5010|5010| 		if (cmpUnitAI && cmpAttack &&
|5011|5011| 		    cmpAttack.GetAttackTypes().some(type => cmpUnitAI.CheckTargetAttackRange(this.isGuardOf, type)))
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5018|5018| 	return false;
|5019|5019| };
|5020|5020| 
|5021|    |-//// External interface functions ////
|    |5021|+// // External interface functions ////
|5022|5022| 
|5023|5023| UnitAI.prototype.SetFormationController = function(ent)
|5024|5024| {
|    | [NORMAL] ESLintBear (no-else-return):
|    | Unnecessary 'else' after 'return'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5174|5174| 	{
|5175|5175| 		if (this.isGuardOf == target && this.order && this.order.type == "Guard")
|5176|5176| 			return;
|5177|    |-		else
|5178|    |-			this.RemoveGuard();
|    |5177|+		this.RemoveGuard();
|5179|5178| 	}
|5180|5179| 
|5181|5180| 	this.AddOrder("Guard", { "target": target, "force": false }, queued);
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5505|5505| 
|5506|5506| 	if (this.IsFormationController())
|5507|5507| 		this.CallMemberFunction("CancelSetupTradeRoute", [target]);
|5508|    |-}
|    |5508|+};
|5509|5509| /**
|5510|5510|  * Adds trade order to the queue. Either walk to the first market, or
|5511|5511|  * start a new route. Not forced, so it can be interrupted by attacks.
|    | [NORMAL] ESLintBear (no-trailing-spaces):
|    | Trailing spaces not allowed.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5526|5526| 	    this.workOrders.length && this.workOrders[0].type == "Trade")
|5527|5527| 	{
|5528|5528| 		let cmpTrader = Engine.QueryInterface(this.entity, IID_Trader);
|5529|    |-		if (cmpTrader.HasBothMarkets() && 
|    |5529|+		if (cmpTrader.HasBothMarkets() &&
|5530|5530| 		   (cmpTrader.GetFirstMarket() == target && cmpTrader.GetSecondMarket() == source ||
|5531|5531| 		    cmpTrader.GetFirstMarket() == source && cmpTrader.GetSecondMarket() == target))
|5532|5532| 		{
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5807|5807| 				{
|5808|5808| 					var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5809|5809| 					var targetClasses = this.order.data.targetClasses;
|5810|    |-					if (targetClasses.attack && cmpIdentity
|5811|    |-						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5810|+					if (targetClasses.attack && cmpIdentity &&
|    |5811|+						!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5812|5812| 						continue;
|5813|5813| 					if (targetClasses.avoid && cmpIdentity
|5814|5814| 						&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5810|5810| 					if (targetClasses.attack && cmpIdentity
|5811|5811| 						&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5812|5812| 						continue;
|5813|    |-					if (targetClasses.avoid && cmpIdentity
|5814|    |-						&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5813|+					if (targetClasses.avoid && cmpIdentity &&
|    |5814|+						MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5815|5815| 						continue;
|5816|5816| 					// Only used by the AIs to prevent some choices of targets
|5817|5817| 					if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ])
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5833|5833| 		{
|5834|5834| 			var cmpIdentity = Engine.QueryInterface(targ, IID_Identity);
|5835|5835| 			var targetClasses = this.order.data.targetClasses;
|5836|    |-			if (cmpIdentity && targetClasses.attack
|5837|    |-				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|    |5836|+			if (cmpIdentity && targetClasses.attack &&
|    |5837|+				!MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5838|5838| 				continue;
|5839|5839| 			if (cmpIdentity && targetClasses.avoid
|5840|5840| 				&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5836|5836| 			if (cmpIdentity && targetClasses.attack
|5837|5837| 				&& !MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.attack))
|5838|5838| 				continue;
|5839|    |-			if (cmpIdentity && targetClasses.avoid
|5840|    |-				&& MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|    |5839|+			if (cmpIdentity && targetClasses.avoid &&
|    |5840|+				MatchesClassList(cmpIdentity.GetClassesList(), targetClasses.avoid))
|5841|5841| 				continue;
|5842|5842| 			// Only used by the AIs to prevent some choices of targets
|5843|5843| 			if (targetClasses.vetoEntities && targetClasses.vetoEntities[targ])
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required after '{'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5996|5996| 
|5997|5997| UnitAI.prototype.SetHeldPosition = function(x, z)
|5998|5998| {
|5999|    |-	this.heldPosition = {"x": x, "z": z};
|    |5999|+	this.heldPosition = { "x": x, "z": z};
|6000|6000| };
|6001|6001| 
|6002|6002| UnitAI.prototype.SetHeldPositionOnEntity = function(entity)
|    | [NORMAL] ESLintBear (object-curly-spacing):
|    | A space is required before '}'.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|5996|5996| 
|5997|5997| UnitAI.prototype.SetHeldPosition = function(x, z)
|5998|5998| {
|5999|    |-	this.heldPosition = {"x": x, "z": z};
|    |5999|+	this.heldPosition = {"x": x, "z": z };
|6000|6000| };
|6001|6001| 
|6002|6002| UnitAI.prototype.SetHeldPositionOnEntity = function(entity)
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6023|6023| 	return false;
|6024|6024| };
|6025|6025| 
|6026|    |-//// Helper functions ////
|    |6026|+// // Helper functions ////
|6027|6027| 
|6028|6028| /**
|6029|6029|  * General getter for ranges.
|    | [NORMAL] ESLintBear (semi):
|    | Missing semicolon.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6042|6042| 		return undefined;
|6043|6043| 
|6044|6044| 	return component.GetRange(type);
|6045|    |-}
|    |6045|+};
|6046|6046| 
|6047|6047| UnitAI.prototype.CanAttack = function(target)
|6048|6048| {
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6210|6210| 	return cmpPack && cmpPack.IsPacking();
|6211|6211| };
|6212|6212| 
|6213|    |-//// Formation specific functions ////
|    |6213|+// // Formation specific functions ////
|6214|6214| 
|6215|6215| UnitAI.prototype.IsAttackingAsFormation = function()
|6216|6216| {
|    | [NORMAL] ESLintBear (operator-linebreak):
|    | '&&' should be placed at the end of the line.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6215|6215| UnitAI.prototype.IsAttackingAsFormation = function()
|6216|6216| {
|6217|6217| 	var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
|6218|    |-	return cmpAttack && cmpAttack.CanAttackAsFormation()
|6219|    |-		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|    |6218|+	return cmpAttack && cmpAttack.CanAttackAsFormation() &&
|    |6219|+		this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|6220|6220| };
|6221|6221| 
|6222|6222| //// Animal specific functions ////
|    | [NORMAL] ESLintBear (spaced-comment):
|    | Expected space or tab after '//' in comment.
|----|    | /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|    |++++| /zpool0/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
|6219|6219| 		&& this.GetCurrentState() == "FORMATIONCONTROLLER.COMBAT.ATTACKING";
|6220|6220| };
|6221|6221| 
|6222|    |-//// Animal specific functions ////
|    |6222|+// // Animal specific functions ////
|6223|6223| 
|6224|6224| UnitAI.prototype.MoveRandomly = function(distance)
|6225|6225| {

binaries/data/mods/public/simulation/components/UnitAI.js
| 338| »   »   »   return·true;
|    | [NORMAL] ESLintBear (consistent-return):
|    | Method 'Order.WalkToTarget' expected no return value.

binaries/data/mods/public/simulation/components/UnitAI.js
|1241| »   »   »   »   return·false;
|    | [NORMAL] ESLintBear (consistent-return):
|    | Method 'Timer' expected no return value.

binaries/data/mods/public/simulation/components/UnitAI.js
|3987| »   var·isWorkType·=·type·=>·type·==·"Gather"·||·type·==·"Trade"·||·type·==·"Repair"·||·type·==·"ReturnResource";
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'type' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4883| »   var·target·=·ents.find(target·=>·this.CanAttack(target));
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'target' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4898| »   var·target·=·ents.find(target·=>
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'target' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4946| »   var·ent·=·ents.find(ent·=>·this.CanHeal(ent));
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'ent' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|4969| »   »   ····cmpAttack.GetAttackTypes().some(type·=>·cmpUnitAI.CheckTargetAttackRange(this.isGuardOf,·type)))
|    | [NORMAL] ESLintBear (no-shadow):
|    | 'type' is already declared in the upper scope.

binaries/data/mods/public/simulation/components/UnitAI.js
|2027| »   »   »   »   »   »   &&·this.order.data.target·!=·msg.data.attacker·&&·this.GetBestAttackAgainst(msg.data.attacker,·true)·!=·"Capture")
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|3125| »   »   »   »   »   this.SetAnimationVariant(this.formationAnimationVariant)
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/UnitAI.js
|3934| »   »   var·order·=·{·"type":·type,·"data":·data·};
|    | [NORMAL] JSHintBear:
|    | 'order' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|4018| »   for·(var·i·=·0;·i·<·this.orderQueue.length;·++i)
|    | [NORMAL] JSHintBear:
|    | 'i' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|4900| »   »   &&·this.CheckTargetDistanceFromHeldPosition(target,·IID_Attack,·this.GetBestAttackAgainst(target,·true))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|4901| »   »   &&·(this.GetStance().respondChaseBeyondVision·||·this.CheckTargetIsInVisionRange(target))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5508| }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/UnitAI.js
|5811| »   »   »   »   »   »   &&·!MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.attack))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5814| »   »   »   »   »   »   &&·MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.avoid))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5827| »   var·targets·=·this.GetTargetsFromUnit();
|    | [NORMAL] JSHintBear:
|    | 'targets' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5828| »   for·(var·targ·of·targets)
|    | [NORMAL] JSHintBear:
|    | 'targ' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5834| »   »   »   var·cmpIdentity·=·Engine.QueryInterface(targ,·IID_Identity);
|    | [NORMAL] JSHintBear:
|    | 'cmpIdentity' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5835| »   »   »   var·targetClasses·=·this.order.data.targetClasses;
|    | [NORMAL] JSHintBear:
|    | 'targetClasses' is already defined.

binaries/data/mods/public/simulation/components/UnitAI.js
|5837| »   »   »   »   &&·!MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.attack))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|5840| »   »   »   »   &&·MatchesClassList(cmpIdentity.GetClassesList(),·targetClasses.avoid))
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.

binaries/data/mods/public/simulation/components/UnitAI.js
|6045| }
|    | [NORMAL] JSHintBear:
|    | Missing semicolon.

binaries/data/mods/public/simulation/components/UnitAI.js
|6219| »   »   &&·this.GetCurrentState()·==·"FORMATIONCONTROLLER.COMBAT.ATTACKING";
|    | [NORMAL] JSHintBear:
|    | Misleading line break before '&&'; readers may interpret this as an expression boundary.
Executing section cli...

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2211/display/redirect

wraitii updated this revision to Diff 11994.May 23 2020, 11:22 AM

Eh, you know what, let's actually do something nice.

There is this "InPosition" logic in cmpFormation, which is very redundant with the finishedOrder logic, but used for walking. It seems to have been a kinda hacky fix by Deiz back in 2012.
But it actually works better than the "finishedOrder" logic because we can then use it to get a share of units that are waiting.

This doesn't actually change any logic beyond the "reset" bug fix from earlier.

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2214/display/redirect

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/vs2015-differential/1686/display/redirect

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/macos-differential/804/display/redirect

Stan added a subscriber: Stan.May 30 2020, 12:36 PM

@Angen @Freagarach can you look again?

How much different is this from resetting finished orders in CallMemberFunction and setting finished order in FinishedOrder? (Apart from the (un)set in position.)
Reason for asking is the shift of responsibility from the entity to the formation(controller).

But it actually works better than the "finishedOrder" logic because we can then use it to get a share of units that are waiting.

Any use case for that?

Also, does this handle entity renaming (promotion)? (And this needs a rebase.)

binaries/data/mods/public/simulation/components/Formation.js
279

-

502

+.

512

Singular/Plural. +.

binaries/data/mods/public/simulation/components/UnitAI.js
6296

Spaces besided =.

How much different is this from resetting finished orders in CallMemberFunction and setting finished order in FinishedOrder? (Apart from the (un)set in position.)
Reason for asking is the shift of responsibility from the entity to the formation(controller).

It should be 100% similar. The fact that there were two systems seems to be simply a relic of past technical debt. If you compare my two last diffs, you'll see I've simply swapped one for another.
I do think it makes sense to move that logic into the formation component here.

Any use case for that?

I don't have one right now, but you could make it so that it starts moving once 80% of units are 'in formation', or something like that. With movement in practice it doesn't work so well because of the chicken-and-egg problem that the controller must wait for entities, but entities must wait for the controller.

Also, does this handle entity renaming (promotion)?

Good question. At a glance, it doesn't seem like it would (but where does current code handle that, too ?)

wraitii updated this revision to Diff 12117.Jun 3 2020, 7:15 PM

Rebased & don't rebase on top of D2763 but of master.

Vulcan added a comment.Jun 3 2020, 7:17 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/vs2015-differential/1773/display/redirect

Vulcan added a comment.Jun 3 2020, 7:17 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2304/display/redirect

wraitii updated this revision to Diff 12118.Jun 3 2020, 7:26 PM

Handle entity renaming explicitly (couldn't actually break it in my tests, but it seems prudent).

Vulcan added a comment.Jun 3 2020, 7:27 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/vs2015-differential/1774/display/redirect

Vulcan added a comment.Jun 3 2020, 7:28 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2305/display/redirect

Freagarach requested changes to this revision.Jun 4 2020, 5:26 PM

Cleans stuff up nicely, not sure about the location but might be just personal preference (it *is* only used for formations, so that makes sense).

Requesting changes over serialisation.

binaries/data/mods/public/simulation/components/Formation.js
74–75

Mind this please :)

503

Could use the function above?

This revision now requires changes to proceed.Jun 4 2020, 5:26 PM

(By the way, I also tested and could not break it, it also fixes the issue described in the ticket.)

binaries/data/mods/public/simulation/components/Formation.js
944–946

Seems necessary, because the member will be removed and added (removal splices it, addition moves members into formation which resets the waiting array only if rearrange is true). So that could leave members.length longer than waitingOnController.length thus returning false on AreAllMembersWaiting whilst that might be true.

wraitii added inline comments.Jun 4 2020, 6:13 PM
binaries/data/mods/public/simulation/components/Formation.js
944–946

Yes I agree, but I couldn't actually trigger it when testing for some reason. It does feel like it should happen though.

Freagarach added inline comments.Jun 4 2020, 7:15 PM
binaries/data/mods/public/simulation/components/Formation.js
944–946

Perhaps because rearrange is true most of the time?

wraitii updated this revision to Diff 12170.Jun 6 2020, 2:09 PM

Update serialization

binaries/data/mods/public/simulation/components/Formation.js
503

?

Vulcan added a comment.Jun 6 2020, 2:11 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2338/display/redirect

Vulcan added a comment.Jun 6 2020, 2:11 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/vs2015-differential/1807/display/redirect

Freagarach resigned from this revision.Jun 6 2020, 2:25 PM

I can only say I tested this and found no strange things :) (Well, I did look at the code, but @Angen is way more capable of seeing design flaws (with formation stuff).)
(Oh and you can update the summary ^^ )

binaries/data/mods/public/simulation/components/Formation.js
503

ResetWaitingEntities (single source of truth or something like that)

Silier accepted this revision.Jun 6 2020, 5:43 PM

Issue reported in ticket cannot be reproduced with this diff.
Removal of FindInPosition is not problematic.

binaries/data/mods/public/simulation/components/Formation.js
262

UnsetWaiting...

binaries/data/mods/public/simulation/components/UnitAI.js
6290

ResetFinishOrder does not exist

This revision is now accepted and ready to land.Jun 6 2020, 5:43 PM
wraitii updated this revision to Diff 12181.Jun 6 2020, 5:55 PM
wraitii marked an inline comment as done.

Final fixes before merging, fix tests.

Vulcan added a comment.Jun 6 2020, 5:56 PM

Build failure - The Moirai have given mortals hearts that can endure.

Link to build: https://jenkins.wildfiregames.com/job/docker-differential/2346/display/redirect

This revision was landed with ongoing or failed builds.Jun 6 2020, 6:07 PM
This revision was automatically updated to reflect the committed changes.

Thanks to both of you :)