Blog

The latest development updates and insights

MindWare 0.1.6 Is Now Available

I’m happy to announce the release of MindWare 0.1.6, the first version to feature a new mobile-friendly UI.

Play online: https://playmindware.com/

I’ve tested the new UI on iOS Safari, and it makes the game fairly nicely playable in my opinion. Of course, the larger your device is, the better the experience.

Because I wasn’t developing the game with mobile devices in mind until very recently, I had to disable some parts on mobile (some minigames and the games section in the player’s home).

I will eventually replace/update all minigames to be mobile-friendly (I’ve already developed a replacement minigame for the one that lets you resit AVA, but I still need to use it throughout the game), but it will be a gradual process as I want to dedicate as much of my time to writing the story as I can now that the UI is updated.

Speaking of the game’s story, I’ve made progress on the transformation quest, and it’s now technically possible to physically become more feminine. I’m aware that the transformation quest needs more love in terms of pacing and polish (the hospital currently doesn’t charge the player money, for example), and I plan to address these issues in future updates.

The only core gameplay change that I would like to implement sooner rather than later has to do with chat messages and some emails — but mostly chat messages.

Right now, the chat messages are written as if the chat happened right at the moment of the player receiving a notification message. As a result, the longer the player takes before they open the chat, the less sense the chat can make. I know that most of you open available chats as soon as they become available in the game, so I will save you a few clicks and open them automatically as soon as they become available. The chat app can then serve as an archive of past chats.

Changelog (beta versions + public release):

Version 0.1.6 (Public)

  • Coding assistants should now be more balanced (but this part of the game still needs a lot of work).
  • New avatar set (custom avatars can now be placed in the “setX” folder).
  • More content with the psychiatrist.

Version 0.1.6 (Supporters-Only Beta 3)

  • Many minor UI design improvements.
  • Top menu buttons now double as notification indicators.
  • Added ByteBunker OmniPedia entry.
  • Minigames are automatically skipped on mobile.
  • Added notification sound effect.
  • Post-infection white overlay now doesn’t flicker.
  • Significantly more robust system for stat changes.
  • Fixed dish washing minigame.
  • Slightly improved the waveform minigame.
  • Fixed bug that stopped rent payments from working.
  • Added first sex scene with cook.
  • Added second sex scene with cook.

Version 0.1.6 (Supporters-Only Beta 2)

  • New mobile-friendly UI.
  • New UI sound system.
  • New music playback system.
  • New start screen.
  • Updated Listen to Music section in player’s apartment.
  • Many minor UI redesign-related changes.

Version 0.1.6 (Supporters-Only Beta 1)

  • Removed difficulty settings.
  • Removed Quick Start button.
  • Reimplemented minigame skip button.
  • Moved option to enable minigame skip buttons to Settings menu.
  • Removed morality mechanic.
  • Removed some sexuality stats.
  • Fixed bug causing scroll to top button to be created endlessly.
  • Made first bruteforce minigame easier.
  • Added 10 showercam feeds.
  • Added version number below game subtitle.
  • Added first Rent Compliance Specialist visit.
  • Implemented Hive Properties debt leading to installation of SUCKER machine.
  • Fixed bug allowing skipping of BrainFry introduction.
  • Increased earnings from coding minigame.
  • Added visible BrainFry work counter to BrainFry passage.
  • Replaced Synapse Steady VX installation clock with video to fix rare bug.
  • Added unpaid rent notification to home passage.
  • Fixed bug causing psychiatrist to say “hello again” on first visit.
  • Fixed Extra Options menu to preserve player name-related variables.
  • Updated Settings menu to correctly set player name variables.

Thank you for your support!

Smarter Stat Changes in Twine/SugarCube Games

Changing a stat in a Twine/SugarCube game is simple on paper but often complicated in practice.

If your game is very simple, you can do something like this:

<<set $stat -= 5>>

If you want to get fancy, you can even prevent the stat from becoming less than 0 by doing this:

<<set $stat to Math.max($stat - 5, 0)>>

This works fine until you add something like an inventory passage that the player can visit at any time. When they come back to the passage with the stat change, the change will happen again.

One way to prevent this is to do the following:

<<if visited() is 1>>
   <<set $stat -= 5>> 
<</if>>

Again, this works if your game is structured in a straightforward way, but it stops working once you introduce some <> macros that reveal passage content after some interaction.

If this interaction happens after you’ve visited the inventory passage and come back, then the visited value won’t be 1 anymore… it will be 2 or more.

To solve this problem, I’ve developed a more robust system for handling stat changes in Twine/SugarCube games. This system ensures that stat changes occur only once, regardless of how many times a player visits a passage or interacts with certain elements. Here’s how it works:

We create a custom widget called statChange to manage these stat changes:

<<widget "statChange">>
    <<if ndef $statChanges>>
        <<set $statChanges to {}>>
    <</if>>
    <<if not $statChanges.hasOwnProperty(_args[0])>>
        <<set _tempStatValue to 0>>
        _args[1]
        <<set $statChanges[_args[0]] to _tempStatValue>>
    <</if>>
<</widget>>

Let’s break down the statChange widget line by line:

This checks if the $statChanges variable is not defined. If it’s not, it initializes it as an empty object. This object will store all the stat changes that have occurred:

<<if ndef $statChanges>>
    <<set $statChanges to {}>>
<</if>>

This checks if the $statChanges object doesn’t have a property with the name of the first argument passed to the widget (which should be the name of the stat being changed):

<<if not $statChanges.hasOwnProperty(_args[0])>>

If the stat hasn’t been changed before, this initializes a temporary variable _tempStatValue to 0:

<<set _tempStatValue to 0>>

This executes the macro:

_args[1]

This records the stat change in the $statChanges object, using the stat name as the key and the change value as the value:

<<set $statChanges[_args[0]] to _tempStatValue>>

We modify our stat-changing widgets to work with this system. For example, here’s one widget from MindWare:

<<widget "moreFeminine">>
    <<set _amount to _args[0]>>
    <<set _playerGender to State.variables.playerGender>>
    <<set _newGender to Math.max(_playerGender - _amount, 0)>>
    
    <<if _newGender == _playerGender>>
        <div class="gender-change"><span class="gender-decrease">♀️ Your feminine gender identity is already at its minimum.</span></div><br>
    <<else>>
        <<set State.variables.playerGender to _newGender>>
        <<set _pointText to _amount == 1 ? "1 point" : (_amount + " points")>>
        <div class="gender-change"><span class="gender-decrease">♀️ Your gender identity has become more feminine by <<print _pointText>>.</span></div><br>
    <</if>>
    <<set _tempStatValue to _amount>>
<</widget>>

To use this system, we simply call the statChange widget with a unique identifier and the stat-changing widget:

<<statChange "ugly_bastard_quest_2_AVA_submit" "<<moreFeminine 5>>">>

This system solves several problems:

  1. It ensures that each specific stat change occurs only once, even if the player revisits the passage multiple times.
  2. It works with <<replace>> macros and other dynamic content, as it’s not dependent on the visited() count.
  3. It allows for more complex stat-changing logic within the widgets, including checks for minimum/maximum values and appropriate feedback messages.
  4. It provides a way to track which specific stat changes have occurred, which can be useful for game logic or debugging.

By using this system, you can create more complex and dynamic games without worrying about unintended repeated stat changes.

MindWare v0.1.5 Is Now Available

The public version of MindWare 0.1.5 is now available.

Here’s what’s new and different:

  • Added post-psychological evaluation chat with Cipher.
  • Added first transition appointment with Dr. Hart.
  • Added first post-appointment chat with Cipher.
  • Added second transition appointment with Dr. Hart.
  • Added second post-appointment chat with Cipher.
  • Added third transition appointment with Dr. Hart.
  • You can now change your nickname and name in the Settings menu.
  • You can now change your gender in the Extra Options menu.
  • Fixed a bug that caused an error in Panacea Clinic under certain conditions.
  • Small tweaks to the game difficulty settings screen.
  • Added the option to enable infinite action points in the Extra Options menu.
  • Added a new OmniPedia section about HiveProperties.
  • Fixed a formatting bug in the Go Outside passage.
  • You can now get drunk and black out.
  • Fixed a bug during the first hospital visit.
  • Added a mobile Synapse Steady VX diagnostics report.
  • Redesigned the original Synapse Steady VX report.
  • The Character Profile screen now displays the correct avatar iamge.
  • You can now undergo your first psychological evaluation at the Panacea Clinic to begin your physical transition.
  • Fixed a bug that caused the autosave feature to not work.
  • The Extra Options menu is now better protected thanks to Moran, a Discord member. Thank you!
  • NEW AVATAR SYSTEM that reflects all five stages of the player character’s transformation.
  • New player avatar images.
  • Added basic support for custom avatar images.
  • You can now change your avatar in the Extra Options menu.

The update contains over 70 new images/videos and more new playable content than several last updates combined.

The new content is available only if your mental condition is at least Unstable (you’ve become feminized by AVA to such an extent that your gender doesn’t match your sex and you’re experiencing gender dysphoria). I’ve added an option in the Extra Options menu to change your gender, so feel free to use it to trigger the new content. Oh, and you can skip the wait between your appointments with Dr. Hart by clicking the button in the task description (click on the task name in the to-do list first).

MindWare v0.1.4 Is Now Available

I always dislike releasing updates that don’t contain a significant amount of new playable content, but sometimes it’s necessary for me to focus on stuff you can’t see. To give you at least something to enjoy, this update contains one randomly triggered encounter when you visit the SynTech location.

While you can currently only experience the encounter as a guy, I’ve also implemented the female experience (note: there’s one GIF used in both the male and female version of the encounter that should technically be used only for the female version — I haven’t been able to find a good alternative for the male version). This is something I will be doing a lot from now on, so I wanted to practice on something smaller first.

Besides the random encounter, I’ve been working on a new avatar system, one that will reflect each of the 5 possible stages of the player character’s male -> female transformation. The code is almost ready, and I now just need to generate a good set of avatar images. To give you some idea, here’s an early test (this character image set won’t be used):

The new avatar system will be available in version 0.1.5, and it will likely feature only one or two sets of character images to choose from. To make up for the limited number of avatars, I will add support for custom avatars so that you can add your own images to the “imgs” folder. Maybe some members of our Discord community will be able to come up with something amazing. If so, I would be more than happy to include their creations in the game as “official” avatars.

Changelog:

  • Fixed a few typos and poor word choices here and there.
  • Added a random encounter when you visit the SynTech location (1 in 20 chance of happening). Hint: you need to be infected with AVA for the encounter to get naughty.
  • Done some preparatory work to implement a new avatar system (will be included in the next version).
  • Implemented several custom macros to change various stats.
  • Made the AVA minigame far easier to reuse.

MindWare’s New Loading Screen and Why It’s Important

I’ve recently implemented a loading screen for an upcoming version of MindWare, and I would like to take a few moments to explain why and share the solution with you.

The Problem

One of the biggest and most persistent issues I’ve been dealing with (responsible for most bug reports I’ve received so far) has been missing or improperly initialized variables when starting a new game or loading a save. This can cause all sorts of weird behavior and frustrating bugs for players.

When a person with limited understanding of how the Twine engine works and virtually no experience with the creation of larger interactive fiction games sets out to create a game like MindWare, they may start by placing important variables in the StoryInit passage. All variables placed in this passage are initialized when you start a new game.

The same inexperienced developer may then add additional variables to the StoryInit passage, such as variables for a new part of the UI, and release a new version of their game. You then load your old save and are greeted with an error message because your save is missing the newly added variables. To fix the error, you would have to start a new game—not desirable at all.

The Solution

I’m not the first person in the world to have dealt with this problem (see here and here, for example), so my solution isn’t something groundbreaking, but I think that it’s polished and reusable enough that others might benefit from it. I also hope to receive feedback from those how are more knowledgable than me.

How it works:

  1. When a new game starts or a save is loaded, a function is called.
  2. This function navigates to a special variable initialization passage.
  3. The variable initialization passage displays a loading screen and includes passages with variables to be initialized (being able to divide variables in to different passages makes it easier to stay organized).
  4. A simulated loading process updates the progress bar.
  5. Once “loading” is complete, the player is returned to either the previous passage (for loaded games) or the Start passage (for fresh playthroughs).

With this solution, I’m able to load variables (most of them anyway) that I have been very generously collected by a Discord user and MindWare supporter UnwrappedGodiva (thank you again!). These variables provide a solid starting point on which I can expand. More importantly, I now have a way to declare future global variables in a way that won’t break old saves.

The Code

This script sets up the logic for when to run the initialization process:

:: Scripts-StartingVariables [script]
// Initialize a flag to track whether StartingVariables has run
setup.startingScriptsRun = false;

// Function to run StartingVariables
setup.runStartingVariables = function() {
    if (!setup.startingScriptsRun) {
        State.variables.previousPassage = State.passage;
        setup.startingScriptsRun = true;
    } else {
    }
};

// Run for new games
$(document).one(':passagestart', function (ev) {
    if (ev.passage.title === "Start") {
        setTimeout(setup.runStartingVariables, 0);
    } else {
    }
});
// Alternatively, you can delete the block of code above and call the runStartingVariables function directly from the Start passage like this:
// <<run setTimeout(setup.runStartingVariables, 0); >>

// Run for loaded games
Save.onLoad.add(function () {
    setup.startingScriptsRun = false;
    setTimeout(setup.runStartingVariables, 0);
});

This is the actual loading screen passage:

:: StartingVariables 
<<nobr>><div id="loading-screen">
  <div class="loading-content">
    <div class="loading-bar-container">
      <div id="loading-bar"></div>
    </div>
    <div class="loading-text">INITIALIZING...</div>
  </div>
</div><</nobr>>

// Include as many passages with variables as you want here
// You can also add your variables directly here 
<<include "UI Variables">>

<script>
(function() {
    // Simulate loading process
    var progress = 0;
    var loadingBar = document.getElementById('loading-bar');
    var loadingInterval = setInterval(function() {
        progress += Math.random() * 10;
        if (progress >= 100) {
            progress = 100;
            clearInterval(loadingInterval);
            setTimeout(function() {
                // Return to the previous passage
                SugarCube.Engine.play(SugarCube.State.variables.previousPassage || "Start");
            }, 500);
        }
        loadingBar.style.width = progress + '%';
    }, 100);
})();
</script>

A passage with variables to load:

:: UI Variables
<<if ndef $scrollToTopEnabled>>
    <<set $scrollToTopEnabled to true>>
<</if>>

The CSS code for the loading screen:

#loading-screen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #000;
    z-index: 9999;
    display: flex;
    justify-content: center;
    align-items: center;
}

.loading-content {
    width: 80%;
    max-width: 600px;
}

.loading-bar-container {
    width: 100%;
    height: 20px;
    background-color: #111;
    border: 2px solid #55BBBC;
    box-shadow: 0 0 10px #55BBBC;
}

#loading-bar {
    width: 0;
    height: 100%;
    background-color: #55BBBC;
    transition: width 0.3s ease;
}

.loading-text {
    color: #55BBBC;
    font-family: 'Orbitron', sans-serif;
    font-size: 24px;
    text-align: center;
    margin-top: 20px;
    text-shadow: 0 0 10px #55BBBC;
}

If you’ve noticed any mistakes or areas that could be improved, please share them with me here or on Discord. Any feedback I receive is greatly appreciated.

SugarCube Custom Video Macro

This custom macro will help you embed videos of various formats such as .mp4, .webm, .mov, .ogg, and .avi in your Twine stories using the SugarCube story format.

Macro.add('video', {
    handler: function () {
        if (this.args.length < 1) {
            return this.error("The video macro requires a path argument.");
        }

        const videoPath = this.args[0];
        const videoWidth = this.args.length > 1 ? this.args[1] : '100%';
        let videoType;

        // Determine the video type based on the file extension
        if (videoPath.endsWith('.mp4')) {
            videoType = 'video/mp4';
        } else if (videoPath.endsWith('.webm')) {
            videoType = 'video/webm';
        } else if (videoPath.endsWith('.mov')) {
            videoType = 'video/mp4';
        } else if (videoPath.endsWith('.ogg')) {
            videoType = 'video/ogg';
        } else if (videoPath.endsWith('.avi')) {
            videoType = 'video/x-msvideo';
        } else {
            return this.error("Unsupported video format.");
        }

        const videoHTML = `<video width="${videoWidth}" autoplay loop muted>
                              <source src="${videoPath}" type="${videoType}">
                              Your browser does not support the video tag.
                           </video>`;

        new Wikifier(this.output, videoHTML);
    }
});

I use this macro to include videos that play automatically in a continuous loop while muted (just like GIFs do). You can easily create other versions of this macro that behave slightly differently by editing the “videoHTML” constant. For example, you can remove the “muted” attribute to play videos with sound and save the modified macro as “video-sound” or something similar.

Alternatively, you could modify it so that it behaves more like the HTML <video> tag by default and accepts the same attributes as additional parameters:

Macro.add('video', {
    handler: function () {
        if (this.args.length < 1) {
            return this.error("The video macro requires a path argument.");
        }

        const videoPath = this.args[0];
        let videoWidth = '100%';
        let videoType;
        let additionalAttributes = [];

        // Check if the second argument is a width or a video attribute
        if (this.args[1] && !this.args[1].includes('=')) {
            if (!this.args[1].includes('autoplay') && !this.args[1].includes('loop') && !this.args[1].includes('muted') && !this.args[1].includes('controls')) {
                videoWidth = this.args[1];
                additionalAttributes = this.args.slice(2);
            } else {
                additionalAttributes = this.args.slice(1);
            }
        } else {
            additionalAttributes = this.args.slice(1);
        }

        // Determine the video type based on the file extension
        if (videoPath.endsWith('.mp4')) {
            videoType = 'video/mp4';
        } else if (videoPath.endsWith('.webm')) {
            videoType = 'video/webm';
        } else if (videoPath.endsWith('.mov')) {
            videoType = 'video/mp4';
        } else if (videoPath.endsWith('.ogg')) {
            videoType = 'video/ogg';
        } else if (videoPath.endsWith('.avi')) {
            videoType = 'video/x-msvideo';
        } else {
            return this.error("Unsupported video format.");
        }

        const additionalAttributesStr = additionalAttributes.join(' ');

        const videoHTML = `<video width="${videoWidth}" ${additionalAttributesStr}>
                              <source src="${videoPath}" type="${videoType}">
                              Your browser does not support the video tag.
                           </video>`;

        new Wikifier(this.output, videoHTML);
    }
});

How to Use the Macro

First, add the Macro to your Story JavaScript passage. You can then use the macro in any passage like this:

:: Start
Welcome to my interactive story!

<<video "path/to/your/video.mp4">>

The width of the video is set to 100% by default, but you can manually overwrite the default setting by entering the width as an additional argument.

<<video "path/to/your/video.mp4" "50%">>

If you’ve decided to go with the second version of the macro, the one that works more like the HTML <video> tag, then you can do something like this:

<<video "videos/intro.mp4" autoplay loop muted controls>>

or this:

<<video "videos/intro.mp4" "75%" autoplay loop muted controls>>

Supported Video Formats

This macro supports the following video formats:

  • .mp4 with MIME type video/mp4
  • .webm with MIME type video/webm
  • .mov with MIME type video/mp4
  • .ogg with MIME type video/ogg
  • .avi with MIME type video/x-msvideo

MindWare v0.1.3 Is Now Available

Changelog:

  • Added the first taxi camera hack mission from Ray, which leads directly to the second one.
  • Added the second taxi camera hack mission from Ray.
  • Added cum eating fetish (unlockable during the taxi mission).
  • Added a chat with Cipher about cum eating (available after the taxi mission).
  • Added information about fetishes in the character screen.

As you can see from the short changelog, this update is all about a new taxi camera hack mission that you can accept from Ray. The mission will trigger automatically when the following conditions are met:

  • You’re more than 5 days deep into Chapter 1
  • Your relationship with Ray is at least 40 points out of 100
  • You’re located in the BrainFry main hub area

I hope you’ll find the mission(s) fun because I had a lot of fun making them. On Monday I will FINALLY start fixing reported bugs (THANK YOU!!! for taking the time to let me know about them — it helps a lot) while also working on the game’s story.

Specifically, my goal is to begin a major relationship sidequest with Trix to which the taxi mission servers as a kind of prequel. Of course, there are also many blank spaces that I need to circle back to and fill, such as the rent mechanic, EroSphere, PornNexus, and others.

On top of that, I have received a lot of excellent suggestions from you, my amazing supporters, and many of them have made it on my todo list.

Thank you for your ongoing support. Stay tuned for more content and improvements coming your way soon!

MindWare v0.1.2 Is Now Available

Here’s what’s new:

  • Three neuroimaging sessions with Xavier added. Supporters can skip waiting using a button in the task description (visible only with Extra Options unlocked).
  • Gender change status messages now say 1 point instead of 1 points.
  • Added sexuality statistics in the Character screen.
  • New bar area in EroSphere.
  • You can now order a drink in EroSphere (doesn’t have any effects yet).
  • The SynTech location is now accessible (but there’s nothing to do there yet).
  • You can now go inside the Panacea Clinic (but there’s nothing to do there yet).
  • Supporters can now teleport inside EroSphere from the Extra Options menu.
  • You can now dance in EroSphere (but it doesn’t lead to anything yet).
  • You can now enter the Glory Booths area (but there’s nothing to do there yet).
  • It’s no longer possible for implantCharge to be lower than 0.

In this update, I’ve focused on adding more neuroimaging sessions with Xavier. There are now three sessions in total, and you can bet that AVA will attempt to exercise her will during them. Depending on your choices, the sessions can lead to future encounters with Xavier, but those are not implemented yet.

I’ve also made several areas accessible and created visuals for them. Unfortunately, life has been pretty busy these last few weeks, so progress on implementing these new parts of the game has been slower than anticipated. However, I am committed to continuing to improve and expand the game.

The next update will begin what I hope to be one of the most fun parts of Chapter 1—a drama-filled quest with Trix and Ray.

Thank you for your patience and continued support.

MindWare v0.1.1 Is Now Available

Here’s what’s new:

  • Expenses are now stored and manipulated more intelligently.
  • Added Community Zone and Panacea Clinic in the navigation hub (in Chapter 1).
  • Navigation hub “Go Back” links now work as they should.
  • GitGud now has a hub passage.
  • AI coding assistant becomes available when you work at BrainFry for the first time since your infection.
  • You can talk with Yuki about your surgery.
  • You can talk with Xavier about your surgery. This leads to a side mission (NOT IMPLEMENTED YET).
  • There’s a chance that Xavier will be “busy” when you visit him at GitGud.
  • Added a few post-surgery linear passages.
  • PornNexus website is now available (NOT FULLY IMPLEMENTED YET).
  • BrainFry and GitGud dialogs now display in the right order (newest first).
  • The prank mission now becomes available on day 4 of the open section of Chapter 1.
  • Relationship status change messages are more informative.
  • The Notifications box now displays available ByteBunker jobs instead of hacking targets.

The story continues! With your Steady Synapse VX implant installed, you can now finally resume your life and see whether it can contain AVA.

To experience all new content, I recommend you use the Quick Start menu to start from the open section of Chapter 1. Later this week, I will publish a walkthrough so that you can easily see what content is and isn’t available in the game.

Unfortunately, I haven’t been able to address many reported bugs in this version because my work life has been keeping me too busy again. If you’ve already reported a bug and it’s still in the game, please give me until the next release to fix it. If you notice a new bug (one that isn’t caused by using an old save) — please report it right away!

Thank you for your continued support!

MindWare v0.1.0 Is Now Available

Here’s what’s new:

  • The skip prank job minigame link now works as it should.
  • HOPEFULLY, sidebars and topbar are fixed.
  • It’s now clearer which ByteBunker jobs are taken.
  • Nicer scrollbars in Safari.
  • Fixed the following reported bug: Notes deleted after saving.
  • Fixed the following reported bug: When starting a new game, if we change the “Stats Box” location to “Top” in the settings, there will be a padding-top (2em) applied to the CSS even if there isn’t anything shown yet.
  • Fixed the following reported bug: There is an S at the top of the settings menu (before the “Display Settings” text)
  • Fixed the following reported bug: hypnosis screen infinitely changing gender to female
  • Fixed the following reported bug: Character Profile “go back” button going to wrong passage
  • EroSphere introduction now shows as intended.
  • Added task descriptions during the linear section of Chapter 1.
  • Added post-surgery chat with Cipher.

This whole update basically continues where version 0.0.9b ended, giving me at least somewhat polished foundation to work with as I gear up to progress the story in the upcoming versions.

Scroll to top