Code edit (1 edits merged)
Please save this source code
Code edit (8 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: unit is not defined' in or related to this line: 'switch (unit.type) {' Line Number: 2176
Code edit (1 edits merged)
Please save this source code
Code edit (14 edits merged)
Please save this source code
User prompt
Please fix the bug: 'ReferenceError: rockIlot2Center is not defined' in or related to this line: 'baseBuilding = {' Line Number: 1740
Code edit (1 edits merged)
Please save this source code
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'TypeError: LK.getTime is not a function' in or related to this line: 'self.lastHitTime = LK.getTime();' Line Number: 1099
Code edit (2 edits merged)
Please save this source code
User prompt
could you implement findFactoryForUnit
Code edit (1 edits merged)
Please save this source code
User prompt
add a new function findEmplacementForBuilding(building, cellX, cellY) that scans the map around the given cellX,cellY to find a free area of rocks that fits the given building size
Code edit (5 edits merged)
Please save this source code
User prompt
Please fix the bug: 'Timeout.tick error: buildable.placeBuilding is not a function' in or related to this line: 'buildable.placeBuilding(placeX, placeY);' Line Number: 2117
Code edit (1 edits merged)
Please save this source code
Code edit (6 edits merged)
Please save this source code
User prompt
in handleDragEnd, don't select buildings if they are under fog
User prompt
don't select ennemy units and building if they are under fog
User prompt
in updateFogOfWar remove the fog in a radius shape instead of a square
Code edit (2 edits merged)
Please save this source code
User prompt
in building growExplosion, remove building from player list of buildings
User prompt
in checkGameEnd, check if player1 of player2 have no more buildings game over if so
Code edit (1 edits merged)
Please save this source code
Code edit (1 edits merged)
Please save this source code
===================================================================
--- original.js
+++ change.js
@@ -906,8 +906,9 @@
self.attackMode = 0; // 0 = not attacking, 1 = attacking, 2 = moving to target
self.lastAttackTime = 0;
self.lastHitTime = 0;
self.lastAttaker = null;
+ self.isArmy = false;
self.defenders = [];
self.actions = unitInfo.actions;
self.asset = self.attachAsset(type, {
anchorX: 0.5,
@@ -938,9 +939,11 @@
console.log("Not Navigating don't select unit...", currentUserActionState);
}
});
self.moveAlongPath = function (path, callback) {
- //console.log("moveAlongPath", path, callback);
+ if (self.isArmy) {
+ console.log("Army " + self.type + " #" + self.id + " moveAlongPath", path, callback);
+ }
self.path = path;
self.pathIndex = 0;
self.isMoving = true;
self.onArrivedCallback = callback;
@@ -1576,8 +1579,9 @@
if (playerId === player1.playerId) {
player1.addUnit(unit);
} else if (playerId === player2.playerId) {
if (aiCurrentlyBuildingForArmy) {
+ unit.isArmy = true;
aiCurrentArmyUnits.push(unit);
}
player2.addUnit(unit);
}
@@ -1658,9 +1662,9 @@
y: targetUnit.cellY
}, {
x: destinationX,
y: destinationY
- });
+ }, targetUnit.attackRange);
targetUnit.moveAlongPath(path);
}
}
function attackActionLogic(theUnit, targetCellX, targetCellY) {
@@ -1916,26 +1920,26 @@
};
var getNextId = function getNextId() {
return nextId++;
};
-var getAllUnitsPerDistance = function getAllUnitsPerDistance(position, unitList) {
- var orderedUnitList = [];
+var orderEntitiesPerDistance = function orderEntitiesPerDistance(position, entityList) {
+ var orderedEntityList = [];
// Calculer la distance de chaque unité par rapport à la position donnée
- unitList.forEach(function (unit) {
- var distance = Math.sqrt(Math.pow(position.cellX - unit.cellX, 2) + Math.pow(position.cellY - unit.cellY, 2));
+ entityList.forEach(function (entity) {
+ var distance = Math.sqrt(Math.pow(position.cellX - entity.cellX, 2) + Math.pow(position.cellY - entity.cellY, 2));
// Ajouter l'unité à la liste
- orderedUnitList.push({
- unit: unit,
+ orderedEntityList.push({
+ entity: entity,
distance: distance
});
- console.log("unit", unit.id, " ", unit.type, " Pos:", unit.cellX, unit.cellY, " distance", distance);
+ console.log("entity", entity.id, " ", entity.type, " Pos:", entity.cellX, entity.cellY, " distance", distance);
});
// Trier les unités en fonction de leurs distances
- orderedUnitList.sort(function (a, b) {
+ orderedEntityList.sort(function (a, b) {
return a.distance - b.distance;
});
- console.log("orderedUnitList", orderedUnitList);
- return orderedUnitList;
+ console.log("orderedEntityList", orderedEntityList);
+ return orderedEntityList;
};
/* ******************************************** GLOBAL GAME VARIABLES ******************************************** */
/* ******************************************** GLOBAL GAME VARIABLES ******************************************** */
/* ******************************************** GLOBAL GAME VARIABLES ******************************************** */
@@ -2046,9 +2050,9 @@
var aiNeededAttackUnitsList = null;
var aiLastAttackWaveTime = 0;
var aiNextAttackWaveSize = 0;
var aiCurrentAttackWave = 1;
-var aiNextAttackWaveDelayMs = 1000 * 5; //1000 * 60; // TODO : handle in AiLevel // TEMP DEBUG !!!// TEMP DEBUG !!!// TEMP DEBUG !!!
+var aiNextAttackWaveDelayMs = 1000 * 5; //1000 * 60; // TODO : handle in AiLevel
var aiUnderAttackDelayMs = aiCurrentLevel.thinkingDelay * 10;
// Think of what AI must do
function aiThinking() {
if (LK.ticks % aiCurrentLevel.thinkingDelay !== 0) {
@@ -2103,31 +2107,36 @@
return tempUnderAttackBuildingArray;
}
function checkUnitsUnderAttack() {
console.log("checkUnitsUnderAttack...");
- // Check delay since lastHitTime of all AI units
+ // Check delay since lastHitTime of all AI units except army
var tempUnderAttackUnitsArray = [];
player2.units.forEach(function (unit) {
- if (Date.now() - unit.lastHitTime < aiUnderAttackDelayMs) {
+ if (!unit.isArmy && Date.now() - unit.lastHitTime < aiUnderAttackDelayMs) {
// Unit is under attack
tempUnderAttackUnitsArray.push(unit);
}
});
return tempUnderAttackUnitsArray;
}
function checkAttckWaveUnitNeeds() {
- console.log("checkAttckWaveUnitNeeds...");
+ console.log("checkAttckWaveUnitNeeds...Wave ", aiCurrentAttackWave);
var tempNeededUnitList = {};
var aiBaseUnitListPerWave = getUnitNeedsPerWave(aiCurrentAttackWave);
+ console.log("Wave requires :", aiBaseUnitListPerWave);
// aiThinking : evaluate army needs => list needed units
// Browse aiCurrentArmyUnits and compare with aiBaseUnitListPerWave
var tempNbQuads = 0;
var tempNbLightTanks = 0;
var tempNbHeavyTanks = 0;
+ console.log("check current ", aiCurrentArmyUnits.length, " army units:", aiCurrentArmyUnits);
for (var i = 0; i < aiCurrentArmyUnits.length; i++) {
+ var _aiCurrentArmyUnits$i, _aiCurrentArmyUnits$i2;
+ console.log("check army unit:", (_aiCurrentArmyUnits$i = aiCurrentArmyUnits[i]) === null || _aiCurrentArmyUnits$i === void 0 ? void 0 : _aiCurrentArmyUnits$i.type, " h=", (_aiCurrentArmyUnits$i2 = aiCurrentArmyUnits[i]) === null || _aiCurrentArmyUnits$i2 === void 0 ? void 0 : _aiCurrentArmyUnits$i2.health);
if (!aiCurrentArmyUnits[i] || aiCurrentArmyUnits[i].health <= 0) {
continue;
}
+ console.log("Take ", aiCurrentArmyUnits[i].type, "#", aiCurrentArmyUnits[i].id, " H=", aiCurrentArmyUnits[i].health);
switch (aiCurrentArmyUnits[i].type) {
case "unitQuad":
tempNbQuads++;
break;
@@ -2141,30 +2150,35 @@
console.error("unknown army unit type:", aiCurrentArmyUnits[i].type);
break;
}
}
- Object.keys(aiBaseUnitListPerWave).forEach(function (unitType) {
- switch (unit.type) {
+ console.log("=> We have:", tempNbQuads, tempNbLightTanks, tempNbHeavyTanks, " units");
+ for (var j = 0; j < Object.keys(aiBaseUnitListPerWave).length; j++) {
+ var tempUnitType = Object.keys(aiBaseUnitListPerWave)[j];
+ if (!aiBaseUnitListPerWave[tempUnitType]) {
+ continue;
+ }
+ switch (tempUnitType) {
case "unitQuad":
- if (tempNbQuads < aiBaseUnitListPerWave[unitType]) {
- tempNeededUnitList[unitType] = aiBaseUnitListPerWave[unitType] - tempNbQuads;
+ if (tempNbQuads < aiBaseUnitListPerWave[tempUnitType]) {
+ tempNeededUnitList[tempUnitType] = aiBaseUnitListPerWave[tempUnitType] - tempNbQuads;
}
break;
case "unitLightTank":
- if (tempNbLightTanks < aiBaseUnitListPerWave[unitType]) {
- tempNeededUnitList[unitType] = aiBaseUnitListPerWave[unitType] - tempNbLightTanks;
+ if (tempNbLightTanks < aiBaseUnitListPerWave[tempUnitType]) {
+ tempNeededUnitList[tempUnitType] = aiBaseUnitListPerWave[tempUnitType] - tempNbLightTanks;
}
break;
case "unitHeavyTank":
- if (tempNbHeavyTanks < aiBaseUnitListPerWave[unitType]) {
- tempNeededUnitList[unitType] = aiBaseUnitListPerWave[unitType] - tempNbHeavyTanks;
+ if (tempNbHeavyTanks < aiBaseUnitListPerWave[tempUnitType]) {
+ tempNeededUnitList[tempUnitType] = aiBaseUnitListPerWave[tempUnitType] - tempNbHeavyTanks;
}
break;
default:
- console.error("unknown base unit type:", unit.type);
- break;
+ console.error("unknown base unit type:", tempUnitType);
}
- });
+ }
+ console.log("=> We need:", tempNeededUnitList);
return tempNeededUnitList;
}
function getUnitNeedsPerWave(waveIndex) {
console.log("getUnitNeedsPerWave...", waveIndex);
@@ -2257,14 +2271,41 @@
} else {
console.warn("5 - No factory found for unit " + tempUnitToBuild);
}
} else {
- console.log("Army is ready:", aiCurrentArmyUnits);
- aiArmyIsReady = true;
+ console.log("Clean Army...", aiCurrentArmyUnits);
+ var tempCleanArmy = aiCurrentArmyUnits.filter(function (unit) {
+ // keep only units alive
+ return !unit.isDestroyed;
+ });
+ aiCurrentArmyUnits = tempCleanArmy;
+ if (aiCurrentArmyUnits.length >= aiCurrentAttackWave) {
+ // ATTENTION !!! Arbitray rue : Nb units == Wave index
+ console.log("Army is ready:", aiCurrentArmyUnits);
+ aiArmyIsReady = true;
+ }
}
// 6) Launch attack wave
- if (aiArmyIsReady && Date.now() - aiLastAttackWaveTime < aiNextAttackWaveDelayMs) {
+ if (aiArmyIsReady && Date.now() - aiLastAttackWaveTime > aiNextAttackWaveDelayMs) {
+ aiLastAttackWaveTime = Date.now();
+ aiCurrentAttackWave++;
+ aiNextAttackWaveDelayMs = Math.min(5 * 20 * 1000, aiCurrentAttackWave * 20 * 1000); //Math.min(5*60*1000, aiCurrentAttackWave * 60 * 1000); TEMP DEBUG !!!
console.warn("6 - ATTACK !!! ATTACK !!! ATTACK !!! ATTACK !!! ATTACK !!!");
+ // Find a building to attack
+ var firstAttaker = null;
+ for (var i = 0; i < aiCurrentArmyUnits.length; i++) {
+ if (!aiCurrentArmyUnits[i] || aiCurrentArmyUnits[i].health <= 0) {
+ continue;
+ }
+ firstAttaker = aiCurrentArmyUnits[i];
+ break;
+ }
+ var nextBuildingTarget = aiFindClosestBuildingToAttack(firstAttaker);
+ if (nextBuildingTarget) {
+ aiStartAttack(nextBuildingTarget);
+ } else {
+ console.warn("6 - No building found to attack");
+ }
}
}
function aiHandleBuildingConstruction(buildingToBuild) {
console.log("aiHandleBuildingConstruction...", buildingToBuild);
@@ -2301,12 +2342,12 @@
console.log("already have defenders...", buildingToDefend.defenders);
return;
}
// List all units per distance to building [] = { unit: unit, distance: distance }
- var potentialDefenders = getAllUnitsPerDistance(buildingToDefend, player2.units);
+ var potentialDefenders = orderEntitiesPerDistance(buildingToDefend, player2.units);
// Browse potentialDefenders and add as defenders the ones that can attack & are idle
potentialDefenders.forEach(function (defenderEntry) {
- var defender = defenderEntry.unit;
+ var defender = defenderEntry.entity;
console.log("potential defender ", defender.id, " attackDamage:", defender.attackDamage, " / moving:", defender.isMoving, " / attackMode:", defender.attackMode);
if (buildingToDefend.defenders.length < 2 && defender.attackDamage && !defender.isMoving && defender.attackMode == 0) {
buildingToDefend.defenders.push(defender);
}
@@ -2330,12 +2371,12 @@
console.log("unit already have defenders...", unitToDefend.defenders);
return;
}
// List all units per distance to building [] = { unit: unit, distance: distance }
- var potentialDefenders = getAllUnitsPerDistance(unitToDefend, player2.units);
+ var potentialDefenders = orderEntitiesPerDistance(unitToDefend, player2.units);
// Browse potentialDefenders and add as defenders the ones that can attack & are idle
potentialDefenders.forEach(function (defenderEntry) {
- var defender = defenderEntry.unit;
+ var defender = defenderEntry.entity;
console.log("potential defender ", defender.id, " attackDamage:", defender.attackDamage, " / moving:", defender.isMoving, " / attackMode:", defender.attackMode);
if (unitToDefend.defenders.length < 2 && defender.attackDamage && !defender.isMoving && defender.attackMode == 0) {
unitToDefend.defenders.push(defender);
}
@@ -2360,8 +2401,27 @@
player2.isCurrentlyBuildingUnit = true;
aiCurrentlyBuildingForArmy = !!forArmy; // Flag to add the unit to the army
enqueueBuildable(unitToBuild, sourceFactory, player2);
}
+function aiFindClosestBuildingToAttack(firstAttaker) {
+ // Browse player1.buildings
+ var potientialTargetBuildings = orderEntitiesPerDistance(firstAttaker, player1.buildings);
+ if (potientialTargetBuildings && potientialTargetBuildings.length > 0) {
+ return potientialTargetBuildings[0].entity;
+ }
+ return null;
+}
+function aiStartAttack(target) {
+ var nbUnits = aiCurrentArmyUnits.length;
+ console.log("aiStartAttack... nbUnits=", nbUnits, " target=", target);
+ // Send all army around the target
+ for (var i = 0; i < nbUnits; i++) {
+ // Find a place for each unit by adding a delta depending on index
+ var deltaX = -1 + i % 3;
+ var deltaY = Math.floor(i / 3);
+ moveActionLogic(aiCurrentArmyUnits[i], target.cellX + deltaX, target.cellY + deltaY);
+ }
+}
/* ***************************************************************************************************** */
/* ********************************************* INIT FUNCTIONS ****************************************** */
/* ***************************************************************************************************** */
// Prepare the map
a tileable sand terrain tile.
A square tileable rock terrain tile WITHOUT BBORDER. Single Game Texture. In-Game asset. 2d. No shadows. No Border
Zenith view of Dune's Wind Trap power facility square fence. Ressembles a bit to Sydney's Opera. Zenith view Directly from above.
grey cancel icon. UI
thin white circle empty.
0x5e86ff
Zenith view of a white rectangular Harvester shape of a garbage truck with a triangular head. Harvesting on sand, with flowing spice in the back. inside a square fence. Zenith view. Directly overhead. Plumb view.
Minimal Ui icon of an right sign aside with an icon of a target. sand background
Minimal icon of a home with direction icon pointing to the home. sand background
3 white flat isometric concentric circles like a target.
Remove background
Gray background
Minimal Ui icon of target sign on a fire icon.. sand background
top view of an explosion effect.
Simple heavy army tank factory buiding a tank with a crane. Square fence... Zenith view Directly overhead. Plumb view.
an empty black popup UI. UI