User prompt
make the game longer, make it a basic background color change from dark gray on top and bottom to black to the middle, be sure the bars fit their places and they dont go on eachother
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'isSelected')' in or related to this line: 'self.choices[i].isSelected = false;' Line Number: 170
Code edit (1 edits merged)
Please save this source code
User prompt
The Angel's Cage
Initial prompt
A retro-styled, choice-driven role-playing game where the player controls a man at the near of the apocalypse.God sends an angel but humans greed and their situation being desperate results as them building a giant machine and trapping the angel inside it, generating the power to save the earth by force. God is angry and our main character thinks all of this thing is wrong, we are trying to get the angel out of the machine. The core mechanic allows the player to resolve every encounter either through combat or through non-violent dialogue and empathy. The narrative dynamically adapts to the player’s behavior, tracking moral choices and altering characters, scenes, and endings accordingly. Its tone shifts between humor, melancholy, and psychological intensity, and it frequently breaks the fourth wall, acknowledging the player’s actions across playthroughs. Visual presentation is minimalistic pixel art, music is highly thematic and character-specific, and the story’s emotional impact relies on subverting expectations of typical RPG tropes. The players answers in some dialogues affects the storyline. Even slight changes can turn the game's stories direction to a whole different perspective and create different levels of tension. There is a secret ending, a good ending, a bad ending, the neutral ending (the canon one), and hellish ending which is brutal and you wouldn't like to see it if you were the player. Secret and hellish are harder to achieve than the other 3. The endings shapes by the answers you give to dialogues and where you decided to show mercy or continued fighting. Even tho what ending you got, the game could make you feel different emotions because even if you achieved the same ending with another player, you can still give different answers to different dialogues to reach it and until you reach that ending the tension of the game will be way different than the others which is the thing that makes this game unique. This looks like an interactive series but it actually has some rpg taste in it and pretty enjoyable fightning mechanics that every age group can enjoy. Dont push yourself to make models by code, i will handle them later.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
playCount: 0,
mercyScore: 0,
dialogueChoices: {},
endingReached: "none",
characterRelationships: {}
});
/****
* Classes
****/
var CombatEnemy = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('combatEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
var healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5
});
healthBar.y = -60;
var healthFill = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x00ff00
});
healthBar.addChild(healthFill);
self.maxHealth = 30;
self.currentHealth = 30;
self.name = '';
self.damage = 5;
self.enemyId = null;
self.setData = function (id, name, health, damage) {
self.enemyId = id;
self.name = name;
self.maxHealth = health;
self.currentHealth = health;
self.damage = damage;
};
self.takeDamage = function (amount) {
self.currentHealth -= amount;
if (self.currentHealth < 0) {
self.currentHealth = 0;
}
var healthPercent = self.currentHealth / self.maxHealth;
healthFill.scaleX = healthPercent;
LK.getSound('combatDamage').play();
};
self.isDefeated = function () {
return self.currentHealth <= 0;
};
return self;
});
var DialogueChoice = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('choiceButton', {
anchorX: 0.5,
anchorY: 0.5
});
var text = new Text2('', {
size: 40,
fill: '#ffffff'
});
text.anchor.set(0.5, 0.5);
self.addChild(text);
self.setText = function (str) {
text.setText(str);
};
self.choiceId = null;
self.isSelected = false;
self.down = function (x, y, obj) {
if (!self.isSelected) {
self.isSelected = true;
LK.getSound('choiceSelect').play();
tween(background, {
alpha: 0.7
}, {
duration: 100
});
}
};
return self;
});
var DialogueSystem = Container.expand(function () {
var self = Container.call(this);
var background = self.attachAsset('dialogueBox', {
anchorX: 0.5,
anchorY: 0.5
});
background.alpha = 0.95;
var speakerName = new Text2('', {
size: 36,
fill: '#ffff00'
});
speakerName.anchor.set(0, 0);
speakerName.x = 20;
speakerName.y = 20;
self.addChild(speakerName);
var dialogueText = new Text2('', {
size: 32,
fill: '#ffffff'
});
dialogueText.anchor.set(0, 0);
dialogueText.x = 30;
dialogueText.y = 70;
dialogueText.wordWrap = true;
dialogueText.wordWrapWidth = 1740;
self.addChild(dialogueText);
self.choices = [];
self.currentNode = null;
self.onChoiceCallback = null;
self.displayDialogue = function (npcName, text, choicesArray) {
speakerName.setText(npcName);
dialogueText.setText(text);
self.clearChoices();
if (choicesArray && choicesArray.length > 0) {
var choiceSpacing = 100;
var startY = 350;
for (var i = 0; i < choicesArray.length; i++) {
var choice = new DialogueChoice();
choice.x = 1024;
choice.y = startY + i * choiceSpacing;
choice.setText(choicesArray[i].text);
choice.choiceId = choicesArray[i].id;
choice.onSelectCallback = choicesArray[i].callback;
self.addChild(choice);
self.choices.push(choice);
}
}
};
self.clearChoices = function () {
for (var i = self.choices.length - 1; i >= 0; i--) {
self.choices[i].destroy();
}
self.choices = [];
};
self.update = function () {
for (var i = 0; i < self.choices.length; i++) {
if (self.choices[i].isSelected) {
if (self.choices[i].onSelectCallback) {
self.choices[i].onSelectCallback();
}
self.clearChoices();
self.choices[i].isSelected = false;
}
}
};
return self;
});
var NPC = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('npcCharacter', {
anchorX: 0.5,
anchorY: 0.5
});
var nameLabel = new Text2('', {
size: 32,
fill: '#ffffff'
});
nameLabel.anchor.set(0.5, 0);
nameLabel.y = 50;
self.addChild(nameLabel);
self.npcId = null;
self.name = '';
self.relationship = 0;
self.dialogueTree = null;
self.isEnemy = false;
self.setData = function (id, name, dialogueTree, isEnemy) {
self.npcId = id;
self.name = name;
self.dialogueTree = dialogueTree;
self.isEnemy = isEnemy;
nameLabel.setText(name);
if (isEnemy) {
sprite.tint = 0xff6666;
}
};
self.updateRelationship = function (delta) {
self.relationship += delta;
storage.characterRelationships[self.npcId] = self.relationship;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var sprite = self.attachAsset('playerCharacter', {
anchorX: 0.5,
anchorY: 0.5
});
var healthBar = self.attachAsset('healthBar', {
anchorX: 0.5,
anchorY: 0.5
});
healthBar.y = -50;
var healthFill = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0,
tint: 0x00ff00
});
healthBar.addChild(healthFill);
self.maxHealth = 50;
self.currentHealth = 50;
self.empathy = 50;
self.maxEmpathy = 100;
self.mercyMeter = 0;
self.takeDamage = function (amount) {
self.currentHealth -= amount;
if (self.currentHealth < 0) {
self.currentHealth = 0;
}
var healthPercent = self.currentHealth / self.maxHealth;
healthFill.scaleX = healthPercent;
LK.getSound('combatDamage').play();
};
self.heal = function (amount) {
self.currentHealth += amount;
if (self.currentHealth > self.maxHealth) {
self.currentHealth = self.maxHealth;
}
};
self.gainEmpathy = function (amount) {
self.empathy += amount;
if (self.empathy > self.maxEmpathy) {
self.empathy = self.maxEmpathy;
}
};
self.recordMercyChoice = function (isMercy) {
if (isMercy) {
self.mercyMeter += 1;
storage.mercyScore += 1;
} else {
self.mercyMeter -= 1;
storage.mercyScore -= 1;
}
};
self.isDefeated = function () {
return self.currentHealth <= 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a0a
});
/****
* Game Code
****/
var gameState = {
currentScene: 'start',
inCombat: false,
inDialogue: false,
sceneCount: 0,
endingType: 'none'
};
var player = null;
var currentNPC = null;
var currentEnemy = null;
var dialogueSystem = null;
var npcList = {};
var combatLog = [];
function initializeGame() {
storage.playCount = (storage.playCount || 0) + 1;
player = game.addChild(new Player());
player.x = 400;
player.y = 1366;
dialogueSystem = game.addChild(new DialogueSystem());
dialogueSystem.x = 1024;
dialogueSystem.y = 1900;
dialogueSystem.alpha = 0;
var angelLabel = new Text2('ANGEL IMPRISONED', {
size: 48,
fill: '#ffd700'
});
angelLabel.anchor.set(0.5, 0.5);
angelLabel.x = 1600;
angelLabel.y = 400;
game.addChild(angelLabel);
var angel = game.addChild(LK.getAsset('angelForm', {
anchorX: 0.5,
anchorY: 0.5
}));
angel.x = 1600;
angel.y = 300;
var machine = game.addChild(LK.getAsset('machineBody', {
anchorX: 0.5,
anchorY: 0.5
}));
machine.x = 1600;
machine.y = 550;
initializeNPCs();
loadStoredRelationships();
LK.playMusic('ambientDrone', {
loop: true
});
startScene('prologue');
}
function initializeNPCs() {
var npcData = {
scientist: {
name: 'Dr. Elena',
dialogueTree: dialogueTreeScientist,
isEnemy: false
},
survivor: {
name: 'Marcus',
dialogueTree: dialogueTreeSurvivor,
isEnemy: false
},
guardian: {
name: 'Sentinel',
dialogueTree: dialogueTreeGuardian,
isEnemy: true
}
};
for (var id in npcData) {
var npc = new NPC();
npc.setData(id, npcData[id].name, npcData[id].dialogueTree, npcData[id].isEnemy);
npcList[id] = npc;
if (!storage.characterRelationships[id]) {
storage.characterRelationships[id] = 0;
}
npc.relationship = storage.characterRelationships[id];
}
}
function loadStoredRelationships() {
for (var id in npcList) {
npcList[id].relationship = storage.characterRelationships[id] || 0;
}
}
function startScene(sceneName) {
gameState.currentScene = sceneName;
gameState.sceneCount += 1;
if (sceneName === 'prologue') {
showPrologue();
} else if (sceneName === 'hub') {
showHub();
} else if (sceneName === 'encounter_scientist') {
showEncounterScientist();
} else if (sceneName === 'encounter_survivor') {
showEncounterSurvivor();
} else if (sceneName === 'encounter_guardian') {
showEncounterGuardian();
} else if (sceneName === 'endgame') {
determineEnding();
}
}
function showPrologue() {
tween(dialogueSystem, {
alpha: 1
}, {
duration: 500
});
var prologueText = 'The world has ended. Heaven sent salvation, but humanity chose slavery. An angel was imprisoned in a machine to harvest divine power. You believe this is wrong. You will free it... or die trying.';
var choices = [{
id: 'start_yes',
text: 'I will free the angel, no matter the cost.',
callback: function callback() {
storage.dialogueChoices['prologue_choice'] = 'start_yes';
LK.setTimeout(function () {
startScene('hub');
}, 500);
}
}, {
id: 'start_question',
text: 'Is the angel really worth humanity\'s suffering?',
callback: function callback() {
storage.dialogueChoices['prologue_choice'] = 'start_question';
gameState.endingType = 'neutral';
LK.setTimeout(function () {
startScene('hub');
}, 500);
}
}];
dialogueSystem.displayDialogue('The Universe', prologueText, choices);
}
function showHub() {
if (gameState.sceneCount === 2) {
var hubText = 'You stand before the machine. Three paths lie before you: seek the scientist who built it, convince the survivor supporting it, or face the guardian protecting it.';
var choices = [{
id: 'hub_scientist',
text: 'Confront Dr. Elena, the machine\'s architect.',
callback: function callback() {
startScene('encounter_scientist');
}
}, {
id: 'hub_survivor',
text: 'Talk to Marcus, who believes the angel should stay imprisoned.',
callback: function callback() {
startScene('encounter_survivor');
}
}, {
id: 'hub_guardian',
text: 'Fight the Sentinel protecting the machine.',
callback: function callback() {
startScene('encounter_guardian');
}
}];
dialogueSystem.displayDialogue('Your Inner Voice', hubText, choices);
}
}
function showEncounterScientist() {
currentNPC = npcList['scientist'];
var scientistText = 'Dr. Elena looks at you with tired eyes. "We did what we had to. This angel... it gives us power to rebuild. Without it, humanity is finished."';
var choices = [{
id: 'sci_mercy',
text: 'I understand your desperation. Let me help find another way.',
callback: function callback() {
player.recordMercyChoice(true);
npcList['scientist'].updateRelationship(2);
storage.dialogueChoices['scientist_choice'] = 'mercy';
combatVsDialogue('scientist', true);
}
}, {
id: 'sci_condemn',
text: 'Your arrogance has damned us all. The angel must be freed.',
callback: function callback() {
player.recordMercyChoice(false);
npcList['scientist'].updateRelationship(-3);
storage.dialogueChoices['scientist_choice'] = 'condemn';
combatVsDialogue('scientist', false);
}
}];
dialogueSystem.displayDialogue('Dr. Elena', scientistText, choices);
}
function showEncounterSurvivor() {
currentNPC = npcList['survivor'];
var survivorText = 'Marcus grips your shoulder. "Everyone I love is alive because of that angel. You want to take that away? What gives you the right?"';
var choices = [{
id: 'surv_mercy',
text: 'Your loved ones matter. But so does freedom. We can find balance.',
callback: function callback() {
player.recordMercyChoice(true);
npcList['survivor'].updateRelationship(2);
storage.dialogueChoices['survivor_choice'] = 'mercy';
combatVsDialogue('survivor', true);
}
}, {
id: 'surv_condemn',
text: 'Love built on slavery is no love at all.',
callback: function callback() {
player.recordMercyChoice(false);
npcList['survivor'].updateRelationship(-3);
storage.dialogueChoices['survivor_choice'] = 'condemn';
combatVsDialogue('survivor', false);
}
}];
dialogueSystem.displayDialogue('Marcus', survivorText, choices);
}
function showEncounterGuardian() {
currentEnemy = new CombatEnemy();
currentEnemy.x = 1600;
currentEnemy.y = 600;
game.addChild(currentEnemy);
currentEnemy.setData('sentinel', 'Sentinel', 40, 8);
var guardianText = 'The mechanical guardian stands motionless, then speaks: "I was programmed to protect. I do not question. Surrender or be destroyed."';
var choices = [{
id: 'guar_talk',
text: 'You\'re more than your programming. You can choose.',
callback: function callback() {
player.recordMercyChoice(true);
storage.dialogueChoices['guardian_choice'] = 'talk';
startCombat('sentinel_dialogue');
}
}, {
id: 'guar_fight',
text: 'Then I\'ll fight you.',
callback: function callback() {
player.recordMercyChoice(false);
storage.dialogueChoices['guardian_choice'] = 'fight';
startCombat('sentinel_combat');
}
}];
dialogueSystem.displayDialogue('Sentinel', guardianText, choices);
}
function combatVsDialogue(npcId, isDialogue) {
gameState.inDialogue = isDialogue;
tween(dialogueSystem, {
alpha: 0
}, {
duration: 300
});
if (isDialogue) {
LK.setTimeout(function () {
resolveEncounter(npcId, true);
}, 400);
} else {
currentEnemy = new CombatEnemy();
currentEnemy.x = 1600;
currentEnemy.y = 600;
game.addChild(currentEnemy);
if (npcId === 'scientist') {
currentEnemy.setData('scientist', 'Dr. Elena', 35, 6);
} else if (npcId === 'survivor') {
currentEnemy.setData('survivor', 'Marcus', 30, 7);
}
startCombat(npcId);
}
}
function startCombat(combatId) {
gameState.inCombat = true;
LK.playMusic('combatTheme', {
loop: true
});
var combatUI = new Text2('COMBAT: ' + currentEnemy.name.toUpperCase(), {
size: 48,
fill: '#ff4444'
});
combatUI.anchor.set(0.5, 0);
combatUI.x = 1024;
combatUI.y = 100;
game.addChild(combatUI);
var attackButton = new DialogueChoice();
attackButton.x = 500;
attackButton.y = 1300;
attackButton.setText('ATTACK (DMG: 8)');
game.addChild(attackButton);
var defendButton = new DialogueChoice();
defendButton.x = 1500;
defendButton.y = 1300;
defendButton.setText('DEFEND');
game.addChild(defendButton);
attackButton.down = function (x, y, obj) {
player.recordMercyChoice(false);
playerAttack();
};
defendButton.down = function (x, y, obj) {
playerDefend();
};
game.combatUI = {
title: combatUI,
attackBtn: attackButton,
defendBtn: defendButton
};
}
function playerAttack() {
if (!gameState.inCombat) return;
var damage = 8 + Math.floor(Math.random() * 4);
currentEnemy.takeDamage(damage);
LK.getSound('combatHit').play();
var damageText = new Text2('-' + damage, {
size: 36,
fill: '#ff0000'
});
damageText.x = currentEnemy.x;
damageText.y = currentEnemy.y - 50;
game.addChild(damageText);
tween(damageText, {
y: damageText.y - 50,
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
damageText.destroy();
}
});
if (currentEnemy.isDefeated()) {
endCombat(true);
} else {
LK.setTimeout(enemyTurn, 600);
}
}
function playerDefend() {
if (!gameState.inCombat) return;
player.heal(5);
var healText = new Text2('+5', {
size: 36,
fill: '#00ff00'
});
healText.x = player.x;
healText.y = player.y - 50;
game.addChild(healText);
tween(healText, {
y: healText.y - 50,
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
healText.destroy();
}
});
LK.setTimeout(enemyTurn, 600);
}
function enemyTurn() {
if (!gameState.inCombat || !currentEnemy) return;
var enemyDamage = currentEnemy.damage + Math.floor(Math.random() * 3);
player.takeDamage(enemyDamage);
var damageText = new Text2('-' + enemyDamage, {
size: 36,
fill: '#ff0000'
});
damageText.x = player.x;
damageText.y = player.y - 50;
game.addChild(damageText);
tween(damageText, {
y: damageText.y - 50,
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
damageText.destroy();
}
});
if (player.isDefeated()) {
endCombat(false);
}
}
function endCombat(playerWon) {
gameState.inCombat = false;
LK.playMusic('ambientDrone', {
loop: true
});
if (game.combatUI) {
game.combatUI.title.destroy();
game.combatUI.attackBtn.destroy();
game.combatUI.defendBtn.destroy();
game.combatUI = null;
}
if (currentEnemy) {
currentEnemy.destroy();
currentEnemy = null;
}
if (playerWon) {
resolveEncounter(null, false);
} else {
LK.showGameOver();
}
}
function resolveEncounter(npcId, throughDialogue) {
tween(dialogueSystem, {
alpha: 1
}, {
duration: 500
});
var resolutionText = '';
if (throughDialogue && npcId === 'scientist') {
resolutionText = 'Dr. Elena looks down, tears forming. "Maybe... maybe there is another way. I\'ll help you free it."';
} else if (!throughDialogue && npcId === 'scientist') {
resolutionText = 'Dr. Elena falls. Your violence has solved the immediate problem, but at what cost?';
} else if (throughDialogue && npcId === 'survivor') {
resolutionText = 'Marcus nods slowly. "You\'re right. Freedom matters more than my fear."';
} else if (!throughDialogue && npcId === 'survivor') {
resolutionText = 'Marcus collapses. You wonder if he was ever your enemy, or just a desperate man.';
} else if (npcId === null) {
resolutionText = 'The path forward clears before you.';
}
var continueChoice = [{
id: 'continue_main',
text: 'Continue',
callback: function callback() {
gameState.sceneCount += 1;
if (gameState.sceneCount >= 4) {
startScene('endgame');
} else {
startScene('hub');
}
}
}];
dialogueSystem.displayDialogue('Narrator', resolutionText, continueChoice);
}
function determineEnding() {
var mercyTotal = storage.mercyScore || 0;
var relationshipSum = 0;
for (var id in storage.characterRelationships) {
relationshipSum += storage.characterRelationships[id];
}
var playCount = storage.playCount || 1;
var prologue = storage.dialogueChoices['prologue_choice'] || '';
var ending = 'neutral';
if (playCount === 1 && mercyTotal <= -5) {
ending = 'bad';
} else if (playCount >= 3 && mercyTotal >= 8 && relationshipSum >= 4) {
ending = 'good';
} else if (playCount >= 5 && mercyTotal >= 10 && relationshipSum >= 6) {
ending = 'secret';
} else if (playCount >= 2 && mercyTotal <= -8) {
ending = 'hellish';
} else {
ending = 'neutral';
}
gameState.endingType = ending;
storage.endingReached = ending;
showEnding(ending);
}
function showEnding(endingType) {
var endingTexts = {
neutral: {
title: 'THE CAGE REMAINS',
text: 'You release the angel. It ascends into ash-grey skies. Humanity survives, changed but unbroken. You wonder if you saved anyone, or simply postponed the inevitable.'
},
good: {
title: 'REDEMPTION',
text: 'Your mercy and choices have won allies. Together, you dismantle the machine peacefully. The angel\'s light spreads, and for the first time in ages, humanity glimpses genuine hope.'
},
bad: {
title: 'ASHES AND SILENCE',
text: 'Your ruthlessness consumed everything. The angel is freed but broken. You stand alone amid the wreckage, victorious and utterly hollow. The universe watches your triumph with indifference.'
},
secret: {
title: 'TRANSCENDENCE',
text: 'Through patience, empathy, and sacrifice across many lives, you\'ve transcended mortal understanding. The angel recognizes you. Reality bends. Is this salvation or damnation?'
},
hellish: {
title: 'DAMNATION',
text: 'Your choices have carved too deep. The machine, damaged beyond control, releases not salvation but annihilation. Fire consumes the world. In hell\'s blazing light, you finally understand what you\'ve done.'
}
};
var ending = endingTexts[endingType] || endingTexts.neutral;
tween(dialogueSystem, {
alpha: 0
}, {
duration: 300
});
var endingTitle = new Text2(ending.title, {
size: 64,
fill: '#ffff00'
});
endingTitle.anchor.set(0.5, 0.5);
endingTitle.x = 1024;
endingTitle.y = 600;
game.addChild(endingTitle);
var endingBody = new Text2(ending.text, {
size: 40,
fill: '#ffffff'
});
endingBody.anchor.set(0.5, 0.5);
endingBody.x = 1024;
endingBody.y = 1000;
endingBody.wordWrap = true;
endingBody.wordWrapWidth = 1800;
game.addChild(endingBody);
var playCountDisplay = new Text2('Playthroughs: ' + (storage.playCount || 1), {
size: 32,
fill: '#888888'
});
playCountDisplay.anchor.set(0.5, 0);
playCountDisplay.x = 1024;
playCountDisplay.y = 2500;
game.addChild(playCountDisplay);
LK.setTimeout(function () {
LK.showYouWin();
}, 3000);
}
var dialogueTreeScientist = {
root: 'start'
};
var dialogueTreeSurvivor = {
root: 'start'
};
var dialogueTreeGuardian = {
root: 'start'
};
game.update = function () {
if (dialogueSystem && dialogueSystem.update) {
dialogueSystem.update();
}
if (player && player.isDefeated() && gameState.inCombat) {
endCombat(false);
}
};
game.down = function (x, y, obj) {
// Main interaction handler
};
game.move = function (x, y, obj) {
// Main move handler
};
initializeGame(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,775 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ playCount: 0,
+ mercyScore: 0,
+ dialogueChoices: {},
+ endingReached: "none",
+ characterRelationships: {}
+});
+
+/****
+* Classes
+****/
+var CombatEnemy = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('combatEnemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var healthBar = self.attachAsset('healthBar', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBar.y = -60;
+ var healthFill = LK.getAsset('healthBar', {
+ anchorX: 0,
+ anchorY: 0,
+ tint: 0x00ff00
+ });
+ healthBar.addChild(healthFill);
+ self.maxHealth = 30;
+ self.currentHealth = 30;
+ self.name = '';
+ self.damage = 5;
+ self.enemyId = null;
+ self.setData = function (id, name, health, damage) {
+ self.enemyId = id;
+ self.name = name;
+ self.maxHealth = health;
+ self.currentHealth = health;
+ self.damage = damage;
+ };
+ self.takeDamage = function (amount) {
+ self.currentHealth -= amount;
+ if (self.currentHealth < 0) {
+ self.currentHealth = 0;
+ }
+ var healthPercent = self.currentHealth / self.maxHealth;
+ healthFill.scaleX = healthPercent;
+ LK.getSound('combatDamage').play();
+ };
+ self.isDefeated = function () {
+ return self.currentHealth <= 0;
+ };
+ return self;
+});
+var DialogueChoice = Container.expand(function () {
+ var self = Container.call(this);
+ var background = self.attachAsset('choiceButton', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var text = new Text2('', {
+ size: 40,
+ fill: '#ffffff'
+ });
+ text.anchor.set(0.5, 0.5);
+ self.addChild(text);
+ self.setText = function (str) {
+ text.setText(str);
+ };
+ self.choiceId = null;
+ self.isSelected = false;
+ self.down = function (x, y, obj) {
+ if (!self.isSelected) {
+ self.isSelected = true;
+ LK.getSound('choiceSelect').play();
+ tween(background, {
+ alpha: 0.7
+ }, {
+ duration: 100
+ });
+ }
+ };
+ return self;
+});
+var DialogueSystem = Container.expand(function () {
+ var self = Container.call(this);
+ var background = self.attachAsset('dialogueBox', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ background.alpha = 0.95;
+ var speakerName = new Text2('', {
+ size: 36,
+ fill: '#ffff00'
+ });
+ speakerName.anchor.set(0, 0);
+ speakerName.x = 20;
+ speakerName.y = 20;
+ self.addChild(speakerName);
+ var dialogueText = new Text2('', {
+ size: 32,
+ fill: '#ffffff'
+ });
+ dialogueText.anchor.set(0, 0);
+ dialogueText.x = 30;
+ dialogueText.y = 70;
+ dialogueText.wordWrap = true;
+ dialogueText.wordWrapWidth = 1740;
+ self.addChild(dialogueText);
+ self.choices = [];
+ self.currentNode = null;
+ self.onChoiceCallback = null;
+ self.displayDialogue = function (npcName, text, choicesArray) {
+ speakerName.setText(npcName);
+ dialogueText.setText(text);
+ self.clearChoices();
+ if (choicesArray && choicesArray.length > 0) {
+ var choiceSpacing = 100;
+ var startY = 350;
+ for (var i = 0; i < choicesArray.length; i++) {
+ var choice = new DialogueChoice();
+ choice.x = 1024;
+ choice.y = startY + i * choiceSpacing;
+ choice.setText(choicesArray[i].text);
+ choice.choiceId = choicesArray[i].id;
+ choice.onSelectCallback = choicesArray[i].callback;
+ self.addChild(choice);
+ self.choices.push(choice);
+ }
+ }
+ };
+ self.clearChoices = function () {
+ for (var i = self.choices.length - 1; i >= 0; i--) {
+ self.choices[i].destroy();
+ }
+ self.choices = [];
+ };
+ self.update = function () {
+ for (var i = 0; i < self.choices.length; i++) {
+ if (self.choices[i].isSelected) {
+ if (self.choices[i].onSelectCallback) {
+ self.choices[i].onSelectCallback();
+ }
+ self.clearChoices();
+ self.choices[i].isSelected = false;
+ }
+ }
+ };
+ return self;
+});
+var NPC = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('npcCharacter', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var nameLabel = new Text2('', {
+ size: 32,
+ fill: '#ffffff'
+ });
+ nameLabel.anchor.set(0.5, 0);
+ nameLabel.y = 50;
+ self.addChild(nameLabel);
+ self.npcId = null;
+ self.name = '';
+ self.relationship = 0;
+ self.dialogueTree = null;
+ self.isEnemy = false;
+ self.setData = function (id, name, dialogueTree, isEnemy) {
+ self.npcId = id;
+ self.name = name;
+ self.dialogueTree = dialogueTree;
+ self.isEnemy = isEnemy;
+ nameLabel.setText(name);
+ if (isEnemy) {
+ sprite.tint = 0xff6666;
+ }
+ };
+ self.updateRelationship = function (delta) {
+ self.relationship += delta;
+ storage.characterRelationships[self.npcId] = self.relationship;
+ };
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var sprite = self.attachAsset('playerCharacter', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ var healthBar = self.attachAsset('healthBar', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ healthBar.y = -50;
+ var healthFill = LK.getAsset('healthBar', {
+ anchorX: 0,
+ anchorY: 0,
+ tint: 0x00ff00
+ });
+ healthBar.addChild(healthFill);
+ self.maxHealth = 50;
+ self.currentHealth = 50;
+ self.empathy = 50;
+ self.maxEmpathy = 100;
+ self.mercyMeter = 0;
+ self.takeDamage = function (amount) {
+ self.currentHealth -= amount;
+ if (self.currentHealth < 0) {
+ self.currentHealth = 0;
+ }
+ var healthPercent = self.currentHealth / self.maxHealth;
+ healthFill.scaleX = healthPercent;
+ LK.getSound('combatDamage').play();
+ };
+ self.heal = function (amount) {
+ self.currentHealth += amount;
+ if (self.currentHealth > self.maxHealth) {
+ self.currentHealth = self.maxHealth;
+ }
+ };
+ self.gainEmpathy = function (amount) {
+ self.empathy += amount;
+ if (self.empathy > self.maxEmpathy) {
+ self.empathy = self.maxEmpathy;
+ }
+ };
+ self.recordMercyChoice = function (isMercy) {
+ if (isMercy) {
+ self.mercyMeter += 1;
+ storage.mercyScore += 1;
+ } else {
+ self.mercyMeter -= 1;
+ storage.mercyScore -= 1;
+ }
+ };
+ self.isDefeated = function () {
+ return self.currentHealth <= 0;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x0a0a0a
+});
+
+/****
+* Game Code
+****/
+var gameState = {
+ currentScene: 'start',
+ inCombat: false,
+ inDialogue: false,
+ sceneCount: 0,
+ endingType: 'none'
+};
+var player = null;
+var currentNPC = null;
+var currentEnemy = null;
+var dialogueSystem = null;
+var npcList = {};
+var combatLog = [];
+function initializeGame() {
+ storage.playCount = (storage.playCount || 0) + 1;
+ player = game.addChild(new Player());
+ player.x = 400;
+ player.y = 1366;
+ dialogueSystem = game.addChild(new DialogueSystem());
+ dialogueSystem.x = 1024;
+ dialogueSystem.y = 1900;
+ dialogueSystem.alpha = 0;
+ var angelLabel = new Text2('ANGEL IMPRISONED', {
+ size: 48,
+ fill: '#ffd700'
+ });
+ angelLabel.anchor.set(0.5, 0.5);
+ angelLabel.x = 1600;
+ angelLabel.y = 400;
+ game.addChild(angelLabel);
+ var angel = game.addChild(LK.getAsset('angelForm', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }));
+ angel.x = 1600;
+ angel.y = 300;
+ var machine = game.addChild(LK.getAsset('machineBody', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ }));
+ machine.x = 1600;
+ machine.y = 550;
+ initializeNPCs();
+ loadStoredRelationships();
+ LK.playMusic('ambientDrone', {
+ loop: true
+ });
+ startScene('prologue');
+}
+function initializeNPCs() {
+ var npcData = {
+ scientist: {
+ name: 'Dr. Elena',
+ dialogueTree: dialogueTreeScientist,
+ isEnemy: false
+ },
+ survivor: {
+ name: 'Marcus',
+ dialogueTree: dialogueTreeSurvivor,
+ isEnemy: false
+ },
+ guardian: {
+ name: 'Sentinel',
+ dialogueTree: dialogueTreeGuardian,
+ isEnemy: true
+ }
+ };
+ for (var id in npcData) {
+ var npc = new NPC();
+ npc.setData(id, npcData[id].name, npcData[id].dialogueTree, npcData[id].isEnemy);
+ npcList[id] = npc;
+ if (!storage.characterRelationships[id]) {
+ storage.characterRelationships[id] = 0;
+ }
+ npc.relationship = storage.characterRelationships[id];
+ }
+}
+function loadStoredRelationships() {
+ for (var id in npcList) {
+ npcList[id].relationship = storage.characterRelationships[id] || 0;
+ }
+}
+function startScene(sceneName) {
+ gameState.currentScene = sceneName;
+ gameState.sceneCount += 1;
+ if (sceneName === 'prologue') {
+ showPrologue();
+ } else if (sceneName === 'hub') {
+ showHub();
+ } else if (sceneName === 'encounter_scientist') {
+ showEncounterScientist();
+ } else if (sceneName === 'encounter_survivor') {
+ showEncounterSurvivor();
+ } else if (sceneName === 'encounter_guardian') {
+ showEncounterGuardian();
+ } else if (sceneName === 'endgame') {
+ determineEnding();
+ }
+}
+function showPrologue() {
+ tween(dialogueSystem, {
+ alpha: 1
+ }, {
+ duration: 500
+ });
+ var prologueText = 'The world has ended. Heaven sent salvation, but humanity chose slavery. An angel was imprisoned in a machine to harvest divine power. You believe this is wrong. You will free it... or die trying.';
+ var choices = [{
+ id: 'start_yes',
+ text: 'I will free the angel, no matter the cost.',
+ callback: function callback() {
+ storage.dialogueChoices['prologue_choice'] = 'start_yes';
+ LK.setTimeout(function () {
+ startScene('hub');
+ }, 500);
+ }
+ }, {
+ id: 'start_question',
+ text: 'Is the angel really worth humanity\'s suffering?',
+ callback: function callback() {
+ storage.dialogueChoices['prologue_choice'] = 'start_question';
+ gameState.endingType = 'neutral';
+ LK.setTimeout(function () {
+ startScene('hub');
+ }, 500);
+ }
+ }];
+ dialogueSystem.displayDialogue('The Universe', prologueText, choices);
+}
+function showHub() {
+ if (gameState.sceneCount === 2) {
+ var hubText = 'You stand before the machine. Three paths lie before you: seek the scientist who built it, convince the survivor supporting it, or face the guardian protecting it.';
+ var choices = [{
+ id: 'hub_scientist',
+ text: 'Confront Dr. Elena, the machine\'s architect.',
+ callback: function callback() {
+ startScene('encounter_scientist');
+ }
+ }, {
+ id: 'hub_survivor',
+ text: 'Talk to Marcus, who believes the angel should stay imprisoned.',
+ callback: function callback() {
+ startScene('encounter_survivor');
+ }
+ }, {
+ id: 'hub_guardian',
+ text: 'Fight the Sentinel protecting the machine.',
+ callback: function callback() {
+ startScene('encounter_guardian');
+ }
+ }];
+ dialogueSystem.displayDialogue('Your Inner Voice', hubText, choices);
+ }
+}
+function showEncounterScientist() {
+ currentNPC = npcList['scientist'];
+ var scientistText = 'Dr. Elena looks at you with tired eyes. "We did what we had to. This angel... it gives us power to rebuild. Without it, humanity is finished."';
+ var choices = [{
+ id: 'sci_mercy',
+ text: 'I understand your desperation. Let me help find another way.',
+ callback: function callback() {
+ player.recordMercyChoice(true);
+ npcList['scientist'].updateRelationship(2);
+ storage.dialogueChoices['scientist_choice'] = 'mercy';
+ combatVsDialogue('scientist', true);
+ }
+ }, {
+ id: 'sci_condemn',
+ text: 'Your arrogance has damned us all. The angel must be freed.',
+ callback: function callback() {
+ player.recordMercyChoice(false);
+ npcList['scientist'].updateRelationship(-3);
+ storage.dialogueChoices['scientist_choice'] = 'condemn';
+ combatVsDialogue('scientist', false);
+ }
+ }];
+ dialogueSystem.displayDialogue('Dr. Elena', scientistText, choices);
+}
+function showEncounterSurvivor() {
+ currentNPC = npcList['survivor'];
+ var survivorText = 'Marcus grips your shoulder. "Everyone I love is alive because of that angel. You want to take that away? What gives you the right?"';
+ var choices = [{
+ id: 'surv_mercy',
+ text: 'Your loved ones matter. But so does freedom. We can find balance.',
+ callback: function callback() {
+ player.recordMercyChoice(true);
+ npcList['survivor'].updateRelationship(2);
+ storage.dialogueChoices['survivor_choice'] = 'mercy';
+ combatVsDialogue('survivor', true);
+ }
+ }, {
+ id: 'surv_condemn',
+ text: 'Love built on slavery is no love at all.',
+ callback: function callback() {
+ player.recordMercyChoice(false);
+ npcList['survivor'].updateRelationship(-3);
+ storage.dialogueChoices['survivor_choice'] = 'condemn';
+ combatVsDialogue('survivor', false);
+ }
+ }];
+ dialogueSystem.displayDialogue('Marcus', survivorText, choices);
+}
+function showEncounterGuardian() {
+ currentEnemy = new CombatEnemy();
+ currentEnemy.x = 1600;
+ currentEnemy.y = 600;
+ game.addChild(currentEnemy);
+ currentEnemy.setData('sentinel', 'Sentinel', 40, 8);
+ var guardianText = 'The mechanical guardian stands motionless, then speaks: "I was programmed to protect. I do not question. Surrender or be destroyed."';
+ var choices = [{
+ id: 'guar_talk',
+ text: 'You\'re more than your programming. You can choose.',
+ callback: function callback() {
+ player.recordMercyChoice(true);
+ storage.dialogueChoices['guardian_choice'] = 'talk';
+ startCombat('sentinel_dialogue');
+ }
+ }, {
+ id: 'guar_fight',
+ text: 'Then I\'ll fight you.',
+ callback: function callback() {
+ player.recordMercyChoice(false);
+ storage.dialogueChoices['guardian_choice'] = 'fight';
+ startCombat('sentinel_combat');
+ }
+ }];
+ dialogueSystem.displayDialogue('Sentinel', guardianText, choices);
+}
+function combatVsDialogue(npcId, isDialogue) {
+ gameState.inDialogue = isDialogue;
+ tween(dialogueSystem, {
+ alpha: 0
+ }, {
+ duration: 300
+ });
+ if (isDialogue) {
+ LK.setTimeout(function () {
+ resolveEncounter(npcId, true);
+ }, 400);
+ } else {
+ currentEnemy = new CombatEnemy();
+ currentEnemy.x = 1600;
+ currentEnemy.y = 600;
+ game.addChild(currentEnemy);
+ if (npcId === 'scientist') {
+ currentEnemy.setData('scientist', 'Dr. Elena', 35, 6);
+ } else if (npcId === 'survivor') {
+ currentEnemy.setData('survivor', 'Marcus', 30, 7);
+ }
+ startCombat(npcId);
+ }
+}
+function startCombat(combatId) {
+ gameState.inCombat = true;
+ LK.playMusic('combatTheme', {
+ loop: true
+ });
+ var combatUI = new Text2('COMBAT: ' + currentEnemy.name.toUpperCase(), {
+ size: 48,
+ fill: '#ff4444'
+ });
+ combatUI.anchor.set(0.5, 0);
+ combatUI.x = 1024;
+ combatUI.y = 100;
+ game.addChild(combatUI);
+ var attackButton = new DialogueChoice();
+ attackButton.x = 500;
+ attackButton.y = 1300;
+ attackButton.setText('ATTACK (DMG: 8)');
+ game.addChild(attackButton);
+ var defendButton = new DialogueChoice();
+ defendButton.x = 1500;
+ defendButton.y = 1300;
+ defendButton.setText('DEFEND');
+ game.addChild(defendButton);
+ attackButton.down = function (x, y, obj) {
+ player.recordMercyChoice(false);
+ playerAttack();
+ };
+ defendButton.down = function (x, y, obj) {
+ playerDefend();
+ };
+ game.combatUI = {
+ title: combatUI,
+ attackBtn: attackButton,
+ defendBtn: defendButton
+ };
+}
+function playerAttack() {
+ if (!gameState.inCombat) return;
+ var damage = 8 + Math.floor(Math.random() * 4);
+ currentEnemy.takeDamage(damage);
+ LK.getSound('combatHit').play();
+ var damageText = new Text2('-' + damage, {
+ size: 36,
+ fill: '#ff0000'
+ });
+ damageText.x = currentEnemy.x;
+ damageText.y = currentEnemy.y - 50;
+ game.addChild(damageText);
+ tween(damageText, {
+ y: damageText.y - 50,
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ damageText.destroy();
+ }
+ });
+ if (currentEnemy.isDefeated()) {
+ endCombat(true);
+ } else {
+ LK.setTimeout(enemyTurn, 600);
+ }
+}
+function playerDefend() {
+ if (!gameState.inCombat) return;
+ player.heal(5);
+ var healText = new Text2('+5', {
+ size: 36,
+ fill: '#00ff00'
+ });
+ healText.x = player.x;
+ healText.y = player.y - 50;
+ game.addChild(healText);
+ tween(healText, {
+ y: healText.y - 50,
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ healText.destroy();
+ }
+ });
+ LK.setTimeout(enemyTurn, 600);
+}
+function enemyTurn() {
+ if (!gameState.inCombat || !currentEnemy) return;
+ var enemyDamage = currentEnemy.damage + Math.floor(Math.random() * 3);
+ player.takeDamage(enemyDamage);
+ var damageText = new Text2('-' + enemyDamage, {
+ size: 36,
+ fill: '#ff0000'
+ });
+ damageText.x = player.x;
+ damageText.y = player.y - 50;
+ game.addChild(damageText);
+ tween(damageText, {
+ y: damageText.y - 50,
+ alpha: 0
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ damageText.destroy();
+ }
+ });
+ if (player.isDefeated()) {
+ endCombat(false);
+ }
+}
+function endCombat(playerWon) {
+ gameState.inCombat = false;
+ LK.playMusic('ambientDrone', {
+ loop: true
+ });
+ if (game.combatUI) {
+ game.combatUI.title.destroy();
+ game.combatUI.attackBtn.destroy();
+ game.combatUI.defendBtn.destroy();
+ game.combatUI = null;
+ }
+ if (currentEnemy) {
+ currentEnemy.destroy();
+ currentEnemy = null;
+ }
+ if (playerWon) {
+ resolveEncounter(null, false);
+ } else {
+ LK.showGameOver();
+ }
+}
+function resolveEncounter(npcId, throughDialogue) {
+ tween(dialogueSystem, {
+ alpha: 1
+ }, {
+ duration: 500
+ });
+ var resolutionText = '';
+ if (throughDialogue && npcId === 'scientist') {
+ resolutionText = 'Dr. Elena looks down, tears forming. "Maybe... maybe there is another way. I\'ll help you free it."';
+ } else if (!throughDialogue && npcId === 'scientist') {
+ resolutionText = 'Dr. Elena falls. Your violence has solved the immediate problem, but at what cost?';
+ } else if (throughDialogue && npcId === 'survivor') {
+ resolutionText = 'Marcus nods slowly. "You\'re right. Freedom matters more than my fear."';
+ } else if (!throughDialogue && npcId === 'survivor') {
+ resolutionText = 'Marcus collapses. You wonder if he was ever your enemy, or just a desperate man.';
+ } else if (npcId === null) {
+ resolutionText = 'The path forward clears before you.';
+ }
+ var continueChoice = [{
+ id: 'continue_main',
+ text: 'Continue',
+ callback: function callback() {
+ gameState.sceneCount += 1;
+ if (gameState.sceneCount >= 4) {
+ startScene('endgame');
+ } else {
+ startScene('hub');
+ }
+ }
+ }];
+ dialogueSystem.displayDialogue('Narrator', resolutionText, continueChoice);
+}
+function determineEnding() {
+ var mercyTotal = storage.mercyScore || 0;
+ var relationshipSum = 0;
+ for (var id in storage.characterRelationships) {
+ relationshipSum += storage.characterRelationships[id];
+ }
+ var playCount = storage.playCount || 1;
+ var prologue = storage.dialogueChoices['prologue_choice'] || '';
+ var ending = 'neutral';
+ if (playCount === 1 && mercyTotal <= -5) {
+ ending = 'bad';
+ } else if (playCount >= 3 && mercyTotal >= 8 && relationshipSum >= 4) {
+ ending = 'good';
+ } else if (playCount >= 5 && mercyTotal >= 10 && relationshipSum >= 6) {
+ ending = 'secret';
+ } else if (playCount >= 2 && mercyTotal <= -8) {
+ ending = 'hellish';
+ } else {
+ ending = 'neutral';
+ }
+ gameState.endingType = ending;
+ storage.endingReached = ending;
+ showEnding(ending);
+}
+function showEnding(endingType) {
+ var endingTexts = {
+ neutral: {
+ title: 'THE CAGE REMAINS',
+ text: 'You release the angel. It ascends into ash-grey skies. Humanity survives, changed but unbroken. You wonder if you saved anyone, or simply postponed the inevitable.'
+ },
+ good: {
+ title: 'REDEMPTION',
+ text: 'Your mercy and choices have won allies. Together, you dismantle the machine peacefully. The angel\'s light spreads, and for the first time in ages, humanity glimpses genuine hope.'
+ },
+ bad: {
+ title: 'ASHES AND SILENCE',
+ text: 'Your ruthlessness consumed everything. The angel is freed but broken. You stand alone amid the wreckage, victorious and utterly hollow. The universe watches your triumph with indifference.'
+ },
+ secret: {
+ title: 'TRANSCENDENCE',
+ text: 'Through patience, empathy, and sacrifice across many lives, you\'ve transcended mortal understanding. The angel recognizes you. Reality bends. Is this salvation or damnation?'
+ },
+ hellish: {
+ title: 'DAMNATION',
+ text: 'Your choices have carved too deep. The machine, damaged beyond control, releases not salvation but annihilation. Fire consumes the world. In hell\'s blazing light, you finally understand what you\'ve done.'
+ }
+ };
+ var ending = endingTexts[endingType] || endingTexts.neutral;
+ tween(dialogueSystem, {
+ alpha: 0
+ }, {
+ duration: 300
+ });
+ var endingTitle = new Text2(ending.title, {
+ size: 64,
+ fill: '#ffff00'
+ });
+ endingTitle.anchor.set(0.5, 0.5);
+ endingTitle.x = 1024;
+ endingTitle.y = 600;
+ game.addChild(endingTitle);
+ var endingBody = new Text2(ending.text, {
+ size: 40,
+ fill: '#ffffff'
+ });
+ endingBody.anchor.set(0.5, 0.5);
+ endingBody.x = 1024;
+ endingBody.y = 1000;
+ endingBody.wordWrap = true;
+ endingBody.wordWrapWidth = 1800;
+ game.addChild(endingBody);
+ var playCountDisplay = new Text2('Playthroughs: ' + (storage.playCount || 1), {
+ size: 32,
+ fill: '#888888'
+ });
+ playCountDisplay.anchor.set(0.5, 0);
+ playCountDisplay.x = 1024;
+ playCountDisplay.y = 2500;
+ game.addChild(playCountDisplay);
+ LK.setTimeout(function () {
+ LK.showYouWin();
+ }, 3000);
+}
+var dialogueTreeScientist = {
+ root: 'start'
+};
+var dialogueTreeSurvivor = {
+ root: 'start'
+};
+var dialogueTreeGuardian = {
+ root: 'start'
+};
+game.update = function () {
+ if (dialogueSystem && dialogueSystem.update) {
+ dialogueSystem.update();
+ }
+ if (player && player.isDefeated() && gameState.inCombat) {
+ endCombat(false);
+ }
+};
+game.down = function (x, y, obj) {
+ // Main interaction handler
+};
+game.move = function (x, y, obj) {
+ // Main move handler
+};
+initializeGame();
\ No newline at end of file
an angel in pain, bleeding and sagging wings. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A cubish machine that has an angel inside of it that absorbs the angels power but you can't see the angel and the power that comes from the angel is moved by pipes that is on the left side of the machine that comes to the front side and sprays there. On the bottom left side there is an user manual and the machine has cogwheels everywhere. It is hanging from the chains that comes down from the heaven. The chains comes above from clouds. The machine has a double angel wing symbol on the top side. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
A normal human being but has chains on arms and muscular body pixelart. In-Game asset. 2d. High contrast. No shadows