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:
commit
f1a6d47dea
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
node_modules
|
||||
build
|
||||
dist
|
||||
dist.zip
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "sass/bootstrap"]
|
||||
path = sass/bootstrap
|
||||
url = https://github.com/twbs/bootstrap.git
|
118
Gulpfile.coffee
Normal file
118
Gulpfile.coffee
Normal 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
20
LICENSE.txt
Normal 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
10
README.md
Normal 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
170
game/begin.coffee
Normal 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
14
game/init.coffee
Normal 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
0
game/story.coffee
Normal file
49
html/index.html
Normal file
49
html/index.html
Normal 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
BIN
img/mit.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 444 B |
15
package.json
Normal file
15
package.json
Normal 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
19
sass/_mixins.scss
Normal 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
13
sass/_variables.scss
Normal 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
1
sass/bootstrap
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 08031d6a76337e9e6d0c7aa3d034b8006e26e705
|
134
sass/main.scss
Normal file
134
sass/main.scss
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue