User prompt
Nice! same thing when player attacks monsters
User prompt
when player looses life, show a -x of life lost in read that pops out of player. βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Also add animation when monster attacks player βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Nice, but also show something like, monster/s defeated when all monsters in the screen are defeated
User prompt
Add an animation for player attacking monster and also for monster death, not just closing the battle screen βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Monster or player attack first is random. If monster attacks first, you should have a message that says monsters strikes first, if not, something like you start. βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
Its great! howerver there is a hero image already in the place where the hero will end up being. make sure it only appears when it comes from offscreen βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
battle screen shoudl have some more animattion. First display a message saying, something like you encountered a mosster! Then, hero and monster should not just appear, but maybe slide into the position from offscreen, and then show a message for battle, before the battle starts. βͺπ‘ Consider importing and using the following plugins: @upit/tween.v1
User prompt
color between clear and closed cells is too similar please make it more different keeping dungeon style
User prompt
remove the text of the grid cells of monsters
User prompt
move hp and dmg a little blow monster and player so they don't overlap
User prompt
Remove the text of Monster and Your in the battle screen
User prompt
create an area of the middle 60% of the height of the screen where the battle elelemtnw will appear. Considering that, movethe player to the bottomleft and enemy top right. but not to tight to the corners.
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'y')' in or related to this line: 'self.playerBattleStatText.y = self.playerDisplay.y + self.playerDisplay.height / 2 + 20; // Position below player image' Line Number: 54
User prompt
In the battle screen, move the stast of the player or monster below their images.
User prompt
Better, but not its too far away. Move them closer to the center of the screen, and put the stats below the image of the monster or player
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'x')' in or related to this line: 'self.playerBattleStatText.x = self.playerDisplay.x;' Line Number: 55
User prompt
impove the visuals of the battle screen. player on the bottom left, enemies on the top right, more like a classic turn based battle screen
User prompt
Also show a image of the player on the battle screen
User prompt
lvl and monstears should be next to each other and on the center top fo the screen, also text should be smaller
User prompt
make exp DMG and HP smaller and put it one next to each other in the bottom m of the screen, not one on top of it
User prompt
show more tips like, Enemy Attacked, or Player Attacks
User prompt
on battle screen, enemy will attack first
User prompt
Stil being diplayed, please try something different
User prompt
Still seing exp dmg and hp when battle screen overlay is up, it should not be displayed.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // BattleScreen: Handles the turn-based combat var BattleScreen = Container.expand(function () { var self = Container.call(this); self.visible = false; // Initially hidden self.alpha = 0; // Set alpha to 0 for fade-in animation // Background overlay self.overlay = self.attachAsset('emptyTileCover', { width: 2048, height: 2732, alpha: 0.8 }); // Monster display self.monsterDisplay = self.attachAsset('monsterTileMonster', { anchorX: 0.5, anchorY: 0.5, x: 2048 - 300, // Position near top-right corner within the battle area y: 2732 * 0.2 + 200, // Position near top-right corner within the battle area scaleX: 2, scaleY: 2 }); // Monster stats text self.monsterStatText = new Text2('', { size: 60, fill: "#fff" }); self.monsterStatText.anchor.set(0.5, 0); // Anchor to top-center self.monsterStatText.x = self.monsterDisplay.x; self.monsterStatText.y = self.monsterDisplay.y + self.monsterDisplay.height / 2 + 60; // Move further below monster image self.addChild(self.monsterStatText); // Player stats text (in battle) self.playerBattleStatText = new Text2('', { size: 60, fill: "#fff" }); self.playerDisplay = self.attachAsset('character', { anchorX: 0.5, anchorY: 0.5, x: 300, // Position near bottom-left corner within the battle area y: 2732 * 0.8 - 200, // Position near bottom-left corner within the battle area scaleX: 2, scaleY: 2 }); self.playerBattleStatText.anchor.set(0.5, 0); // Anchor to top-center if (self.playerDisplay) { self.playerBattleStatText.x = self.playerDisplay.x; self.playerBattleStatText.y = self.playerDisplay.y + self.playerDisplay.height / 2 + 60; // Move further below player image } else { self.playerBattleStatText.x = 300; // Default position if playerDisplay is not available self.playerBattleStatText.y = 2732 * 0.8 - 200 + 60 + 50; // Default position below estimated player image position } self.addChild(self.playerBattleStatText); // Player image self.playerDisplay = self.attachAsset('character', { anchorX: 0.5, anchorY: 0.5, x: 300, // Position near bottom-left corner within the battle area y: 2732 * 0.8 - 200, // Position near bottom-left corner within the battle area // Position below player stats scaleX: 2, scaleY: 2 }); // Action button (Attack) self.attackBtn = new Text2('ATTACK', { size: 80, fill: "#fff", font: "Impact" }); self.attackBtn.anchor.set(0.5, 0.5); self.attackBtn.x = 2048 / 2; self.attackBtn.y = 2732 - 300; // Position near bottom self.addChild(self.attackBtn); self.attackBtn.down = function () { if (!self.visible) return; self.playerTurn(); }; self.currentMonster = null; // Reference to the monster tile being fought // Start battle self.startBattle = function (monsterTile) { self.currentMonster = monsterTile; self.visible = true; game.addChild(self); // Add battle screen to game tween(self, { alpha: 1 }, { duration: 300, easing: tween.easeOut }); // Animate appearance self.updateBattleStats(); self.attackBtn.visible = true; // Trigger monster's turn first after a short delay LK.setTimeout(self.monsterTurn, 500); }; // End battle self.endBattle = function (win) { self.visible = false; self.alpha = 0; // Reset alpha self.attackBtn.visible = false; if (win) { self.currentMonster.defeat(); monstersLeft--; player.gainExp(self.currentMonster.exp); updateGUI(); if (monstersLeft <= 0) { LK.showYouWin(); gameOver = true; } } else { // Player lost, game over is handled in handleTileDown } self.currentMonster = null; self.parent.removeChild(self); // Remove battle screen from game }; // Update battle stats display self.updateBattleStats = function () { if (self.currentMonster) { self.monsterStatText.setText('HP:' + self.currentMonster.hp + '/' + self.currentMonster.maxHp + ' DMG:' + self.currentMonster.damage); self.playerBattleStatText.setText('HP:' + player.hp + '/' + player.maxHp + ' DMG:' + player.damage); } }; // Player's turn self.playerTurn = function () { if (!self.currentMonster) return; self.currentMonster.hp -= player.damage; LK.effects.flashObject(self.monsterDisplay, 0xffe066, 300); // Show "Player Attacks!" text var playerAttackText = new Text2('Player Attacks!', { size: 80, fill: 0xffe066 }); playerAttackText.anchor.set(0.5, 0.5); playerAttackText.x = 2048 / 2; playerAttackText.y = self.monsterStatText.y - 100; self.addChild(playerAttackText); tween(playerAttackText, { alpha: 0 }, { duration: 1000, easing: tween.easeOut, onComplete: function onComplete() { playerAttackText.destroy(); } }); self.updateBattleStats(); if (self.currentMonster.hp <= 0) { self.endBattle(true); // Player wins } else { LK.setTimeout(self.monsterTurn, 500); // Monster's turn after a delay } }; // Monster's turn self.monsterTurn = function () { if (!self.currentMonster) return; player.takeDamage(self.currentMonster.damage); LK.effects.flashObject(self.monsterDisplay, 0xff0000, 300); // Flash monster indicating it attacked LK.effects.flashObject(self.playerBattleStatText, 0xff0000, 300); // Flash player stats indicating damage // Show "Monster Attacked!" text var monsterAttackText = new Text2('Monster Attacked!', { size: 80, fill: 0xff0000 }); monsterAttackText.anchor.set(0.5, 0.5); monsterAttackText.x = 2048 / 2; monsterAttackText.y = self.playerBattleStatText.y + 100; self.addChild(monsterAttackText); tween(monsterAttackText, { alpha: 0 }, { duration: 1000, easing: tween.easeOut, onComplete: function onComplete() { monsterAttackText.destroy(); } }); self.updateBattleStats(); if (player.hp <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); gameOver = true; revealAllMonsters(); self.endBattle(false); // Player loses } }; return self; }); // EmptyTile: Represents a safe tile (no monster) var EmptyTile = Container.expand(function () { var self = Container.call(this); self.revealed = false; self.adjacentMonsters = 0; self.cover = self.attachAsset('emptyTileCover', { anchorX: 0.5, anchorY: 0.5 }); self.bg = self.attachAsset('emptyTileBg', { anchorX: 0.5, anchorY: 0.5, alpha: 0 // Hidden until revealed }); self.adjText = new Text2('', { size: 48, fill: "#fff" }); self.adjText.anchor.set(0.5, 0.5); self.adjText.alpha = 0; self.addChild(self.adjText); self.reveal = function () { if (self.revealed) return; self.revealed = true; self.cover.alpha = 0.2; self.bg.alpha = 1; if (self.adjacentMonsters > 0) { self.adjText.setText(self.adjacentMonsters + ''); self.adjText.alpha = 1; } }; return self; }); // MonsterTile: Represents a monster hidden under a tile var MonsterTile = Container.expand(function () { var self = Container.call(this); // Monster stats self.hp = 1; self.maxHp = 1; self.damage = 1; self.exp = 1; self.revealed = false; self.defeated = false; // Visuals self.cover = self.attachAsset('monsterTileCover', { anchorX: 0.5, anchorY: 0.5 }); self.monster = self.attachAsset('monsterTileMonster', { anchorX: 0.5, anchorY: 0.5, alpha: 0 // Hidden until revealed }); // Show monster stats as text (hidden until revealed) self.statText = new Text2('', { size: 48, fill: "#fff" }); self.statText.anchor.set(0.5, 0.5); self.statText.alpha = 0; self.addChild(self.statText); // Reveal the monster self.reveal = function () { if (self.revealed) return; self.revealed = true; self.cover.alpha = 0.2; self.monster.alpha = 1; self.statText.setText(''); self.statText.alpha = 0; }; // Mark as defeated self.defeat = function () { self.defeated = true; self.monster.alpha = 0.3; self.cover.alpha = 0.1; self.statText.setText(''); self.statText.alpha = 0; }; return self; }); // Player: Holds player stats and methods var Player = Container.expand(function () { var self = Container.call(this); self.maxHp = 10; self.hp = 10; self.damage = 2; self.exp = 0; self.level = 1; self.expToLevel = 5; // Level up: spend exp to increase stats or heal self.levelUp = function (choice) { if (self.exp < self.expToLevel) return false; self.exp -= self.expToLevel; self.level += 1; self.expToLevel = Math.floor(self.expToLevel * 1.5); if (choice === 'hp') { self.maxHp += 3; self.hp = self.maxHp; } else if (choice === 'damage') { self.damage += 1; } else if (choice === 'heal') { self.hp = self.maxHp; } return true; }; // Take damage self.takeDamage = function (amount) { self.hp -= amount; if (self.hp < 0) self.hp = 0; }; // Gain exp self.gainExp = function (amount) { self.exp += amount; }; // Heal self.heal = function (amount) { self.hp += amount; if (self.hp > self.maxHp) self.hp = self.maxHp; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x22223a }); /**** * Game Code ****/ // --- Game Constants --- function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } var GRID_COLS = 8; var GRID_ROWS = 8; var TILE_SIZE = 180; var GRID_OFFSET_X = Math.floor((2048 - GRID_COLS * TILE_SIZE) / 2); var GRID_OFFSET_Y = Math.floor(2732 * 0.2 + (2732 * 0.6 - GRID_ROWS * TILE_SIZE) / 2); // Center the grid vertically within the middle 60% var MONSTER_COUNT = 12; // --- Asset Initialization --- // --- Game State --- var player = new Player(); var grid = []; // 2D array [row][col] var tileObjs = []; // Flat array of all tile objects for easy iteration var monstersLeft = MONSTER_COUNT; var revealedTiles = 0; var totalSafeTiles = GRID_COLS * GRID_ROWS - MONSTER_COUNT; var gameOver = false; var battleScreen = new BattleScreen(); // --- GUI Elements --- var hpText = new Text2('', { size: 40, fill: 0xFF6666 }); hpText.anchor.set(0.5, 1); // Anchor to bottom-center LK.gui.bottom.addChild(hpText); var dmgText = new Text2('', { size: 40, fill: "#fff" }); dmgText.anchor.set(0.5, 1); // Anchor to bottom-center LK.gui.bottom.addChild(dmgText); var expText = new Text2('', { size: 40, fill: 0xFFE066 }); expText.anchor.set(0.5, 1); // Anchor to bottom-center LK.gui.bottom.addChild(expText); var levelText = new Text2('', { size: 40, fill: 0xA3E635 }); levelText.anchor.set(0, 0.5); // Anchor to left-middle LK.gui.top.addChild(levelText); var monstersLeftText = new Text2('', { size: 40, fill: "#fff" }); monstersLeftText.anchor.set(0, 0.5); // Anchor to left-middle LK.gui.top.addChild(monstersLeftText); var levelUpBtn = new Text2('LEVEL UP', { size: 70, fill: "#fff", font: "Impact" }); levelUpBtn.anchor.set(0.5, 0.5); levelUpBtn.alpha = 0.7; levelUpBtn.visible = false; levelUpBtn.down = function () { if (!this.visible) return; showLevelUpChoices(); }; LK.gui.top.addChild(levelUpBtn); var levelUpChoiceBtns = []; var levelUpChoices = [{ label: "Max HP +3 & Heal", value: "hp" }, { label: "Damage +1", value: "damage" }, { label: "Heal to Max", value: "heal" }]; for (var i = 0; i < levelUpChoices.length; i++) { var btn = new Text2(levelUpChoices[i].label, { size: 60, fill: "#fff", font: "Impact" }); btn.anchor.set(0.5, 0.5); btn.visible = false; btn.alpha = 0.9; // Capture the current choice for this button's event handler var currentChoice = levelUpChoices[i]; btn.down = function () { if (!this.visible) return; player.levelUp(currentChoice.value); hideLevelUpChoices(); updateGUI(); // If player still has enough EXP, show the level up button again if (!gameOver && player.exp >= player.expToLevel) { levelUpBtn.visible = true; levelUpBtn.alpha = 1; } }; LK.gui.bottom.addChild(btn); levelUpChoiceBtns.push(btn); } // --- Helper Functions --- function updateGUI() { if (battleScreen.visible) { hpText.visible = false; dmgText.visible = false; expText.visible = false; levelText.visible = false; monstersLeftText.visible = false; levelUpBtn.visible = false; for (var i = 0; i < levelUpChoiceBtns.length; i++) { levelUpChoiceBtns[i].visible = false; } battleScreen.updateBattleStats(); // Update battle screen stats when visible return; } else { hpText.visible = true; dmgText.visible = true; expText.visible = true; levelText.visible = true; monstersLeftText.visible = true; } hpText.setText('HP: ' + player.hp + '/' + player.maxHp); hpText.x = -200; // Position to the left of center hpText.y = -40; // Position near the bottom edge dmgText.setText('DMG: ' + player.damage); dmgText.x = 0; // Center horizontally dmgText.y = -40; // Position near the bottom edge expText.setText('EXP: ' + player.exp + '/' + player.expToLevel); expText.x = 200; // Position to the right of center expText.y = -40; // Position near the bottom edge // Position levelText and monstersLeftText side-by-side at the top-center, accounting for 100x100 top-left area levelText.setText('LVL: ' + player.level); levelText.x = -100; // Position to the left of center (adjusted for safe area) levelText.y = 60; // Position near the top edge monstersLeftText.setText('Monsters: ' + monstersLeft); monstersLeftText.x = 100; // Position to the right of center monstersLeftText.y = 60; // Position near the top edge // Show level up button if enough exp if (!gameOver && player.exp >= player.expToLevel && !levelUpChoiceBtns.some(function (btn) { return btn.visible; })) { levelUpBtn.visible = true; levelUpBtn.alpha = 1; } else { levelUpBtn.visible = false; } } // Returns true if (row, col) is inside grid function inBounds(row, col) { return row >= 0 && row < GRID_ROWS && col >= 0 && col < GRID_COLS; } // Get all adjacent tile positions function getAdjacent(row, col) { var adj = []; for (var dr = -1; dr <= 1; dr++) { for (var dc = -1; dc <= 1; dc++) { if (dr === 0 && dc === 0) continue; var nr = row + dr, nc = col + dc; if (inBounds(nr, nc)) adj.push([nr, nc]); } } return adj; } // Reveal empty tiles recursively (flood fill) function revealEmptyTiles(row, col) { var tile = grid[row][col]; if (tile.revealed) return; tile.reveal(); revealedTiles++; if (tile.adjacentMonsters === 0) { var adj = getAdjacent(row, col); for (var i = 0; i < adj.length; i++) { var _adj$i = _slicedToArray(adj[i], 2), nr = _adj$i[0], nc = _adj$i[1]; var t = grid[nr][nc]; if (t instanceof EmptyTile && !t.revealed) { revealEmptyTiles(nr, nc); } } } } // Reveal all monsters (on game over) function revealAllMonsters() { for (var i = 0; i < tileObjs.length; i++) { var t = tileObjs[i]; if (t instanceof MonsterTile && !t.revealed) { t.reveal(); } } } // --- Board Generation --- function generateBoard() { // Clear previous for (var i = 0; i < tileObjs.length; i++) { tileObjs[i].destroy(); } grid = []; tileObjs = []; monstersLeft = MONSTER_COUNT; revealedTiles = 0; totalSafeTiles = GRID_COLS * GRID_ROWS - MONSTER_COUNT; gameOver = false; // Place monsters var monsterPositions = []; while (monsterPositions.length < MONSTER_COUNT) { var r = Math.floor(Math.random() * GRID_ROWS); var c = Math.floor(Math.random() * GRID_COLS); var key = r + ',' + c; var found = false; for (var i = 0; i < monsterPositions.length; i++) { if (monsterPositions[i][0] === r && monsterPositions[i][1] === c) { found = true; break; } } if (!found) monsterPositions.push([r, c]); } // Build grid for (var row = 0; row < GRID_ROWS; row++) { grid[row] = []; for (var col = 0; col < GRID_COLS; col++) { var isMonster = false; for (var i = 0; i < monsterPositions.length; i++) { if (monsterPositions[i][0] === row && monsterPositions[i][1] === col) { isMonster = true; break; } } var tile; if (isMonster) { tile = new MonsterTile(); // Randomize monster stats a bit tile.maxHp = tile.hp = 1 + Math.floor(Math.random() * (1 + player.level)); tile.damage = 1 + Math.floor(Math.random() * (1 + Math.floor(player.level / 2))); tile.exp = 1 + Math.floor(Math.random() * 2); } else { tile = new EmptyTile(); } tile.x = GRID_OFFSET_X + col * TILE_SIZE + TILE_SIZE / 2; tile.y = GRID_OFFSET_Y + row * TILE_SIZE + TILE_SIZE / 2; game.addChild(tile); grid[row][col] = tile; tileObjs.push(tile); } } // Set adjacent monster counts for empty tiles for (var row = 0; row < GRID_ROWS; row++) { for (var col = 0; col < GRID_COLS; col++) { var tile = grid[row][col]; if (tile instanceof EmptyTile) { var adj = getAdjacent(row, col); var count = 0; for (var i = 0; i < adj.length; i++) { var _adj$i2 = _slicedToArray(adj[i], 2), nr = _adj$i2[0], nc = _adj$i2[1]; if (grid[nr][nc] instanceof MonsterTile) count++; } tile.adjacentMonsters = count; } } } } // --- Game Logic --- function handleTileDown(x, y, obj) { if (gameOver) return; if (battleScreen.visible) return; // Don't allow tile interaction if battle screen is up // Find which tile was pressed for (var i = 0; i < tileObjs.length; i++) { var tile = tileObjs[i]; if (tile.revealed) continue; if (tile.cover && tile.cover.alpha > 0.1) { // Check if (x, y) is inside tile var dx = x - tile.x; var dy = y - tile.y; if (Math.abs(dx) < TILE_SIZE / 2 && Math.abs(dy) < TILE_SIZE / 2) { // Reveal tile if (tile instanceof EmptyTile) { revealEmptyTiles(Math.floor((tile.y - GRID_OFFSET_Y) / TILE_SIZE), Math.floor((tile.x - GRID_OFFSET_X) / TILE_SIZE)); updateGUI(); // Win check if (revealedTiles >= totalSafeTiles) { LK.showYouWin(); gameOver = true; revealAllMonsters(); } } else if (tile instanceof MonsterTile) { // Reveal monster and start battle tile.reveal(); // Reveal the monster visually // Start the battle sequence battleScreen.startBattle(tile); } break; } } } } // --- Level Up UI --- function showLevelUpChoices() { levelUpBtn.visible = false; for (var i = 0; i < levelUpChoiceBtns.length; i++) { var btn = levelUpChoiceBtns[i]; btn.visible = true; btn.x = (i - 1) * 400; // x relative to LK.gui.bottom (which is screen center horizontally) btn.y = -2732 * 0.15; // Position choices above the bottom boundary of the battle area btn.alpha = 1; } } function hideLevelUpChoices() { for (var i = 0; i < levelUpChoiceBtns.length; i++) { levelUpChoiceBtns[i].visible = false; } } // --- Event Handlers --- game.down = function (x, y, obj) { // The click handling for levelUpBtn and levelUpChoiceBtns // has been moved to their own 'down' event handlers. // Check for tile interactions handleTileDown(x, y, obj); }; game.update = function () { if (battleScreen.visible) return; // Don't update game elements when battle screen is up // Animate level up button if (levelUpBtn.visible) { levelUpBtn.x = 0; // Centered horizontally relative to LK.gui.top levelUpBtn.y = 120; levelUpBtn.alpha = 0.8 + 0.2 * Math.sin(LK.ticks / 20); } // Animate level up choices for (var i = 0; i < levelUpChoiceBtns.length; i++) { var btn = levelUpChoiceBtns[i]; if (btn.visible) { btn.x = (i - 1) * 400; // x relative to LK.gui.bottom btn.y = -2732 * 0.15; // Position choices above the bottom boundary of the battle area btn.alpha = 0.9 + 0.1 * Math.sin(LK.ticks / 15 + i); } } if (battleScreen.visible) { for (var i = 0; i < tileObjs.length; i++) { tileObjs[i].visible = false; } } else { for (var i = 0; i < tileObjs.length; i++) { tileObjs[i].visible = true; } } }; // --- Start Game --- generateBoard(); updateGUI();
===================================================================
--- original.js
+++ change.js