Skip to content

Commit

Permalink
Moar updates.
Browse files Browse the repository at this point in the history
  • Loading branch information
rob-allen committed Oct 6, 2017
1 parent a73a9d4 commit 400eed8
Show file tree
Hide file tree
Showing 14 changed files with 706 additions and 23 deletions.
6 changes: 5 additions & 1 deletion .angular-cli.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
"outDir": "dist",
"assets": [
"assets",
"favicon.ico"
"favicon.ico",
"crit-spell.json",
"crit-weapon.json",
"fumble-weapon.json",
"fumble-spell.json"
],
"index": "index.html",
"main": "main.ts",
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ website.

http://www.critter-5e.com/

# GitHub Repo

https://github.com/allenr98/critter-5e

## Development server

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"@angular/platform-browser": "^4.2.4",
"@angular/platform-browser-dynamic": "^4.2.4",
"@angular/router": "^4.2.4",
"bootstrap": "^4.0.0-alpha.6",
"core-js": "^2.4.1",
"font-awesome": "^4.7.0",
"rxjs": "^5.4.2",
"zone.js": "^0.8.14"
},
Expand Down
30 changes: 30 additions & 0 deletions src/app/app.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
body{margin:40px;}
.btn-circle {
width: 30px;
height: 30px;
text-align: center;
padding: 6px 0;
font-size: 12px;
line-height: 1.428571429;
border-radius: 15px;
}
.btn-circle.btn-lg {
width: 50px;
height: 50px;
padding: 13px 13px;
font-size: 18px;
line-height: 1.33;
border-radius: 25px;
}
.result-text {
font-size: 12px;
}

.flex, .flex > div[class*='col-'] {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
flex:1 0 auto;
}
121 changes: 103 additions & 18 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,105 @@
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
<img width="300" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
<div class="main-center-div">
<div style="text-align:center">
<h1>
Welcome to {{title}}!
</h1>
Based on the excellent D&D Fifth Edition critical success and failure charts by <a
href="http://www.questionablyqualified.com/dungeons-and-dragons/dnd-5e-crit-confirmed-critical-hit-charts-and-fumble-charts">Questionably
Qualified</a>.
</div>
<div id="allTheWords" class="collapse in" style="margin-top: 18px;">
<div>
<h2 style="margin-top: 18px;">The RAW(Rules as Written) Critical Hit Rules</h2>
<p>All critical hits and misses still follow the original 5e rules of rolling another set of the attacks damage
dice. This includes rolling extra dice for abilities that are a part of the attack such as damage from sneak
attack, hex, or the initial strike of green flame blade.</p>
<h2 style="margin-top: 18px;">Where The Tables Fit In</h2>
<p>These tables simply contain a list of additional effects that take place on top of the existing critical roll
rules.There are individual tables below for both weapon attacks and spell attacks because let's be honest, there
is a difference between missing with a bow and missing with a scorching ray.</p>
</div>
</div>
<div class="small" style="text-align: center;">
<a href="#" data-toggle="collapse" data-target="#allTheWords">Show/Hide App Info</a>
</div>
<div style="text-align: center;" class="form-container">
<form id="critForm" [formGroup]="rForm" (ngSubmit)="addPost(rForm.value)"
class="form-horizontal" method="post" action="">
<div class="form-group">
<h2 style="margin-top: 18px;">Choose the type of attack:</h2>
<div data-toggle="buttons">
<label class="btn btn-default btn-circle btn-lg active" (click)="selectAttackType('melee')"
data-toggle="tooltip" title="Melee Attack">
<input type="radio" name="selectedType" value="melee">
<i class="fa fa-gavel"></i>
</label>
<label class="btn btn-default btn-circle btn-lg" (click)="selectAttackType('ranged')"
data-toggle="tooltip" title="Ranged Attack">
<input type="radio" name="selectedType" value="ranged">
<i class="fa fa-crosshairs"></i>
</label>
<label class="btn btn-default btn-circle btn-lg" (click)="selectAttackType('spell')"
data-toggle="tooltip" title="Spell Attack">
<input type="radio" name="selectedType" value="spell">
<i class="fa fa-bolt"></i>
</label>
</div>
</div>
<div class="row form-group">
<button type="submit" class="btn btn-primary btn-default form-control result-text" (click)="selectFunction('critical')">Roll Critical Hit!</button>
<button type="submit" class="btn btn-secondary form-control result-text" (click)="selectFunction('fumble')">Roll Fumble!</button>
</div>
<div *ngIf="result?.description.length > 0" style="border-top: solid 1px;">
<div class="container-fluid">
<div class="row">
<div class="col-md-12" style="margin-top: 18px;">
<div class="panel panel-default panel-primary">
<div class="panel-heading" style="text-align: center;">
{{ selectedType }} - {{ selectedFunction }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 result-text flex-first">
<div class="panel panel-default panel-info">
<div class="panel-heading" style="text-align: center;">
<label>Roll</label>
</div>
<div class="panel-body" style="text-align: center;">
{{ roll }}
</div>
</div>
</div>
<div class="col-md-6 result-text flex-column">
<div class="panel panel-default panel-info">
<div class="panel-heading" style="text-align: center;">
<label>Description</label>
</div>
<div class="panel-body" style="text-align: center;">
{{ result.description }}
</div>
</div>
</div>
<div class="col-md-12 result-text flex-column">
<div class="panel panel-default panel-info">
<div class="panel-heading" style="text-align: center;">
<label>Effect</label>
</div>
<div class="panel-body">
{{ result.effect }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 result-text flex-last">
<button type="button" class="btn btn-outline-danger form-control result-text" (click)="clearResults()">Clear</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<h2><a target="_blank" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>

147 changes: 145 additions & 2 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,153 @@
import { Component } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import * as critical_data from '../assets/crit-weapon.json';
import * as fumble_data from '../assets/fumble-weapon.json';
import * as spell_critical_data from '../assets/crit-spell.json';
import * as spell_fumble_data from '../assets/fumble-spell.json';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
styleUrls: ['./app.component.css'],
})
export class AppComponent {
title = 'app';
title = '5e Critter';
rForm: FormGroup;
selectedType: 'melee';
selectedFunction: 'critical';
roll;
result;

critWeapon;
critSpell;
fumbleWeapon;
fumbleSpell;

static getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

constructor(private formBuilder: FormBuilder) {

this.critWeapon = (<any>critical_data);
this.fumbleWeapon = (<any>fumble_data);
this.critSpell = (<any>spell_critical_data);
this.fumbleSpell = (<any>spell_fumble_data);

this.rForm = formBuilder.group({
selectedType: 'melee',
result: '',
'validate': ''
});

}

addPost(formPost) {
if (!this.selectedType || this.selectedType == null ) {
this.selectedType = formPost.selectedType;
}
console.log('type: ', this.selectedType);
console.log('func: ', this.selectedFunction);

// Get a random number between 1 and 100
this.roll = AppComponent.getRandom(1, 100);
const crit = this.getResult(this.roll, this.selectedType, this.selectedFunction);
this.result = {
'description': crit.description,
'effect': crit.effect
};
}

getResult(roll, type, func) {
let returnValue = {
'roll': 'Invalid',
'description': 'Invalid roll',
'effect': 'Value: ' + roll
};

if (roll >= 1 || roll <= 100) {
if (func === 'critical') {
if (type === 'melee' || type === 'ranged') {
returnValue = this.findInList(roll, this.critWeapon);
} else if (type === 'spell') {
returnValue = this.findInList(roll, this.critSpell);
} else {
returnValue = {
'roll': 'Invalid',
'description': 'Invalid attack type',
'effect': 'Value: ' + type
};
}
} else if (func === 'fumble') {
if (type === 'melee' || type === 'ranged') {
returnValue = this.findInMultipurposeList(roll, this.fumbleWeapon, type);
} else if (type === 'spell') {
returnValue = this.findInList(roll, this.fumbleSpell);
} else {
returnValue = {
'roll': 'Invalid',
'description': 'Invalid attack type',
'effect': 'Value: ' + type
};
}
} else {
returnValue = {
'roll': 'Invalid',
'description': 'Invalid function selection',
'effect': 'Value: ' + func
};
}
}

return returnValue;
}

findInList(roll, list) {
let returnValue = {
'roll': 'n/a',
'description': 'Not found',
'effect': 'n/a'
};
list.forEach(item => {
const splitRange = item.roll.split('-');
if ( roll >= splitRange[0] && roll <= splitRange[1]) {
returnValue = item;
}
});

return returnValue;
}

findInMultipurposeList(roll, list, type) {
let returnValue = {
'roll': 'n/a',
'description': 'Not found',
'effect': 'n/a'
};
list.forEach(item => {
const splitRange = item.roll.split('-');
if ( roll >= splitRange[0] && roll <= splitRange[1] && (item.type === type || item.type === 'both')) {
returnValue = item;
}
});

return returnValue;
}

selectAttackType(value) {
this.selectedType = value;
this.result = {
'description': ''
};
}

selectFunction(value) {
this.selectedFunction = value;
}

clearResults() {
this.result = {
'description': ''
};
}
}
7 changes: 6 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
BrowserModule,
FormsModule,
HttpModule,
ReactiveFormsModule
],
providers: [],
bootstrap: [AppComponent]
Expand Down
Loading

0 comments on commit 400eed8

Please sign in to comment.