mirror of
https://github.com/naturalcrit/homebrewery.git
synced 2025-12-27 00:42:40 +00:00
setting up a default monster manual and encoutners
This commit is contained in:
42
client/naturalCrit/defaultMonsterManual.js
Normal file
42
client/naturalCrit/defaultMonsterManual.js
Normal file
@@ -0,0 +1,42 @@
|
||||
module.exports = {
|
||||
goblin : {
|
||||
hp : 40,
|
||||
mov: 30,
|
||||
ac : 13,
|
||||
attr : {
|
||||
str : 8,
|
||||
con : 8,
|
||||
dex : 8,
|
||||
int : 8,
|
||||
wis : 8,
|
||||
cha : 8
|
||||
},
|
||||
attacks : {
|
||||
dagger : {
|
||||
atk : "1d20-5",
|
||||
dmg : "1d4+5",
|
||||
type : "pierce",
|
||||
notes : "Super cool"
|
||||
},
|
||||
bow : {
|
||||
atk : "1d20+2",
|
||||
dmg : "6d6",
|
||||
rng : "30"
|
||||
}
|
||||
},
|
||||
spells : {
|
||||
fireball: {
|
||||
dmg : "6d6",
|
||||
uses : 4
|
||||
},
|
||||
"healing bolt" : {
|
||||
heal : "2d8+4",
|
||||
uses : 6
|
||||
}
|
||||
},
|
||||
abilities : {
|
||||
"pack tactics" : "Does a thing"
|
||||
},
|
||||
items : ['healing_potion', 'healing_potion', 'ring']
|
||||
}
|
||||
}
|
||||
@@ -127,6 +127,14 @@ var MonsterCard = React.createClass({
|
||||
})
|
||||
},
|
||||
|
||||
renderAbilities : function(){
|
||||
return _.map(this.props.abilities, function(text, name){
|
||||
return <div className='ability' key={name}>
|
||||
<span className='name'>{name}</span>: {text}
|
||||
</div>
|
||||
});
|
||||
},
|
||||
|
||||
renderItems : function(){
|
||||
var self = this;
|
||||
var usedItems = this.state.usedItems.slice(0);
|
||||
@@ -172,7 +180,7 @@ var MonsterCard = React.createClass({
|
||||
</div>
|
||||
|
||||
<div className='abilitiesContainer'>
|
||||
{this.props.abilities}
|
||||
{this.renderAbilities()}
|
||||
</div>
|
||||
<div className='itemContainer'>
|
||||
<i className='fa fa-flask' />
|
||||
|
||||
@@ -104,10 +104,16 @@
|
||||
}
|
||||
}
|
||||
.abilitiesContainer{
|
||||
margin-top : 5px;
|
||||
margin-top : 10px;
|
||||
.ability{
|
||||
font-size: 0.7em;
|
||||
.name{
|
||||
font-weight: 800;
|
||||
}
|
||||
}
|
||||
}
|
||||
.itemContainer{
|
||||
margin-top : 5px;
|
||||
margin-top : 10px;
|
||||
i{
|
||||
font-size : 0.7em;
|
||||
}
|
||||
|
||||
@@ -2,12 +2,9 @@ var React = require('react');
|
||||
var _ = require('lodash');
|
||||
var cx = require('classnames');
|
||||
|
||||
|
||||
var Sidebar = require('./sidebar/sidebar.jsx');
|
||||
|
||||
var Encounter = require('./encounter/encounter.jsx');
|
||||
|
||||
|
||||
var encounters = [
|
||||
{
|
||||
name : 'The Big Bad',
|
||||
@@ -47,46 +44,7 @@ var encounters = [
|
||||
|
||||
];
|
||||
|
||||
var monsterManual = {
|
||||
'goblin' : {
|
||||
"hp" : 40,
|
||||
"mov": 30,
|
||||
"ac" : 13,
|
||||
"attr" : {
|
||||
"str" : 8,
|
||||
"con" : 8,
|
||||
"dex" : 8,
|
||||
"int" : 8,
|
||||
"wis" : 8,
|
||||
"cha" : 8
|
||||
},
|
||||
"attacks" : {
|
||||
"dagger" : {
|
||||
"atk" : "1d20-5",
|
||||
"dmg" : "1d4+5",
|
||||
"type" : "pierce",
|
||||
"notes" : "Super cool"
|
||||
},
|
||||
"bow" : {
|
||||
"atk" : "1d20+2",
|
||||
"dmg" : "6d6",
|
||||
"rng" : "30"
|
||||
}
|
||||
},
|
||||
"spells" : {
|
||||
"fireball": {
|
||||
"dmg" : "6d6",
|
||||
"uses" : 4
|
||||
},
|
||||
"healing_bolt" : {
|
||||
"heal" : "2d8+4",
|
||||
"uses" : 6
|
||||
}
|
||||
},
|
||||
"abilities" : ["pack tactics"],
|
||||
"items" : ['healing_potion', 'healing_potion', 'ring']
|
||||
}
|
||||
}
|
||||
var defaultMonsterManual = require('./defaultMonsterManual.js');
|
||||
|
||||
var attrMod = function(attr){
|
||||
return Math.floor(attr/2) - 5;
|
||||
@@ -100,7 +58,7 @@ var NaturalCrit = React.createClass({
|
||||
return {
|
||||
selectedEncounterIndex : 0,
|
||||
encounters : JSON.parse(localStorage.getItem('encounters')) || encounters,
|
||||
monsterManual : JSON.parse(localStorage.getItem('monsterManual')) || monsterManual,
|
||||
monsterManual : JSON.parse(localStorage.getItem('monsterManual')) || defaultMonsterManual,
|
||||
|
||||
players : localStorage.getItem('players') || 'jasper 13\nzatch 19'
|
||||
|
||||
@@ -128,6 +86,7 @@ var NaturalCrit = React.createClass({
|
||||
localStorage.setItem("players", e.target.value);
|
||||
},
|
||||
handleSelectedEncounterChange : function(encounterIndex){
|
||||
console.log(encounterIndex);
|
||||
this.setState({
|
||||
selectedEncounterIndex : encounterIndex
|
||||
});
|
||||
@@ -146,7 +105,9 @@ var NaturalCrit = React.createClass({
|
||||
return encounter.name == self.state.selectedEncounter;
|
||||
});
|
||||
|
||||
if(this.state.selectedEncounterIndex != null){
|
||||
|
||||
|
||||
if(this.state.selectedEncounterIndex != null && selectedEncounter != null){
|
||||
var selectedEncounter = this.state.encounters[this.state.selectedEncounterIndex]
|
||||
return <Encounter
|
||||
key={selectedEncounter.name}
|
||||
|
||||
0
client/naturalCrit/randomEncounter.js
Normal file
0
client/naturalCrit/randomEncounter.js
Normal file
@@ -1,5 +1,10 @@
|
||||
.dmDice{
|
||||
|
||||
h3{
|
||||
color : white;
|
||||
background-color: @teal;
|
||||
}
|
||||
|
||||
.roll{
|
||||
cursor: pointer;
|
||||
.noselect();
|
||||
@@ -21,8 +26,7 @@
|
||||
}
|
||||
|
||||
&:hover{
|
||||
background-color: fade(@red, 20%);
|
||||
background-color: fade(@teal, 20%);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,13 +2,70 @@ var React = require('react');
|
||||
var _ = require('lodash');
|
||||
var cx = require('classnames');
|
||||
|
||||
var JSONFileEditor = require('naturalCrit/jsonFileEditor/jsonFileEditor.jsx');
|
||||
|
||||
var Encounters = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
encounters : [],
|
||||
selectedEncounter : 0,
|
||||
|
||||
onJSONChange : function(encounterIndex, json){},
|
||||
onSelectEncounter : function(encounterIndex){},
|
||||
onRemoveEncounter : function(encounterIndex){}
|
||||
};
|
||||
},
|
||||
|
||||
handleJSONChange : function(encounterIndex, json){
|
||||
this.props.onJSONChange(encounterIndex, json);
|
||||
},
|
||||
handleSelectEncounter : function(encounterIndex){
|
||||
this.props.onSelectEncounter(encounterIndex);
|
||||
},
|
||||
handleRemoveEncounter : function(encounterIndex){
|
||||
this.props.onRemoveEncounter(encounterIndex);
|
||||
},
|
||||
|
||||
|
||||
renderEncounters : function(){
|
||||
var self = this;
|
||||
return _.map(this.props.encounters, function(encounter, index){
|
||||
|
||||
var isSelected = self.props.selectedEncounter == index;
|
||||
return <div className={cx('encounter' , {'selected' : isSelected})} key={index}>
|
||||
|
||||
<i onClick={self.handleSelectEncounter.bind(self, index)} className={cx('select', 'fa', {
|
||||
'fa-square-o' : !isSelected,
|
||||
'fa-check-square-o' : isSelected,
|
||||
})} />
|
||||
|
||||
|
||||
<JSONFileEditor
|
||||
name={encounter.name}
|
||||
json={encounter}
|
||||
onJSONChange={self.handleJSONChange.bind(self, index)}
|
||||
/>
|
||||
|
||||
<i onClick={self.handleRemoveEncounter.bind(self, index)} className='remove fa fa-times' />
|
||||
</div>
|
||||
})
|
||||
},
|
||||
|
||||
render : function(){
|
||||
var self = this;
|
||||
return(
|
||||
<div className='encounters'>
|
||||
Encounters Ready!
|
||||
<h3>
|
||||
<i className='fa fa-flag' /> Encounters
|
||||
<button className='addEncounter'>
|
||||
<i className='fa fa-plus' />
|
||||
</button>
|
||||
</h3>
|
||||
{this.renderEncounters()}
|
||||
|
||||
<div className='controls'>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,53 @@
|
||||
.encounters{
|
||||
|
||||
.encounters{
|
||||
margin-bottom : 20px;
|
||||
h3{
|
||||
background-color : @red;
|
||||
color : white;
|
||||
button{
|
||||
.animate(color);
|
||||
float : right;
|
||||
cursor : pointer;
|
||||
background-color : transparent;
|
||||
border : none;
|
||||
outline : none;
|
||||
&:hover{
|
||||
color : white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.encounter{
|
||||
position : relative;
|
||||
padding-left : 15px;
|
||||
border-left : 0px solid @teal;
|
||||
.animateAll();
|
||||
&:hover{
|
||||
i.remove{
|
||||
opacity : 1;
|
||||
}
|
||||
}
|
||||
i.remove{
|
||||
.animate(opacity);
|
||||
position : absolute;
|
||||
top : 3px;
|
||||
right : 3px;
|
||||
cursor : pointer;
|
||||
opacity : 0;
|
||||
font-size : 0.6em;
|
||||
color : #333;
|
||||
&:hover{
|
||||
color : @red;
|
||||
}
|
||||
}
|
||||
i.select{
|
||||
cursor : pointer;
|
||||
}
|
||||
.jsonFileEditor{
|
||||
display : inline-block;
|
||||
}
|
||||
&.selected{
|
||||
//background-color : fade(@green, 30%);
|
||||
border-left : 8px solid @teal;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,16 +40,8 @@ var Sidebar = React.createClass({
|
||||
})
|
||||
},
|
||||
|
||||
handleJSONChange : function(encounterIndex, json){
|
||||
this.props.onJSONChange(encounterIndex, json);
|
||||
},
|
||||
handleSelectEncounter : function(encounterIndex){
|
||||
this.props.onSelectEncounter(encounterIndex);
|
||||
},
|
||||
handleRemoveEncounter : function(encounterIndex){
|
||||
this.props.onRemoveEncounter(encounterIndex);
|
||||
},
|
||||
|
||||
/*
|
||||
renderEncounters : function(){
|
||||
var self = this;
|
||||
|
||||
@@ -74,7 +66,7 @@ var Sidebar = React.createClass({
|
||||
</div>
|
||||
})
|
||||
},
|
||||
|
||||
*/
|
||||
render : function(){
|
||||
var self = this;
|
||||
return(
|
||||
@@ -82,7 +74,8 @@ var Sidebar = React.createClass({
|
||||
<div className='logo'>
|
||||
<svg onClick={this.handleLogoClick} version="1.1" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100"><path d="M80.644,87.982l16.592-41.483c0.054-0.128,0.088-0.26,0.108-0.394c0.006-0.039,0.007-0.077,0.011-0.116 c0.007-0.087,0.008-0.174,0.002-0.26c-0.003-0.046-0.007-0.091-0.014-0.137c-0.014-0.089-0.036-0.176-0.063-0.262 c-0.012-0.034-0.019-0.069-0.031-0.103c-0.047-0.118-0.106-0.229-0.178-0.335c-0.004-0.006-0.006-0.012-0.01-0.018L67.999,3.358 c-0.01-0.013-0.003-0.026-0.013-0.04L68,3.315V4c0,0-0.033,0-0.037,0c-0.403-1-1.094-1.124-1.752-0.976 c0,0.004-0.004-0.012-0.007-0.012C66.201,3.016,66.194,3,66.194,3H66.19h-0.003h-0.003h-0.004h-0.003c0,0-0.004,0-0.007,0 s-0.003-0.151-0.007-0.151L20.495,15.227c-0.025,0.007-0.046-0.019-0.071-0.011c-0.087,0.028-0.172,0.041-0.253,0.083 c-0.054,0.027-0.102,0.053-0.152,0.085c-0.051,0.033-0.101,0.061-0.147,0.099c-0.044,0.036-0.084,0.073-0.124,0.113 c-0.048,0.048-0.093,0.098-0.136,0.152c-0.03,0.039-0.059,0.076-0.085,0.117c-0.046,0.07-0.084,0.145-0.12,0.223 c-0.011,0.023-0.027,0.042-0.036,0.066L2.911,57.664C2.891,57.715,3,57.768,3,57.82v0.002c0,0.186,0,0.375,0,0.562 c0,0.004,0,0.004,0,0.008c0,0,0,0,0,0.002c0,0,0,0,0,0.004v0.004v0.002c0,0.074-0.002,0.15,0.012,0.223 C3.015,58.631,3,58.631,3,58.633c0,0.004,0,0.004,0,0.008c0,0,0,0,0,0.002c0,0,0,0,0,0.004v0.004c0,0,0,0,0,0.002v0.004 c0,0.191-0.046,0.377,0.06,0.545c0-0.002-0.03,0.004-0.03,0.004c0,0.004-0.03,0.004-0.03,0.004c0,0.002,0,0.002,0,0.002 l-0.045,0.004c0.03,0.047,0.036,0.09,0.068,0.133l29.049,37.359c0.002,0.004,0,0.006,0.002,0.01c0.002,0.002,0,0.004,0.002,0.008 c0.006,0.008,0.014,0.014,0.021,0.021c0.024,0.029,0.052,0.051,0.078,0.078c0.027,0.029,0.053,0.057,0.082,0.082 c0.03,0.027,0.055,0.062,0.086,0.088c0.026,0.02,0.057,0.033,0.084,0.053c0.04,0.027,0.081,0.053,0.123,0.076 c0.005,0.004,0.01,0.008,0.016,0.01c0.087,0.051,0.176,0.09,0.269,0.123c0.042,0.014,0.082,0.031,0.125,0.043 c0.021,0.006,0.041,0.018,0.062,0.021c0.123,0.027,0.249,0.043,0.375,0.043c0.099,0,0.202-0.012,0.304-0.027l45.669-8.303 c0.057-0.01,0.108-0.021,0.163-0.037C79.547,88.992,79.562,89,79.575,89c0.004,0,0.004,0,0.004,0c0.021,0,0.039-0.027,0.06-0.035 c0.041-0.014,0.08-0.034,0.12-0.052c0.021-0.01,0.044-0.019,0.064-0.03c0.017-0.01,0.026-0.015,0.033-0.017 c0.014-0.008,0.023-0.021,0.037-0.028c0.14-0.078,0.269-0.174,0.38-0.285c0.014-0.016,0.024-0.034,0.038-0.048 c0.109-0.119,0.201-0.252,0.271-0.398c0.006-0.01,0.016-0.018,0.021-0.029c0.004-0.008,0.008-0.017,0.011-0.026 c0.002-0.004,0.003-0.006,0.005-0.01C80.627,88.021,80.635,88.002,80.644,87.982z M77.611,84.461L48.805,66.453l32.407-25.202 L77.611,84.461z M46.817,63.709L35.863,23.542l43.818,14.608L46.817,63.709z M84.668,40.542l8.926,5.952l-11.902,29.75 L84.668,40.542z M89.128,39.446L84.53,36.38l-6.129-12.257L89.128,39.446z M79.876,34.645L37.807,20.622L65.854,6.599L79.876,34.645 z M33.268,19.107l-6.485-2.162l23.781-6.487L33.268,19.107z M21.92,18.895l8.67,2.891L10.357,47.798L21.92,18.895z M32.652,24.649 l10.845,39.757L7.351,57.178L32.652,24.649z M43.472,67.857L32.969,92.363L8.462,60.855L43.472,67.857z M46.631,69.09l27.826,17.393 l-38.263,6.959L46.631,69.09z"></path></svg>
|
||||
<span className='name'>
|
||||
Natural<span className='crit'>Crit</span>
|
||||
<div>Natural<span className='crit'>Crit</span></div>
|
||||
<small>Combat Manager</small>
|
||||
</span>
|
||||
</div>
|
||||
<div className='contents'>
|
||||
@@ -95,21 +88,16 @@ var Sidebar = React.createClass({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='encounterContainer'>
|
||||
<h3>
|
||||
<i className='fa fa-flag' /> Encounters
|
||||
<button className='addEncounter'>
|
||||
<i className='fa fa-plus' />
|
||||
</button>
|
||||
</h3>
|
||||
{this.renderEncounters()}
|
||||
|
||||
<div className='controls'>
|
||||
<Encounters
|
||||
encounters={this.props.encounters}
|
||||
selectedEncounter={this.props.selectedEncounter}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
onJSONChange={this.props.onJSONChange}
|
||||
onSelectEncounter={this.props.onSelectEncounter}
|
||||
onRemoveEncounter={this.props.onRemoveEncounter}
|
||||
|
||||
<Encounters />
|
||||
/>
|
||||
|
||||
<div className='addPlayers'>
|
||||
<h3> <i className='fa fa-group' /> Players </h3>
|
||||
|
||||
@@ -45,12 +45,20 @@
|
||||
span.name{
|
||||
.animateAll();
|
||||
position : absolute;
|
||||
top : 13px;
|
||||
top : 15px;
|
||||
left : 50px;
|
||||
opacity : 1;
|
||||
font-size: 0.9em;
|
||||
line-height: 0.5em;
|
||||
span.crit{
|
||||
font-family : 'CodeBold';
|
||||
}
|
||||
small{
|
||||
font-size: 0.3em;
|
||||
font-family : 'Open Sans';
|
||||
font-weight: 800;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
.contents{
|
||||
@@ -66,49 +74,6 @@
|
||||
font-weight : 800;
|
||||
text-transform : uppercase;
|
||||
}
|
||||
.encounterContainer{
|
||||
margin-bottom : 20px;
|
||||
h3{
|
||||
background-color : @red;
|
||||
color : white;
|
||||
|
||||
button{
|
||||
outline: none;
|
||||
border : none;
|
||||
cursor: pointer;
|
||||
background-color: transparent;
|
||||
.animate(color);
|
||||
float : right;
|
||||
&:hover{
|
||||
color : white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.encounter{
|
||||
padding-left: 20px;
|
||||
position: relative;
|
||||
i.remove{
|
||||
position: absolute;
|
||||
top : 3px;
|
||||
right : 3px;
|
||||
font-size: 0.6em;
|
||||
cursor: pointer;
|
||||
color : #333;
|
||||
&:hover{
|
||||
color: @red;
|
||||
}
|
||||
}
|
||||
i.select{
|
||||
cursor: pointer;
|
||||
}
|
||||
.jsonFileEditor{
|
||||
display: inline-block;
|
||||
}
|
||||
&.selected{
|
||||
background-color : fade(@green, 30%);
|
||||
}
|
||||
}
|
||||
}
|
||||
.addPlayers{
|
||||
h3{
|
||||
color : white;
|
||||
@@ -121,12 +86,5 @@
|
||||
}
|
||||
}
|
||||
|
||||
.dmDice{
|
||||
h3{
|
||||
color : white;
|
||||
background-color: @teal;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,9 @@
|
||||
.jsonEditor{
|
||||
display : initial;
|
||||
}
|
||||
button.showEditor{
|
||||
color: @red;
|
||||
}
|
||||
}
|
||||
.jsonEditor{
|
||||
position : absolute;
|
||||
@@ -26,9 +29,6 @@
|
||||
.controls{
|
||||
display: inline-block;
|
||||
float: right;
|
||||
//position : absolute;
|
||||
//top : 0px;
|
||||
//right : 0px;
|
||||
|
||||
button{
|
||||
outline: none;
|
||||
|
||||
Reference in New Issue
Block a user