mirror of
https://gitlab.com/Oreolek/salet.git
synced 2024-06-01 07:48:20 +03:00
Cycling rewrite, Raconteur's purge
- Rewrote cycling shortcuts into the library. It's more object-oriented now (and slightly less obvious, but we can get around that). - Removed Raconteur situations entirely. Their functionality is 100% integrated now.
This commit is contained in:
parent
407305a54c
commit
0ed470dae6
|
@ -22,21 +22,11 @@ actlink = (content, ref) ->
|
|||
return "<a href='./#{ref}' class='once'>#{content}</a>"
|
||||
textcycle = (content, ref) ->
|
||||
return "<a href='./_replacer_#{ref}' class='cycle' id='#{ref}'>#{content}</a>"
|
||||
|
||||
# TODO: hide this somewhere in exports or autoreplacer shortcuts
|
||||
cyclelink = (content) ->
|
||||
return "<a href='./_replacer_cyclewriter' class='cycle' id='cyclewriter'>#{content}</a>"
|
||||
|
||||
# Cycling link. It's implied there can be only one per situation.
|
||||
# You are welcome to improve this code.
|
||||
cycle = (obj, character) ->
|
||||
responses = obj.cycle_gallery()
|
||||
character.sandbox.cycle_index ?= [] # initialize with empty array
|
||||
character.sandbox.cycle_index[obj.name] ?= 0 # initialize with 0
|
||||
response = responses[character.sandbox.cycle_index[obj.name]]
|
||||
character.sandbox.cycle_index[obj.name]++
|
||||
if character.sandbox.cycle_index[obj.name] == responses.length
|
||||
character.sandbox.cycle_index[obj.name] = 0
|
||||
return textcycle(response, 'cyclewriter')
|
||||
|
||||
# usage: writemd( system, "Text to write")
|
||||
writemd = (system, text) ->
|
||||
text = markdown(text)
|
||||
|
|
|
@ -19,10 +19,7 @@ room "plaza",
|
|||
return "Upwards"
|
||||
else
|
||||
return "Town plaza"
|
||||
cycle_gallery: () -> # it needs to be a function if you want localization
|
||||
return [
|
||||
"quirky", "distinct", "kooky", "crazy", "quaint"
|
||||
]
|
||||
cycle: ["quirky", "distinct", "kooky", "crazy", "quaint"]
|
||||
ways: ["shop"]
|
||||
before: (character, system, from) ->
|
||||
if from == 'world'
|
||||
|
@ -32,8 +29,6 @@ room "plaza",
|
|||
"""
|
||||
else
|
||||
"You quickly find the central plaza."
|
||||
writers:
|
||||
cyclewriter: (character) -> cycle(this, character)
|
||||
objects:
|
||||
policeman: obj "policeman",
|
||||
dsc: "There is a policeman nearby. You could ask him {{for directions.}}"
|
||||
|
@ -65,14 +60,13 @@ room "lair",
|
|||
dsc: """
|
||||
The Lair of Yog-Sothoth is a very *n'gai* cave, full of *buggs-shoggogs* and *n'ghaa ng'aa*.
|
||||
"""
|
||||
objects: {
|
||||
objects:
|
||||
bugg: obj "bugg",
|
||||
dsc: "You see a particularly beautiful slimy {{bugg.}}"
|
||||
takeable: false
|
||||
act: () =>
|
||||
here().drop(@name)
|
||||
return "You eat the bugg mass. Delicious and raw. Perhaps it's a good lair to live in."
|
||||
}
|
||||
|
||||
dialogue "Yes", "merchant", "merchant", """
|
||||
Yes.
|
||||
|
@ -86,14 +80,13 @@ room "shop-inside",
|
|||
dsc: """
|
||||
The insides are painted pastel white, honouring The Great Milk Spill of 1985.
|
||||
"""
|
||||
objects: {
|
||||
objects:
|
||||
merchant: obj "merchant",
|
||||
dsc: "A {{merchant}} eyes you warily."
|
||||
takeable: false
|
||||
act: (character, system) =>
|
||||
undum.processClick("merchdialogue")
|
||||
return ""
|
||||
}
|
||||
|
||||
###
|
||||
I want to be able to do this but I can't because I'm lost in all the `this` and @objects and `new`.
|
||||
|
|
19
lib/cycle.coffee
Normal file
19
lib/cycle.coffee
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Cycling interface.
|
||||
# Rooms: cycle through this.cycle_gallery
|
||||
# Objects: cycle through this.cycle_gallery
|
||||
|
||||
cyclelink = (content) ->
|
||||
return "<a href='./_replacer_cyclewriter' class='cycle' id='cyclewriter'>#{content}</a>"
|
||||
|
||||
cycle = (responses, name, character) ->
|
||||
if typeof responses == "function"
|
||||
responses = responses()
|
||||
character.sandbox.cycle_index ?= [] # initialize with empty array
|
||||
character.sandbox.cycle_index[name] ?= 0 # initialize with 0
|
||||
response = responses[character.sandbox.cycle_index[name]]
|
||||
character.sandbox.cycle_index[name]++
|
||||
if character.sandbox.cycle_index[name] == responses.length
|
||||
character.sandbox.cycle_index[name] = 0
|
||||
return cyclelink(response)
|
||||
|
||||
module.exports = cycle
|
|
@ -1,9 +1,9 @@
|
|||
# I confess that this world model heavily borrows from INSTEAD engine. - A.Y.
|
||||
|
||||
undum = require('./undum.js')
|
||||
RaconteurSituation = require('./situation.coffee')
|
||||
obj = require('./obj.coffee')
|
||||
markdown = require('./markdown.coffee')
|
||||
cycle = require('./cycle.coffee')
|
||||
|
||||
way_to = (content, ref) ->
|
||||
return "<a href='#{ref}' class='way' id='waylink-#{ref}'>#{content}</a>"
|
||||
|
@ -60,12 +60,13 @@ update_ways = (ways, name) ->
|
|||
for node in min_key
|
||||
addClass(document.getElementById("waylink-#{node}"), "destination")
|
||||
|
||||
class SaletRoom extends RaconteurSituation
|
||||
class SaletRoom extends undum.Situation
|
||||
constructor: (spec) ->
|
||||
RaconteurSituation.call(this, spec)
|
||||
undum.Situation.call(this, spec)
|
||||
for index, value of spec
|
||||
this[index] = value
|
||||
return this
|
||||
visited: 0
|
||||
title: "Room"
|
||||
objects: {}
|
||||
extendSection: false
|
||||
|
@ -143,7 +144,7 @@ class SaletRoom extends RaconteurSituation
|
|||
An internal function to get the room's description and the descriptions of
|
||||
every object in this room.
|
||||
###
|
||||
look: (character, system, f) ->
|
||||
look: (character, system, f) =>
|
||||
update_ways(@ways, @name)
|
||||
retval = ""
|
||||
|
||||
|
@ -173,24 +174,55 @@ class SaletRoom extends RaconteurSituation
|
|||
You could interpret this as an EXAMINE verb or USE one, it's your call.
|
||||
###
|
||||
act: (character, system, action) =>
|
||||
if (link = action.match(/^_act_(.+)$/)) #object action
|
||||
if (link = action.match(/^_(act|cycle)_(.+)$/)) #object action
|
||||
for name, thing of @objects
|
||||
if name == link[1]
|
||||
# If it's takeable, the player can take this object.
|
||||
# If not, we check the "act" function.
|
||||
if thing.takeable
|
||||
character.sandbox.inventory.push thing
|
||||
@drop name
|
||||
cls(system)
|
||||
@entering.fcall(this, character, system, @name)
|
||||
return print(thing.take.fcall(thing, character, system))
|
||||
if thing.act
|
||||
return print(thing.act.fcall(thing, character, system))
|
||||
if name == link[2]
|
||||
if link[1] == "act"
|
||||
# If it's takeable, the player can take this object.
|
||||
# If not, we check the "act" function.
|
||||
if thing.takeable
|
||||
character.sandbox.inventory.push thing
|
||||
@drop name
|
||||
cls(system)
|
||||
@entering.fcall(this, character, system, @name)
|
||||
return print(thing.take.fcall(thing, character, system))
|
||||
if thing.act
|
||||
return print(thing.act.fcall(thing, character, system))
|
||||
elseif link[1] == "cycle"
|
||||
# TODO object cyclewriter
|
||||
# the loop is done but no return came - match not found
|
||||
console.error("Could not find #{link[1]} in current room.")
|
||||
|
||||
# default Raconteur action
|
||||
return RaconteurSituation.prototype.act.call(this, character, system, action)
|
||||
# we're done with objects, now check the regular actions
|
||||
actionClass = action.match(/^_(\w+)_(.+)$/)
|
||||
that = this
|
||||
|
||||
responses = {
|
||||
writer: (ref) ->
|
||||
content = that.writers[ref].fcall(that, character, system, action)
|
||||
output = markdown(content)
|
||||
system.writeInto(output, '#current-situation')
|
||||
replacer: (ref) ->
|
||||
content = that.writers[ref].fcall(that, character, system, action)
|
||||
output = "<span>"+content+"</span>" # <p> tags are usually bad for replacers
|
||||
system.replaceWith(output, '#'+ref)
|
||||
inserter: (ref) ->
|
||||
content = that.writers[ref].fcall(that, character, system, action)
|
||||
output = markdown(content)
|
||||
system.writeInto(output, '#'+ref)
|
||||
}
|
||||
|
||||
if (actionClass)
|
||||
# Matched a special action class
|
||||
[responder, ref] = [actionClass[1], actionClass[2]]
|
||||
|
||||
if(!@writers.hasOwnProperty(actionClass[2]))
|
||||
throw new Error("Tried to call undefined writer: #{action}");
|
||||
responses[responder](ref);
|
||||
else if (@actions.hasOwnProperty(action))
|
||||
@actions[action].call(this, character, system, action);
|
||||
else
|
||||
throw new Error("Tried to call undefined action: #{action}");
|
||||
|
||||
# Marks every room in the game with distance to this room
|
||||
destination: () =>
|
||||
|
@ -205,6 +237,17 @@ class SaletRoom extends RaconteurSituation
|
|||
node.distance = current_room.distance + 1
|
||||
candidates.push(node)
|
||||
|
||||
register: () =>
|
||||
if not @name?
|
||||
console.error("Situation has no name")
|
||||
return this
|
||||
undum.game.situations[@name] = this
|
||||
return this
|
||||
|
||||
writers:
|
||||
cyclewriter: (character) ->
|
||||
cycle(this.cycle, this.name, character)
|
||||
|
||||
room = (name, spec) ->
|
||||
spec ?= {}
|
||||
spec.name = name
|
||||
|
|
|
@ -1,87 +0,0 @@
|
|||
###
|
||||
This file is built on top of Raconteur.
|
||||
Raconteur is copyright (c) 2015 Bruno Dias
|
||||
This file is copyright (c) 2016 Alexander Yakovlev
|
||||
|
||||
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.
|
||||
###
|
||||
|
||||
undum = require('./undum.js')
|
||||
markdown = require('./markdown.coffee')
|
||||
|
||||
###
|
||||
The prototype RaconteurSituation is the basic spec for situations
|
||||
created with Raconteur. It should be able to handle any use case for Undum.
|
||||
This prototype is fairly complex; see the API documentation.
|
||||
###
|
||||
|
||||
RaconteurSituation = (spec) ->
|
||||
if RaconteurSituation.arguments.length == 0
|
||||
return
|
||||
undum.Situation.call(this, spec)
|
||||
|
||||
for key, value of spec
|
||||
this[key] ?= value
|
||||
|
||||
@visited = 0
|
||||
return this
|
||||
RaconteurSituation.inherits(undum.Situation)
|
||||
|
||||
###
|
||||
Situation.prototype.act() is called by Undum whenever an action link
|
||||
(Ie, a link that doesn't point at another situation or an external URL) is
|
||||
clicked.
|
||||
|
||||
Raconteur's version of act() is set up to implement commonly used
|
||||
functionality: "writer" links, "replacer" links, "inserter" links, and
|
||||
generic "action" links that call functions which access the underlying
|
||||
Undum API.
|
||||
###
|
||||
|
||||
RaconteurSituation.prototype.act = (character, system, action) ->
|
||||
actionClass = action.match(/^_(\w+)_(.+)$/)
|
||||
that = this
|
||||
|
||||
responses = {
|
||||
writer: (ref) ->
|
||||
content = that.writers[ref].fcall(that, character, system, action)
|
||||
output = markdown(content)
|
||||
system.writeInto(output, '#current-situation')
|
||||
replacer: (ref) ->
|
||||
content = that.writers[ref].fcall(that, character, system, action)
|
||||
output = "<span>"+content+"</span>" # <p> tags are usually bad for replacers
|
||||
system.replaceWith(output, '#'+ref)
|
||||
inserter: (ref) ->
|
||||
content = that.writers[ref].fcall(that, character, system, action)
|
||||
output = markdown(content)
|
||||
system.writeInto(output, '#'+ref)
|
||||
}
|
||||
|
||||
if (actionClass)
|
||||
# Matched a special action class
|
||||
[responder, ref] = [actionClass[1], actionClass[2]]
|
||||
|
||||
if(!@writers.hasOwnProperty(actionClass[2]))
|
||||
throw new Error("Tried to call undefined writer: #{action}");
|
||||
responses[responder](ref);
|
||||
else if (@actions.hasOwnProperty(action))
|
||||
@actions[action].call(this, character, system, action);
|
||||
else
|
||||
throw new Error("Tried to call undefined action: #{action}");
|
||||
|
||||
RaconteurSituation.prototype.register = () ->
|
||||
if not @name?
|
||||
console.error("Situation has no name")
|
||||
return this
|
||||
undum.game.situations[@name] = this
|
||||
return this
|
||||
|
||||
module.exports = RaconteurSituation
|
Loading…
Reference in a new issue