mirror of
https://github.com/Oreolek/shooter.git
synced 2024-05-19 09:18:16 +03:00
Story time!
This commit is contained in:
parent
a7f2316cfa
commit
e332f3e1d4
206
game/gameplay.coffee
Normal file
206
game/gameplay.coffee
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
situation = require('raconteur')
|
||||||
|
$ = require("jquery")
|
||||||
|
md = require('markdown-it')
|
||||||
|
markdown = new md({
|
||||||
|
typographer: true,
|
||||||
|
html: true
|
||||||
|
})
|
||||||
|
|
||||||
|
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)
|
||||||
|
textcycle = (content, ref) -> a(content).replacer(ref).class("cycle").id(ref)
|
||||||
|
writemd = (system, text) ->
|
||||||
|
if typeof text is Function
|
||||||
|
text = text()
|
||||||
|
system.write(markdown.render(text))
|
||||||
|
|
||||||
|
# This is an easy game.
|
||||||
|
# I'm thinking if you want more harder approach, you can:
|
||||||
|
# a) remove bullet counter (you don't know how many bullets left in a clip)
|
||||||
|
# b) remove canChoose restriction (you can shoot any time you want, but if you have no bullets - nothing comes out and you've lost a turn)
|
||||||
|
|
||||||
|
kill_enemy = (character, system) ->
|
||||||
|
if character.qualities.enemies == 0
|
||||||
|
return
|
||||||
|
character.sandbox.nicked = 0
|
||||||
|
character.sandbox.killed++
|
||||||
|
if character.qualities.enemies >= 1
|
||||||
|
system.setQuality("enemies", character.qualities.enemies - 1)
|
||||||
|
if character.qualities.enemies == 0
|
||||||
|
system.doLink("finale")
|
||||||
|
|
||||||
|
spend_bullet = (character, system) ->
|
||||||
|
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
||||||
|
character.sandbox.shots++
|
||||||
|
if bullets >= 1
|
||||||
|
coin = system.rnd.randomInt(1,2)
|
||||||
|
audio = 'shot1'
|
||||||
|
if coin == 2
|
||||||
|
audio = 'shot2'
|
||||||
|
audio = document.getElementById(audio)
|
||||||
|
audio.currentTime=0
|
||||||
|
audio.play()
|
||||||
|
character.sandbox.clips[character.sandbox.current_clip]--
|
||||||
|
bullets--
|
||||||
|
system.setQuality("bullets", bullets)
|
||||||
|
$("#clip img").attr("src", "img/clip"+bullets+".png")
|
||||||
|
|
||||||
|
spend_clip = (character, system) ->
|
||||||
|
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
||||||
|
clips = character.sandbox.clips.length
|
||||||
|
if clips < 2
|
||||||
|
return
|
||||||
|
audio = document.getElementById("reload")
|
||||||
|
audio.currentTime=0
|
||||||
|
audio.play()
|
||||||
|
if bullets == 0
|
||||||
|
character.sandbox.clips.splice(character.sandbox.current_clip, 1)
|
||||||
|
clips = character.sandbox.clips.length
|
||||||
|
writemd(system, "emptyclip".l())
|
||||||
|
system.setQuality("clips", clips)
|
||||||
|
if character.sandbox.current_clip < clips - 1
|
||||||
|
character.sandbox.current_clip++
|
||||||
|
else
|
||||||
|
character.sandbox.current_clip = 0
|
||||||
|
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
||||||
|
system.setQuality("bullets", bullets)
|
||||||
|
$("#clip img").attr("src", "img/clip"+bullets+".png")
|
||||||
|
# Pacifist event
|
||||||
|
if character.sandbox.killed > 15 and character.sandbox.seen_pacifist == 0
|
||||||
|
system.doLink("pacifist")
|
||||||
|
character.sandbox.seen_pacifist = 1
|
||||||
|
# Finale buildup
|
||||||
|
if character.sandbox.killed > 21
|
||||||
|
setTimeout( play_step(0.2), 1500)
|
||||||
|
|
||||||
|
situation "hit",
|
||||||
|
content: (character, system, from) ->
|
||||||
|
response = "player_hit".l().oneOf().randomly(system)
|
||||||
|
return response()
|
||||||
|
choices: ["#shoot"]
|
||||||
|
before: (character, system, from) ->
|
||||||
|
kill_enemy(character, system)
|
||||||
|
choices: ["#shoot"]
|
||||||
|
|
||||||
|
situation "nicked",
|
||||||
|
content: (character, system, from) ->
|
||||||
|
if character.sandbox.nicked == 1
|
||||||
|
kill_enemy(character, system)
|
||||||
|
response = "player_finished".l().oneOf().randomly(system)
|
||||||
|
return response()
|
||||||
|
else
|
||||||
|
character.sandbox.nicked = 1
|
||||||
|
response = "player_nicked".l().oneOf().randomly(system)
|
||||||
|
return response()
|
||||||
|
choices: ["#shoot"]
|
||||||
|
|
||||||
|
situation "miss",
|
||||||
|
content: (character, system, from) ->
|
||||||
|
response = "player_missed".l().oneOf().randomly(system)
|
||||||
|
return response()
|
||||||
|
choices: ["#shoot"]
|
||||||
|
|
||||||
|
situation "trick",
|
||||||
|
before: (character, system, from) ->
|
||||||
|
kill_enemy(character, system)
|
||||||
|
kill_enemy(character, system)
|
||||||
|
content: (character, system, from) ->
|
||||||
|
response = "player_trickshot".l().oneOf().randomly(system)
|
||||||
|
return response()
|
||||||
|
choices: ["#shoot"]
|
||||||
|
|
||||||
|
situation "shoot",
|
||||||
|
tags: ["shoot"],
|
||||||
|
optionText: (character, system, from) ->
|
||||||
|
return "shoot".l().oneOf().randomly(system)
|
||||||
|
canChoose: (character, system) ->
|
||||||
|
return character.qualities.bullets > 0
|
||||||
|
before: (character, system, from) ->
|
||||||
|
spend_bullet(character, system)
|
||||||
|
system.clearContent()
|
||||||
|
after: (character, system, from) ->
|
||||||
|
roll = system.rnd.dice(1,20) # d20 roll
|
||||||
|
hit_threshold = 15
|
||||||
|
miss_threshold = 18
|
||||||
|
switch
|
||||||
|
when roll < hit_threshold then system.doLink("hit")
|
||||||
|
when roll > miss_threshold then system.doLink("miss")
|
||||||
|
else system.doLink("nicked")
|
||||||
|
|
||||||
|
situation "trick_shot",
|
||||||
|
tags: ["shoot"],
|
||||||
|
optionText: (character, system, from) ->
|
||||||
|
return "trick_shot".l()
|
||||||
|
canView: (character, system) ->
|
||||||
|
return character.sandbox.trick_shot == 1
|
||||||
|
canChoose: (character, system) ->
|
||||||
|
return character.qualities.bullets > 0
|
||||||
|
before: (character, system, from) ->
|
||||||
|
spend_bullet(character, system)
|
||||||
|
system.clearContent()
|
||||||
|
after: (character, system, from) ->
|
||||||
|
roll = system.rnd.dice(1,20) # d20 roll
|
||||||
|
trick_threshold = 5
|
||||||
|
hit_threshold = 12
|
||||||
|
miss_threshold = 16
|
||||||
|
switch
|
||||||
|
when roll < trick_threshold then system.doLink("trick")
|
||||||
|
when roll < hit_threshold then system.doLink("hit")
|
||||||
|
when roll > miss_threshold then system.doLink("miss")
|
||||||
|
else system.doLink("nicked")
|
||||||
|
|
||||||
|
situation "reload",
|
||||||
|
tags: ["shoot"],
|
||||||
|
choices: ["#shoot"],
|
||||||
|
optionText: "reload".l(),
|
||||||
|
canView: (character, system) ->
|
||||||
|
return character.sandbox.seen_reload || character.qualities.bullets < 6
|
||||||
|
canChoose: (character, system) ->
|
||||||
|
return character.qualities.bullets < 6 and character.sandbox.clips.length > 1
|
||||||
|
before: (character, system) ->
|
||||||
|
character.sandbox.seen_reload = 1
|
||||||
|
system.clearContent()
|
||||||
|
after: (character, system) ->
|
||||||
|
spend_clip(character, system)
|
||||||
|
writemd(system, "reload_response".l())
|
||||||
|
if character.sandbox.trick_shot == 0 and character.sandbox.clips.length == 4
|
||||||
|
character.sandbox.trick_shot = 1
|
||||||
|
writemd(system, "trick_shot_discover".l()(character))
|
||||||
|
return true
|
||||||
|
|
||||||
|
situation "search",
|
||||||
|
tags: ["shoot"],
|
||||||
|
optionText: "search".l(),
|
||||||
|
canView: (character, system) ->
|
||||||
|
return character.sandbox.seen_search || character.qualities.clips < 5
|
||||||
|
canChoose: (character, system) ->
|
||||||
|
return character.qualities.clips < 5
|
||||||
|
before: (character, system) ->
|
||||||
|
system.clearContent()
|
||||||
|
character.sandbox.seen_search = 1
|
||||||
|
after: (character, system) ->
|
||||||
|
response = "search_response".l().oneOf().randomly(system)
|
||||||
|
writemd(system, response())
|
||||||
|
roll = system.rnd.dice(1,20) # d20 roll
|
||||||
|
find_threshold = 10
|
||||||
|
if roll < find_threshold
|
||||||
|
system.doLink("found")
|
||||||
|
else
|
||||||
|
system.doLink("not_found")
|
||||||
|
|
||||||
|
situation "found",
|
||||||
|
choices: ["#shoot"],
|
||||||
|
before: (character, system, from) ->
|
||||||
|
bullets = system.rnd.randomInt(2,4)
|
||||||
|
character.sandbox.clips[character.sandbox.clips.length] = bullets
|
||||||
|
system.setQuality("clips", character.sandbox.clips.length)
|
||||||
|
content: (character, system, from) ->
|
||||||
|
response = "clips_found".l().oneOf().randomly(system)
|
||||||
|
return response()
|
||||||
|
|
||||||
|
situation "not_found",
|
||||||
|
choices: ["#shoot"],
|
||||||
|
content: (character, system, from) ->
|
||||||
|
response = "clips_not_found".l().oneOf().randomly(system)
|
||||||
|
return response()
|
272
game/main.coffee
272
game/main.coffee
|
@ -5,277 +5,18 @@
|
||||||
situation = require('raconteur')
|
situation = require('raconteur')
|
||||||
undum = require('undum-commonjs')
|
undum = require('undum-commonjs')
|
||||||
oneOf = require('raconteur/lib/oneOf.js')
|
oneOf = require('raconteur/lib/oneOf.js')
|
||||||
elements = require('raconteur/lib/elements.js')
|
|
||||||
qualities = require('raconteur/lib/qualities.js')
|
qualities = require('raconteur/lib/qualities.js')
|
||||||
md = require('markdown-it')
|
|
||||||
markdown = new md({
|
|
||||||
typographer: true,
|
|
||||||
html: true
|
|
||||||
})
|
|
||||||
undumloc = require("./ru.coffee").language
|
undumloc = require("./ru.coffee").language
|
||||||
undum.language["ru"] = undumloc
|
undum.language["ru"] = undumloc
|
||||||
undumloc = require("./en.coffee").language
|
undumloc = require("./en.coffee").language
|
||||||
undum.language["en"] = undumloc
|
undum.language["en"] = undumloc
|
||||||
$ = require("jquery")
|
$ = require("jquery")
|
||||||
|
|
||||||
a = elements.a
|
|
||||||
span = elements.span
|
|
||||||
img = elements.img
|
|
||||||
|
|
||||||
undum.game.id = "7a1aba32-f0fd-4e3b-ba5a-59e3fa9e6012"
|
|
||||||
undum.game.version = "2.0"
|
|
||||||
|
|
||||||
way_to = (content, ref) -> a(content).class('way').ref(ref)
|
|
||||||
textlink = (content, ref) -> a(content).once().writer(ref)
|
|
||||||
textcycle = (content, ref) -> a(content).replacer(ref).class("cycle").id(ref)
|
|
||||||
is_visited = (situation) -> undum.game.situations[situation].visited == 1
|
|
||||||
writemd = (system, text) ->
|
|
||||||
if typeof text is Function
|
|
||||||
text = text()
|
|
||||||
system.write(markdown.render(text))
|
|
||||||
Array.prototype.oneOf = () ->
|
Array.prototype.oneOf = () ->
|
||||||
oneOf.apply(null, this)
|
oneOf.apply(null, this)
|
||||||
|
|
||||||
# This is an easy game.
|
undum.game.id = "7a1aba32-f0fd-4e3b-ba5a-59e3fa9e6012"
|
||||||
# I'm thinking if you want more harder approach, you can:
|
undum.game.version = "2.0"
|
||||||
# a) remove bullet counter (you don't know how many bullets left in a clip)
|
|
||||||
# b) remove canChoose restriction (you can shoot any time you want, but if you have no bullets - nothing comes out and you've lost a turn)
|
|
||||||
|
|
||||||
kill_enemy = (character, system) ->
|
|
||||||
if character.qualities.enemies == 0
|
|
||||||
return
|
|
||||||
character.sandbox.nicked = 0
|
|
||||||
character.sandbox.killed++
|
|
||||||
if character.qualities.enemies >= 1
|
|
||||||
system.setQuality("enemies", character.qualities.enemies - 1)
|
|
||||||
if character.qualities.enemies == 0
|
|
||||||
system.doLink("finale")
|
|
||||||
|
|
||||||
spend_bullet = (character, system) ->
|
|
||||||
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
|
||||||
character.sandbox.shots++
|
|
||||||
if bullets >= 1
|
|
||||||
coin = system.rnd.randomInt(1,2)
|
|
||||||
audio = 'shot1'
|
|
||||||
if coin == 2
|
|
||||||
audio = 'shot2'
|
|
||||||
audio = document.getElementById(audio)
|
|
||||||
audio.currentTime=0
|
|
||||||
audio.play()
|
|
||||||
character.sandbox.clips[character.sandbox.current_clip]--
|
|
||||||
bullets--
|
|
||||||
system.setQuality("bullets", bullets)
|
|
||||||
$("#clip img").attr("src", "img/clip"+bullets+".png")
|
|
||||||
|
|
||||||
spend_clip = (character, system) ->
|
|
||||||
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
|
||||||
clips = character.sandbox.clips.length
|
|
||||||
if clips < 2
|
|
||||||
return
|
|
||||||
audio = document.getElementById("reload")
|
|
||||||
audio.currentTime=0
|
|
||||||
audio.play()
|
|
||||||
if bullets == 0
|
|
||||||
character.sandbox.clips.splice(character.sandbox.current_clip, 1)
|
|
||||||
clips = character.sandbox.clips.length
|
|
||||||
writemd(system, "emptyclip".l())
|
|
||||||
system.setQuality("clips", clips)
|
|
||||||
if character.sandbox.current_clip < clips - 1
|
|
||||||
character.sandbox.current_clip++
|
|
||||||
else
|
|
||||||
character.sandbox.current_clip = 0
|
|
||||||
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
|
||||||
system.setQuality("bullets", bullets)
|
|
||||||
$("#clip img").attr("src", "img/clip"+bullets+".png")
|
|
||||||
if character.sandbox.killed > 15 and character.sandbox.seen_pacifist == 0
|
|
||||||
system.doLink("pacifist")
|
|
||||||
character.sandbox.seen_pacifist = 1
|
|
||||||
if character.sandbox.killed > 21
|
|
||||||
setTimeout( play_step(0.2), 1500)
|
|
||||||
|
|
||||||
play_step = (volume) ->
|
|
||||||
rand = Math.random();
|
|
||||||
step1 = document.getElementById("step1")
|
|
||||||
step2 = document.getElementById("step2")
|
|
||||||
audio = step1
|
|
||||||
if rand > 0.5
|
|
||||||
audio = step2
|
|
||||||
audio.currentTime = 0
|
|
||||||
audio.volume = volume
|
|
||||||
audio.play()
|
|
||||||
|
|
||||||
situation 'start',
|
|
||||||
content: () ->
|
|
||||||
link = textcycle("head".l(), "leg")
|
|
||||||
return "intro".l()(link)
|
|
||||||
choices: ["#shoot"],
|
|
||||||
writers:
|
|
||||||
leg: ""
|
|
||||||
|
|
||||||
situation "hit",
|
|
||||||
content: (character, system, from) ->
|
|
||||||
response = "player_hit".l().oneOf().randomly(system)
|
|
||||||
return response()
|
|
||||||
choices: ["#shoot"]
|
|
||||||
before: (character, system, from) ->
|
|
||||||
kill_enemy(character, system)
|
|
||||||
choices: ["#shoot"]
|
|
||||||
|
|
||||||
situation "nicked",
|
|
||||||
content: (character, system, from) ->
|
|
||||||
if character.sandbox.nicked == 1
|
|
||||||
kill_enemy(character, system)
|
|
||||||
response = "player_finished".l().oneOf().randomly(system)
|
|
||||||
return response()
|
|
||||||
else
|
|
||||||
character.sandbox.nicked = 1
|
|
||||||
response = "player_nicked".l().oneOf().randomly(system)
|
|
||||||
return response()
|
|
||||||
choices: ["#shoot"]
|
|
||||||
|
|
||||||
situation "miss",
|
|
||||||
content: (character, system, from) ->
|
|
||||||
response = "player_missed".l().oneOf().randomly(system)
|
|
||||||
return response()
|
|
||||||
choices: ["#shoot"]
|
|
||||||
|
|
||||||
situation "trick",
|
|
||||||
before: (character, system, from) ->
|
|
||||||
kill_enemy(character, system)
|
|
||||||
kill_enemy(character, system)
|
|
||||||
content: (character, system, from) ->
|
|
||||||
response = "player_trickshot".l().oneOf().randomly(system)
|
|
||||||
return response()
|
|
||||||
choices: ["#shoot"]
|
|
||||||
|
|
||||||
situation "shoot",
|
|
||||||
tags: ["shoot"],
|
|
||||||
optionText: (character, system, from) ->
|
|
||||||
return "shoot".l().oneOf().randomly(system)
|
|
||||||
canChoose: (character, system) ->
|
|
||||||
return character.qualities.bullets > 0
|
|
||||||
before: (character, system, from) ->
|
|
||||||
spend_bullet(character, system)
|
|
||||||
system.clearContent()
|
|
||||||
after: (character, system, from) ->
|
|
||||||
roll = system.rnd.dice(1,20) # d20 roll
|
|
||||||
hit_threshold = 15
|
|
||||||
miss_threshold = 18
|
|
||||||
switch
|
|
||||||
when roll < hit_threshold then system.doLink("hit")
|
|
||||||
when roll > miss_threshold then system.doLink("miss")
|
|
||||||
else system.doLink("nicked")
|
|
||||||
|
|
||||||
situation "trick_shot",
|
|
||||||
tags: ["shoot"],
|
|
||||||
optionText: (character, system, from) ->
|
|
||||||
return "trick_shot".l()
|
|
||||||
canView: (character, system) ->
|
|
||||||
return character.sandbox.trick_shot == 1
|
|
||||||
canChoose: (character, system) ->
|
|
||||||
return character.qualities.bullets > 0
|
|
||||||
before: (character, system, from) ->
|
|
||||||
spend_bullet(character, system)
|
|
||||||
system.clearContent()
|
|
||||||
after: (character, system, from) ->
|
|
||||||
roll = system.rnd.dice(1,20) # d20 roll
|
|
||||||
trick_threshold = 5
|
|
||||||
hit_threshold = 12
|
|
||||||
miss_threshold = 16
|
|
||||||
switch
|
|
||||||
when roll < trick_threshold then system.doLink("trick")
|
|
||||||
when roll < hit_threshold then system.doLink("hit")
|
|
||||||
when roll > miss_threshold then system.doLink("miss")
|
|
||||||
else system.doLink("nicked")
|
|
||||||
|
|
||||||
situation "reload",
|
|
||||||
tags: ["shoot"],
|
|
||||||
choices: ["#shoot"],
|
|
||||||
optionText: "reload".l(),
|
|
||||||
canView: (character, system) ->
|
|
||||||
return character.sandbox.seen_reload || character.qualities.bullets < 6
|
|
||||||
canChoose: (character, system) ->
|
|
||||||
return character.qualities.bullets < 6 and character.sandbox.clips.length > 1
|
|
||||||
before: (character, system) ->
|
|
||||||
character.sandbox.seen_reload = 1
|
|
||||||
system.clearContent()
|
|
||||||
after: (character, system) ->
|
|
||||||
spend_clip(character, system)
|
|
||||||
writemd(system, "reload_response".l())
|
|
||||||
if character.sandbox.trick_shot == 0 and character.sandbox.clips.length == 4
|
|
||||||
character.sandbox.trick_shot = 1
|
|
||||||
writemd(system, "trick_shot_discover".l()(character))
|
|
||||||
return true
|
|
||||||
|
|
||||||
situation "search",
|
|
||||||
tags: ["shoot"],
|
|
||||||
optionText: "search".l(),
|
|
||||||
canView: (character, system) ->
|
|
||||||
return character.sandbox.seen_search || character.qualities.clips < 5
|
|
||||||
canChoose: (character, system) ->
|
|
||||||
return character.qualities.clips < 5
|
|
||||||
before: (character, system) ->
|
|
||||||
system.clearContent()
|
|
||||||
character.sandbox.seen_search = 1
|
|
||||||
after: (character, system) ->
|
|
||||||
response = "search_response".l().oneOf().randomly(system)
|
|
||||||
writemd(system, response())
|
|
||||||
roll = system.rnd.dice(1,20) # d20 roll
|
|
||||||
find_threshold = 10
|
|
||||||
if roll < find_threshold
|
|
||||||
system.doLink("found")
|
|
||||||
else
|
|
||||||
system.doLink("not_found")
|
|
||||||
|
|
||||||
situation "found",
|
|
||||||
choices: ["#shoot"],
|
|
||||||
before: (character, system, from) ->
|
|
||||||
bullets = system.rnd.randomInt(2,4)
|
|
||||||
character.sandbox.clips[character.sandbox.clips.length] = bullets
|
|
||||||
system.setQuality("clips", character.sandbox.clips.length)
|
|
||||||
content: (character, system, from) ->
|
|
||||||
response = "clips_found".l().oneOf().randomly(system)
|
|
||||||
return response()
|
|
||||||
|
|
||||||
situation "not_found",
|
|
||||||
choices: ["#shoot"],
|
|
||||||
content: (character, system, from) ->
|
|
||||||
response = "clips_not_found".l().oneOf().randomly(system)
|
|
||||||
return response()
|
|
||||||
|
|
||||||
situation "finale",
|
|
||||||
content: (character, system) ->
|
|
||||||
if character.sandbox.shots < 36
|
|
||||||
return "finale_perfect".l()
|
|
||||||
return "finale".l()
|
|
||||||
|
|
||||||
situation "pacifist",
|
|
||||||
choices: ["#pacifist"],
|
|
||||||
content: (character, system) ->
|
|
||||||
return "pacifist".l()
|
|
||||||
|
|
||||||
situation "shoot_pacifist",
|
|
||||||
optionText: "Убить пацифиста",
|
|
||||||
tags: "pacifist",
|
|
||||||
choices: ["#shoot"],
|
|
||||||
before: (character, system) ->
|
|
||||||
character.sandbox.shot_pacifist = 1
|
|
||||||
content: (character, system) ->
|
|
||||||
link = textcycle("head".l(), "leg")
|
|
||||||
return "shoot_pacifist".l()(link)
|
|
||||||
writers:
|
|
||||||
head: textcycle("head".l(), "leg")
|
|
||||||
leg: textcycle("leg".l(), "arm")
|
|
||||||
arm: textcycle("arm".l(), "head")
|
|
||||||
|
|
||||||
situation "spare_pacifist",
|
|
||||||
optionText: "Опустить оружие",
|
|
||||||
tags: "pacifist",
|
|
||||||
before: (character, system) ->
|
|
||||||
character.sandbox.shot_pacifist = 0
|
|
||||||
choices: ["#shoot"],
|
|
||||||
content: (character, system) ->
|
|
||||||
return "spare_pacifist".l()
|
|
||||||
|
|
||||||
qualities
|
qualities
|
||||||
head:
|
head:
|
||||||
|
@ -297,8 +38,15 @@ undum.game.init = (character, system) ->
|
||||||
character.sandbox.killed = 0
|
character.sandbox.killed = 0
|
||||||
character.sandbox.seen_pacifist = 0
|
character.sandbox.seen_pacifist = 0
|
||||||
character.sandbox.shot_pacifist = undefined
|
character.sandbox.shot_pacifist = undefined
|
||||||
|
window.is_visited = (situation) -> undum.game.situations[situation].visited == 1
|
||||||
$("#title").click(() ->
|
$("#title").click(() ->
|
||||||
$("#clip").fadeIn()
|
$("#clip").fadeIn()
|
||||||
)
|
)
|
||||||
|
# setInterval( () ->
|
||||||
|
# console.log( 'Character object:', character )
|
||||||
|
#, 1000 );
|
||||||
|
|
||||||
|
require("./gameplay.coffee")
|
||||||
|
require("./story.coffee")
|
||||||
|
|
||||||
window.onload = undum.begin
|
window.onload = undum.begin
|
||||||
|
|
|
@ -18,14 +18,22 @@ module.exports.language =
|
||||||
random_error: "Проинициализируйте Random с непустым зерном перед использованием."
|
random_error: "Проинициализируйте Random с непустым зерном перед использованием."
|
||||||
dice_string_error: "не могу интерпретировать вашу cтроку кубиков: '{string}'."
|
dice_string_error: "не могу интерпретировать вашу cтроку кубиков: '{string}'."
|
||||||
erase_message: "Это навсегда удалит вашего персонажа и немедленно вернёт вас на старт игры. Вы уверены?"
|
erase_message: "Это навсегда удалит вашего персонажа и немедленно вернёт вас на старт игры. Вы уверены?"
|
||||||
intro: (link) -> """
|
start: (link) -> """
|
||||||
-- Проклятье, они продолжают идти!
|
-- Антоша, тебе правда сейчас нужен пистолет?
|
||||||
|
|
||||||
Узкий коридор, я и непрекращающаяся очередь сверкающих белоснежной кожей андроидов.
|
Мы сидим, обнявшись, во дворе нашего дома.
|
||||||
Я уверен, что я представлял этот Новый Год совершенно не так.
|
Кристина #{link}.
|
||||||
|
Я поправляю кобуру на поясе.
|
||||||
|
"""
|
||||||
|
endintro: """
|
||||||
|
Раньше, чем я успеваю открыть рот, перед нами открывается большой зелёный портал,
|
||||||
|
из которого выходит высокий металлический человек.
|
||||||
|
|
||||||
Один ящик андроидов содержит тридцать пять машин.
|
-- Стоять!
|
||||||
Это будет длинная битва.
|
|
||||||
|
-- Дорогая, -- я отставляю её в сторону и встаю между ней и злым роботом. -- Пули говорят быстрее слов.
|
||||||
|
|
||||||
|
(игрок нажимает на кнопку, Кристина комментирует в случае промаха.)
|
||||||
"""
|
"""
|
||||||
androidattack: "Один из андроидов доходит до меня и кусает!"
|
androidattack: "Один из андроидов доходит до меня и кусает!"
|
||||||
emptyclip: "Я выбрасываю пустой картридж."
|
emptyclip: "Я выбрасываю пустой картридж."
|
||||||
|
|
196
game/story.coffee
Normal file
196
game/story.coffee
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
situation = require('raconteur')
|
||||||
|
|
||||||
|
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)
|
||||||
|
textcycle = (content, ref) -> a(content).replacer(ref).class("cycle").id(ref).toString()
|
||||||
|
writemd = (system, text) ->
|
||||||
|
if typeof text is Function
|
||||||
|
text = text()
|
||||||
|
system.write(markdown.render(text))
|
||||||
|
|
||||||
|
###
|
||||||
|
--- Intro dialogue ---
|
||||||
|
I believe a dialogue is always a mini-game in itself.
|
||||||
|
Undum's implicit choice system is perfect for "floating modules"-type of dialogue
|
||||||
|
BUT it also means that every phrase should be a separate situation.
|
||||||
|
###
|
||||||
|
|
||||||
|
situation "start",
|
||||||
|
content: () ->
|
||||||
|
return "start".l()(this.writers.smell)
|
||||||
|
choices: ["#start"],
|
||||||
|
writers:
|
||||||
|
smell: textcycle("пахнет сладким мёдом", "look")
|
||||||
|
look: textcycle("смотрит вдаль, о чём-то задумавшись", "touch")
|
||||||
|
touch: textcycle("крепко обнимает меня, впиваясь ногтями в плечо", "smell")
|
||||||
|
|
||||||
|
situation 'answer1',
|
||||||
|
optionText: "Милая, я просто за тебя беспокоюсь.",
|
||||||
|
choices: ['#answer1'],
|
||||||
|
tags: "start",
|
||||||
|
canView: true,
|
||||||
|
content: """
|
||||||
|
-- Милая, я просто за тебя беспокоюсь.
|
||||||
|
|
||||||
|
-- Почему?
|
||||||
|
Я не на работе.
|
||||||
|
Ты не на работе.
|
||||||
|
Вокруг дома стоит надёжная защита.
|
||||||
|
"""
|
||||||
|
|
||||||
|
situation 'branch1-a',
|
||||||
|
optionText: "Защиты недостаточно.",
|
||||||
|
choices: ['#start'],
|
||||||
|
tags: "answer1",
|
||||||
|
canView: true,
|
||||||
|
content: """
|
||||||
|
-- Защиты недостаточно. -- я кладу руку на рукоять пистолета.
|
||||||
|
|
||||||
|
-- Антоша, это -- наш романтический вечер. Ты можешь оставить пистолет в доме.
|
||||||
|
"""
|
||||||
|
|
||||||
|
situation 'branch1-b',
|
||||||
|
optionText: "Я всегда держу его при себе.",
|
||||||
|
choices: ['#start'],
|
||||||
|
tags: "answer1",
|
||||||
|
canView: true,
|
||||||
|
content: """
|
||||||
|
-- Я всегда держу его при себе. Это нормально.
|
||||||
|
|
||||||
|
-- Антон!
|
||||||
|
Я три недели ждала, когда у нас наконец-то будет вечер на двоих.
|
||||||
|
Положи пистолет и расслабься.
|
||||||
|
"""
|
||||||
|
|
||||||
|
situation 'dlg-intro-finale1',
|
||||||
|
optionText: "Я и так расслаблен.",
|
||||||
|
choices: ['#stage3'],
|
||||||
|
tags: "answer2",
|
||||||
|
canView: true,
|
||||||
|
content: () -> """
|
||||||
|
-- О чём ты говоришь?
|
||||||
|
Я и так расслаблен.
|
||||||
|
Смотри, какой красивый закат, эти #{this.writers.birds}.
|
||||||
|
Только ты и я, как ты и хотела.
|
||||||
|
|
||||||
|
-- Да, но я не хочу ни в кого стрелять!
|
||||||
|
""",
|
||||||
|
writers:
|
||||||
|
birds: textcycle("птички поют", "flowers"),
|
||||||
|
flowers: textcycle("цветочки растут", "trees"),
|
||||||
|
trees: textcycle("деревья так похожи на магические руны", "birds")
|
||||||
|
|
||||||
|
situation 'answer2',
|
||||||
|
optionText: "Я его даже не трогаю.",
|
||||||
|
choices: ['#answer2', "#stage2"],
|
||||||
|
tags: "start",
|
||||||
|
content: """
|
||||||
|
-- Я его даже не трогаю.
|
||||||
|
|
||||||
|
-- Да, но ты держишь его рядом.
|
||||||
|
Ты не можешь расслабиться, я чувствую.
|
||||||
|
"""
|
||||||
|
|
||||||
|
situation 'lazy',
|
||||||
|
optionText: "Я просто не вынимал его из кобуры.",
|
||||||
|
choices: ['#lazy', "#stage2"],
|
||||||
|
tags: "start",
|
||||||
|
content: """
|
||||||
|
-- Я просто не вынимал его из кобуры.
|
||||||
|
Какое это имеет значение?
|
||||||
|
|
||||||
|
-- Только не говори мне, что ты и на предохранитель поленился его поставить.
|
||||||
|
"""
|
||||||
|
|
||||||
|
situation 'lazy2',
|
||||||
|
optionText: "Конечно, он на предохранителе.",
|
||||||
|
choices: ['#stage2'],
|
||||||
|
tags: "lazy",
|
||||||
|
content: """
|
||||||
|
-- Конечно, он на предохранителе.
|
||||||
|
Видишь, ничего страшного. -- я вытащил пистолет, чтобы показать ей.
|
||||||
|
|
||||||
|
-- Антон!
|
||||||
|
Ты вообще меня слушаешь?!
|
||||||
|
Не трогай пистолет!
|
||||||
|
|
||||||
|
Я со вздохом возращаю оружие в кобуру.
|
||||||
|
"""
|
||||||
|
|
||||||
|
situation 'lazy3',
|
||||||
|
optionText: "Я не собираюсь стрелять.",
|
||||||
|
choices: ['#stage3'],
|
||||||
|
tags: "stage2",
|
||||||
|
content: """
|
||||||
|
-- Я не собираюсь стрелять.
|
||||||
|
|
||||||
|
-- Тогда зачем ты его взял?!
|
||||||
|
"""
|
||||||
|
|
||||||
|
situation 'dlg-intro-finale2',
|
||||||
|
optionText: "Это просто мой пистолет.",
|
||||||
|
choices: ['#intro'],
|
||||||
|
tags: "stage3",
|
||||||
|
content: """
|
||||||
|
-- Это просто мой пистолет.
|
||||||
|
Лучше посмотри на эти розовые облака в небе.
|
||||||
|
Вон то похоже на зайчика, правда?
|
||||||
|
|
||||||
|
-- О Великие Боги, у тебя и патроны с собой?!
|
||||||
|
""",
|
||||||
|
|
||||||
|
situation 'endintro',
|
||||||
|
optionText: "Объясниться и помириться"
|
||||||
|
content: () ->
|
||||||
|
return "endintro".l()
|
||||||
|
choices: ["#shoot"],
|
||||||
|
tags: "intro"
|
||||||
|
|
||||||
|
## Pacifist event
|
||||||
|
|
||||||
|
situation "pacifist",
|
||||||
|
choices: ["#pacifist"],
|
||||||
|
content: (character, system) ->
|
||||||
|
return "pacifist".l()
|
||||||
|
|
||||||
|
situation "shoot_pacifist",
|
||||||
|
optionText: "Убить пацифиста",
|
||||||
|
tags: "pacifist",
|
||||||
|
choices: ["#shoot"],
|
||||||
|
before: (character, system) ->
|
||||||
|
character.sandbox.shot_pacifist = 1
|
||||||
|
content: (character, system) ->
|
||||||
|
link = textcycle("head".l(), "leg")
|
||||||
|
return "shoot_pacifist".l()(link)
|
||||||
|
writers:
|
||||||
|
head: textcycle("head".l(), "leg")
|
||||||
|
leg: textcycle("leg".l(), "arm")
|
||||||
|
arm: textcycle("arm".l(), "head")
|
||||||
|
|
||||||
|
situation "spare_pacifist",
|
||||||
|
optionText: "Опустить оружие",
|
||||||
|
tags: "pacifist",
|
||||||
|
before: (character, system) ->
|
||||||
|
character.sandbox.shot_pacifist = 0
|
||||||
|
choices: ["#shoot"],
|
||||||
|
content: (character, system) ->
|
||||||
|
return "spare_pacifist".l()
|
||||||
|
|
||||||
|
## Finale buildup
|
||||||
|
play_step = (volume) ->
|
||||||
|
rand = Math.random();
|
||||||
|
step1 = document.getElementById("step1")
|
||||||
|
step2 = document.getElementById("step2")
|
||||||
|
audio = step1
|
||||||
|
if rand > 0.5
|
||||||
|
audio = step2
|
||||||
|
audio.currentTime = 0
|
||||||
|
audio.volume = volume
|
||||||
|
audio.play()
|
||||||
|
|
||||||
|
situation "finale",
|
||||||
|
content: (character, system) ->
|
||||||
|
if character.sandbox.shots < 36
|
||||||
|
return "finale_perfect".l()
|
||||||
|
return "finale".l()
|
|
@ -2,20 +2,16 @@
|
||||||
<html lang="ru">
|
<html lang="ru">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
<title>Пули говорят быстрее</title>
|
||||||
<title>Тридцать пять выстрелов</title>
|
|
||||||
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<link rel="stylesheet" href="css/main.css">
|
<link rel="stylesheet" href="css/main.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
|
|
||||||
<div id="mid_panel">
|
<div id="mid_panel">
|
||||||
<div id="title">
|
<div id="title">
|
||||||
<div class="label">
|
<div class="label">
|
||||||
|
<h1>Пули говорят быстрее</h1>
|
||||||
<h1>Тридцать пять выстрелов</h1>
|
|
||||||
<h3>Научно-фантастический онлайн кибертекстовый шутер от первого лица</h3>
|
<h3>Научно-фантастический онлайн кибертекстовый шутер от первого лица</h3>
|
||||||
<p>от <b><a href="https://oreolek.ru/">Oreolek'а</a></b></p>
|
<p>от <b><a href="https://oreolek.ru/">Oreolek'а</a></b></p>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
|
Loading…
Reference in a new issue