User prompt
Y que cuando presione un botón del npc cuando estoy tradeando, ese será lo que quiero comprar y cuando lo presione se compra con la cierta cantidad de recursos y ya el npc desaparece porque ya tradeaste con el, y que aparezca cada 3 días
User prompt
El arma que suelta el boss, que aparezca un mensaje que diga "Hacer click para agarrar", y que tenga esa arma por el resto de la partida, y también hay un bug en el texto de recarga qué a partir de la noche 3 se buguea y se queda el texto allí, y que en cada noche los monstruos hagan un 0.5% más de daño
User prompt
Optimiza el juego que no me deja entrar
User prompt
Arregla bugs qué los boss aparecen cada 5 noches
User prompt
Quitarle los colores a los personajes y optimiza el juego para que pueda entrenar
User prompt
Que los días y noches duren solo 30 segundos, y que los días pasen en orden del (1,2,3,4,5..........100) y que cada día la noche dura un segundo más
User prompt
Chat el npc solo aparece cada 5 días, y al inicio no puede estar, y que los días pasen uno por uno porque están pasando muy rápido, y que el npc se pueda tradear porque no deja
User prompt
Optimiza el juego para que pueda entrar
User prompt
Pero que el npc tenga el mismo tamaño que el player, y que no se mueva, y que cuando presione c empieze a tradear, y que el npc aparezca cada 5 días y dale una textura, también agrega jefes random al juego, que cada jefe aparezca cada 10 días
User prompt
Chat pero debe aparecer un npc para tradear, y que cuando se presione c puedas tradear con el npc, y que cuando este tradeando el personaje principal no se pueda mover hasta que acabe de tradear o presionale close
User prompt
Ahora cuando le presionen play en el menú principal, pon un texto que diga, "presiona (c) para recolectar recursos, y sobrevive en las noches"
User prompt
Haz que s e pueda recolectar los resources
User prompt
Pero que se pueda recolectar recursos, porque no deja arregla esto pro favorrrrrrrr, que se pueda recolectar recursos
User prompt
Pero haz que se pueda recolectar recursos
User prompt
Pero soluciona este error, arregla la hitbox de los recursos hazla más grande pero no tanto para que pueda agarrar recursos
User prompt
Pero no tan grandes, y soluciona el error de que toco los recursos y no funciona no los recolectó, arregla esto
User prompt
Los recursos hazlos más grandes y arregla la hitbox de los recursos porque intento tocar los recursos para recolectar los y no se recolectan
User prompt
Chat lo de que los recursos tengan contacto con el player eso quita lo xd déjalo como antes
User prompt
Chat al inicio no puede tener esos buff, eso sucede solo si compras las cosas del npc qué intercambia cada 5 días, y también agrega un botón que te permita agarrar el arma que suelta el boss, y por último los proyectiles del boss hazlos más grandes, y que el player al tener contacto con los recursos al tocarlos, el player los agarre
User prompt
Pero por o cada día que pase, aparezca los cinco recursos +2 recursos más, y en el siguiente día 7 +2 recursos y ais sucesivamente, y que aparezca un npc qué tradea 2 cosas la primera es una mejora al arma, que ahora haga 10% más de daño, pero vale 50 de recursos, y el otro es un menos de 10% de costo cuando el llegue otra vez, el llega cada 5 días, y que el venda cualquiera mejora aleatoria tu le agregas, pero mientra mejor sea la mejora más debe costar ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Vamos a hacerle un rework a el recurso, que los recursos al inicio solo aparezcan 5, ya después aparece 2 recursos más cada día
User prompt
no le aumentes la hitbox a los recursos ese no es el problema, el problema es que hay recursos que trato de tomar pero no se toman, se quedan allí así
User prompt
Pero cuando intento tomar un recurso no se toma soluciona este error grande
User prompt
Soluciona errores, porque cuando voy a agarrar recursos no deja, y dale un poco más de hitbox a los monstruos y al boss
User prompt
Please fix the bug: 'Uncaught ReferenceError: updateUIVisibility is not defined' in or related to this line: 'updateUIVisibility();' Line Number: 1365
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
});
bombGraphics.tint = 0xFF0000; // Red bombs
self.speed = 6;
self.type = 'bomb';
self.direction = {
x: 0,
y: 0
};
self.explosionRadius = 120;
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Remove bomb if it goes off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
for (var i = bombs.length - 1; i >= 0; i--) {
if (bombs[i] === self) {
bombs.splice(i, 1);
break;
}
}
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('bossTexture', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.5
});
bossGraphics.tint = 0x4a0080; // Darker purple for boss
self.health = 20;
self.maxHealth = 20;
self.speed = 0; // Boss doesn't move
self.damage = 30;
self.type = 'boss';
self.spawnTimer = 0;
self.attackTimer = 0;
self.attackWarning = null;
self.attackCooldown = 300; // 5 seconds between attacks
self.update = function () {
// Boss stays at center
self.x = 1024;
self.y = 1366;
// Attack system
self.attackTimer++;
if (self.attackTimer >= self.attackCooldown) {
self.attackTimer = 0;
// Special lightning attack when health is low
if (self.health <= 5) {
// Create multiple warnings
var warningPositions = [];
for (var w = 0; w < 5; w++) {
var warning = game.addChild(new Text2('!', {
size: 150,
fill: 0xFFFF00
}));
warning.anchor.set(0.5, 0.5);
warning.x = player.x + (Math.random() - 0.5) * 300;
warning.y = player.y + (Math.random() - 0.5) * 300;
warning.alpha = 1;
warningPositions.push(warning);
// Flash warning
tween(warning, {
alpha: 0.3,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
easing: tween.easeInOut
});
}
// Lightning attack after 2 seconds
LK.setTimeout(function () {
for (var i = 0; i < warningPositions.length; i++) {
var warning = warningPositions[i];
if (warning) {
// Create lightning effect
var lightning = game.addChild(LK.getAsset('lightningTexture', {
anchorX: 0.5,
anchorY: 0.5
}));
lightning.x = warning.x;
lightning.y = warning.y;
lightning.tint = 0xFFFF00;
// Check if player is in lightning area
var dx = player.x - warning.x;
var dy = player.y - warning.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
playerHealth -= 40;
healthText.setText('Health: ' + playerHealth);
LK.getSound('damage').play();
if (playerHealth <= 0) {
LK.showGameOver();
}
}
// Lightning effect lasts 3 seconds
LK.setTimeout(function () {
if (lightning) {
lightning.destroy();
}
}, 3000);
warning.destroy();
}
}
}, 2000);
} else {
// Normal attack
if (self.attackWarning) {
self.attackWarning.destroy();
}
self.attackWarning = game.addChild(LK.getAsset('bossAttackTexture', {
anchorX: 0.5,
anchorY: 0.5
}));
self.attackWarning.x = player.x;
self.attackWarning.y = player.y;
self.attackWarning.alpha = 1;
self.attackWarning.tint = 0xFF0000;
// Flash warning
tween(self.attackWarning, {
alpha: 0.3,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeInOut
});
// Attack after 2 seconds
LK.setTimeout(function () {
if (self.attackWarning) {
// Check if player is still in attack area
var dx = player.x - self.attackWarning.x;
var dy = player.y - self.attackWarning.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 100) {
// Player is in attack area, take damage
playerHealth -= self.damage;
healthText.setText('Health: ' + playerHealth);
LK.getSound('damage').play();
if (playerHealth <= 0) {
LK.showGameOver();
}
}
// Create explosion effect
LK.effects.flashObject(self.attackWarning, 0xFF6600, 500);
self.attackWarning.destroy();
self.attackWarning = null;
}
}, 2000);
}
}
// Spawn zombies every 10 seconds (600 frames at 60fps)
self.spawnTimer++;
if (self.spawnTimer >= 600) {
self.spawnTimer = 0;
// Spawn a zombie near the boss
var zombie = new CorruptedScout();
zombie.x = self.x + (Math.random() - 0.5) * 200;
zombie.y = self.y + (Math.random() - 0.5) * 200;
zombie.health = 15; // Weaker zombies
monsters.push(zombie);
game.addChild(zombie);
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
return true;
}
return false;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bulletTexture', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
bulletGraphics.tint = 0xffff00; // Yellow bullets
self.speed = 8;
self.damage = 1;
self.type = 'bullet';
self.direction = {
x: 0,
y: 0
};
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Remove bullet if it goes off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
self.destroy();
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i] === self) {
bullets.splice(i, 1);
break;
}
}
}
};
return self;
});
var CorruptedScout = Container.expand(function () {
var self = Container.call(this);
var scoutGraphics = self.attachAsset('corruptedScout', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.maxHealth = 2;
self.speed = 2;
self.damage = 10;
self.type = 'scout';
self.isDead = false;
self.deadTimer = 0;
self.update = function () {
if (self.isDead) {
self.deadTimer++;
if (self.deadTimer >= 120) {
// 2 seconds at 60fps
self.destroy();
for (var i = monsters.length - 1; i >= 0; i--) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
}
return;
}
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Calculate intended next position
var nextX = self.x + dx / distance * self.speed;
var nextY = self.y + dy / distance * self.speed;
var blocked = false;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (wall.health > 0) {
// Simulate monster at next position
var tempDist = Math.sqrt((nextX - wall.x) * (nextX - wall.x) + (nextY - wall.y) * (nextY - wall.y));
if (tempDist < 50) {
blocked = true;
break;
}
}
}
if (!blocked) {
self.x = nextX;
self.y = nextY;
// Running animation - scale and rotate slightly
tween.stop(self, {
scaleX: true,
scaleY: true,
rotation: true
});
tween(self, {
scaleX: 1.1,
scaleY: 0.9,
rotation: dx > 0 ? 0.1 : -0.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
self.isDead = true;
self.alpha = 0.5;
scoutGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
return self;
});
var CorruptedSwarm = Container.expand(function () {
var self = Container.call(this);
var swarmGraphics = self.attachAsset('corruptedSwarm', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.maxHealth = 1;
self.speed = 3;
self.damage = 5;
self.type = 'swarm';
self.isDead = false;
self.deadTimer = 0;
self.update = function () {
if (self.isDead) {
self.deadTimer++;
if (self.deadTimer >= 120) {
// 2 seconds at 60fps
self.destroy();
for (var i = monsters.length - 1; i >= 0; i--) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
}
return;
}
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Calculate intended next position
var nextX = self.x + dx / distance * self.speed;
var nextY = self.y + dy / distance * self.speed;
var blocked = false;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (wall.health > 0) {
var tempDist = Math.sqrt((nextX - wall.x) * (nextX - wall.x) + (nextY - wall.y) * (nextY - wall.y));
if (tempDist < 50) {
blocked = true;
break;
}
}
}
if (!blocked) {
self.x = nextX;
self.y = nextY;
// Running animation - scale and rotate slightly
tween.stop(self, {
scaleX: true,
scaleY: true,
rotation: true
});
tween(self, {
scaleX: 1.1,
scaleY: 0.9,
rotation: dx > 0 ? 0.1 : -0.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
self.isDead = true;
self.alpha = 0.5;
swarmGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
return self;
});
var CorruptedTank = Container.expand(function () {
var self = Container.call(this);
var tankGraphics = self.attachAsset('corruptedTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.speed = 1;
self.damage = 25;
self.type = 'tank';
self.isDead = false;
self.deadTimer = 0;
self.update = function () {
if (self.isDead) {
self.deadTimer++;
if (self.deadTimer >= 120) {
// 2 seconds at 60fps
self.destroy();
for (var i = monsters.length - 1; i >= 0; i--) {
if (monsters[i] === self) {
monsters.splice(i, 1);
break;
}
}
}
return;
}
// Always pursue the player
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
// Calculate intended next position
var nextX = self.x + dx / distance * self.speed;
var nextY = self.y + dy / distance * self.speed;
var blocked = false;
for (var i = 0; i < walls.length; i++) {
var wall = walls[i];
if (wall.health > 0) {
var tempDist = Math.sqrt((nextX - wall.x) * (nextX - wall.x) + (nextY - wall.y) * (nextY - wall.y));
if (tempDist < 50) {
blocked = true;
break;
}
}
}
if (!blocked) {
self.x = nextX;
self.y = nextY;
// Running animation - scale and rotate slightly
tween.stop(self, {
scaleX: true,
scaleY: true,
rotation: true
});
tween(self, {
scaleX: 1.1,
scaleY: 0.9,
rotation: dx > 0 ? 0.1 : -0.1
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.floor(damage * characterStats.damageMultiplier);
self.health -= actualDamage;
if (self.health <= 0) {
self.isDead = true;
self.alpha = 0.5;
tankGraphics.rotation = Math.PI / 2; // Rotate to show fallen
return true;
}
return false;
};
return self;
});
var DualPistol = Container.expand(function () {
var self = Container.call(this);
var pistolGraphics = self.attachAsset('pistolTexture', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
});
pistolGraphics.tint = 0xFFD700; // Gold color
self.type = 'dualPistol';
self.bullets = 6;
self.maxBullets = 6;
self.isReloading = false;
self.reloadTimer = 0;
self.update = function () {
self.rotation += 0.05;
if (self.isReloading) {
self.reloadTimer--;
if (self.reloadTimer <= 0) {
self.isReloading = false;
self.bullets = self.maxBullets;
}
}
};
self.canShoot = function () {
return self.bullets > 0 && !self.isReloading;
};
self.shoot = function () {
if (self.canShoot()) {
self.bullets--;
if (self.bullets <= 0) {
self.isReloading = true;
self.reloadTimer = 180; // 3 seconds
}
return true;
}
return false;
};
return self;
});
var Resource = Container.expand(function () {
var self = Container.call(this);
var resourceGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.type = 'resource';
self.update = function () {
self.rotation += 0.05;
};
return self;
});
var TraderNPC = Container.expand(function () {
var self = Container.call(this);
var traderGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
traderGraphics.tint = 0xFFD700; // Gold color for trader
self.type = 'trader';
self.update = function () {
// Gentle floating animation
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
self.rotation += 0.02;
};
return self;
});
var Trap = Container.expand(function () {
var self = Container.call(this);
var trapGraphics = self.attachAsset('trap', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 30;
self.cooldown = 0;
self.type = 'trap';
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
}
};
self.activate = function () {
if (self.cooldown <= 0) {
self.cooldown = 60;
LK.effects.flashObject(self, 0xff6b35, 300);
return self.damage;
}
return 0;
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.type = 'wall';
// Track monster hits
self.hitCount = 0;
self.lastMonsterHitTick = 0; // LK.ticks of last monster hit
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.health = 0;
wallGraphics.alpha = 0.3;
} else {
wallGraphics.alpha = 0.5 + self.health / self.maxHealth * 0.5;
}
};
self.registerMonsterHit = function () {
self.hitCount++;
self.lastMonsterHitTick = LK.ticks;
if (self.hitCount >= 3) {
self.health = 0;
wallGraphics.alpha = 0.3;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Initialize game safely with error handling
try {
// Frames left for placement cooldown (60 = 1s)
// Update UI visibility based on game state
var _updateUIVisibility = function _updateUIVisibility() {
if (gameState === 'mainMenu') {
mainMenuContainer.alpha = 1;
characterMenuContainer.alpha = 0;
gameStateText.alpha = 0;
timerText.alpha = 0;
healthText.alpha = 0;
resourceText.alpha = 0;
nightText.alpha = 0;
joystickBase.alpha = 0;
joystickKnob.alpha = 0;
wallButton.alpha = 0;
trapButton.alpha = 0;
collectButton.alpha = 0;
wallButtonText.alpha = 0;
trapButtonText.alpha = 0;
collectButtonText.alpha = 0;
wallIcon.alpha = 0;
trapIcon.alpha = 0;
defenseText.alpha = 0;
healButton.alpha = 0;
healButtonText.alpha = 0;
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
} else if (gameState === 'characterSelect') {
mainMenuContainer.alpha = 0;
characterMenuContainer.alpha = 1;
gameStateText.alpha = 0;
timerText.alpha = 0;
healthText.alpha = 0;
resourceText.alpha = 0;
nightText.alpha = 0;
joystickBase.alpha = 0;
joystickKnob.alpha = 0;
wallButton.alpha = 0;
trapButton.alpha = 0;
collectButton.alpha = 0;
wallButtonText.alpha = 0;
trapButtonText.alpha = 0;
collectButtonText.alpha = 0;
wallIcon.alpha = 0;
trapIcon.alpha = 0;
defenseText.alpha = 0;
healButton.alpha = 0;
healButtonText.alpha = 0;
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
} else {
mainMenuContainer.alpha = 0;
characterMenuContainer.alpha = 0;
gameStateText.alpha = 1;
timerText.alpha = 1;
healthText.alpha = 1;
resourceText.alpha = 1;
nightText.alpha = 1;
joystickBase.alpha = 0.5;
joystickKnob.alpha = 1;
wallButton.alpha = 1;
trapButton.alpha = 1;
collectButton.alpha = 1;
wallButtonText.alpha = 1;
trapButtonText.alpha = 1;
collectButtonText.alpha = 1;
wallIcon.alpha = 1;
trapIcon.alpha = 1;
defenseText.alpha = gameState === 'day' ? 1 : 0;
}
};
// Add backgrounds
var dayBackground = game.addChild(LK.getAsset('dayBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
dayBackground.alpha = 1;
var nightBackground = game.addChild(LK.getAsset('nightBackground', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
nightBackground.alpha = 0;
var gameState = 'mainMenu'; // Start with main menu
var currentNight = 0;
var dayTimer = 1800; // 30 seconds at 60fps
var nightTimer = 0;
var playerHealth = 100;
var playerResources = 50;
var selectedDefense = 'wall';
var walls = [];
var traps = [];
var resources = [];
var monsters = [];
var boss = null;
var bullets = [];
var bombs = [];
var playerPistol = true; // Player has pistol
var pistolBullets = 5; // Bullets left before reload
var pistolReloading = false; // Is pistol reloading
var pistolReloadTimer = 0; // Frames left for reload (180 = 3s)
var hasDualPistol = false; // Player has dual pistol
var dualPistolWeapon = null; // Dual pistol weapon object
var dualPistolPickup = null; // Dual pistol pickup object
var selectedCharacter = storage.selectedCharacter || 0; // 0=damage, 1=heal, 2=discount
var characterStats = {
damageMultiplier: selectedCharacter === 0 ? 1.3 : 1.0,
healPerNight: selectedCharacter === 1 ? 10 : 0,
discountMultiplier: selectedCharacter === 2 ? 0.8 : 1.0
};
// Trader system variables
var currentDay = storage.currentDay || 1;
var traderActive = false;
var traderContainer = null;
var weaponUpgradePurchased = storage.weaponUpgradePurchased || false;
var costReductionPurchased = storage.costReductionPurchased || false;
var traderUpgrades = [{
name: "Weapon Damage +10%",
cost: 50,
type: "weapon",
purchased: false
}, {
name: "Build Cost -10%",
cost: 30,
type: "cost",
purchased: false
}, {
name: "Health +20",
cost: 40,
type: "health",
purchased: false
}, {
name: "Speed +20%",
cost: 35,
type: "speed",
purchased: false
}, {
name: "Reload Speed +30%",
cost: 45,
type: "reload",
purchased: false
}];
// Special ability states
var berserkMode = false;
var berserkUsed = false;
var medicReviveUsed = false;
var engineerBoostActive = false;
var engineerBoostUsed = false;
var slowEnemiesActive = false;
var slowEnemiesTimer = 0;
// Heal button for medic character
var healButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: -250,
y: 0,
scaleX: 3,
scaleY: 3
});
healButton.tint = 0x00FF00;
healButton.alpha = 0;
var healButtonText = new Text2('HEAL', {
size: 60,
fill: 0xFFFFFF
});
healButtonText.anchor.set(0.5, 0.5);
healButtonText.x = -250;
healButtonText.y = 0;
healButtonText.alpha = 0;
LK.gui.center.addChild(healButton);
LK.gui.center.addChild(healButtonText);
var pistolReloadText = new Text2('', {
size: 80,
fill: 0xFF0000
});
pistolReloadText.anchor.set(0.5, 0.5);
pistolReloadText.x = 0;
pistolReloadText.y = 200;
pistolReloadText.alpha = 0;
LK.gui.center.addChild(pistolReloadText);
// Main Menu UI
var mainMenuContainer = new Container();
var mainMenuTitle = new Text2('SURVIVAL GAME', {
size: 120,
fill: 0xFFFFFF
});
mainMenuTitle.anchor.set(0.5, 0.5);
mainMenuTitle.x = 0;
mainMenuTitle.y = -300;
mainMenuContainer.addChild(mainMenuTitle);
var playButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -100,
scaleX: 4,
scaleY: 2
});
var playButtonText = new Text2('PLAY', {
size: 80,
fill: 0xFFFFFF
});
playButtonText.anchor.set(0.5, 0.5);
playButtonText.x = 0;
playButtonText.y = -100;
mainMenuContainer.addChild(playButton);
mainMenuContainer.addChild(playButtonText);
var charactersButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 50,
scaleX: 4,
scaleY: 2
});
var charactersButtonText = new Text2('CHARACTERS', {
size: 80,
fill: 0xFFFFFF
});
charactersButtonText.anchor.set(0.5, 0.5);
charactersButtonText.x = 0;
charactersButtonText.y = 50;
mainMenuContainer.addChild(charactersButton);
mainMenuContainer.addChild(charactersButtonText);
LK.gui.center.addChild(mainMenuContainer);
// Character Selection UI
var characterMenuContainer = new Container();
var characterMenuTitle = new Text2('SELECT CHARACTER', {
size: 100,
fill: 0xFFFFFF
});
characterMenuTitle.anchor.set(0.5, 0.5);
characterMenuTitle.x = 0;
characterMenuTitle.y = -400;
characterMenuContainer.addChild(characterMenuTitle);
// Character 1 - Damage
var char1Button = LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: -100,
scaleX: 2,
scaleY: 2
});
var char1Text = new Text2('WARRIOR\n+30% Damage', {
size: 50,
fill: 0xFFFFFF
});
char1Text.anchor.set(0.5, 0.5);
char1Text.x = -300;
char1Text.y = 50;
characterMenuContainer.addChild(char1Button);
characterMenuContainer.addChild(char1Text);
// Character 2 - Heal
var char2Button = LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -100,
scaleX: 2,
scaleY: 2
});
char2Button.tint = 0x00FF00;
var char2Text = new Text2('MEDIC\n+10 Health\nper Night', {
size: 50,
fill: 0xFFFFFF
});
char2Text.anchor.set(0.5, 0.5);
char2Text.x = 0;
char2Text.y = 50;
characterMenuContainer.addChild(char2Button);
characterMenuContainer.addChild(char2Text);
// Character 3 - Discount
var char3Button = LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: -100,
scaleX: 2,
scaleY: 2
});
char3Button.tint = 0x0000FF;
var char3Text = new Text2('ENGINEER\n-20% Build\nCost', {
size: 50,
fill: 0xFFFFFF
});
// Set initial character selection visual state
if (selectedCharacter === 0) {
char1Button.tint = 0x00FF00;
} else if (selectedCharacter === 1) {
char2Button.tint = 0x00FF00;
} else if (selectedCharacter === 2) {
char3Button.tint = 0x00FF00;
}
char3Text.anchor.set(0.5, 0.5);
char3Text.x = 300;
char3Text.y = 50;
characterMenuContainer.addChild(char3Button);
characterMenuContainer.addChild(char3Text);
var backButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 300,
scaleX: 3,
scaleY: 2
});
var backButtonText = new Text2('BACK', {
size: 60,
fill: 0xFFFFFF
});
backButtonText.anchor.set(0.5, 0.5);
backButtonText.x = 0;
backButtonText.y = 300;
characterMenuContainer.addChild(backButton);
characterMenuContainer.addChild(backButtonText);
characterMenuContainer.alpha = 0;
LK.gui.center.addChild(characterMenuContainer);
var player = game.addChild(LK.getAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
// Apply character colors
if (selectedCharacter === 1) {
player.tint = 0x00FF00; // Green for medic
} else if (selectedCharacter === 2) {
player.tint = 0x0000FF; // Blue for engineer
} else {
player.tint = 0xFFFFFF; // White for warrior
}
// Button visibility is now handled by the UI buttons
disablePlacement = false;
var gameStateText = new Text2('Day Phase', {
size: 80,
fill: 0xFFFFFF
});
gameStateText.anchor.set(0.5, 0);
LK.gui.top.addChild(gameStateText);
var timerText = new Text2('30s', {
size: 60,
fill: 0xFFFF00
});
timerText.anchor.set(0.5, 0);
timerText.y = 100;
LK.gui.top.addChild(timerText);
var healthText = new Text2('Health: 100', {
size: 50,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 120;
var resourceText = new Text2('Resources: 50', {
size: 50,
fill: 0xFFD700
});
resourceText.anchor.set(0, 0);
resourceText.y = 60;
LK.gui.topLeft.addChild(resourceText);
resourceText.x = 120;
var nightText = new Text2('Night: 0', {
size: 50,
fill: 0x8B3A8B
});
nightText.anchor.set(1, 0);
LK.gui.topRight.addChild(nightText);
// Boss health bar UI elements
var bossHealthBar = LK.getAsset('healthBarTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 150,
scaleX: 10,
scaleY: 1
});
bossHealthBar.tint = 0x333333;
bossHealthBar.alpha = 0;
LK.gui.top.addChild(bossHealthBar);
var bossHealthBarFill = LK.getAsset('healthBarTexture', {
anchorX: 0.0,
anchorY: 0.5,
x: -300,
y: 150,
scaleX: 10,
scaleY: 1
});
bossHealthBarFill.tint = 0xFF0000;
bossHealthBarFill.alpha = 0;
LK.gui.top.addChild(bossHealthBarFill);
var bossHealthText = new Text2('BOSS', {
size: 50,
fill: 0xFF0000
});
bossHealthText.anchor.set(0.5, 0.5);
bossHealthText.x = 0;
bossHealthText.y = 100;
bossHealthText.alpha = 0;
LK.gui.top.addChild(bossHealthText);
// Joystick control elements
var joystickBase = LK.getAsset('joystickTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: -300,
scaleX: 2.5,
scaleY: 2.5
});
joystickBase.alpha = 0.5;
LK.gui.bottomLeft.addChild(joystickBase);
var joystickKnob = LK.getAsset('joystickTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: -300,
scaleX: 1.5,
scaleY: 1.5
});
joystickKnob.tint = 0xFFFFFF;
LK.gui.bottomLeft.addChild(joystickKnob);
var joystickActive = false;
var joystickCenterX = 200;
var joystickCenterY = -300;
var joystickRadius = 60;
var defenseText = new Text2('Defense: Wall (Cost: 10)', {
size: 40,
fill: 0xFFFFFF
});
defenseText.anchor.set(0.5, 1);
defenseText.y = -120;
defenseText.alpha = 0;
LK.gui.bottom.addChild(defenseText);
// Action buttons on the right side
var wallButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: -200,
scaleX: 2.5,
scaleY: 2.5
});
LK.gui.bottomRight.addChild(wallButton);
var wallIcon = LK.getAsset('wall', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: -200,
scaleX: 1.5,
scaleY: 1.5
});
LK.gui.bottomRight.addChild(wallIcon);
var trapButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: -150,
y: -200,
scaleX: 2.5,
scaleY: 2.5
});
LK.gui.bottomRight.addChild(trapButton);
var trapIcon = LK.getAsset('trap', {
anchorX: 0.5,
anchorY: 0.5,
x: -150,
y: -200,
scaleX: 1.5,
scaleY: 1.5
});
LK.gui.bottomRight.addChild(trapIcon);
var collectButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: -300,
y: -350,
scaleX: 2.5,
scaleY: 2.5
});
LK.gui.bottomRight.addChild(collectButton);
var wallButtonText = new Text2('W', {
size: 40,
fill: 0xFFFFFF
});
wallButtonText.anchor.set(0.5, 0.5);
wallButtonText.x = -300;
wallButtonText.y = -200;
LK.gui.bottomRight.addChild(wallButtonText);
var trapButtonText = new Text2('T', {
size: 40,
fill: 0xFFFFFF
});
trapButtonText.anchor.set(0.5, 0.5);
trapButtonText.x = -150;
trapButtonText.y = -200;
LK.gui.bottomRight.addChild(trapButtonText);
var collectButtonText = new Text2('C', {
size: 40,
fill: 0xFFFFFF
});
collectButtonText.anchor.set(0.5, 0.5);
collectButtonText.x = -300;
collectButtonText.y = -350;
LK.gui.bottomRight.addChild(collectButtonText);
// Movement control variables
var moveX = 0;
var moveY = 0;
var playerSpeed = 5;
// Pistol graphics
var pistolGraphics = null;
var pistolTimer = 0;
// Game mode state
var gameMode = 'build'; // 'build' or 'collect'
var disablePlacement = false; // Prevents placing objects while a button is pressed
var placementCooldown = 0;
_updateUIVisibility();
} catch (error) {
console.error('Game initialization error:', error);
// Fallback initialization
gameState = 'mainMenu';
playerHealth = 100;
playerResources = 50;
}
function createTraderUI() {
traderContainer = new Container();
// Background
var traderBg = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
scaleX: 8,
scaleY: 6
});
traderBg.tint = 0x333333;
traderContainer.addChild(traderBg);
// Title
var traderTitle = new Text2('TRADER', {
size: 80,
fill: 0xFFD700
});
traderTitle.anchor.set(0.5, 0.5);
traderTitle.x = 0;
traderTitle.y = -200;
traderContainer.addChild(traderTitle);
// Create upgrade buttons
var availableUpgrades = traderUpgrades.filter(function (upgrade) {
return !upgrade.purchased;
});
// Show up to 3 random upgrades
for (var i = 0; i < Math.min(3, availableUpgrades.length); i++) {
var upgrade = availableUpgrades[Math.floor(Math.random() * availableUpgrades.length)];
var yPos = -50 + i * 80;
var upgradeButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: yPos,
scaleX: 6,
scaleY: 1.5
});
upgradeButton.upgradeData = upgrade;
traderContainer.addChild(upgradeButton);
var upgradeText = new Text2(upgrade.name + ' - ' + upgrade.cost + ' Resources', {
size: 40,
fill: 0xFFFFFF
});
upgradeText.anchor.set(0.5, 0.5);
upgradeText.x = 0;
upgradeText.y = yPos;
traderContainer.addChild(upgradeText);
// Remove from available list to prevent duplicates
availableUpgrades.splice(availableUpgrades.indexOf(upgrade), 1);
}
// Close button
var closeButton = LK.getAsset('buttonTexture', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 150,
scaleX: 3,
scaleY: 2
});
var closeText = new Text2('CLOSE', {
size: 60,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 0;
closeText.y = 150;
traderContainer.addChild(closeButton);
traderContainer.addChild(closeText);
LK.gui.center.addChild(traderContainer);
}
function closeTrader() {
if (traderContainer) {
traderContainer.destroy();
traderContainer = null;
}
traderActive = false;
}
function purchaseUpgrade(upgrade) {
if (playerResources >= upgrade.cost) {
playerResources -= upgrade.cost;
resourceText.setText('Resources: ' + playerResources);
upgrade.purchased = true;
// Apply upgrade effects
switch (upgrade.type) {
case "weapon":
characterStats.damageMultiplier += 0.1;
weaponUpgradePurchased = true;
storage.weaponUpgradePurchased = true;
break;
case "cost":
characterStats.discountMultiplier *= 0.9;
costReductionPurchased = true;
storage.costReductionPurchased = true;
break;
case "health":
playerHealth = Math.min(120, playerHealth + 20);
healthText.setText('Health: ' + playerHealth);
break;
case "speed":
playerSpeed *= 1.2;
break;
case "reload":
// This will be applied in reload logic
break;
}
closeTrader();
LK.getSound('collect').play();
}
}
var placementCooldownText = new Text2('', {
size: 80,
fill: 0xFF0000
});
placementCooldownText.anchor.set(0.5, 0.5);
placementCooldownText.x = 0;
placementCooldownText.y = 0;
placementCooldownText.alpha = 0;
LK.gui.center.addChild(placementCooldownText);
// Spawn initial resources - 5 + 2 per day progression
var resourcesToSpawn = 5 + (currentDay - 1) * 2;
for (var i = 0; i < resourcesToSpawn; i++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 1200;
resources.push(resource);
game.addChild(resource);
}
function spawnMonster(type) {
var monster;
switch (type) {
case 'scout':
monster = new CorruptedScout();
break;
case 'tank':
monster = new CorruptedTank();
break;
case 'swarm':
monster = new CorruptedSwarm();
break;
default:
monster = new CorruptedScout();
}
// Spawn from edges
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
monster.x = Math.random() * 2048;
monster.y = -50;
break;
case 1:
// Right
monster.x = 2098;
monster.y = Math.random() * 2732;
break;
case 2:
// Bottom
monster.x = Math.random() * 2048;
monster.y = 2782;
break;
case 3:
// Left
monster.x = -50;
monster.y = Math.random() * 2732;
break;
}
monsters.push(monster);
game.addChild(monster);
}
function switchToNight() {
gameState = 'night';
currentNight++;
nightTimer = 1800 + (currentNight - 1) * 600; // Base 30s + 10s per night
gameStateText.setText('Night ' + currentNight);
timerText.setText(Math.ceil(nightTimer / 60) + 's');
nightText.setText('Night: ' + currentNight);
// Switch to night background
dayBackground.alpha = 0;
nightBackground.alpha = 1;
LK.playMusic('nightfall');
defenseText.setText('Night Phase - Survive!');
// Show heal button for medic character
if (characterStats.healPerNight > 0 && currentNight > 0) {
healButton.alpha = 1;
healButtonText.alpha = 1;
}
// Spawn initial monsters for the night - start with 6 and increase gradually
var initialMonsters = Math.min(6 + Math.floor(currentNight * 0.5), 8); // Start with 6, cap at 8
for (var i = 0; i < initialMonsters; i++) {
spawnMonster('scout'); // Start with scouts for the initial wave
}
// Spawn boss every 3rd night
if (currentNight % 3 === 0 && boss === null) {
boss = new Boss();
// Spawn boss at center
boss.x = 1024;
boss.y = 1366;
game.addChild(boss);
// Show boss health bar
bossHealthBar.alpha = 1;
bossHealthBarFill.alpha = 1;
bossHealthText.alpha = 1;
}
}
function switchToDay() {
gameState = 'day';
currentDay++;
storage.currentDay = currentDay;
dayTimer = 1800; // 30 seconds
gameStateText.setText('Day ' + currentDay);
timerText.setText('30s');
// Switch to day background
dayBackground.alpha = 1;
nightBackground.alpha = 0;
LK.stopMusic();
// Reset to default mode
gameMode = 'build';
selectedDefense = 'wall';
defenseText.setText('Defense: Wall (Cost: 10)');
wallButtonText.tint = 0x00FF00;
trapButtonText.tint = 0xFFFFFF;
collectButtonText.tint = 0xFFFFFF;
// Initialize wall button as selected
wallButton.tint = 0x00FF00;
trapButton.tint = 0xFFFFFF;
wallIcon.tint = 0x00FF00;
trapIcon.tint = 0xFFFFFF;
// Spawn new resources - progressive system: 5 + 2 * (currentDay - 1)
var resourcesToSpawn = 5 + (currentDay - 1) * 2;
for (var i = 0; i < resourcesToSpawn; i++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 1200;
resources.push(resource);
game.addChild(resource);
}
// Check if trader should appear (every 5 days)
if (currentDay % 5 === 0) {
traderActive = true;
createTraderUI();
}
}
// Joystick movement handler
function updateJoystick(x, y) {
var dx = x - joystickCenterX;
var dy = y - joystickCenterY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > joystickRadius) {
dx = dx / distance * joystickRadius;
dy = dy / distance * joystickRadius;
}
joystickKnob.x = joystickCenterX + dx;
joystickKnob.y = joystickCenterY + dy;
// Calculate movement values (-1 to 1)
moveX = dx / joystickRadius;
moveY = dy / joystickRadius;
}
function resetJoystick() {
joystickKnob.x = joystickCenterX;
joystickKnob.y = joystickCenterY;
moveX = 0;
moveY = 0;
joystickActive = false;
}
// Action button handlers
wallButton.down = function (x, y, obj) {
if (gameState === 'day') {
selectedDefense = 'wall';
gameMode = 'build';
defenseText.setText('Defense: Wall (Cost: 10)');
wallButtonText.tint = 0x00FF00;
trapButtonText.tint = 0xFFFFFF;
collectButtonText.tint = 0xFFFFFF;
// Update button visual states
wallButton.tint = 0x00FF00;
trapButton.tint = 0xFFFFFF;
wallIcon.tint = 0x00FF00;
trapIcon.tint = 0xFFFFFF;
}
disablePlacement = true;
placementCooldown = 60;
placementCooldownText.alpha = 1;
placementCooldownText.setText('1');
};
trapButton.down = function (x, y, obj) {
if (gameState === 'day') {
selectedDefense = 'trap';
gameMode = 'build';
defenseText.setText('Defense: Trap (Cost: 15)');
wallButtonText.tint = 0xFFFFFF;
trapButtonText.tint = 0x00FF00;
collectButtonText.tint = 0xFFFFFF;
// Update button visual states
wallButton.tint = 0xFFFFFF;
trapButton.tint = 0x00FF00;
wallIcon.tint = 0xFFFFFF;
trapIcon.tint = 0x00FF00;
}
disablePlacement = true;
placementCooldown = 60;
placementCooldownText.alpha = 1;
placementCooldownText.setText('1');
};
collectButton.down = function (x, y, obj) {
if (gameState === 'day') {
gameMode = 'collect';
defenseText.setText('Mode: Resource Collection');
wallButtonText.tint = 0xFFFFFF;
trapButtonText.tint = 0xFFFFFF;
collectButtonText.tint = 0x00FF00;
// Reset button visual states
wallButton.tint = 0xFFFFFF;
trapButton.tint = 0xFFFFFF;
wallIcon.tint = 0xFFFFFF;
trapIcon.tint = 0xFFFFFF;
}
disablePlacement = true;
placementCooldown = 60;
placementCooldownText.alpha = 1;
placementCooldownText.setText('1');
};
// Joystick event handlers
game.down = function (x, y, obj) {
if (gameState === 'mainMenu') {
var local = LK.gui.center.toLocal({
x: x,
y: y
}, game);
// Check play button
if (local.x >= -200 && local.x <= 200 && local.y >= -150 && local.y <= -50) {
gameState = 'day';
_updateUIVisibility();
return;
}
// Check characters button
if (local.x >= -200 && local.x <= 200 && local.y >= 0 && local.y <= 100) {
gameState = 'characterSelect';
_updateUIVisibility();
return;
}
return;
}
if (gameState === 'characterSelect') {
var local = LK.gui.center.toLocal({
x: x,
y: y
}, game);
// Check character 1
if (local.x >= -400 && local.x <= -200 && local.y >= -200 && local.y <= 0) {
selectedCharacter = 0;
storage.selectedCharacter = 0;
characterStats.damageMultiplier = 1.3;
characterStats.healPerNight = 0;
characterStats.discountMultiplier = 1.0;
// Update character appearance
char1Button.tint = 0x00FF00;
char2Button.tint = 0x00FF00;
char3Button.tint = 0x0000FF;
// Apply character color to player
player.tint = 0xFFFFFF; // White for warrior
gameState = 'day';
_updateUIVisibility();
return;
}
// Check character 2
if (local.x >= -100 && local.x <= 100 && local.y >= -200 && local.y <= 0) {
selectedCharacter = 1;
storage.selectedCharacter = 1;
characterStats.damageMultiplier = 1.0;
characterStats.healPerNight = 10;
characterStats.discountMultiplier = 1.0;
// Update character appearance
char1Button.tint = 0xFFFFFF;
char2Button.tint = 0x00FF00;
char3Button.tint = 0x0000FF;
// Apply character color to player
player.tint = 0x00FF00; // Green for medic
// Update player graphics to use medic texture
player.destroy();
player = game.addChild(LK.getAsset('medicPlayer', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
player.tint = 0x00FF00;
gameState = 'day';
_updateUIVisibility();
return;
}
// Check character 3
if (local.x >= 200 && local.x <= 400 && local.y >= -200 && local.y <= 0) {
selectedCharacter = 2;
storage.selectedCharacter = 2;
characterStats.damageMultiplier = 1.0;
characterStats.healPerNight = 0;
characterStats.discountMultiplier = 0.8;
// Update character appearance
char1Button.tint = 0xFFFFFF;
char2Button.tint = 0x00FF00;
char3Button.tint = 0x00FF00;
// Apply character color to player
player.tint = 0x0000FF; // Blue for engineer
// Update player graphics to use engineer texture
player.destroy();
player = game.addChild(LK.getAsset('engineerPlayer', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
player.tint = 0x0000FF;
gameState = 'day';
_updateUIVisibility();
return;
}
// Check back button
if (local.x >= -150 && local.x <= 150 && local.y >= 250 && local.y <= 350) {
gameState = 'mainMenu';
_updateUIVisibility();
return;
}
return;
}
// Check if touch is on joystick base
var local = LK.gui.bottomLeft.toLocal({
x: x,
y: y
}, game);
var dx = local.x - joystickCenterX;
var dy = local.y - joystickCenterY;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= joystickRadius + 30) {
joystickActive = true;
updateJoystick(local.x, local.y);
return;
}
// Check heal button
if (healButton.alpha > 0) {
var local = LK.gui.center.toLocal({
x: x,
y: y
}, game);
if (local.x >= -370 && local.x <= -130 && local.y >= -120 && local.y <= 120) {
playerHealth = Math.min(100, playerHealth + characterStats.healPerNight);
healthText.setText('Health: ' + playerHealth);
healButton.alpha = 0;
healButtonText.alpha = 0;
LK.getSound('collect').play();
return;
}
}
// Check trader interactions
if (traderActive && traderContainer) {
var local = LK.gui.center.toLocal({
x: x,
y: y
}, game);
// Check upgrade buttons
for (var i = 0; i < traderContainer.children.length; i++) {
var child = traderContainer.children[i];
if (child.upgradeData) {
var childBounds = child.getBounds();
if (local.x >= childBounds.x && local.x <= childBounds.x + childBounds.width && local.y >= childBounds.y && local.y <= childBounds.y + childBounds.height) {
purchaseUpgrade(child.upgradeData);
return;
}
}
}
// Check close button
if (local.x >= -180 && local.x <= 180 && local.y >= 90 && local.y <= 210) {
closeTrader();
return;
}
}
if (disablePlacement) {
return; // Prevent placing objects while a button is pressed
}
if (gameState === 'day') {
if (gameMode === 'build') {
var baseCost = selectedDefense === 'wall' ? 10 : 15;
var cost = Math.floor(baseCost * characterStats.discountMultiplier);
if (playerResources >= cost) {
var defense;
if (selectedDefense === 'wall') {
defense = new Wall();
} else {
defense = new Trap();
}
defense.x = x;
defense.y = y;
if (selectedDefense === 'wall') {
walls.push(defense);
} else {
traps.push(defense);
}
game.addChild(defense);
playerResources -= cost;
resourceText.setText('Resources: ' + playerResources);
LK.getSound('build').play();
}
} else if (gameMode === 'collect') {
// Enhanced resource collection in collect mode - collect all resources in range
var resourcesCollected = 0;
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
var dx = x - resource.x;
var dy = y - resource.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 250) {
playerResources += resource.value;
resourceText.setText('Resources: ' + playerResources);
resource.destroy();
resources.splice(i, 1);
resourcesCollected++;
// Don't break - collect all resources in range
}
}
if (resourcesCollected > 0) {
LK.getSound('collect').play();
}
}
} else if (gameState === 'night' && hasDualPistol && dualPistolWeapon && dualPistolWeapon.canShoot()) {
// Shoot dual pistol (2 bullets)
if (dualPistolWeapon.shoot()) {
var dx = x - player.x;
var dy = y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Shoot two bullets with slight angle difference
for (var b = 0; b < 2; b++) {
var projectile = new Bullet();
projectile.x = player.x;
projectile.y = player.y;
// Add slight angle variation for dual shots
var angle = Math.atan2(dy, dx) + (b === 0 ? -0.1 : 0.1);
projectile.direction.x = Math.cos(angle);
projectile.direction.y = Math.sin(angle);
bullets.push(projectile);
game.addChild(projectile);
}
// Create dual pistol graphics
if (pistolGraphics) {
pistolGraphics.destroy();
}
pistolGraphics = game.addChild(LK.getAsset('pistolTexture', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0
}));
pistolGraphics.tint = 0xFFD700;
pistolGraphics.x = player.x + dx / distance * 40;
pistolGraphics.y = player.y + dy / distance * 40;
pistolGraphics.rotation = Math.atan2(dy, dx);
pistolTimer = 20;
// Animate pistol with tween
tween(pistolGraphics, {
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 100,
easing: tween.easeOut
});
LK.getSound('shoot').play();
// Update reload text
if (dualPistolWeapon.isReloading) {
pistolReloadText.alpha = 1;
pistolReloadText.setText('Dual Pistol Reloading...');
}
}
} else if (gameState === 'night' && playerPistol && !pistolReloading && pistolBullets > 0) {
// Shoot bullet or bomb towards click position
var projectile;
if (selectedCharacter === 1) {
// Medic shoots bombs
projectile = new Bomb();
} else {
// Others shoot bullets
projectile = new Bullet();
}
projectile.x = player.x;
projectile.y = player.y;
// Calculate direction to target
var dx = x - player.x;
var dy = y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
projectile.direction.x = dx / distance;
projectile.direction.y = dy / distance;
if (selectedCharacter === 1) {
bombs.push(projectile);
} else {
bullets.push(projectile);
}
game.addChild(projectile);
// Create pistol graphics
if (pistolGraphics) {
pistolGraphics.destroy();
}
pistolGraphics = game.addChild(LK.getAsset('pistolTexture', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
pistolGraphics.tint = 0x888888;
pistolGraphics.x = player.x + dx / distance * 40;
pistolGraphics.y = player.y + dy / distance * 40;
pistolGraphics.rotation = Math.atan2(dy, dx);
pistolTimer = 20; // Show pistol for 20 frames
// Animate pistol with tween
tween(pistolGraphics, {
scaleX: 2.0,
scaleY: 2.0
}, {
duration: 100,
easing: tween.easeOut
});
tween(pistolGraphics, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeIn
});
LK.getSound('shoot').play();
pistolBullets--;
if (pistolBullets === 0) {
pistolReloading = true;
pistolReloadTimer = 180; // 3 seconds at 60fps
pistolReloadText.alpha = 1;
pistolReloadText.setText('Reloading...');
}
}
// Check for dual pistol pickup
if (dualPistolPickup && !hasDualPistol) {
var dx = x - dualPistolPickup.x;
var dy = y - dualPistolPickup.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
hasDualPistol = true;
dualPistolWeapon = new DualPistol();
dualPistolPickup.destroy();
dualPistolPickup = null;
LK.getSound('collect').play();
}
}
};
game.move = function (x, y, obj) {
if (joystickActive) {
var local = LK.gui.bottomLeft.toLocal({
x: x,
y: y
}, game);
updateJoystick(local.x, local.y);
}
};
game.up = function (x, y, obj) {
if (joystickActive) {
resetJoystick();
}
};
game.update = function () {
// Skip game logic if in menu states
if (gameState === 'mainMenu' || gameState === 'characterSelect') {
return;
}
// Handle joystick movement
if (Math.abs(moveX) > 0.1 || Math.abs(moveY) > 0.1) {
player.x = Math.max(50, Math.min(1998, player.x + moveX * playerSpeed));
player.y = Math.max(50, Math.min(2682, player.y + moveY * playerSpeed));
// Running animation - scale player slightly and add rotation
tween.stop(player, {
scaleX: true,
scaleY: true,
rotation: true
});
tween(player, {
scaleX: 1.1,
scaleY: 0.9,
rotation: moveX * 0.1
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(player, {
scaleX: 1.0,
scaleY: 1.0,
rotation: 0
}, {
duration: 150,
easing: tween.easeIn
});
}
});
}
// Handle pistol reload timer
if (pistolReloading) {
pistolReloadTimer--;
pistolReloadText.alpha = 1;
pistolReloadText.setText('Reload: ' + Math.ceil(pistolReloadTimer / 60) + 's');
// Apply reload speed upgrade
var reloadTime = 180;
for (var i = 0; i < traderUpgrades.length; i++) {
if (traderUpgrades[i].type === "reload" && traderUpgrades[i].purchased) {
reloadTime = 126; // 30% faster reload
break;
}
}
if (pistolReloadTimer <= 0) {
pistolReloading = false;
pistolBullets = 5;
pistolReloadText.alpha = 0;
}
}
// Handle dual pistol reload
if (hasDualPistol && dualPistolWeapon && dualPistolWeapon.isReloading) {
pistolReloadText.alpha = 1;
pistolReloadText.setText('Dual Pistol: ' + Math.ceil(dualPistolWeapon.reloadTimer / 60) + 's');
if (!dualPistolWeapon.isReloading) {
pistolReloadText.alpha = 0;
}
}
// Handle pistol graphics timer
if (pistolTimer > 0) {
pistolTimer--;
if (pistolTimer <= 0 && pistolGraphics) {
pistolGraphics.destroy();
pistolGraphics = null;
}
}
// Placement cooldown logic
if (placementCooldown > 0) {
placementCooldown--;
if (placementCooldown > 0) {
placementCooldownText.alpha = 1;
placementCooldownText.setText('' + Math.ceil(placementCooldown / 60));
disablePlacement = true;
} else {
placementCooldownText.alpha = 0;
disablePlacement = false;
}
}
if (gameState === 'day') {
dayTimer--;
timerText.setText(Math.ceil(dayTimer / 60) + 's');
if (dayTimer <= 0) {
switchToNight();
}
// Resource collection - improved collision detection
var processedResources = 0;
var maxResourcesPerFrame = 5; // Increase limit for better responsiveness
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
// Skip if resource doesn't exist
if (!resource) {
resources.splice(i, 1);
continue;
}
// Limit processing to prevent lag
if (processedResources >= maxResourcesPerFrame) {
break;
}
processedResources++;
var dx = player.x - resource.x;
var dy = player.y - resource.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Use consistent larger hitbox for better collection
if (distance < 150) {
playerResources += resource.value;
resourceText.setText('Resources: ' + playerResources);
resource.destroy();
resources.splice(i, 1);
LK.getSound('collect').play();
}
}
} else if (gameState === 'night') {
nightTimer--;
timerText.setText(Math.ceil(nightTimer / 60) + 's');
// Don't spawn monsters when boss is present (unless boss has special spawn ability)
if (boss === null) {
// Spawn monsters with heavily reduced lag from night 3 onwards
var spawnRate = currentNight >= 3 ? 360 : 240; // Much slower spawn rate to reduce lag
var maxMonsters = currentNight >= 3 ? 3 : 5; // Significantly fewer monsters after night 3
if (LK.ticks % spawnRate === 0 && monsters.length < maxMonsters) {
var monsterTypes = ['scout', 'tank', 'swarm'];
var type = monsterTypes[Math.floor(Math.random() * monsterTypes.length)];
spawnMonster(type);
}
}
// Handle slow enemies timer
if (slowEnemiesTimer > 0) {
slowEnemiesTimer--;
if (slowEnemiesTimer <= 0) {
slowEnemiesActive = false;
}
}
// Monster AI and collision - process only every few frames to reduce lag
var shouldProcessMonsters = LK.ticks % 3 === 0; // Process every third frame
var processedMonsters = 0;
var maxMonstersPerFrame = 2; // Limit monsters processed per frame
for (var i = monsters.length - 1; i >= 0; i--) {
var monster = monsters[i];
// Skip if monster doesn't exist
if (!monster) {
monsters.splice(i, 1);
continue;
}
// Skip dead monsters for collision and movement
if (monster.isDead) {
continue;
}
// Limit processing to prevent lag
if (processedMonsters >= maxMonstersPerFrame) {
break;
}
processedMonsters++;
// Apply slow effect if active
var originalSpeed = monster.speed;
if (slowEnemiesActive) {
monster.speed = originalSpeed * 0.3; // 70% slower
}
// Skip AI processing for some frames to reduce lag - process only 1 in 3 monsters per frame
if (!shouldProcessMonsters && i % 3 !== 0) {
continue;
}
// Check collision with player
var dx = player.x - monster.x;
var dy = player.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 70) {
playerHealth -= monster.damage;
healthText.setText('Health: ' + playerHealth);
monster.destroy();
monsters.splice(i, 1);
LK.getSound('damage').play();
}
// Resource collection is now handled in the main collection loop above
// This prevents double-collection and conflicts
if (distance < 70) {
// Check for special abilities when health drops to 30
if (playerHealth <= 30) {
if (selectedCharacter === 0 && !berserkUsed) {
// Warrior berserk mode
berserkMode = true;
berserkUsed = true;
playerSpeed = 8; // Increased speed
characterStats.damageMultiplier = 2.0; // Double damage
slowEnemiesActive = true;
slowEnemiesTimer = 600; // 10 seconds
LK.effects.flashScreen(0xFF0000, 1000); // Red flash
} else if (selectedCharacter === 1 && !medicReviveUsed) {
// Medic auto-heal
playerHealth = 50;
medicReviveUsed = true;
healthText.setText('Health: ' + playerHealth);
LK.effects.flashScreen(0x00FF00, 1000); // Green flash
} else if (selectedCharacter === 2 && !engineerBoostUsed) {
// Engineer boost
engineerBoostActive = true;
engineerBoostUsed = true;
playerSpeed = 7; // Increased speed
LK.effects.flashScreen(0x0000FF, 1000); // Blue flash
}
}
if (playerHealth <= 0) {
LK.showGameOver();
}
continue;
}
// Check collision with walls
var hitWall = false;
for (var j = 0; j < walls.length; j++) {
var wall = walls[j];
if (wall.health > 0 && !monster.isDead && monster.intersects(wall)) {
// Monster only attacks wall every 2 seconds (120 ticks)
// Only if player is within 300px or monster is within 300px of wall (simulate "seeing" wall)
var playerDist = Math.sqrt((player.x - monster.x) * (player.x - monster.x) + (player.y - monster.y) * (player.y - monster.y));
var wallDist = Math.sqrt((wall.x - monster.x) * (wall.x - monster.x) + (wall.y - monster.y) * (wall.y - monster.y));
if (playerDist < 300 || wallDist < 300) {
if (LK.ticks - wall.lastMonsterHitTick >= 120) {
wall.registerMonsterHit();
wall.takeDamage(monster.damage);
LK.effects.flashObject(wall, 0xff0000, 200);
// If wall is destroyed after 3 hits, set health to 0 and alpha to 0.3
if (wall.hitCount >= 3 || wall.health <= 0) {
wall.health = 0;
wall.alpha = 0.3;
}
}
}
// Monster stays and keeps attacking, do not destroy monster
hitWall = true;
break;
}
}
if (hitWall) continue;
// Check collision with traps
for (var k = 0; k < traps.length; k++) {
var trap = traps[k];
if (!monster.isDead && monster.intersects(trap)) {
var trapDamage = trap.activate();
if (trapDamage > 0) {
var isDead = monster.takeDamage(trapDamage);
if (isDead) {
// Add kill animation
tween(monster, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
LK.setScore(LK.getScore() + 10);
break;
}
}
}
}
}
// Handle boss combat
if (boss !== null) {
// Update boss health bar
var healthPercent = boss.health / boss.maxHealth;
bossHealthBarFill.scaleX = 10 * healthPercent;
bossHealthText.setText('BOSS: ' + boss.health + '/' + boss.maxHealth);
}
// Handle bomb collisions and explosions
var processedBombs = 0;
var maxBombsPerFrame = 2; // Limit bombs processed per frame
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
// Skip if bomb doesn't exist
if (!bomb) {
bombs.splice(i, 1);
continue;
}
// Limit processing to prevent lag
if (processedBombs >= maxBombsPerFrame) {
break;
}
processedBombs++;
var bombHit = false;
// Check collision with monsters
for (var j = monsters.length - 1; j >= 0; j--) {
var monster = monsters[j];
var dx = bomb.x - monster.x;
var dy = bomb.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 50) {
// Create explosion effect
LK.effects.flashObject(bomb, 0xFF6600, 500);
// Stun and damage all monsters within explosion radius
for (var k = monsters.length - 1; k >= 0; k--) {
var targetMonster = monsters[k];
var expDx = bomb.x - targetMonster.x;
var expDy = bomb.y - targetMonster.y;
var expDistance = Math.sqrt(expDx * expDx + expDy * expDy);
if (expDistance < bomb.explosionRadius) {
var isDead = targetMonster.takeDamage(2);
// Stun effect - reduce speed temporarily
targetMonster.speed = targetMonster.speed * 0.1;
if (isDead) {
// Add kill animation
tween(targetMonster, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
LK.setScore(LK.getScore() + 10);
}
}
}
bomb.destroy();
bombs.splice(i, 1);
bombHit = true;
break;
}
}
// Check collision with boss
if (!bombHit && boss !== null) {
var dx = bomb.x - boss.x;
var dy = bomb.y - boss.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
// Explosion damage to boss
var isBossDead = boss.takeDamage(3);
if (isBossDead) {
LK.setScore(LK.getScore() + 100);
// Drop dual pistol weapon
if (!hasDualPistol && !dualPistolPickup) {
dualPistolPickup = new DualPistol();
dualPistolPickup.x = boss.x;
dualPistolPickup.y = boss.y;
game.addChild(dualPistolPickup);
}
boss.destroy();
boss = null;
// Hide boss health bar
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
LK.effects.flashScreen(0x00ff00, 500);
}
bomb.destroy();
bombs.splice(i, 1);
}
}
}
// Handle bullet collisions - process only every other frame to reduce lag
if (LK.ticks % 2 === 0) {
var processedBullets = 0;
var maxBulletsPerFrame = 3; // Limit bullets processed per frame
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
// Skip if bullet doesn't exist
if (!bullet) {
bullets.splice(i, 1);
continue;
}
// Limit processing to prevent lag
if (processedBullets >= maxBulletsPerFrame) {
break;
}
processedBullets++;
var bulletHit = false;
// Modify bullet size for engineer
if (engineerBoostActive && selectedCharacter === 2) {
bullet.scaleX = 2.0;
bullet.scaleY = 2.0;
}
// Check collision with monsters
for (var j = monsters.length - 1; j >= 0; j--) {
var monster = monsters[j];
// Skip dead monsters
if (monster.isDead) continue;
var dx = bullet.x - monster.x;
var dy = bullet.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var hitRadius = engineerBoostActive && selectedCharacter === 2 ? 70 : 50;
if (distance < hitRadius) {
var isDead = monster.takeDamage(bullet.damage);
if (isDead) {
// Add kill animation
tween(monster, {
scaleX: 1.5,
scaleY: 1.5,
alpha: 0.3
}, {
duration: 200,
easing: tween.easeOut
});
LK.setScore(LK.getScore() + 10);
}
bullet.destroy();
bullets.splice(i, 1);
bulletHit = true;
break;
}
}
// Check collision with boss
if (!bulletHit && boss !== null) {
var dx = bullet.x - boss.x;
var dy = bullet.y - boss.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 80) {
var isBossDead = boss.takeDamage(bullet.damage);
if (isBossDead) {
LK.setScore(LK.getScore() + 100);
// Drop dual pistol weapon
if (!hasDualPistol && !dualPistolPickup) {
dualPistolPickup = new DualPistol();
dualPistolPickup.x = boss.x;
dualPistolPickup.y = boss.y;
game.addChild(dualPistolPickup);
}
boss.destroy();
boss = null;
// Hide boss health bar
bossHealthBar.alpha = 0;
bossHealthBarFill.alpha = 0;
bossHealthText.alpha = 0;
LK.effects.flashScreen(0x00ff00, 500); // Green flash for boss kill
}
bullet.destroy();
bullets.splice(i, 1);
}
}
}
}
if (nightTimer <= 0 && boss === null) {
// Clear remaining monsters
for (var m = monsters.length - 1; m >= 0; m--) {
monsters[m].destroy();
monsters.splice(m, 1);
}
// Clear remaining bullets
for (var b = bullets.length - 1; b >= 0; b--) {
bullets[b].destroy();
bullets.splice(b, 1);
}
// Clear remaining bombs
for (var bomb = bombs.length - 1; bomb >= 0; bomb--) {
bombs[bomb].destroy();
bombs.splice(bomb, 1);
}
switchToDay();
}
}
}; ===================================================================
--- original.js
+++ change.js
@@ -549,8 +549,25 @@
self.rotation += 0.05;
};
return self;
});
+var TraderNPC = Container.expand(function () {
+ var self = Container.call(this);
+ var traderGraphics = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ scaleX: 1.5,
+ scaleY: 1.5
+ });
+ traderGraphics.tint = 0xFFD700; // Gold color for trader
+ self.type = 'trader';
+ self.update = function () {
+ // Gentle floating animation
+ self.y += Math.sin(LK.ticks * 0.1) * 0.5;
+ self.rotation += 0.02;
+ };
+ return self;
+});
var Trap = Container.expand(function () {
var self = Container.call(this);
var trapGraphics = self.attachAsset('trap', {
anchorX: 0.5,
@@ -731,8 +748,40 @@
damageMultiplier: selectedCharacter === 0 ? 1.3 : 1.0,
healPerNight: selectedCharacter === 1 ? 10 : 0,
discountMultiplier: selectedCharacter === 2 ? 0.8 : 1.0
};
+ // Trader system variables
+ var currentDay = storage.currentDay || 1;
+ var traderActive = false;
+ var traderContainer = null;
+ var weaponUpgradePurchased = storage.weaponUpgradePurchased || false;
+ var costReductionPurchased = storage.costReductionPurchased || false;
+ var traderUpgrades = [{
+ name: "Weapon Damage +10%",
+ cost: 50,
+ type: "weapon",
+ purchased: false
+ }, {
+ name: "Build Cost -10%",
+ cost: 30,
+ type: "cost",
+ purchased: false
+ }, {
+ name: "Health +20",
+ cost: 40,
+ type: "health",
+ purchased: false
+ }, {
+ name: "Speed +20%",
+ cost: 35,
+ type: "speed",
+ purchased: false
+ }, {
+ name: "Reload Speed +30%",
+ cost: 45,
+ type: "reload",
+ purchased: false
+ }];
// Special ability states
var berserkMode = false;
var berserkUsed = false;
var medicReviveUsed = false;
@@ -1111,8 +1160,118 @@
gameState = 'mainMenu';
playerHealth = 100;
playerResources = 50;
}
+function createTraderUI() {
+ traderContainer = new Container();
+ // Background
+ var traderBg = LK.getAsset('buttonTexture', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 0,
+ scaleX: 8,
+ scaleY: 6
+ });
+ traderBg.tint = 0x333333;
+ traderContainer.addChild(traderBg);
+ // Title
+ var traderTitle = new Text2('TRADER', {
+ size: 80,
+ fill: 0xFFD700
+ });
+ traderTitle.anchor.set(0.5, 0.5);
+ traderTitle.x = 0;
+ traderTitle.y = -200;
+ traderContainer.addChild(traderTitle);
+ // Create upgrade buttons
+ var availableUpgrades = traderUpgrades.filter(function (upgrade) {
+ return !upgrade.purchased;
+ });
+ // Show up to 3 random upgrades
+ for (var i = 0; i < Math.min(3, availableUpgrades.length); i++) {
+ var upgrade = availableUpgrades[Math.floor(Math.random() * availableUpgrades.length)];
+ var yPos = -50 + i * 80;
+ var upgradeButton = LK.getAsset('buttonTexture', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: yPos,
+ scaleX: 6,
+ scaleY: 1.5
+ });
+ upgradeButton.upgradeData = upgrade;
+ traderContainer.addChild(upgradeButton);
+ var upgradeText = new Text2(upgrade.name + ' - ' + upgrade.cost + ' Resources', {
+ size: 40,
+ fill: 0xFFFFFF
+ });
+ upgradeText.anchor.set(0.5, 0.5);
+ upgradeText.x = 0;
+ upgradeText.y = yPos;
+ traderContainer.addChild(upgradeText);
+ // Remove from available list to prevent duplicates
+ availableUpgrades.splice(availableUpgrades.indexOf(upgrade), 1);
+ }
+ // Close button
+ var closeButton = LK.getAsset('buttonTexture', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 0,
+ y: 150,
+ scaleX: 3,
+ scaleY: 2
+ });
+ var closeText = new Text2('CLOSE', {
+ size: 60,
+ fill: 0xFFFFFF
+ });
+ closeText.anchor.set(0.5, 0.5);
+ closeText.x = 0;
+ closeText.y = 150;
+ traderContainer.addChild(closeButton);
+ traderContainer.addChild(closeText);
+ LK.gui.center.addChild(traderContainer);
+}
+function closeTrader() {
+ if (traderContainer) {
+ traderContainer.destroy();
+ traderContainer = null;
+ }
+ traderActive = false;
+}
+function purchaseUpgrade(upgrade) {
+ if (playerResources >= upgrade.cost) {
+ playerResources -= upgrade.cost;
+ resourceText.setText('Resources: ' + playerResources);
+ upgrade.purchased = true;
+ // Apply upgrade effects
+ switch (upgrade.type) {
+ case "weapon":
+ characterStats.damageMultiplier += 0.1;
+ weaponUpgradePurchased = true;
+ storage.weaponUpgradePurchased = true;
+ break;
+ case "cost":
+ characterStats.discountMultiplier *= 0.9;
+ costReductionPurchased = true;
+ storage.costReductionPurchased = true;
+ break;
+ case "health":
+ playerHealth = Math.min(120, playerHealth + 20);
+ healthText.setText('Health: ' + playerHealth);
+ break;
+ case "speed":
+ playerSpeed *= 1.2;
+ break;
+ case "reload":
+ // This will be applied in reload logic
+ break;
+ }
+ closeTrader();
+ LK.getSound('collect').play();
+ }
+}
var placementCooldownText = new Text2('', {
size: 80,
fill: 0xFF0000
});
@@ -1120,10 +1279,11 @@
placementCooldownText.x = 0;
placementCooldownText.y = 0;
placementCooldownText.alpha = 0;
LK.gui.center.addChild(placementCooldownText);
-// Spawn initial resources - only 5 at start
-for (var i = 0; i < 5; i++) {
+// Spawn initial resources - 5 + 2 per day progression
+var resourcesToSpawn = 5 + (currentDay - 1) * 2;
+for (var i = 0; i < resourcesToSpawn; i++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 1200;
resources.push(resource);
@@ -1207,10 +1367,12 @@
}
}
function switchToDay() {
gameState = 'day';
+ currentDay++;
+ storage.currentDay = currentDay;
dayTimer = 1800; // 30 seconds
- gameStateText.setText('Day Phase');
+ gameStateText.setText('Day ' + currentDay);
timerText.setText('30s');
// Switch to day background
dayBackground.alpha = 1;
nightBackground.alpha = 0;
@@ -1226,16 +1388,22 @@
wallButton.tint = 0x00FF00;
trapButton.tint = 0xFFFFFF;
wallIcon.tint = 0x00FF00;
trapIcon.tint = 0xFFFFFF;
- // Spawn new resources - only 2 per day
- for (var i = 0; i < 2; i++) {
+ // Spawn new resources - progressive system: 5 + 2 * (currentDay - 1)
+ var resourcesToSpawn = 5 + (currentDay - 1) * 2;
+ for (var i = 0; i < resourcesToSpawn; i++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 1200;
resources.push(resource);
game.addChild(resource);
}
+ // Check if trader should appear (every 5 days)
+ if (currentDay % 5 === 0) {
+ traderActive = true;
+ createTraderUI();
+ }
}
// Joystick movement handler
function updateJoystick(x, y) {
var dx = x - joystickCenterX;
@@ -1445,8 +1613,31 @@
LK.getSound('collect').play();
return;
}
}
+ // Check trader interactions
+ if (traderActive && traderContainer) {
+ var local = LK.gui.center.toLocal({
+ x: x,
+ y: y
+ }, game);
+ // Check upgrade buttons
+ for (var i = 0; i < traderContainer.children.length; i++) {
+ var child = traderContainer.children[i];
+ if (child.upgradeData) {
+ var childBounds = child.getBounds();
+ if (local.x >= childBounds.x && local.x <= childBounds.x + childBounds.width && local.y >= childBounds.y && local.y <= childBounds.y + childBounds.height) {
+ purchaseUpgrade(child.upgradeData);
+ return;
+ }
+ }
+ }
+ // Check close button
+ if (local.x >= -180 && local.x <= 180 && local.y >= 90 && local.y <= 210) {
+ closeTrader();
+ return;
+ }
+ }
if (disablePlacement) {
return; // Prevent placing objects while a button is pressed
}
if (gameState === 'day') {
@@ -1670,8 +1861,16 @@
if (pistolReloading) {
pistolReloadTimer--;
pistolReloadText.alpha = 1;
pistolReloadText.setText('Reload: ' + Math.ceil(pistolReloadTimer / 60) + 's');
+ // Apply reload speed upgrade
+ var reloadTime = 180;
+ for (var i = 0; i < traderUpgrades.length; i++) {
+ if (traderUpgrades[i].type === "reload" && traderUpgrades[i].purchased) {
+ reloadTime = 126; // 30% faster reload
+ break;
+ }
+ }
if (pistolReloadTimer <= 0) {
pistolReloading = false;
pistolBullets = 5;
pistolReloadText.alpha = 0;
Crea picos de madera, que todos estén unidos en una tablilla por abajo y que arriba estén los picos. In-Game asset. 2d. High contrast. No shadows
Crea un botón de color azul pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de lava pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un guerrero pixel, sin armas, y que tenga la cabeza un poco más grande que el cuerpo tipo pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un monstruo corrupto morado de piedra qué no sea tan terrorífico, y que sea pixel.Y qué tenga manos grandes, y torso y que la cabeza no sea tan terrorífico, y no le ponga ojos perturbadores, y que su cabeza sea de un tamaño moderado no muy grande, que algo que si sea grande sea sus brazos, y que tenga algas moradas y que tenga algunas piedras moradas y otras piedras que no sean moradas qué sean grises In-Game asset. 2d. High contrast. No shadows.
Genera una imagen verde solo verde oscuro. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una avispa no terroríficas, pixel y que sean moradas. Que sea corrupta In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un corrupto pixel, y que no sea terrorífico y que sea morado. In-Game asset. 2d. High contrast. No shadows
Genera una imagen morado oscuro solo morado oscuro In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una roca morada sonriente. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un círculo verde pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un destello brillante morado pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una pistola pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de una bala pixel. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un médico guerrero pixel, y que su cabeza sea un poco más grande que el cuerpo. Y que no tenga armas In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un albañil guerrero pixel, que su cabeza sea un poco más grande que su cuerpo, y que no tenga armas. In-Game asset. 2d. High contrast. No shadows
Genera una imagen de un comerciante pixel y que su cabeza sea un poco más grande que su cuerpo. In-Game asset. 2d. High contrast. No shadows
Crea una imagen de un texto que diga "The corrupt survival" qué sea pixel y en la palabra "i" ponle una espada pixel. In-Game asset. 2d. High contrast. No shadows