0
0
Fork 0
mirror of https://gitlab.com/Oreolek/salet-module.git synced 2024-07-02 23:05:02 +03:00

Modular API (WIP)

This commit is contained in:
Alexander Yakovlev 2016-01-25 23:05:32 +07:00
parent 63dbeb49f4
commit 566c8b27a2
6 changed files with 81 additions and 96 deletions

View file

@ -3,10 +3,7 @@ room = require("../../lib/room.coffee")
obj = require('../../lib/obj.coffee') obj = require('../../lib/obj.coffee')
dialogue = require('../../lib/dialogue.coffee') dialogue = require('../../lib/dialogue.coffee')
oneOf = require('../../lib/oneOf.coffee') oneOf = require('../../lib/oneOf.coffee')
salet = require('../../lib/salet.coffee') require('../../lib/salet.coffee')
salet.game_id = "your-game-id-here"
salet.game_version = "1.0"
### ###
Element helpers. There is no real need to build monsters like a().id("hello") Element helpers. There is no real need to build monsters like a().id("hello")
@ -26,29 +23,9 @@ textcycle = (content, ref) ->
cyclelink = (content) -> cyclelink = (content) ->
return "<a href='./_replacer_cyclewriter' class='cycle' id='cyclewriter'>#{content}</a>" return "<a href='./_replacer_cyclewriter' class='cycle' id='cyclewriter'>#{content}</a>"
# usage: writemd( system, "Text to write")
writemd = (system, text) ->
text = markdown(text)
system.write(text)
get_room = (name) ->
return undum.game.situations[name]
# Function to return the current room.
# Works because our `enter()` function sets the `data-situation` attribute.
here = () ->
return undum.game.situations[document.getElementById("current-situation").getAttribute("data-situation")]
# The first room of the game. # The first room of the game.
# For accessibility reasons the text is provided in HTML, not here. # For accessibility reasons the text is provided in HTML, not here.
room "start", room "start",
dsc: """ dsc: """
""", """,
choices: "#start" choices: "#start"
# This function needs to go after the start room.
is_visited = (situation) ->
place = undum.game.situations[situation]
if place
return Boolean place.visited
return 0

View file

@ -1,4 +1,7 @@
# This is where you initialize your game. # This is where you initialize your game.
# All code in this file comes last, so the game is almost ready by this point.
salet.init = (character, system) -> $(document).ready(() ->
salet.game_id = "your-game-id-here"
salet.game_version = "1.0"
salet.beginGame()
)

View file

@ -1,5 +1,5 @@
markdown = require('./markdown.coffee') markdown = require('./markdown.coffee')
salet = require('./salet.coffee') require('./salet.coffee')
objlink = (content, ref) -> objlink = (content, ref) ->
return "<a href='./_act_#{ref}' class='once'>#{content}</a>" return "<a href='./_act_#{ref}' class='once'>#{content}</a>"

View file

@ -5,7 +5,7 @@ markdown = require('./markdown.coffee')
cycle = require('./cycle.coffee') cycle = require('./cycle.coffee')
Random = require('./random.js') Random = require('./random.js')
languages = require('./localize.coffee') languages = require('./localize.coffee')
salet = require('./salet.coffee') require('./salet.coffee')
# Assertion # Assertion
assert = console.assert assert = console.assert
@ -21,10 +21,6 @@ addClass = (element, className) ->
else else
element.className += ' ' + className element.className += ' ' + className
cls = (system) ->
system.clearContent()
system.clearContent("#intro")
update_ways = (ways, name) -> update_ways = (ways, name) ->
content = "" content = ""
distances = [] distances = []
@ -118,41 +114,41 @@ class SaletRoom
My version of `enter` splits the location description from the effects. My version of `enter` splits the location description from the effects.
Also if f == this.name (we're in the same location) the `before` and `after` callbacks are ignored. Also if f == this.name (we're in the same location) the `before` and `after` callbacks are ignored.
### ###
entering: (character, system, f) => entering: (system, f) =>
if @clear and f? if @clear and f?
cls(system) system.view.clearContent()
if f != @name and f? if f != @name and f?
@visited++ @visited++
if salet.rooms[f].exit? if system.rooms[f].exit?
salet.rooms[f].exit(character, system, @name) system.rooms[f].exit system, @name
if @enter if @enter
@enter character, system, f @enter system, f
current_situation = "" room_content = ""
if not @extendSection if not @extendSection
classes = if @classes then ' ' + @classes.join(' ') else '' classes = if @classes then ' ' + @classes.join(' ') else ''
situation = document.getElementById('current-room') room = document.getElementById('current-room')
if situation? if room?
situation.removeAttribute('id') room.removeAttribute('id')
# Javascript DOM manipulation functions like jQuery's append() or document.createElement # Javascript DOM manipulation functions like jQuery's append() or document.createElement
# don't work like a typical printLn - they create *DOM nodes*. # 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. # You can't leave an unclosed tag just like that. So we have to buffer the output.
current_situation = "<section id='current-room' data-situation='#{@name}' class='situation-#{@name}#{classes}'>" room_content = "<section id='current-room' data-room='#{@name}' class='room-#{@name}#{classes}'>"
if f != @name and @before? if f != @name and @before?
current_situation += markdown(@before.fcall(this, character, system, f)) room_content += markdown(@before.fcall(this, system, f))
current_situation += @look character, system, f room_content += @look system, f
if f != @name and @after? if f != @name and @after?
current_situation += markdown(@after.fcall(this, character, system, f)) room_content += markdown(@after.fcall(this, system, f))
if not @extendSection if not @extendSection
current_situation += "</section>" room_content += "</section>"
system.write(current_situation) system.write(room_content)
if @choices if @choices
system.writeChoices(system.getSituationIdChoices(@choices, @minChoices, @maxChoices)) system.writeChoices(system.getSituationIdChoices(@choices, @minChoices, @maxChoices))
@ -272,7 +268,13 @@ room = (name, spec) ->
spec ?= {} spec ?= {}
spec.name = name spec.name = name
retval = new SaletRoom(spec) retval = new SaletRoom(spec)
retval.register() $(document).ready(() ->
if salet
retval.register()
else
sleep(1000)
retval.register()
)
return retval return retval
module.exports = room module.exports = room

View file

@ -1,5 +1,5 @@
markdown = require('./markdown.coffee') markdown = require('./markdown.coffee')
view = require('./view.coffee') SaletView = require('./view.coffee')
Random = require('./random.js') Random = require('./random.js')
### ###
@ -48,7 +48,7 @@ augmentLinks = (content) ->
# If we're a once-click, remove all matching links. # If we're a once-click, remove all matching links.
if (a.hasClass("once") || href.match(/[?&]once[=&]?/)) if (a.hasClass("once") || href.match(/[?&]once[=&]?/))
view.clearLinks(href) @view.clearLinks(href)
processClick(href) processClick(href)
return false return false
@ -92,13 +92,13 @@ class Salet
situation. It is called before the corresponding situation situation. It is called before the corresponding situation
has its `enter` method called. has its `enter` method called.
### ###
entering: (character, oldSituationId, newSituationId) -> enter: (oldSituationId, newSituationId) ->
### ###
Hook for when the situation has already been carried out Hook for when the situation has already been carried out
and printed. and printed.
### ###
afterEnter: (character, oldSituationId, newSituationId) -> afterEnter: (oldSituationId, newSituationId) ->
### ###
This function is called before carrying out any action in This function is called before carrying out any action in
@ -110,21 +110,21 @@ class Salet
on to the situation. Note that this is the only one of on to the situation. Note that this is the only one of
these global handlers that can consume the event. these global handlers that can consume the event.
### ###
beforeAction: (character, situationId, actionId) -> beforeAction: (situationId, actionId) ->
### ###
This function is called after carrying out any action in This function is called after carrying out any action in
any situation. It is called after the corresponding any situation. It is called after the corresponding
situation has its `act` method called. situation has its `act` method called.
### ###
afterAction: (character, situationId, actionId) -> afterAction: (situationId, actionId) ->
### ###
This function is called after leaving any situation. It is This function is called after leaving any situation. It is
called after the corresponding situation has its `exit` called after the corresponding situation has its `exit`
method called. method called.
### ###
exit: (character, oldSituationId, newSituationId) -> exit: (oldSituationId, newSituationId) ->
### ###
Returns a list of situation ids to choose from, given a set of Returns a list of situation ids to choose from, given a set of
@ -307,7 +307,7 @@ class Salet
@linkStack.push(code) @linkStack.push(code)
return return
view.mark_all_links_old @view.mark_all_links_old
# We're processing, so make the stack available. # We're processing, so make the stack available.
@linkStack = [] @linkStack = []
@ -375,32 +375,30 @@ class Salet
processLink(code) processLink(code)
# Transitions between situations. # Transitions between situations.
doTransitionTo: (newSituationId) -> doTransitionTo: (newRoomId) ->
oldSituationId = current oldRoomId = @current
oldSituation = @getCurrentRoom() oldRoom = @getCurrentRoom()
newSituation = @rooms[newSituationId] newRoom = @rooms[newRoomId]
assert(newSituation, "unknown_situation".l({id:newSituationId})) assert(newRoom, "unknown_situation".l({id:newRoomId}))
# We might not have an old situation if this is the start of the game. # We might not have an old situation if this is the start of the game.
if (oldSituation) if (oldRoom and @exit)
if (@exit) @exit(oldRoomId, newRoomId)
@exit(@character, oldSituationId, newSituationId);
@current = newRoomId
# Remove links and transient sections. # Remove links and transient sections.
view.remove_transient(@interactive) @view.remove_transient(@interactive)
# Move the character.
current = newSituationId
# Notify the incoming situation. # Notify the incoming situation.
if (@enter) if (@enter)
@enter(@character, this, oldSituationId, newSituationId) @enter(oldRoomId, newRoomId)
newSituation.entering(@character, oldSituationId) newRoom.entering(this, oldRoomId)
# additional hook for when the situation text has already been printed # additional hook for when the situation text has already been printed
if (@afterEnter) if (@afterEnter)
@afterEnter(@character, oldSituationId, newSituationId) @afterEnter(oldRoomId, newRoomId)
### ###
Erases the character in local storage. This is permanent! Erases the character in local storage. This is permanent!
@ -436,9 +434,9 @@ class Salet
localStorage.setItem(getSaveId(), JSON.stringify(@progress)) localStorage.setItem(getSaveId(), JSON.stringify(@progress))
# Switch the button highlights. # Switch the button highlights.
view.disableSaving() @view.disableSaving()
view.enableErasing() @view.enableErasing()
view.enableLoading() @view.enableLoading()
# Loads the game from the given data # Loads the game from the given data
loadGame: (characterData) -> loadGame: (characterData) ->
@ -447,7 +445,7 @@ class Salet
character = new Character() character = new Character()
@rnd = new Random(@progress.seed) @rnd = new Random(@progress.seed)
view.clearContent() @view.clearContent()
# Now play through the actions so far: # Now play through the actions so far:
if (@init) if (@init)
@ -465,17 +463,19 @@ class Salet
now = new Date().getTime() * 0.001 now = new Date().getTime() * 0.001
startTime = now - @progress.saveTime startTime = now - @progress.saveTime
view: new SaletView
beginGame: () -> beginGame: () ->
# Handle storage. # Handle storage.
storedCharacter = false storedCharacter = false
if (view.hasLocalStorage()) if (@view.hasLocalStorage())
storedCharacter = localStorage.getItem(@getSaveId()) storedCharacter = localStorage.getItem(@getSaveId())
if (storedCharacter) if (storedCharacter)
try try
@loadGame(JSON.parse(storedCharacter)) @loadGame(JSON.parse(storedCharacter))
view.disableSaving() @view.disableSaving()
view.enableErasing() @view.enableErasing()
catch err catch err
@erase_save(true) @erase_save(true)
else else
@ -485,16 +485,15 @@ class Salet
@rnd = new Random(@progress.seed) @rnd = new Random(@progress.seed)
@progress.sequence = [{link:@start, when:0}] @progress.sequence = [{link:@start, when:0}]
view.clearContent() @view.clearContent()
# Start the game # Start the game
startTime = new Date().getTime() * 0.001 @startTime = new Date().getTime() * 0.001
@time = 0
if (@init) if (@init)
@init(character) @init(character)
# Do the first state. # Do the first state.
@doTransitionTo(@start); @doTransitionTo(@start)
# Any point that an option list appears, its options are its first links. # Any point that an option list appears, its options are its first links.
$("body").on('click', "ul.options li, #menu li", (event) -> $("body").on('click', "ul.options li, #menu li", (event) ->
@ -502,17 +501,25 @@ class Salet
link = $("a", this) link = $("a", this)
if (link.length > 0) if (link.length > 0)
$(link.get(0)).click() $(link.get(0)).click()
); )
salet = new Salet getRoom: (name) ->
return @rooms[name]
# Just an alias for getCurrentRoom
here: () -> @getCurrentRoom()
isVisited: (name) ->
place = @getRoom(name)
if place
return Boolean place.visited
return 0
# Set up the game when everything is loaded. # Set up the game when everything is loaded.
$(document).ready(() -> $(document).ready(() ->
if (view.hasLocalStorage()) salet = new Salet
salet.view.init()
if (salet.view.hasLocalStorage())
$("#erase").click(salet.erase_save) # is Salet defined here? $("#erase").click(salet.erase_save) # is Salet defined here?
$("#save").click(salet.saveGame) $("#save").click(salet.saveGame)
salet.beginGame()
) )
module.exports = salet

View file

@ -12,12 +12,13 @@ but they could be something else entirely. (That's why IDs are hardcoded.)
class SaletView class SaletView
init: () -> init: () ->
$("#ways").on("click", "a", (event) -> $("#content, #ways").on("click", "a", (event) ->
event.preventDefault() event.preventDefault()
salet.processClick($(this).attr("href")) salet.processClick($(this).attr("href"))
) )
$("#inventory").on("click", "a", (event) -> $("#inventory").on("click", "a", (event) ->
event.preventDefault() event.preventDefault()
alert("Not done yet")
) )
$("#load").on("click", "a", (event) -> $("#load").on("click", "a", (event) ->
window.location.reload() window.location.reload()
@ -192,9 +193,4 @@ class SaletView
hasStorage = false hasStorage = false
return hasStorage return hasStorage
view = new SaletView module.exports = SaletView
$(document).ready(() ->
view.init()
)
module.exports = view