DX3 DiceRoller/BCDiceAPIを使ってスマホでダブルクロスの判定
『ダブルクロス』の新しいサプリメント『バッドシティ』も出たことだし、またダブルクロスを遊ぶ機会があるかもしれないと思ったものの。
『レネゲイドウォー』の時のダイス30個振りは、楽しくもあり、ちょっと面倒くさくもあり。判定に時間もかかるしね!
あと『シャドウラン』はiPhoneのアプリで以下のが便利そうだったことも、思い立った一因です。
App名: SchattenWurf for Shadowrun、デベロッパ: Daniel Benkmann https://t.co/DxgO4EOtvP
— ꋫꀗ꒐ꌥꌇꀗ꒐ (@akiyuki3) 2018年12月17日
で。そういえば以前 html/javascriptで dicerollするコードを書いたはずなのですが、大昔すぎて PC更新したりしたらどこか消えてしまいました。でももう一度書くのも面倒だなぁ。そういえばBCDiceのWebAPIがあったはず。あれを利用すれば各種ダイスボットのコードを書かなくてもいいはず。それにDiceBot界のデファクトスタンダードなので、処理結果に対する信頼性も高いというメリットもあり。
というわけで。ちょっと書いてみました。
とりあえずiPhoneとXperia(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>