mirror of
https://github.com/Oreolek/shooter.git
synced 2024-05-26 04:38:10 +03:00
Version 0.5 - the minimal playable version.
This commit is contained in:
parent
9df72b5ae3
commit
0c32acd500
|
@ -26,7 +26,7 @@ var reload = browserSync.reload;
|
||||||
|
|
||||||
function html (target) {
|
function html (target) {
|
||||||
return function () {
|
return function () {
|
||||||
return gulp.src('html/index.html')
|
return gulp.src(['html/index.html','html/en.html'])
|
||||||
.pipe(gulp.dest(target));
|
.pipe(gulp.dest(target));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -158,4 +158,4 @@ gulp.task('zip', ['dist'], function () {
|
||||||
return gulp.src('dist/**')
|
return gulp.src('dist/**')
|
||||||
.pipe(zip('dist.zip'))
|
.pipe(zip('dist.zip'))
|
||||||
.pipe(gulp.dest('.'));
|
.pipe(gulp.dest('.'));
|
||||||
});
|
});
|
||||||
|
|
148
game/main.coffee
148
game/main.coffee
|
@ -1,5 +1,6 @@
|
||||||
# copyright (c) Alexander Yakovlev 2015.
|
# copyright (c) Alexander Yakovlev 2015.
|
||||||
# Distributed under the MIT license. See LICENSE for information.
|
# This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
# To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0
|
||||||
|
|
||||||
situation = require('raconteur')
|
situation = require('raconteur')
|
||||||
undum = require('undum-commonjs')
|
undum = require('undum-commonjs')
|
||||||
|
@ -13,13 +14,15 @@ markdown = new md({
|
||||||
typographer: true,
|
typographer: true,
|
||||||
html: true
|
html: true
|
||||||
})
|
})
|
||||||
|
undumloc = require("./ru.coffee").language
|
||||||
|
undum.language["ru"] = undumloc
|
||||||
|
|
||||||
a = elements.a
|
a = elements.a
|
||||||
span = elements.span
|
span = elements.span
|
||||||
img = elements.img
|
img = elements.img
|
||||||
|
|
||||||
undum.game.id = "7a1aba32-f0fd-4e3b-ba5a-59e3fa9e6012"
|
undum.game.id = "7a1aba32-f0fd-4e3b-ba5a-59e3fa9e6012"
|
||||||
undum.game.version = "0.1"
|
undum.game.version = "0.5"
|
||||||
|
|
||||||
way_to = (content, ref) -> a(content).class('way').ref(ref)
|
way_to = (content, ref) -> a(content).class('way').ref(ref)
|
||||||
textlink = (content, ref) -> a(content).once().writer(ref)
|
textlink = (content, ref) -> a(content).once().writer(ref)
|
||||||
|
@ -31,6 +34,11 @@ writemd = (system, text) ->
|
||||||
|
|
||||||
link_colour = "#B68000"
|
link_colour = "#B68000"
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
spend_bullet = (character, system) ->
|
spend_bullet = (character, system) ->
|
||||||
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
||||||
if bullets >= 1
|
if bullets >= 1
|
||||||
|
@ -38,21 +46,25 @@ spend_bullet = (character, system) ->
|
||||||
system.setQuality("bullets", bullets - 1)
|
system.setQuality("bullets", bullets - 1)
|
||||||
|
|
||||||
spend_clip = (character, system) ->
|
spend_clip = (character, system) ->
|
||||||
clips = character.sandbox.clips.length
|
|
||||||
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
bullets = character.sandbox.clips[character.sandbox.current_clip]
|
||||||
if clips == 0
|
clips = character.sandbox.clips.length
|
||||||
|
if clips < 2
|
||||||
return
|
return
|
||||||
if bullets == 0
|
if bullets == 0
|
||||||
character.sandbox.clips.splice(character.sandbox.current_clip, 1)
|
character.sandbox.clips.splice(character.sandbox.current_clip, 1)
|
||||||
system.setQuality("bullets", character.sandbox.clips[character.sandbox.current_clip])
|
clips = character.sandbox.clips.length
|
||||||
system.setQuality("clips", clips - 1)
|
|
||||||
writemd(system, "Я выбрасываю пустой картридж.")
|
writemd(system, "Я выбрасываю пустой картридж.")
|
||||||
|
system.setQuality("clips", clips)
|
||||||
|
if character.sandbox.current_clip < clips - 1
|
||||||
|
character.sandbox.current_clip++
|
||||||
else
|
else
|
||||||
if character.sandbox.current_clip < clips - 1
|
character.sandbox.current_clip = 0
|
||||||
character.sandbox.current_clip++
|
system.setQuality("bullets", character.sandbox.clips[character.sandbox.current_clip])
|
||||||
else
|
|
||||||
character.sandbox.current_clip == 0
|
check_distance = (character, system) ->
|
||||||
system.setQuality("bullets", character.sandbox.clips[character.sandbox.current_clip])
|
if character.sandbox.distance == 0
|
||||||
|
system.setQuality("health", character.qualities.health - 1)
|
||||||
|
system.writemd("Один из андроидов доходит до меня и кусает!")
|
||||||
|
|
||||||
situation 'start',
|
situation 'start',
|
||||||
content: """
|
content: """
|
||||||
|
@ -60,6 +72,9 @@ situation 'start',
|
||||||
|
|
||||||
Узкий коридор, я и непрекращающаяся очередь сверкающих белоснежной кожей андроидов.
|
Узкий коридор, я и непрекращающаяся очередь сверкающих белоснежной кожей андроидов.
|
||||||
Я уверен, что я представлял этот Новый Год совершенно не так.
|
Я уверен, что я представлял этот Новый Год совершенно не так.
|
||||||
|
|
||||||
|
Один ящик андроидов содержит тридцать пять машин.
|
||||||
|
Это будет длинная битва.
|
||||||
""",
|
""",
|
||||||
choices: ["#shoot"],
|
choices: ["#shoot"],
|
||||||
|
|
||||||
|
@ -72,8 +87,11 @@ situation "hit",
|
||||||
return response()
|
return response()
|
||||||
choices: ["#shoot"]
|
choices: ["#shoot"]
|
||||||
before: (character, system, from) ->
|
before: (character, system, from) ->
|
||||||
system.setQuality("enemies", character.qualities.enemies - 1)
|
|
||||||
character.sandbox.nicked = 0
|
character.sandbox.nicked = 0
|
||||||
|
if character.qualities.enemies > 1
|
||||||
|
system.setQuality("enemies", character.qualities.enemies - 1)
|
||||||
|
if character.qualities.enemies == 0
|
||||||
|
system.doLink("finale")
|
||||||
choices: ["#shoot"]
|
choices: ["#shoot"]
|
||||||
|
|
||||||
situation "nicked",
|
situation "nicked",
|
||||||
|
@ -108,25 +126,41 @@ situation "miss",
|
||||||
situation "shoot",
|
situation "shoot",
|
||||||
tags: ["shoot"],
|
tags: ["shoot"],
|
||||||
optionText: (character, system, from) ->
|
optionText: (character, system, from) ->
|
||||||
response = oneOf(
|
return oneOf(
|
||||||
"Выстрел",
|
"Выстрел",
|
||||||
|
"Бдыщь!",
|
||||||
|
"Выстрелить",
|
||||||
|
"Нажать на курок",
|
||||||
|
"Атака",
|
||||||
|
"Стрельба",
|
||||||
"СТРЕЛЯТЬ!",
|
"СТРЕЛЯТЬ!",
|
||||||
"УБИТЬ ИХ ИЗ ПИСТОЛЕТА",
|
"УБИТЬ ИХ ИЗ ПИСТОЛЕТА",
|
||||||
"НЕНАВИЖУ АНДРОИДОВ"
|
"НЕНАВИЖУ АНДРОИДОВ",
|
||||||
).stopping(system)
|
"АННИГИЛЯЦИЯ МЕХАНОИДОВ",
|
||||||
return response()
|
"Уничтожить механоидов",
|
||||||
|
"Отправить пулю в андроида",
|
||||||
|
"Послать пулю взрывом",
|
||||||
|
"Нажать на курок во имя ЧЕЛОВЕЧЕСТВА",
|
||||||
|
"Прыгнуть к стене и выстрелить из пистолета в полёте",
|
||||||
|
"Присесть и выстрелить с колена",
|
||||||
|
"Взять пистолет в обе руки и нажать на курок",
|
||||||
|
"Не спеша прицелиться и выстрелить"
|
||||||
|
).randomly(system)
|
||||||
canChoose: (character, system) ->
|
canChoose: (character, system) ->
|
||||||
return character.qualities.bullets > 0
|
return character.qualities.bullets > 0
|
||||||
before: (character, system, from) ->
|
before: (character, system, from) ->
|
||||||
spend_bullet(character, system)
|
spend_bullet(character, system)
|
||||||
|
character.sandbox.distance = 3
|
||||||
system.clearContent()
|
system.clearContent()
|
||||||
after: (character, system, from) ->
|
after: (character, system, from) ->
|
||||||
# d20 roll
|
roll = system.rnd.dice(1,20) # d20 roll
|
||||||
# 1-14 - hit, 15-18 - nicked, 19-20 = miss
|
hit_threshold = 15
|
||||||
roll = system.rnd.randomInt(1,20)
|
miss_threshold = 18
|
||||||
|
if character.qualities.health < 2
|
||||||
|
hit_threshold = 18
|
||||||
switch
|
switch
|
||||||
when roll < 15 then system.doLink("hit")
|
when roll < hit_threshold then system.doLink("hit")
|
||||||
when roll > 18 then system.doLink("miss")
|
when roll > miss_threshold then system.doLink("miss")
|
||||||
else system.doLink("nicked")
|
else system.doLink("nicked")
|
||||||
|
|
||||||
situation "reload",
|
situation "reload",
|
||||||
|
@ -134,18 +168,79 @@ situation "reload",
|
||||||
choices: ["#shoot"],
|
choices: ["#shoot"],
|
||||||
optionText: "Перезарядить пистолет",
|
optionText: "Перезарядить пистолет",
|
||||||
canView: (character, system) ->
|
canView: (character, system) ->
|
||||||
return character.qualities.bullets < 6
|
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) ->
|
before: (character, system) ->
|
||||||
|
character.sandbox.seen_reload = 1
|
||||||
system.clearContent()
|
system.clearContent()
|
||||||
|
character.sandbox.distance--
|
||||||
after: (character, system) ->
|
after: (character, system) ->
|
||||||
spend_clip(character, system)
|
spend_clip(character, system)
|
||||||
writemd(system, "Я вставляю другой картридж в пистолет. Надеюсь, в нём есть патроны.")
|
writemd(system, "Я вставляю другой картридж в пистолет. Надеюсь, в нём есть патроны.")
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# А теперь plot twist: у пистолета есть шанс осечки и промаха. Ты теряешь патрон. Всего патронов у тебя 36, а врагов 35.
|
situation "search",
|
||||||
|
tags: ["shoot"],
|
||||||
|
optionText: "Искать чужие картриджи",
|
||||||
|
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
|
||||||
|
character.sandbox.distance--
|
||||||
|
after: (character, system) ->
|
||||||
|
response = oneOf(
|
||||||
|
"Я в спешке шарю по полу, пытаясь найти хотя бы один целый картридж.",
|
||||||
|
"Я быстро оглядываюсь в поисках картриджей на полу."
|
||||||
|
).randomly(system)
|
||||||
|
writemd(system, response())
|
||||||
|
roll = system.rnd.dice(1,20) # d20 roll
|
||||||
|
find_threshold = 10
|
||||||
|
if character.qualities.health < 2
|
||||||
|
find_threshold += 2
|
||||||
|
if character.sandbox.distance < 2
|
||||||
|
find_threshold += 2
|
||||||
|
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 = oneOf(
|
||||||
|
"Ага! Есть один. Надеюсь, в нём есть патроны.",
|
||||||
|
"А, вот какой-то. На вес тяжёлый -- надеюсь, в нём есть патроны."
|
||||||
|
).randomly(system)
|
||||||
|
return response()
|
||||||
|
|
||||||
|
situation "not_found",
|
||||||
|
choices: ["#shoot"],
|
||||||
|
content: (character, system, from) ->
|
||||||
|
response = oneOf(
|
||||||
|
"Нет, ничего нет.",
|
||||||
|
"Ну хотя бы один! Нет, не нашёл."
|
||||||
|
).randomly(system)
|
||||||
|
return response()
|
||||||
|
|
||||||
situation "finale",
|
situation "finale",
|
||||||
content: """
|
content: """
|
||||||
|
Ба-бах!
|
||||||
|
|
||||||
|
Последний андроид внезапно взрывается, как будто нашпигованный взрывчаткой.
|
||||||
|
А, впрочем, с этими машинами никогда не знаешь наверняка.
|
||||||
|
Я отворачиваюсь и ухожу прочь, не обращая внимания на взрыв.
|
||||||
|
|
||||||
|
Моя работа сделана.
|
||||||
|
|
||||||
|
<center><h3>КОНЕЦ</h3></center>
|
||||||
""",
|
""",
|
||||||
|
|
||||||
qualities
|
qualities
|
||||||
|
@ -153,13 +248,18 @@ qualities
|
||||||
bullets: qualities.integer('Патронов в картридже'),
|
bullets: qualities.integer('Патронов в картридже'),
|
||||||
clips: qualities.integer('Картриджей с патронами'),
|
clips: qualities.integer('Картриджей с патронами'),
|
||||||
enemies: qualities.integer('Врагов впереди'),
|
enemies: qualities.integer('Врагов впереди'),
|
||||||
|
health: qualities.fudgeAdjectives('Здоровье'),
|
||||||
|
|
||||||
undum.game.init = (character, system) ->
|
undum.game.init = (character, system) ->
|
||||||
system.setQuality("bullets", 6)
|
system.setQuality("bullets", 6)
|
||||||
system.setQuality("clips", 6)
|
system.setQuality("clips", 6)
|
||||||
system.setQuality("enemies", 35)
|
system.setQuality("enemies", 35)
|
||||||
character.sandbox.clips = [6,6,6,6]
|
system.setQuality("health", 3)
|
||||||
|
character.sandbox.clips = [5,5]#[6,6,6,6,6,6]
|
||||||
character.sandbox.current_clip = 0
|
character.sandbox.current_clip = 0
|
||||||
character.sandbox.nicked = 0
|
character.sandbox.nicked = 0
|
||||||
|
character.sandbox.distance = 3
|
||||||
|
character.sandbox.seen_reload = 0
|
||||||
|
character.sandbox.seen_search = 0
|
||||||
|
|
||||||
window.onload = undum.begin
|
window.onload = undum.begin
|
||||||
|
|
21
game/ru.coffee
Normal file
21
game/ru.coffee
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
module.exports.language =
|
||||||
|
terrible: "ужасно",
|
||||||
|
poor: "бедно",
|
||||||
|
mediocre: "средне",
|
||||||
|
fair: "нормально"
|
||||||
|
good: "хорошо"
|
||||||
|
great: "прекрасно"
|
||||||
|
superb: "идеально"
|
||||||
|
yes: "да"
|
||||||
|
no: "нет"
|
||||||
|
no_group_definition: "Невозможно найти определение группы {id}."
|
||||||
|
link_not_valid: "Ссылка '{link}' не выглядит правильной."
|
||||||
|
link_no_action: "Ссылка с ситуацией '.' должна иметь действие."
|
||||||
|
unknown_situation: "Вы не можете переместиться в неизвестную ситуацию {id}."
|
||||||
|
erase_message: "Это навсегда удалит вашего персонажа и немедленно вернёт вас к началу игры. Вы уверены?"
|
||||||
|
no_current_situation: "Я не могу отобразить, потому что у нас нет текущей ситуации."
|
||||||
|
no_local_storage: "Локальное хранилище недоступно."
|
||||||
|
random_seed_error: "Вы должны задать верное случайное зерно."
|
||||||
|
random_error: "Проинициализируйте Random с непустым зерном перед использованием."
|
||||||
|
dice_string_error: "не могу интерпретировать вашу cтроку кубиков: '{string}'."
|
||||||
|
erase_message: "Это навсегда удалит вашего персонажа и немедленно вернёт вас на старт игры. Вы уверены?"
|
95
html/en.html
Normal file
95
html/en.html
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
|
||||||
|
<title>Thirty five shots</title>
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="css/main.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="toolbar">
|
||||||
|
<h1>Thirty five shots</h1>
|
||||||
|
<div class="nav">
|
||||||
|
<a href="#" class="button" id="menu-button">Menu</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ul id="menu">
|
||||||
|
<li><a href="#title, #content_wrapper">Story</a></li>
|
||||||
|
<li><a href="#character_panel">Character</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div id="page">
|
||||||
|
|
||||||
|
<div id="tools_wrapper">
|
||||||
|
<div id="character_panel" class="tools right">
|
||||||
|
<div id="character">
|
||||||
|
<div id="character_text">
|
||||||
|
<div id="character_text_content"></div>
|
||||||
|
</div>
|
||||||
|
<div id="qualities"></div>
|
||||||
|
</div>
|
||||||
|
<div class='buttons'>
|
||||||
|
<button id="save">Save</button><button id="erase">Erase</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- End of div.tools_wrapper -->
|
||||||
|
|
||||||
|
<div id="mid_panel">
|
||||||
|
<div id="title">
|
||||||
|
<div class="label">
|
||||||
|
|
||||||
|
<h1>Thirty five shots</h1>
|
||||||
|
<noscript>
|
||||||
|
<p class="noscript_message">This game requires Javascript.</p>
|
||||||
|
</noscript>
|
||||||
|
<p class="click_message">click to play</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content_wrapper">
|
||||||
|
<div id="content">
|
||||||
|
</div>
|
||||||
|
<a name="end_of_content"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="legal">
|
||||||
|
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/" class="footright"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a>
|
||||||
|
<p>Approximate play time: five minites.</p>
|
||||||
|
<p>Made using <a href="http://undum.com">Undum</a> and <a href="http://sequitur.github.io/raconteur/">Raconteur</a>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div> <!-- End of div.page -->
|
||||||
|
|
||||||
|
<div id="ui_library">
|
||||||
|
<div id="quality" class="quality">
|
||||||
|
<span class="name" data-attr="name"></span>
|
||||||
|
<span class="value" data-attr="value"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="quality_group" class="quality_group">
|
||||||
|
<h2 data-attr="title"></h2>
|
||||||
|
<div class="qualities_in_group">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="progress_bar" class="progress_bar">
|
||||||
|
<span class="name" data-attr="name"></span>
|
||||||
|
<span class="value" data-attr="value"></span>
|
||||||
|
<div class="progress_bar_track">
|
||||||
|
<div class="progress_bar_color" data-attr="width">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="left_label" data-attr="left_label"></span>
|
||||||
|
<span class="right_label" data-attr="right_label"></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr id="turn_separator">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="content_library"></div>
|
||||||
|
<script type="text/javascript" src="game/undum.js"></script>
|
||||||
|
<script type="text/javascript" src="game/bundle.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -55,7 +55,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="legal">
|
<div id="legal">
|
||||||
<p>Приблизительное время прохождения игры: пятнадцать минут. Но вы схватите идею за пять.</p>
|
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/" class="footright"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a>
|
||||||
|
<p>Приблизительное время прохождения игры: пять минут.</p>
|
||||||
<p>Написано при помощи <a href="http://undum.com">Undum</a> и <a href="http://sequitur.github.io/raconteur/">Raconteur</a>.</p>
|
<p>Написано при помощи <a href="http://undum.com">Undum</a> и <a href="http://sequitur.github.io/raconteur/">Raconteur</a>.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -458,3 +458,6 @@ img.left {
|
||||||
.center-block {
|
.center-block {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
.footright {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue