1
0
Fork 0
mirror of https://gitlab.com/Oreolek/black_phone.git synced 2024-04-30 16:19:42 +03:00

Salet version bump

This commit is contained in:
Alexander Yakovlev 2016-03-10 19:57:05 +07:00
parent 5435ce886f
commit fc79e54460
14 changed files with 159 additions and 105 deletions

View file

@ -4,7 +4,7 @@
room = require("../../lib/room.coffee")
obj = require('../../lib/obj.coffee')
dialogue = require('../../lib/dialogue.coffee')
dialogue = require('../../lib/util/dialogue.coffee')
oneOf = require('../../lib/oneOf.coffee')
Salet = require('../../lib/salet.coffee')
@ -93,7 +93,7 @@ code_check = (salet) ->
return output
room "start", salet,
before: () ->
extendSection: true,
dsc: """
Peter opened his door to find an empty silent corridor.
He went to the neighbor's door and met a closed door.

View file

@ -48,11 +48,9 @@
</div>
<div id="tools_wrapper" class="row">
<div class='ways'>
<h2>Other rooms</h2>
<div id="ways"></div>
</div>
<div class='buttons'>
<button id="save">Save</button><button id="erase">Restart</button>
<small class="text-muted" id="ways_hint">Click these links to explore other rooms</small>
<ul class="nav nav-pills" id="ways">
</ul>
</div>
</div> <!-- End of div.tools_wrapper -->
@ -64,7 +62,10 @@
<p>Betatesting credit: <a href="https://verityvirtue.wordpress.com/">Verity Virtue</a></p>
</div>
<div id="footright">
<a href="./LICENSE.txt"><img src="img/mit.png" alt="This program is licensed under MIT license."></a>
<p class='buttons'>
<button id="erase" class="btn btn-outline-danger">Restart</button>
</p>
<p><a href="./LICENSE.txt"><img src="img/mit.png" alt="This program is licensed under MIT license."></a></p>
</div>
</div>
</div>

View file

@ -36,9 +36,10 @@ languageCodes = Object.keys(languages)
localize = (languageCode, message) ->
for thisCode in languageCodes
localized = languages[languageCode][message]
if localized
return localized
if languages[languageCode]?
localized = languages[languageCode][message]
if localized
return localized
return message
# API
@ -48,13 +49,14 @@ String.prototype.l = (args) ->
# Find the localized form.
localized = localize(lang, this)
# Merge in any replacement content.
if args
for name in args
localized = localized.replace(
new RegExp("\\{"+name+"\\}"), args[name]
)
if typeof(localized) == "function"
localized = localized(args)
else # Merge in any replacement content.
if args
for name in args
localized = localized.replace(
new RegExp("\\{"+name+"\\}"), args[name]
)
return localized
module.exports = languages;

View file

@ -166,5 +166,7 @@ oneOf = (ary...) ->
Array.prototype.oneOf = () ->
oneOf.apply(null, this)
String.prototype.oneOf = () ->
return this
module.exports = oneOf;

View file

@ -6,9 +6,9 @@ markdown = require('./markdown.coffee')
assert = (msg, assertion) -> console.assert assertion, msg
Function.prototype.fcall = Function.prototype.call;
Function.prototype.fcall = Function.prototype.call
Boolean.prototype.fcall = () ->
return this
return this.valueOf()
String.prototype.fcall = () ->
return this
@ -68,6 +68,8 @@ class SaletRoom
@entering = (system, f) =>
if @clear and f?
system.view.clearContent()
else
system.view.removeTransient()
if f != @name and f?
@visited++
@ -77,32 +79,29 @@ class SaletRoom
if @enter
@enter system, f
room_content = ""
if not @extendSection
classes = if @classes then ' ' + @classes.join(' ') else ''
room = document.getElementById('current-room')
if room?
room.removeAttribute('id')
# Javascript DOM manipulation functions like jQuery's append() or document.createElement
# don't work like a typical printLn - they create *DOM nodes*.
# You can't leave an unclosed tag just like that. So we have to buffer the output.
room_content = "<section id='current-room' data-room='#{@name}' class='room-#{@name}#{classes}'>"
system.view.append "<section id='current-room' data-room='#{@name}' class='room-#{@name}#{classes}'></section>"
if f != @name and @before?
room_content += markdown(@before.fcall(this, system, f))
system.view.write markdown(@before.fcall(this, system, f))
room_content += @look system, f
system.view.write @look system, f
if f != @name and @after?
room_content += markdown(@after.fcall(this, system, f))
system.view.write markdown(@after.fcall(this, system, f))
if not @extendSection
room_content += "</section>"
system.view.write(room_content)
if @beforeChoices?
@beforeChoices.fcall(this, system, f)
if @choices
system.view.writeChoices(system, system.getSituationIdChoices(@choices, @maxChoices))
if @afterChoices?
@afterChoices.fcall(this, system, f)
if system.autosave
system.saveGame()
@ -164,7 +163,6 @@ class SaletRoom
# If it's takeable, the player can take this object.
# If not, we check the "act" function.
if thing.takeable
console.log system
system.character.take(thing)
@drop name
system.view.clearContent()

View file

@ -2,7 +2,7 @@ markdown = require('./markdown.coffee')
SaletView = require('./view.coffee')
Random = require('./random.js')
character = require('./character.coffee')
languages = require('./localize.coffee')
require('./localize.coffee')
###
fcall() (by analogy with fmap) is added to the prototypes of both String and
@ -10,7 +10,7 @@ Function. When called on a Function, it's an alias for Function#call();
when called on a String, it only returns the string itself, discarding any input.
###
Function.prototype.fcall = Function.prototype.call;
Function.prototype.fcall = Function.prototype.call
Boolean.prototype.fcall = () ->
return this
String.prototype.fcall = () ->
@ -27,12 +27,12 @@ There is only one instance of this class.
class Salet
constructor: (spec) ->
@character = character()
# REDEFINE THIS IN YOUR GAME
@game_id = null
@game_version = "1.0"
@autosave = true
@rnd = null
@time = 0
@ -230,7 +230,7 @@ class Salet
return
@view.mark_all_links_old
# We're processing, so make the stack available.
@linkStack = []
@ -241,7 +241,7 @@ class Salet
@processOneLink(code)
# We're done, so remove the stack to prevent future pushes.
@linkStack = null;
@linkStack = null
# Scroll to the top of the new content.
@view.endOutputTransaction()
@ -298,13 +298,13 @@ class Salet
newRoom = @rooms[newRoomId]
assert(newRoom, "unknown_situation".l({id:newRoomId}))
# We might not have an old situation if this is the start of the game.
if (oldRoom and @exit)
@exit(oldRoomId, newRoomId)
@current = newRoomId
# Remove links and transient sections.
@view.removeTransient(@interactive)
@ -361,7 +361,9 @@ class Salet
# Loads the game from the given data
@loadGame = (saveFile) =>
@progress = saveFile.progress
@character = saveFile.character
@character = new Character
for index, value of saveFile.character
@character[index] = value
@rnd = new Random(@progress.seed)
@ -370,9 +372,8 @@ class Salet
if saveFile.progress? and saveFile.progress.sequence.length > 1
@view.clearContent()
# Now play through the actions so far:
if (@init)
@init()
# Start the game
@init()
# Run through all the player's history.
interactive = false
@ -408,14 +409,12 @@ class Salet
else
@progress.seed = new Date().toString()
character = new Character()
@rnd = new Random(@progress.seed)
@progress.sequence = [{link:@start, when:0}]
# Start the game
@startTime = new Date().getTime() * 0.001
if (@init)
@init(character)
@init()
# Do the first state.
@doTransitionTo(@start)
@ -433,7 +432,8 @@ class Salet
for index, value of spec
this[index] = value
return this
return this
salet = (spec) ->
spec ?= {}

2
lib/util/README.md Normal file
View file

@ -0,0 +1,2 @@
These functions are not used by Salet core.
But you can `require` them in your game and use thusly.

View file

@ -1,12 +1,5 @@
room = require("./room.coffee")
randomid = () ->
alphabet = "abcdefghijklmnopqrstuvwxyz0123456789" # see the dreaded linkRe expression in Undum
rndstr = []
for i in [1..10]
rndstr.push alphabet.charAt(Math.floor(Math.random() * alphabet.length))
return rndstr.join('').toString()
room = require("../room.coffee")
randomid = require("./randomid.coffee")
###
A dialogue shortcut.
Usage:

30
lib/util/phrase.coffee Normal file
View file

@ -0,0 +1,30 @@
room = require("../room.coffee")
randomid = require("./randomid.coffee")
###
A phrase shortcut.
Usage:
phrase "Point out a thing in her purse (mildly)", "start", """
Point out a thing in her purse (mildly)
""", "character.sandbox.mild = true"
@param title phrase Phrase (question)
@param salet Salet core
@param string tag tag marking viewing condition
@param string text Response
@param string effect an optional parameter, eval'd code
###
phrase = (title, salet, tag, text, effect) ->
retval = room(randomid(), salet, {
optionText: title
dsc: text
clear: false # backlog is useful in dialogues
choices: "#"+tag
tags: [tag]
})
if effect?
retval.before = (character, system) ->
eval(effect)
return retval
module.exports = phrase

6
lib/util/randomid.coffee Normal file
View file

@ -0,0 +1,6 @@
module.exports = () ->
alphabet = "abcdefghijklmnopqrstuvwxyz0123456789" # see the dreaded linkRe expression in Undum
rndstr = []
for i in [1..10]
rndstr.push alphabet.charAt(Math.floor(Math.random() * alphabet.length))
return rndstr.join('').toString()

View file

@ -109,6 +109,14 @@ class SaletView
block = document.getElementById("content")
block.innerHTML = content
# Append content to a block. Does not replace the old content.
append: (content, elementSelector = "#content") =>
if content == ""
return
content = @prepareContent(content)
block = document.querySelector(elementSelector)
block.innerHTML = block.innerHTML + markdown(content)
# Replaces the text in the given block with the given text.
# !! Does not call markdown on the provided text. !!
replace: (content, elementSelector) =>
@ -149,8 +157,8 @@ class SaletView
if (not listOfIds? or listOfIds.length == 0)
return
currentRoom = salet.getCurrentRoom();
$options = $("<ul>").addClass("options");
currentRoom = salet.getCurrentRoom()
$options = $("<ul>").addClass("options")
for roomId in listOfIds
room = salet.rooms[roomId]
assert(room, "unknown_situation".l({id:roomId}))
@ -180,7 +188,7 @@ class SaletView
for a in $('#content').find('a')
a = $(a)
if (a.hasClass('sticky') || a.attr("href").match(/[?&]sticky[=&]?/))
return;
return
a.replaceWith($("<span>").addClass("ex_link").html(a.html()))
contentToHide = $('#content .transient, #content ul.options')
contentToHide.add($("#content a").filter(() ->
@ -260,20 +268,30 @@ class SaletView
$(link.get(0)).click()
)
showBlock: (selector) ->
block = document.querySelector(selector)
if block
block.style.display = "block"
hideBlock: (selector) ->
block = document.querySelector(selector)
if block
block.style.display = "none"
updateWays: (salet, ways, name) ->
if document.getElementById("ways") == null
return
content = ""
distances = []
if ways then for way in ways
if salet.rooms[way]?
title = salet.rooms[way].title.fcall(this, name)
content += way_to(title, way)
content += "<li class='nav-item'><a class='nav-link' href='#{way}'>#{title}</a></li>"
distances.push({
key: way
distance: salet.rooms[way].distance
})
document.querySelector(".ways h2").style.display = "block"
@showBlock(".ways #ways_hint")
else
document.querySelector(".ways h2").style.display = "none"
@hideBlock(".ways #ways_hint")
document.getElementById("ways").innerHTML = content
min = Infinity
min_key = []

View file

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

@ -1 +1 @@
Subproject commit 699c6bb383d0c0179ff0b895ce0520b005db28b1
Subproject commit ada8f213433b357af0528d06ec03148ae9d106f3

View file

@ -10,6 +10,10 @@
@import "bootstrap/scss/images";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/buttons";
//@import "bootstrap/scss/animation";
//@import "bootstrap/scss/dropdown";
@import "bootstrap/scss/nav";
@import "bootstrap/scss/responsive-embed";
@import "bootstrap/scss/utilities";
@ -40,10 +44,12 @@ body {
h1,
h2,
h3 {
//color: rgba(33,17,0,0.9);
text-shadow: rgba(255,255,255,0.5) 2px 2px 2px,
rgba(0,0,0,0.1) -1px -1px 2px;
}
h2 {
font-size: 1.5rem;
}
.warnings {
font-size: small;
font-style: italic;
@ -65,17 +71,18 @@ body {
#tools_wrapper {
.ways {
padding: 0.5em;
@include col(9, 10);
@include col(8, 9);
@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;
.destination {
font-weight: bold;
}
.menu {
@include col(3, 4);
span {
cursor: pointer;
}
}
}
@ -88,6 +95,10 @@ body {
@media (min-width: breakpoint-min(sm)) {
@include make-col-offset(1);
}
.pic {
text-align: center;
margin-bottom: 1em;
}
p {
hyphens: auto;
}
@ -140,51 +151,30 @@ body {
color: darken($body-color, 10%);
font-size: smaller;
#footleft {
@include make-col();
@media (min-width: breakpoint-min(sm)) {
@include make-col-span(10);
@include make-col(10);
}
@media (max-width: breakpoint-max(xs)) {
@include make-col-span(12);
@include make-col(12);
}
}
#footright {
text-align: right;
@include make-col();
@media (min-width: breakpoint-min(sm)) {
@include make-col-span(2);
@include make-col(2);
}
@media (max-width: breakpoint-max(xs)) {
@include make-col-span(12);
@include make-col(12);
margin-bottom: 1em;
}
}
}
#content_library,
#ui_library,
#menu {
#ui_library {
display: none;
}
.controls {
display: none;
@include make-col();
@include make-col-span(12);
@media (max-width: breakpoint-max(xs)) {
margin-bottom: 1em;
}
#clip {
@include halfcolumn();
text-align: center;
img {
max-height: 50px;
}
}
.volume {
@include halfcolumn();
}
}
.way {
color: $waycolor;
margin-right: 1em;
@ -211,3 +201,17 @@ hr {
width: 50%;
border-color: $body-color;
}
// fade-in animation
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation-name: fadeIn;
}