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
User prompt
call updateFogOfWar(); after every building placement
===================================================================
--- original.js
+++ change.js
@@ -192,9 +192,8 @@
'name': 'Light Tank',
'cost': 400,
'energy': 0,
'constructionTime': 8,
- // 5 TEMP DEBUG !!!
'className': 'UnitLightTank',
'buildable': []
},
'unitHeavyTank': {
@@ -231,8 +230,9 @@
self.y = y * tileSize;
self.type = type;
self.isBuilding = true;
self.playerId = playerId;
+ self.id = getNextId();
self.name = name;
var buildableInfo = buildableRepository.getBuildableInfo(type);
self.health = buildableInfo.health;
self.buildable = buildable || []; // New property to store what the building can build
@@ -244,8 +244,9 @@
self.asset.y = self.y;
self.buildingQueue = [];
self.lastAttackTime = 0;
self.lastHitTime = 0;
+ self.defenders = [];
self.damage = function (points) {
console.log("Building " + self.name + " hit! " + points);
self.health -= points;
self.lastHitTime = Date.now();
@@ -530,9 +531,8 @@
self.addChild(building.assetEffect);
}
}
if (cell.fog) {
- // TEMP DEBUG !!! TEMP DEBUG !!! TEMP DEBUG !!! TEMP DEBUG !!!
var fogAsset = cell.fogAsset;
fogAsset.x = screenX - 1;
fogAsset.y = screenY - 1;
if (!fogAsset.parent) {
@@ -863,8 +863,9 @@
var self = Container.call(this);
self.playerId = playerId;
self.type = type;
self.isUnit = true;
+ self.id = getNextId();
var unitInfo = unitRepository.getUnitInfo(type);
self.name = unitInfo.name;
self.health = unitInfo.health; // Range for attacking
self.isDestroyed = false;
@@ -875,8 +876,9 @@
self.attackSpeed = unitInfo.attackSpeed; // Speed of attack (time between attacks)
self.attackMode = 0; // 0 = not attacking, 1 = attacking, 2 = moving to target
self.lastAttackTime = 0;
self.lastHitTime = 0;
+ self.defenders = [];
self.actions = unitInfo.actions;
self.asset = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5,
@@ -885,10 +887,10 @@
self.speed = 200; // Set the unit speed
self.cellX = cellX;
self.cellY = cellY;
var screenCoord = worldCellToScreenCoord(cellX, cellY);
- self.x = screenCoord.x; // cellX * tileSize + tileSize / 2;
- self.y = screenCoord.y; //cellY * tileSize + tileSize / 2;
+ self.x = screenCoord.x;
+ self.y = screenCoord.y;
self.cellW = 1;
self.cellH = 1;
console.log("clear onArrivedCallback 0");
self.onArrivedCallback = null;
@@ -1162,10 +1164,10 @@
var deltaX = 0;
var deltaY = 0;
if (alternate) {
//console.log("search alternate spot...");
- deltaX = -1 + Math.random() * 2;
- deltaY = -1 + Math.random() * 2;
+ deltaX = -2 + Math.random() * 4;
+ deltaY = -2 + Math.random() * 4;
}
var closestSpiceSpot = findClosestSpiceSpot(self.cellX + deltaX, self.cellY + deltaY);
if (closestSpiceSpot) {
//console.log("closestSpiceSpot :", closestSpiceSpot);
@@ -1175,13 +1177,24 @@
}, {
x: closestSpiceSpot.x,
y: closestSpiceSpot.y
});
+ if (!path || path.length == 0) {
+ console.warn("No path to spot! retry later");
+ LK.setTimeout(function () {
+ self.startHarvesting(true);
+ }, 1000);
+ return;
+ }
self.moveAlongPath(path); //self.setHarvesting
//console.log("Ok at site setHarvesting...");
self.harvestingMode = 1;
} else {
- //console.log("No spice found!");
+ console.warn("No spice found! retry later");
+ // Try again later
+ LK.setTimeout(function () {
+ self.startHarvesting(true);
+ }, 1000);
}
};
self.startUnloading = function () {
self.harvestingMode = 3;
@@ -1200,29 +1213,12 @@
self.harvestedSpiceOnCellCounter += self.harvestSpeed;
if (self.harvestedSpiceOnCellCounter >= 200) {
self.asset.tint = getPlayerTint(self.playerId);
gameMap.clearCellSpice(self.cellX, self.cellY);
+ self.harvestedSpiceOnCellCounter = 0;
if (self.harvestedSpiceOnTripCounter >= self.harvestedSpiceCapacity) {
self.harvestingMode = 2; // Returning
- self.harvestedSpiceOnCellCounter = 0;
- var closestRefinery = findClosestRefinery(self);
- if (closestRefinery) {
- var path = gameMap.findPath({
- x: self.cellX,
- y: self.cellY
- }, {
- x: closestRefinery.cellX,
- y: closestRefinery.cellY
- }, 0, closestRefinery);
- if (path.length > 0) {
- //console.log("Returning to Refiniery...");
- self.moveAlongPath(path, self.startUnloading);
- } else {
- console.warn("No path to Refinery !");
- }
- }
} else {
- self.harvestedSpiceOnCellCounter = 0;
self.startHarvesting();
}
} else {
// Make the unit blink in orange more smoothly
@@ -1230,9 +1226,34 @@
self.asset.tint = blinkPhase < 0.5 ? 0xFFA500 : getPlayerTint(self.playerId);
self.asset.rotation += 45 / 400 * (Math.PI / 180);
}
}
+ if (self.harvestingMode == 2) {
+ // Returning
+ var closestRefinery = findClosestRefinery(self);
+ if (closestRefinery) {
+ var path = gameMap.findPath({
+ x: self.cellX,
+ y: self.cellY
+ }, {
+ x: closestRefinery.cellX,
+ y: closestRefinery.cellY
+ }, 0, closestRefinery);
+ if (path.length > 0) {
+ //console.log("Returning to Refiniery...");
+ self.moveAlongPath(path, self.startUnloading);
+ } else {
+ console.warn("No path to Refinery !");
+ // Wait for the refinery to be ready
+ self.harvestingMode = 0; // Idle
+ LK.setTimeout(function () {
+ self.harvestingMode = 2;
+ }, 2000);
+ }
+ }
+ }
if (self.harvestingMode == 3) {
+ // Unloading
self.harvestedSpiceOnTripCounter -= self.unloadSpeed;
// Add the unloaded spice to the player's spice counter
if (self.playerId === player1.playerId) {
player1.spice += self.unloadSpeed;
@@ -1356,12 +1377,12 @@
function findClosestRefinery(unit) {
var closestRefinery = null;
var minDistance = Number.MAX_VALUE;
var playerBuildings = unit.playerId === player1.playerId ? player1.buildings : player2.buildings;
- console.log("Player has " + playerBuildings.length + " buildings");
+ //console.log("Player has " + playerBuildings.length + " buildings");
playerBuildings.forEach(function (building) {
if (building instanceof SpiceRefinery) {
- console.log("Found Refinery at " + building.cellX + "," + building.cellY);
+ //console.log("Found Refinery at " + building.cellX + "," + building.cellY);
var dx = unit.cellX - building.cellX;
var dy = unit.cellY - building.cellY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < minDistance) {
@@ -1369,9 +1390,9 @@
minDistance = distance;
}
}
});
- console.log("OK result ", closestRefinery);
+ //console.log("OK result ", closestRefinery);
return closestRefinery ? {
cellX: closestRefinery.cellX,
cellY: closestRefinery.cellY
} : null;
@@ -1620,9 +1641,9 @@
x: destinationX,
y: destinationY
});
}
- if (path.length > 0) {
+ if (path && path.length > 0) {
console.log("Valid harvesting, path:", path);
targetUnit.moveAlongPath(path, targetUnit.startHarvesting);
} else {
console.log("No path, direct harvesting ");
@@ -1840,8 +1861,22 @@
var getPlayerTint = function getPlayerTint(id) {
//console.log("getPlayerTint", id);
return player1.playerId === id ? player1.tint : player2.tint;
};
+var getNextId = function getNextId() {
+ return nextId++;
+};
+var getAllUnitsPerDistance = function getAllUnitsPerDistance(position, unitList) {
+ var distanceList = {};
+ unitList.forEach(function (unit) {
+ distanceList[unit.id] = Math.sqrt(Math.pow(position.x - unit.x, 2) + Math.pow(position.y - unit.y, 2));
+ });
+ // Order by distance
+ var orderedDistanceList = Object.keys(distanceList).sort(function (a, b) {
+ return distanceList[a] - distanceList[b];
+ });
+ return orderedDistanceList;
+};
/* ******************************************** GLOBAL GAME VARIABLES ******************************************** */
/* ******************************************** GLOBAL GAME VARIABLES ******************************************** */
/* ******************************************** GLOBAL GAME VARIABLES ******************************************** */
var gameIsRunning = false;
@@ -1858,8 +1893,9 @@
cellW: Math.floor(game.width / tileSize) + 1,
// ~20
cellH: Math.floor(mapHeight / tileSize) + 1 // ~21
};
+var nextId = 1;
// Init view port
viewPort.wCellX = Math.max(0, Math.min(mapXSize - viewPort.cellW, viewPort.wCellX));
viewPort.wCellY = Math.max(0, Math.min(mapYSize - viewPort.cellH, viewPort.wCellY));
viewPort.wX = viewPort.wCellX * tileSize;
@@ -1908,10 +1944,10 @@
/* ********************************************* AI FUNCTIONS ****************************************** */
/* ***************************************************************************************************** */
var AI_LEVEL = {
EASY: {
- acttingDelay: 1000,
- thinkingDelay: 1000
+ acttingDelay: 500,
+ thinkingDelay: 500
},
NORMAL: {
acttingDelay: 300,
thinkingDelay: 600
@@ -1937,8 +1973,9 @@
var aiCurrentUnitConstruction = null;
var aiCurrentBuildingConstruction = null;
var aiNeededBuildingList = null;
var aiNeededUnitsList = null;
+var aiBuildingsUnderAttackList = null;
// Think of what AI must do
function aiThinking() {
if (LK.ticks % aiCurrentLevel.thinkingDelay !== 0) {
return;
@@ -1947,9 +1984,11 @@
// Check buildings requirements
aiNeededBuildingList = checkBuildingRequirements();
// Check units requirements
aiNeededUnitsList = checkUnitRequirements();
- // Check defense needs
+ // Check buildings defense needs
+ aiBuildingsUnderAttackList = checkBuildingUnderAttack();
+ // Check units defense needs
// Check attack opportunities
}
function checkBuildingRequirements() {
console.log("checkBuildingRequirements...");
@@ -1974,8 +2013,20 @@
}
}
return tempNeededBuildingList;
}
+function checkBuildingUnderAttack() {
+ console.log("checkBuildingUnderAttack...");
+ // Check delay since lastHitTime of all AI buildings
+ var tempUnderAttackBuildingArray = [];
+ player2.buildings.forEach(function (building) {
+ if (Date.now() - building.lastHitTime < 10000) {
+ // Building is under attack
+ tempUnderAttackBuildingArray.push(building);
+ }
+ });
+ return tempUnderAttackBuildingArray;
+}
function checkUnitRequirements() {
console.log("checkUnitRequirements...");
console.log("player2 units:", player2.units);
// 1) Count currently owned units
@@ -2007,9 +2058,9 @@
console.log("aiActing...");
// 1) Meet buildings requirements
console.log("aiNeededBuildingList:", aiNeededBuildingList);
if (Object.keys(aiNeededBuildingList).length > 0 && !player2.isCurrentlyBuilding) {
- aiHandleBuilding(Object.keys(aiNeededBuildingList)[0]);
+ aiHandleBuildingConstruction(Object.keys(aiNeededBuildingList)[0]);
}
// 2) Meet units requirements
console.log("aiNeededUnitsList:", aiNeededUnitsList);
if (Object.keys(aiNeededUnitsList).length > 0 && !player2.isCurrentlyBuildingUnit) {
@@ -2020,11 +2071,18 @@
} else {
console.warn("2 - No factory found for unit " + tempUnitToBuild);
}
}
+ // 3) Meet building defense needs
+ console.log("aiBuildingsUnderAttackList:", aiBuildingsUnderAttackList);
+ if (aiBuildingsUnderAttackList.length > 0) {
+ aiBuildingsUnderAttackList.forEach(function (building) {
+ aiHandleBuildingUnderAttack(building);
+ });
+ }
}
-function aiHandleBuilding(buildingToBuild) {
- console.log("aiHandleBuilding...", buildingToBuild);
+function aiHandleBuildingConstruction(buildingToBuild) {
+ console.log("aiHandleBuildingConstruction...", buildingToBuild);
if (player2.isCurrentlyBuilding) {
console.log("Already building building...");
return;
}
@@ -2049,8 +2107,19 @@
var placeX = freePosition.cellX;
var placeY = freePosition.cellY;
handleBuildingPlacement(buildable, placeX, placeY);
}
+function aiHandleBuildingUnderAttack(buildingToDefend) {
+ console.log("aiHandleBuildingUnderAttack...", buildingToDefend);
+ // Check if already have defenders
+ if (buildingToDefend.defenders.length > 1) {
+ console.log("already have defenders...", buildingToDefend.defenders);
+ return;
+ }
+ // List all units per distance to building
+ var potentialDefenders = getAllUnitsPerDistance(buildingToDefend, player2.units);
+ console.warn("potentialDefenders:", potentialDefenders);
+}
function aiHandleUnitConstruction(unitToBuild, sourceFactory) {
console.log("aiHandleUnitConstruction...", unitToBuild, sourceFactory);
if (player2.isCurrentlyBuildingUnit) {
console.log("Already building unit...");
@@ -2071,10 +2140,9 @@
gameMap.init(mapXSize, mapYSize); // Initialize with a 20x20 grid
// Define a fixed rock ilot near the center left of the map
rockIlot1Center = {
x: 8,
- //Math.floor(mapXSize * 0.15), // TEMP DEBUG !!!// TEMP DEBUG !!!// TEMP DEBUG !!!
- y: 10 //Math.floor(mapYSize * 0.25)// TEMP DEBUG !!!// TEMP DEBUG !!!// TEMP DEBUG !!!
+ y: 10
};
console.log("rockIlot1Center : ", rockIlot1Center);
var rockIlot1Radius = 4;
for (var x = rockIlot1Center.x - rockIlot1Radius; x <= rockIlot1Center.x + rockIlot1Radius; x++) {
@@ -2100,10 +2168,9 @@
// Player 2 base
// Define a fixed rock ilot near the center right of the map
var rockIlot2Center = {
x: 30,
- //Math.floor(mapXSize * 0.85),// TEMP DEBUG !!!// TEMP DEBUG !!!// TEMP DEBUG !!!
- y: 30 //Math.floor(mapYSize * 0.5)// TEMP DEBUG !!!// TEMP DEBUG !!!// TEMP DEBUG !!!
+ y: 30
};
var rockIlot2Radius = 4;
for (var x = rockIlot2Center.x - rockIlot2Radius; x <= rockIlot2Center.x + rockIlot2Radius; x++) {
for (var y = rockIlot2Center.y - rockIlot2Radius; y <= rockIlot2Center.y + rockIlot2Radius; y++) {
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