/* * Plugin: ageCheck.js * Description: A simple plugin to verify user's age. * Uses sessionStorage/localStorage API to store if user is verified. * Options can be passed for easy customization. * Author: Michael Soriano * Author's website: http://michaelsoriano.com * */ (function ($) { $.ageCheck = function (options) { const settings = $.extend({ minAge: 21, redirectTo: '', redirectOnFail: '', title: 'Age Verification', copy: 'This Website requires you to be [21] years or older to enter. Please enter your Date of Birth in the fields below in order to continue:', success: null, successMsg: { header: 'Success!', body: 'You are now being redirected back to the application...' }, underAgeMsg: 'Sorry, you are not old enough to view this site...', underAge: null, errorMsg: { invalidDay: 'Day is invalid or empty', invalidYear: 'Year is invalid or empty' }, storage: 'sessionStorage', storageExpires: null, }, options); var storage = window[settings.storage]; const _this = { month: '', day: '', year: '', age: '', errors: [], setValues() { const month = $('.ac-container .month').val(); const day = $('.ac-container .day').val(); _this.month = month; _this.day = day.replace(/^0+/, ''); // remove leading zero _this.year = $('.ac-container .year').val(); }, validate() { _this.errors = []; if (/^([0-9]|[12]\d|3[0-1])$/.test(_this.day) === false) { _this.errors.push(settings.errorMsg.invalidDay); } if (/^(19|20)\d{2}$/.test(_this.year) === false) { _this.errors.push(settings.errorMsg.invalidYear); } _this.clearErrors(); _this.displayErrors(); return _this.errors.length < 1; }, clearErrors() { $('.errors').html(''); }, displayErrors() { let html = ''; setTimeout(() => { $('.ac-container .errors').html(html); }, 200); }, reCenter(b) { b.css('top', `${Math.max(0, (($(window).height() - (b.outerHeight() + 150)) / 2))}px`); b.css('left', `${Math.max(0, (($(window).width() - b.outerWidth()) / 2))}px`); }, buildHtml() { const copy = settings.copy; const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; let html = ''; html += '
'; html += '
'; html += `

${settings.title}

`; html += `

${copy.replace('[21]', `${settings.minAge}`)}` + '

'; html += '
'; html += '
'; html += ''; html += ''; html += '
'; $('body').append(html); $('.ac-overlay').animate({ opacity: 0.8, }, 500, () => { _this.reCenter($('.ac-container')); $('.ac-container').css({ opacity: 1, }); }); $('.ac-container .day, .ac-container .year').focus(function () { $(this).removeAttr('placeholder'); }); }, setAge() { _this.age = ''; const birthday = new Date(_this.year, _this.month, _this.day); const ageDifMs = Date.now() - birthday.getTime(); const ageDate = new Date(ageDifMs); // miliseconds from epoch _this.age = Math.abs(ageDate.getUTCFullYear() - 1970); }, getStorage() { if(settings.storage === 'cookie') { return document.cookie.split(';').filter((item) => item.trim().startsWith('ageVerified=')).length; } else { return storage.getItem('ageVerified') === 'true'; } }, setStorage(key, val, expires) { try { if(settings.storage === 'cookie') { if(expires) { let date = new Date(); date.setTime(date.getTime() + (expires * 24 * 60 * 60 * 1000)); expires = date.toGMTString(); } document.cookie = "ageVerified=true; expires=" + expires + ";"; } else { storage.setItem(key, val); } return true; } catch (e) { return false; } }, handleSuccess() { const successMsg = `

${settings.successMsg.header}

${settings.successMsg.body}

`; $('.ac-container').html(successMsg); setTimeout(() => { $('.ac-container').animate({ top: '-350px', }, 200, () => { $('.ac-overlay').animate({ opacity: '0', }, 500, () => { if (settings.redirectTo !== '') { window.location.replace(settings.redirectTo); } else { $('.ac-overlay, .ac-container').remove(); if (settings.success) { settings.success(); } } }); }); }, 2000); }, handleUnderAge() { const underAgeMsg = `

${settings.underAgeMsg}

`; $('.ac-container').html(underAgeMsg); if (settings.redirectOnFail !== '') { setTimeout(() => { window.location.replace(settings.redirectOnFail); }, 2000); } if (settings.underAge) { settings.underAge(); } }, }; // end _this if (_this.getStorage()) { return false; } _this.buildHtml(); $('.ac-container button').on('click', () => { _this.setValues(); if (_this.validate() === true) { _this.setAge(); if (_this.age >= settings.minAge) { if (!_this.setStorage('ageVerified', 'true', settings.storageExpires)) { console.log(settings.storage + ' not supported by your browser'); } _this.handleSuccess(); } else { _this.handleUnderAge(); } } }); $(window).resize(() => { _this.reCenter($('.ac-container')); setTimeout(() => { _this.reCenter($('.ac-container')); }, 500); }); }; }(jQuery));
top of page

Where The Water Tastes Like Wine

Where the Water Tastes Like Wine is a Narrative-Adventure game about traveling, sharing stories, and surviving manifest destiny. Featuring gorgeous hand-drawn illustrations, Where the Water Tastes Like Wine combines 2D visuals with a 3D overworld US map.

Players wander across a folkloric Depression era United States at their own pace, meeting strangers with their own stories to tell. Through these interactions, players will be able to collect unique stories which can then be re-told to unlock new interactions. In this way the in-game stories themselves act as a currency to progress through the game, and it’s up to the player to pair the right story with the unique needs of each of the characters that you will encounter throughout your travels. Only through these right pairings will characters reveal their true selves, and bestow you with the most powerful stories, the true ones which reveal something about their own lives. In Where The Water Tastes Like Wine, stories organically take on a life of their own as they grow larger and transform as they're told- and re-told.

TITLE:

Where The Water Tastes Like Wine

GENRE:

Adventure, Narrative

DEVELOPER:

Serenity Forge, Dim Bulb Games

PUBLISHER:

PM Studios, Serenity Forge

RELEASE DATE:

Aug. 2, 2021

ESRB_XONiC.jpg
Button_BuyNow.png
Button_BuyNow_VGP.png
bottom of page