What's new
Choice of Mods

Join our amazing community to find Choicescript games and modifications to improve your gameplay!

Resource icon

Vampire The Masquerade — Parliament of Knives v1.2.14 Mod Menu 1.2.14

Register to download this resource for free!

sethcom

New member
Member
If you extracted the APK and play on the browser like me, then this code should hopefully fix the achievements and missing variable errors. You can add it to the bottom of index.html.

I only tested it with Vampire The Masquerade — Parliament of Knives and Choice of Magics, so I'm not sure if it will work with every game uploaded by @DanFabulich.

HTML:
<script>
  function setupNav() {
    const lines = allScenes[_global.nav.getStartupScene()].lines;

    const achievements = [];
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i].trim();

      if (line.startsWith('*achievement')) {
        const parts = line.split(/\s+/);
        const achievementName = parts[1];
        const isVisible = parts[2] === 'visible';
        const points = parseInt(parts[3], 10);
        const title = parts.slice(4).join(' ');

        const desc1 = (lines[i + 1] || '').trim().replace(/^\t/, '');
        const desc2 = (lines[i + 2] || '').trim().replace(/^\t/, '');

        achievements.push([
          achievementName,
          isVisible,
          points,
          title,
          desc2,
          desc1
        ]);
      }
    }

    const purchases = {};

    for (const chapter of Object.keys(allScenes)) {
      purchases[chapter] = 'adfree';
    }

    const sceneList = [];
    let inSceneList = false;

    for (let line of lines) {
      const trimmed = line.trim();

      if (trimmed.startsWith('*scene_list')) {
        inSceneList = true;
        continue;
      }

      if (inSceneList && trimmed.startsWith('*') && !trimmed.startsWith('*scene_list')) {
        break;
      }

      if (inSceneList) {
        if (trimmed === '') continue;
        const sceneName = trimmed.replace(/^\$?\s*/, '');
        sceneList.push(sceneName);
      }
    }

    nav = new SceneNavigator(sceneList);

    nav.setStartingStatsClone(stats);
    if (achievements.length) {
      nav.loadAchievements(achievements);
    }

    if (nav.loadProducts) nav.loadProducts([], purchases);

    document.querySelector('#achievementsButton').removeAttribute('style');
  }

  setupNav();
</script>
 

DanFabulich

Sheriff of ChoiceofMods
Staff member
Co-Admin
VIP
Moderator
Approved Releaser
Vergil's Brother
Member
If you extracted the APK and play on the browser like me, then this code should hopefully fix the achievements and missing variable errors. You can add it to the bottom of index.html.

I only tested it with Vampire The Masquerade — Parliament of Knives and Choice of Magics, so I'm not sure if it will work with every game uploaded by @DanFabulich.

HTML:
<script>
  function setupNav() {
    const lines = allScenes[_global.nav.getStartupScene()].lines;

    const achievements = [];
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i].trim();

      if (line.startsWith('*achievement')) {
        const parts = line.split(/\s+/);
        const achievementName = parts[1];
        const isVisible = parts[2] === 'visible';
        const points = parseInt(parts[3], 10);
        const title = parts.slice(4).join(' ');

        const desc1 = (lines[i + 1] || '').trim().replace(/^\t/, '');
        const desc2 = (lines[i + 2] || '').trim().replace(/^\t/, '');

        achievements.push([
          achievementName,
          isVisible,
          points,
          title,
          desc2,
          desc1
        ]);
      }
    }

    const purchases = {};

    for (const chapter of Object.keys(allScenes)) {
      purchases[chapter] = 'adfree';
    }

    const sceneList = [];
    let inSceneList = false;

    for (let line of lines) {
      const trimmed = line.trim();

      if (trimmed.startsWith('*scene_list')) {
        inSceneList = true;
        continue;
      }

      if (inSceneList && trimmed.startsWith('*') && !trimmed.startsWith('*scene_list')) {
        break;
      }

      if (inSceneList) {
        if (trimmed === '') continue;
        const sceneName = trimmed.replace(/^\$?\s*/, '');
        sceneList.push(sceneName);
      }
    }

    nav = new SceneNavigator(sceneList);

    nav.setStartingStatsClone(stats);
    if (achievements.length) {
      nav.loadAchievements(achievements);
    }

    if (nav.loadProducts) nav.loadProducts([], purchases);

    document.querySelector('#achievementsButton').removeAttribute('style');
  }

  setupNav();
</script>
did you try triggering any achievement to see if it works ?
 

sethcom

New member
Member
did you try triggering any achievement to see if it works ?

Earning achievements works with the code I wrote.

The reason why the errors happened is because of this minor issue in index.html:

JavaScript:
nav = new SceneNavigator(["startup"]);
stats = {};

This sets up the nav object with the default "startup" scene. You can see that this is the default code for any ChoiceScript game:


The issue is that the actual game always has a custom mygame.js that initializes nav with all the proper variables and achievements. To use Vampire The Masquerade — Parliament of Knives as an example, this is the mygame.js that comes with the game:

JavaScript:
nav = new SceneNavigator(
[
 "startup",
 "ch1_incursion",
 "ch2_misgivings",
 "ch3_collusion",
 "ch4_council",
 "ch5_exhibition",
 all the other scenes...
]
);
stats = 
{
 "choice_title": "Parliament of Knives",
 "primer_obtained": "false",
 "chapter": "1",
 "return_to_previous_chapter": "false",
 "restore_function_toggled_on": "false",
 "name_and_clan_chosen": "false",
 "name": "Nameless",
 "last_name": "nil",
 all the other variables...
}
;
purchases = 
{
 "ch4_council": "adfree",
 "ch5_exhibition": "adfree",
 all the other purchase keys...
}
;
achievements = 
[
 [
  "surprise_attack",
  true,
  10,
  "Surprise Attack!",
  "Reached Ward without being spotted first.",
  "Locate Ward during the Blood Hunt without being seen."
 ],
 all the other achievement arrays...
]
;

nav.setStartingStatsClone(stats);
if (achievements.length) {
  nav.loadAchievements(achievements);
}

if (nav.loadProducts) nav.loadProducts([], purchases);

That code runs every time the game is opened either on the phone or in the browser. This code is missing in your release. From what I've seen of index.html, you moved all JavaScript files and game scene files into one easily distributable index.html file, but you forgot to include the code from the custom mygame.js. This leads to an issue where whenever you refresh the page, or exit and come back, the nav object is not properly set up.

Saving, restarting, then loading the recently made quick save fixes it because the first lines of the first scene initialize nav properly, but the second you refresh or exit, that nav object is lost, and because you resume from a later part in the game, the code to fix nav never runs.

The code I posted is basically me trying to replicate what mygame.js is supposed to do. I get the startup code from allScenes[_global.nav.getStartupScene()].lines, and from the ChoiceScript code itself, extract the achievements and scenes. The purchase keys don't seem to be present in the game's code, so I just set all scenes to "adfree". The stats variable seems to be saved in the browser itself, so I don't need to extract it from the game's code. After I have the sceneList, the stats, the achievements, and the purchases, I can then recreate the nav object properly. I also unhide the achievements button.

From what I can tell, this fixes everything, at least for the two games I tested. I can now refresh and exit, and none of the achievements or scenes get lost.

The only issue I can think of is that some games won't have an achievement button, which might cause document.querySelector('#achievementsButton').removeAttribute('style'); to throw an error.
 
Top