module Gamefic::Scriptable
A class module that enables scripting.
Narratives extend Scriptable
to enable definition of scripts and seeds. Modules can also be extended with Scriptable
to make them includable to other Scriptables.
@example Include a scriptable module in a plot
module MyScript extend Gamefic::Scriptable respond :myscript do |actor| actor.tell "This command was added by MyScript" end end class MyPlot < Gamefic::Plot include MyScript end
Public Instance Methods
Seed an entity with an attribute method.
@example
class Plot < Gamefic::Plot attr_seed :thing, Gamefic::Entity, name: 'thing' end plot = Plot.new plot.thing #=> #<Gamefic::Entity a thing>
@param name [Symbol] The attribute name @param klass [Class<Gamefic::Entity>] @return [Proxy]
# File lib/gamefic/scriptable.rb, line 124 def attr_seed name, klass, **opts ivname = "@#{name}" define_method(name) do return instance_variable_get(ivname) if instance_variable_defined?(ivname) instance_variable_set(ivname, make(klass, **opts)) end seed { send name } Proxy.new(:attr, name) end
@return [Array<Block>]
# File lib/gamefic/scriptable.rb, line 41 def blocks @blocks ||= [] end
@return [Array<Block>]
# File lib/gamefic/scriptable.rb, line 90 def included_blocks included_modules.that_are(Scriptable) .uniq .reverse .flat_map(&:blocks) .concat(blocks) end
Lazy reference an entity by its attribute or method.
@example
lazy_attr(:method)
@param key [Symbol] @return [Proxy]
# File lib/gamefic/scriptable.rb, line 166 def lazy_attr key Gamefic.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`lazy_attr` is deprecated. Use `pick` or `pick!` instead." Proxy.new(:attr, key) end
Lazy reference an entity by its instance variable.
@example
lazy_ivar(:@variable)
@param key [Symbol] @return [Proxy]
# File lib/gamefic/scriptable.rb, line 153 def lazy_ivar key Gamefic.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`lazy_ivar` is deprecated. Use `pick` or `pick!` instead." Proxy.new(:ivar, key) end
Seed an entity.
@example
make_seed Gamefic::Entity, name: 'thing'
@param klass [Class<Gamefic::Entity>] @return [Proxy]
# File lib/gamefic/scriptable.rb, line 105 def make_seed klass, **opts seed { make(klass, **opts) } Proxy::Pick.new(klass, opts[:name], raise: true) end
:nocov:
# File lib/gamefic/scriptable.rb, line 195 def method_missing method, *args, &block return super unless respond_to_missing?(method) script { send(method, *args, &block) } end
Create an anonymous module that includes the features of a Scriptable
module but does not include its scripts.
This can be useful when you need access to the Scriptable’s constants and instance methods, but you don’t want to duplicate its rules.
@deprecated Removing script blocks is no longer necessary. This method
will simply return self until it's removed.
@return [Module<self>]
# File lib/gamefic/scriptable.rb, line 224 def no_scripts Logging.logger.warn "#{caller.first ? "#{caller.first}: " : ''}Calling `no_scripts` on Scriptable modules is no longer necessary." self end
Lazy pick an entity.
@example
pick('the red box')
@param args [Array] @return [Proxy]
# File lib/gamefic/scriptable.rb, line 179 def pick *args Proxy::Pick.new(*args) end
Lazy pick an entity or raise
# File lib/gamefic/scriptable.rb, line 187 def pick! *args Proxy::Pick.new(*args) end
@param symbol [Symbol] @return [Proxy]
# File lib/gamefic/scriptable.rb, line 137 def proxy symbol Logging.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`proxy` is deprecated. Use `pick` or `pick!` instead." if symbol.to_s.start_with?('@') Proxy.new(:ivar, symbol) else Proxy.new(:attr, symbol) end end
# File lib/gamefic/scriptable.rb, line 209 def respond_to_missing?(method, _with_private = false) [Scriptable::Actions, Scriptable::Events, Scriptable::Scenes].flat_map(&:public_instance_methods) .include?(method) end
Add a block of code to be executed during initialization.
These blocks are primarily used to define actions, scenes, and hooks in the narrative’s rulebook. Entities
and game data should be initialized with ‘seed`.
@example
class MyPlot < Gamefic::Plot script do introduction do |actor| actor.tell 'Hello, world!' end respond :wait do |actor| actor.tell 'Time passes.' end end end
# File lib/gamefic/scriptable.rb, line 65 def script &block blocks.push Block.new(:script, block) end
Add a block of code to generate content after initialization.
Seeds run after the initial scripts have been executed. Their primary use is to add entities and other data components, especially randomized or procedurally generated content that can vary between instances.
@note Seeds do not get executed when a narrative is restored from a
snapshot.
@example
class MyPlot < Gamefic::Plot seed do @thing = make Gamefic::Entity, name: 'a thing' end end
# File lib/gamefic/scriptable.rb, line 85 def seed &block blocks.push Block.new(:seed, block) end