0
0
Fork 0
mirror of https://gitlab.com/Oreolek/salet-module.git synced 2024-06-16 15:10:52 +03:00

Initial commit - scaffold

This commit is contained in:
Alexander Yakovlev 2016-01-07 18:27:57 +07:00
commit f1a6d47dea
15 changed files with 570 additions and 0 deletions

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
node_modules
build
dist
dist.zip

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "sass/bootstrap"]
path = sass/bootstrap
url = https://github.com/twbs/bootstrap.git

118
Gulpfile.coffee Normal file
View file

@ -0,0 +1,118 @@
browserSync = require('browser-sync')
gulp = require('gulp')
coffee = require("gulp-coffee")
sass = require('gulp-sass')
zip = require('gulp-zip')
concat = require('gulp-concat')
reload = browserSync.reload;
# Copy assets over without touching them
assets = (target) ->
return () ->
return gulp.src([
'img/*.png',
'img/*.jpeg',
'img/*.jpg'
]).pipe(gulp.dest(target))
gulp.task('assets', assets('./build'));
gulp.task('sass', function () {
gulp.src('sass/main.scss')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('./build/css'));
});
gulp.task('html', html('./build'));
gulp.task('concatCoffee', function() {
return gulp.src([
'./game/begin.coffee',
'./game/story.coffee',
'./game/init.coffee',
])
.pipe(concat('./main.coffee'))
.pipe(gulp.dest('./build/game'));
});
gulp.task('coffee', ['concatCoffee'])
bundler.on('update', coffee);
bundler.on('log', gutil.log); # Output build logs to terminal
gulp.task('build', ['html', 'img', 'sass', 'coffee'])
gulp.task('serve', ['build'], () ->
browserSync({
server: {
baseDir: 'build'
}
})
sassListener = () ->
reload('./build/css/main.css');
gulp.watch(['./html/*.html'], ['html']);
gulp.watch(['./sass/*.scss'], ['sass']);
gulp.watch(['./build/css/main.css'], sassListener);
gulp.watch(['./img/*.png', './img/*.jpeg', './img/*.jpg'], ['img']);
gulp.watch(['./game/*.coffee'], ['coffee']);
gulp.watch(
['./build/game/bundle.js', './build/img/*', './build/index.html'],
browserSync.reload)
})
/* Distribution tasks */
var undumDistBundler = browserify();
undumDistBundler.require('undum-commonjs');
gulp.task('undum-dist', function () {
return undumDistBundler.bundle().pipe(source('undum.js'))
.pipe(buffer())
.pipe(uglify())
.pipe(gulp.dest('./dist/game'));
});
gulp.task('html-dist', html('./dist'));
gulp.task('img-dist', img('./dist/img'));
gulp.task('legal-dist', function () {
return gulp.src(['LICENSE.txt'])
.pipe(gulp.dest("./dist"));
});
gulp.task('sass-dist', function () {
return gulp.src('./sass/main.scss')
.pipe(sass({outputStyle: 'compressed'}))
.pipe(gulp.dest('./dist/css'));
});
var distBundler = browserify({
debug: false,
entries: ['./build/game/main.coffee'],
transform: ['coffeeify']
});
distBundler.external('undum-commonjs');
gulp.task('coffee-dist', ['undum-dist', 'concatCoffee'], function () {
return distBundler.bundle()
.pipe(source('bundle.js'))
.pipe(buffer())
.pipe(uglify())
.on('error', gutil.log)
.pipe(gulp.dest('./dist/game'));
});
gulp.task('dist', ['html-dist', 'img-dist', 'sass-dist', 'coffee-dist', 'legal-dist'],
function () {
return;
});
gulp.task('zip', ['dist'], function () {
return gulp.src('dist/**')
.pipe(zip('dist.zip'))
.pipe(gulp.dest('.'));
});

20
LICENSE.txt Normal file
View file

@ -0,0 +1,20 @@
Copyright (c) 2016 Alexander Yakovlev, https://oreolek.ru/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

10
README.md Normal file
View file

@ -0,0 +1,10 @@
# Salet
A general client-side framework for cybertext interactive fiction games.
**Salet** is based upon the ideas of [Undum,](https://github.com/idmillington/undum) but is not a direct follower.
## License
The code, documentation, styles, design and images are all distributed under the MIT license.
This permits you to modify and use them, even for commercial use.
A copy of the MIT license is found in the LICENSE file.

170
game/begin.coffee Normal file
View file

@ -0,0 +1,170 @@
situation = require('raconteur')
undum = require('undum-commonjs')
oneOf = require('raconteur/lib/oneOf.js')
qualities = require('raconteur/lib/qualities.js')
$ = require("jquery")
Array.prototype.oneOf = () ->
oneOf.apply(null, this)
md = require('markdown-it')
markdown = new md({
typographer: true,
html: true
})
shortid = require('shortid')
# you have to alter linkRe in Undum core to use that.
# Undum doesn't allow using uppercase letters in situation names by default.
undum.game.id = "6a909a4-586a-4089-bd18-26da684d1c8d"
undum.game.version = "1.0"
a = require('raconteur/lib/elements.js').a
way_to = (content, ref) -> a(content).class('way').ref(ref)
textlink = (content, ref) -> a(content).once().writer(ref)
actlink = (content, ref) -> a(content).once().action(ref)
textcycle = (content, ref) -> a(content).replacer(ref).class("cycle").id(ref).toString()
# usage: writemd( system, "Text to write")
writemd = (system, text) ->
if typeof text is Function
text = text()
text = markdown.render(text)
system.write(text)
preparemd = (text, mark) ->
if typeof text is Function
text = text()
text = markdown.render(text)
if mark?
text = """
<div class="#{mark}">
#{text}
</div>
"""
return text
money = (character, system, amount) ->
system.setQuality("money", character.qualities.money + amount)
code_can_input = (character) ->
return character.sandbox.code.length < 8
code_print = (character) ->
mask = 8 - character.sandbox.code.length
retval = character.sandbox.code
if mask > 0
for i in [1..mask]
retval += "_"
return retval
code_input = (character, digit) ->
if code_can_input(character)
character.sandbox.code = character.sandbox.code + digit
code_reset = (character) ->
character.sandbox.code = ""
code_check = (character, system) ->
if character.sandbox.code.length >= 8
# There is an Undum.. let's call it a feature
# that prevents the player from entering "3112".
# You see, you can't select the situation 1 when you are
# already in this situation, so you can't input 1 twice.
if character.sandbox.code == "01012017"
character.sandbox.box_opened = 1
if character.sandbox.knows_the_code == 0
writemd(system, """
Is he an extraordinary puzzle cracker or was it a sheer luck, but Ronald manages to *guess* the code.
""")
else
writemd(system, """
New Year 2017.
L. Y. must be Leonard Yakovlev, a famous painter.
Some tabloids tried to connect him with Ana but it seemed like a weak link.
By that logic, his sketch is worth more than all the cash here.
Ronald thinks about it, but decides to "let the woman have her memories".
""")
writemd(system, """
Something clicks and box opens.
The phone is slick, black and light in Ronald's hand.
It springs to life, humming with purpose.
The screen plays an animation: "LOADING..."
Ronald has no other business here.
It's time to go.
""")
system.doLink("bedroom")
else
writemd(system, "Something clicks and the display resets, but the box stays locked.")
if character.sandbox.code == "000000"
writemd(system, "Of course, Ronald didn't hope it would be that easy.")
character.sandbox.code = ""
update_ways = (ways) ->
content = ""
for way in ways
if undum.game.situations[way]?
content += way_to(undum.game.situations[way].title, way)
$("#ways").html(content)
situation "start",
content: """
Peter had so much trouble sleeping he had to drown his pills in at least an hour of thoughts.
A violent ringing of the bell awakened him.
He rose from the bed, grumbling:
Crazy neighbors and their guests. It must be three o'clock!”
The visitor entered the hallway.
It was him ringing the bell, but he was not going to meet Peter.
In fact, he wasn't looking for meeting anybody here.
Fourth floor, apartment 406.
There, he tried two keys.
The second of them fitted the lock.
Burglary is a curious line of employment.
Befittedly, Ronald Chernoff was very curious about a black phone behind the door of apartment 406 in a wooden box on a small table no farther than two meters from the bed.
A gift, a prototype, a valuable treasure left by Anastacia Kozlowa when she fled the country.
Of course, one had to be reasonably au fait with her *Instagram* to notice that.
Peter opened his door to find an empty silent corridor.
He went to the neighbor's door and met a closed door.
Ronald was working inside, quietly walking around the apartment.
He began the inspection from [the living room.](living-room)
<hr>
"""
is_visited = (situation) ->
situations = undum.game.situations[situation]
if situations
return Boolean situations.visited
return 0
# N-th level examine function
level = (text, mark) ->
$("#content .#{mark}").fadeOut()
return preparemd(text, mark)
lvl1 = (text) ->
$("#content .lvl2").fadeOut()
$("#content .lvl3").fadeOut()
$("#content .lvl4").fadeOut()
level(text, "lvl1")
lvl2 = (text) ->
$("#content .lvl3").fadeOut()
$("#content .lvl4").fadeOut()
level(text, "lvl2")
lvl3 = (text) ->
$("#content .lvl4").fadeOut()
level(text, "lvl3")
lvl4 = (text) ->
level(text, "lvl4")

14
game/init.coffee Normal file
View file

@ -0,0 +1,14 @@
# This is where you initialize your game.
# All code in this file comes last, so the game is almost ready by this point.
player "Player"
money: 0
status: "Good"
undum.game.init = (character, system) ->
$("#ways").on("click", "a", (event) ->
event.preventDefault()
undum.processClick($(this).attr("href"))
)
window.onload = undum.begin

0
game/story.coffee Normal file
View file

49
html/index.html Normal file
View file

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Salet tutorial</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href='https://fonts.googleapis.com/css?family=PT+Sans:400,400italic|PT+Sans+Caption' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<div id="page" class="container">
<div id="content_wrapper" class="row">
<div id="content">
<h1>Salet tutorial</h1>
</div>
<a name="end_of_content"></a>
</div>
<div id="tools_wrapper" class="row">
<div class='ways'>
<h2>Other rooms</h2>
<div id="ways"></div>
</div>
<div class='buttons'>
<button id="undo">Undo</button>
<button id="save">Save</button>
<button id="load">Load</button>
<button id="erase">Restart</button>
</div>
</div><!-- end of tools -->
<div class="row">
<div id="legal">
<div id="footleft">
<!-- Author credit goes here -->
<p>The game was written by <b><a href="http://en.oreolek.ru/" target="_blank">Oreolek.</a></b></p>
<!-- It's a good gesture to specify how long is your game. -->
<p>Approximate play time: five minutes.</p>
<p>Written using <a href="http://git.oreolek.ru/oreolek/salet" target="_blank">Salet.</a>
</div>
<div id="footright">
<a href="./LICENSE.txt"><img src="img/mit.png" alt="This program is licensed under MIT license."></a>
</div>
</div>
</div>
</div> <!-- End of div.page -->
<script type="text/javascript" src="game/main.js"></script>
</body>
</html>

BIN
img/mit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 444 B

15
package.json Normal file
View file

@ -0,0 +1,15 @@
{
"dependencies": {
},
"private": true,
"devDependencies": {
"gulp": "^3.8.11",
"gulp-uglify": "^1.2.0",
"gulp-sass": "^2.1.1",
"gulp-coffee": "^2.3.1",
"gulp-zip": "^3.0.2",
"gulp-shell": "^0.5.1",
"gulp-concat": "^2.6.0",
"browser-sync": "^2.11.0"
}
}

19
sass/_mixins.scss Normal file
View file

@ -0,0 +1,19 @@
@mixin halfcolumn() {
@include make-col();
@media (min-width: breakpoint-min(sm)) {
@include make-col-span(6);
}
@media (max-width: breakpoint-max(xs)) {
@include make-col-span(12);
}
}
@mixin col($sm-width, $xs-width) {
@include make-col;
@media (min-width: breakpoint-min(sm)) {
@include make-col-span($sm-width);
}
@media (max-width: breakpoint-max(xs)) {
@include make-col-span($xs-width);
}
}

13
sass/_variables.scss Normal file
View file

@ -0,0 +1,13 @@
$font-family-sans-serif: 'PT Sans','Open Sans',"Helvetica Neue", Helvetica, Arial, sans-serif;
$headings-font-family: "PT Sans Caption",$font-family-sans-serif;
$font-family-base: $font-family-sans-serif;
$body-bg: #F1EED9;
$body-color: #58351A;
$link-color: #382313;
$btn-bg: #C33601;
$btn-color: $body-color;
$secondary-bg: #F1EED9;
$waycolor: $link-color;
$text_background: $body-bg; // can be btn-bg

1
sass/bootstrap Submodule

@ -0,0 +1 @@
Subproject commit 08031d6a76337e9e6d0c7aa3d034b8006e26e705

134
sass/main.scss Normal file
View file

@ -0,0 +1,134 @@
@import "mixins";
@import "variables";
// Bootstrap v4 stripped core
@import "bootstrap/scss/variables";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/normalize";
@import "bootstrap/scss/print";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/type";
@import "bootstrap/scss/images";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/buttons";
@import "bootstrap/scss/responsive-embed";
@import "bootstrap/scss/utilities";
body {
overflow-y: scroll;
overflow-x: hidden;
background: $body-bg;
}
#tools_wrapper {
display: none; // Shown by Javascript
.ways {
padding: 0.5em;
// @include col(4, 5);
@include col(9, 10);
@media (min-width: breakpoint-min(sm)) {
@include make-col-offset(1);
}
}
.buttons {
@include col(1, 2);
button {
@extend .btn;
@include button-variant($btn-color, $btn-bg, $btn-color);
margin-bottom: 1em;
}
}
}
#content_wrapper {
background: $text_background;
border-radius: 5px;
}
#content {
@include col(10, 12);
@media (min-width: breakpoint-min(sm)) {
@include make-col-offset(1);
}
p {
hyphens: auto;
}
padding: 1em;
ul {
margin: 0;
padding: 0 0 0 1em;
}
ul.options {
padding: 0;
text-align: center;
margin-top: 0.5em;
margin-bottom: 0.7em;
list-style-type: none;
border-radius: 4px;
li {
padding: 0.5em;
}
li:hover {
cursor: pointer;
}
li:last-child {
border-bottom: none;
}
}
section {
border-top: 1px dashed #bbb;
}
.situation-start {
border-top: none;
}
img.right {
float: right;
margin: 1.1em 0 1.1em 1.1em;
}
img.left {
float: left;
margin: 1.1em 1.1em 1.1em 0;
}
h3 {
text-align: center;
}
}
#legal {
@include col(10,12);
@media (min-width: breakpoint-min(sm)) {
@include make-col-offset(1);
}
margin-top: 1em;
color: darken($body-color, 10%);
font-size: smaller;
display: none; // Shown by Javascript
#footleft {
@include make-col();
@media (min-width: breakpoint-min(sm)) {
@include make-col-span(10);
}
@media (max-width: breakpoint-max(xs)) {
@include make-col-span(12);
}
}
#footright {
text-align: right;
@include make-col();
@media (min-width: breakpoint-min(sm)) {
@include make-col-span(2);
}
@media (max-width: breakpoint-max(xs)) {
@include make-col-span(12);
margin-bottom: 1em;
}
}
}
.way {
color: $waycolor;
margin-right: 1em;
}
.cycle {
color: darkgreen;
border-bottom: darkgreen dashed 1px;
}
hr {
width: 50%;
border-color: $body-color;
}