DX3 DiceRoller/BCDiceAPIを使ってスマホでダブルクロスの判定


DX3 DiceRoller


ダブルクロス』の新しいサプリメント『バッドシティ』も出たことだし、またダブルクロスを遊ぶ機会があるかもしれないと思ったものの。
『レネゲイドウォー』の時のダイス30個振りは、楽しくもあり、ちょっと面倒くさくもあり。判定に時間もかかるしね!


あと『シャドウラン』はiPhoneのアプリで以下のが便利そうだったことも、思い立った一因です。


で。そういえば以前 html/javascriptで dicerollするコードを書いたはずなのですが、大昔すぎて PC更新したりしたらどこか消えてしまいました。でももう一度書くのも面倒だなぁ。そういえばBCDiceのWebAPIがあったはず。あれを利用すれば各種ダイスボットのコードを書かなくてもいいはず。それにDiceBot界のデファクトスタンダードなので、処理結果に対する信頼性も高いというメリットもあり。
というわけで。ちょっと書いてみました。


とりあえずiPhoneXperia(Android)で使ってみましたが、実用に耐えうるのではないかと思っています。
一応ダイスロールボタンを押したよの合図として音が出るようになっています。使用する際は音量オンがよいかと思います。
お試しください。

  • もっとかっこいい画面デザインとか
  • 結果を共有する機能とか(どどんとふのWebAPIとか利用すれば、指定の部屋に書き込んで共有できるよとか)
  • いやそもそもこれだけの機能だったら、わざわざWebAPIを呼ばずにユドナリウムからOpalでjs変換したコードを流用すればいいのでは?

とか、いろいろあるとは思いますが、まぁ、そこはそれ。

謝辞

  • BCDiceを提供するWebAPIサーバーの仕組みを利用させていただいています。感謝!

GitHub - ysakasin/bcdice-api: BCDiceを提供するWebAPIサーバー

  • 以下のサーバーのWebAPIを利用させていただいています。感謝!

HTTPS版BCDice-API – 大ちゃんのいろいろ雑記

  • あともちろんBCDice本体の開発の方々にも感謝!

ソースコード

他システムのDiceBotを利用する際に転用できるのではないかと思いますので、ソースコードを公開しておきます。
門外漢な分野なので変なことになっているかもしれませんが、ご参考まで。

<html>
<head id="header">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=no">
<title>DX3 DiceRoller</title>
<style type="text/css">
<!--
div{
  font-size : 150%;
}
input{
  font-size : 200%;
  width: 150px;
  text-align: center;
}

.btn{
  display: inline-block;
  text-decoration: none;
  color: #668ad8;
  width: 65px;
  height: 65px;
  line-height: 65px;
  border-radius: 50%;
  border: solid 2px #668ad8;
  text-align: center;
  vertical-align: middle;
  overflow: hidden;
  font-weight: bold;
  transition: .4s;
}

.btn:hover {
    background: #b3e1ff;
}
.btn-flat-border {
  display: inline-block;
  text-decoration: none;
  color: #668ad8;
  width: 285px;
  height: 60px;
  line-height: 60px;
  border-radius: 3px;
  border: solid 2px #668ad8;
  text-align: center;
  vertical-align: middle;
  overflow: hidden;
  font-weight: bold;
  transition: .4s;
}

.btn-flat-border:hover {
  background: #b3e1ff;
}
-->
</style>
<script><!--
const BCDiceApiURL = "https://www.taruki.com/bcdice-api/v1/diceroll?system=DoubleCross&command="

function $(id) { return document.getElementById(id); }

function judge(){
	var strDice = document.getElementById('dice').value
	var strModify = document.getElementById('modify').value
	var strCritical = document.getElementById('critical').value

	if (strDice && strCritical) {
		var strCommand = strDice + "DX" + strCritical
		if (strModify) {
			strCommand = strCommand + "+" + strModify
		}
		console.log(strCommand);
		document.getElementById('sound').play();
		requestBCDiceAPI(strCommand);
	}
}

function judgeReroll(){
	var intModify = 0;

	document.getElementById('dice').value = 1;
	if( localStorage.getItem('diceResult')) {
		intModify = localStorage.getItem('diceResult');
	}
console.log( intModify);
	document.getElementById('modify').value = intModify;

	var strDice = document.getElementById('dice').value
	var strModify = document.getElementById('modify').value
	var strCritical = document.getElementById('critical').value

	if (strDice && strCritical) {
		var strCommand = strDice + "DX" + strCritical
		if (strModify) {
			strCommand = strCommand + "+" + strModify
		}
		console.log(strCommand);
		document.getElementById('sound').play();
		requestBCDiceAPI(strCommand);
	}
}

function damage(){
	var strDice = document.getElementById('dice').value
	var strModify = document.getElementById('modify').value

	if (strDice) {
		var strCommand = strDice + "D10"
		if (strModify) {
			strCommand = strCommand + "+" + strModify
		}
		console.log(strCommand);
		document.getElementById('sound').play();
		requestBCDiceAPI(strCommand);
	}
}

function emotion(){
	document.getElementById('sound').play();
	requestBCDiceAPI("ET");
}

function entry(){
	var strCommand = "1D10"
	console.log(strCommand);
	document.getElementById('sound').play();
	requestBCDiceAPI(strCommand);
}

function requestBCDiceAPI(strCommand){
	var intResult;
	const request = new XMLHttpRequest();
	strRequest = BCDiceApiURL + encodeURIComponent(strCommand)
	console.log(strRequest);
	request.open('GET', strRequest);
	request.addEventListener("load",(event)=>{
		var json = JSON.parse(event.target.responseText);
		console.log(json);
		$('result').innerHTML = json.result + "<br/>";

		intResult=0;
		strResult = json.result;
		if ( strResult.indexOf('DX') !== -1 && strResult.indexOf('ファンブル') === -1) {
			intResult= parseInt(strResult.substr(strResult.lastIndexOf('>')+1));
			var intModify = parseInt(document.getElementById('modify').value)
			var intRerollModify = 10 - ((intResult - intModify) % 10 );
			intResult= intResult + intRerollModify;
		}
		console.log( intResult);
		localStorage.setItem('diceResult', intResult)
	});
	request.send();
}
// -->
</script>
</head>
<body>
<audio id="sound" preload="auto"><source src="http://aldente.sakura.ne.jp/public/diceRoll.mp3"></audio>
<div id="result"></div>
<hr>
<table>
	<tr>
		<td>ダイス数</td>
		<td><input type="number" id="dice" min="1" value="1"/></td>
	</tr>
	<tr>
		<td>修正値</td>
		<td><input type="number" id="modify" min="0" value="0"/></td>
	</tr>
	<tr>
		<td>クリティカル値</td>
		<td><input type="number" id="critical" min="2" value="10"/></td>
	</tr>
</table>
<hr>
<table>
	<tr>
		<td><a href="#" class="btn" onclick="judge();">判定</a></td>
		<td><a href="#" class="btn" onclick="judgeReroll();">判定振足</a></td>
		<td><a href="#" class="btn" onclick="damage();">ダメージ</a></td>
		<td><a href="#" class="btn" onclick="emotion();">感情</a></td>
	</tr>
</table>
<table>
	<tr>
		<a href="#" class="btn-flat-border" onclick="entry();">シーン登場</a>
	</tr>
</table>
</body>
</html>