Skip to content
Snippets Groups Projects
Commit a31073bc authored by Martin Lehoux's avatar Martin Lehoux
Browse files

characters creation

parent 40747563
Branches
No related tags found
No related merge requests found
const express = require('express');
const fs = require('fs');
const session = require('express-session');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
......@@ -6,7 +7,7 @@ const morgan = require('morgan');
const mongoDBStore = require('connect-mongodb-session')(session);
// Config
const config = require('./config.json');
const config = require('js-yaml').safeLoad(fs.readFileSync('./config.yml', 'utf8'));
// Middlewares
const userLoader = require('./middlewares/userLoader');
const loginChecker = require('./middlewares/loginChecker');
......@@ -15,6 +16,7 @@ const render = require('./utils/render');
const { warn, error } = require('./utils/notifications');
// Routes
const authRouter = require('./routes/auth');
const charactersRouter = require('./routes/characters');
// Configuration
const app = express();
......@@ -36,14 +38,16 @@ app.use(session({
// Middlewares
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/media', express.static('media'));
app.use(userLoader);
app.use(loginChecker);
// Routes
app.get('/', (req, res) => {
app.get('/', async (req, res) => {
return render(req, res, 'home');
});
app.use('/auth', authRouter);
app.use('/characters', charactersRouter);
mongoose.connect('mongodb://localhost/rolegame', err => {
if (err) {
......
const changeAvatar = (avatar) => {
$('#avatar').attr('src', `/media/avatars/${avatar}`);
};
const attributes = {
'strength': 10,
'constitution': 10,
'dexterity': 10,
'intelligence': 10,
'wisdom': 10,
'charisma': 10
};
const costTable = {
7: -4,
8: -2,
9: -1,
10: 0,
11: 1,
12: 2,
13: 3,
14: 5,
15: 7,
16: 10,
17: 13,
18: 17
};
const getScore = () => Object.keys(attributes).reduce((total, el) => total + costTable[attributes[el]], 0);
const reduceAttribute = (attribute) => {
attributes[attribute] --;
if (attributes[attribute]<7) {
attributes[attribute] ++;
alert("You can't have attribute under 7.");
} else {
document.getElementById(attribute).innerText = attributes[attribute];
$(`#${attribute}-bar`).progress('decrement', 1);
document.getElementById('available-points').innerHTML = initAttributesPoints - getScore();
}
};
const augmentAttribute = (attribute) => {
attributes[attribute] ++;
if (getScore()>initAttributesPoints) {
attributes[attribute] --;
alert("Not enough points.");
} else if (attributes[attribute]>18) {
alert("You can't have attribute over 18.");
attributes[attribute] --;
} else {
document.getElementById(attribute).innerText = attributes[attribute];
$(`#${attribute}-bar`).progress('increment', 1);
document.getElementById('available-points').innerHTML = initAttributesPoints - getScore();
}
};
const createCharacter = () => {
const form = document.getElementById('create-character');
Object.keys(attributes).forEach(attribute => {
const input = document.createElement("input");
input.setAttribute("name", attribute);
input.setAttribute("value", attributes[attribute]);
input.setAttribute("type", "hidden");
form.appendChild(input);
});
form.submit();
};
const mongoose = require('mongoose');
const random = require('random');
const fs = require('fs');
const { maxActionPoints } = require('js-yaml').safeLoad(fs.readFileSync('./config.yml', 'utf8'));
const Character = new mongoose.Schema({
name: String,
level: Number,
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
name: { type: String, require: true },
avatar: { type: String },
birthDate: { type: Date, required: true, default: Date.now },
actionPoints: { type: Number, default: maxActionPoints, min: 0, max: maxActionPoints },
attributes: {
strength: { type: Number, default: 10 },
constitution: { type: Number, default: 10 },
dexterity: { type: Number, default: 10 },
intelligence: { type: Number, default: 10 },
wisdom: { type: Number, default: 10 },
charisma: { type: Number, default: 10 },
}
});
function randomAttribute() {
let dices = [];
let min = random.int(1,6);
for (let i = 0; i < 3; i++) {
let number = random.int(1,6);
if (number < min) {
dices.push(min);
min = number;
} else {
dices.push(number);
}
}
return dices.reduce((total, val) => total + val);
}
// Character.statics.generateCharacter = async function(name, userId, avatar) {
// const character = await this.create({
// name,
// user: userId,
// avatar,
// attributes: {
// strength: randomAttribute(),
// constitution: randomAttribute(),
// dexterity: randomAttribute(),
// intelligence: randomAttribute(),
// wisdom: randomAttribute(),
// charisma: randomAttribute(),
// }
// });
// return character;
// }
module.exports = mongoose.model('Character', Character);
\ No newline at end of file
const express = require('express');
const fs = require('fs');
const { initAttributesPoints, costTable, attributes, maxActionPoints, maxCharactersNumber } = require('js-yaml').safeLoad(fs.readFileSync('./config.yml', 'utf8'));
const Character = require('../models/character');
const render = require('../utils/render');
const { warn, error } = require('../utils/notifications');
const router = express.Router();
const getScore = (data) => Object.keys(data).reduce((total, el) => total + costTable[data[el]], 0);
router.get('/', async (req, res) => {
// TODO: Login required
const avatars = fs.readdirSync('media/avatars');
Character.find({ user: req.session.user._id }, (err, characters) => {
return render(req, res, 'characters', { characters, avatars, initAttributesPoints, maxActionPoints });
});
});
// router.post('/generate', async (req, res) => {
// // TODO: Login required
// if (!req.body.name) {
// return error(req, res, 'Name required');
// }
// const character = await Character.generateCharacter(req.body.name, req.session.user._id, req.body.avatar);
// return res.redirect('/characters');
// });
router.post('/create', async (req, res) => {
const validatedAttributes = attributes.reduce((obj, name) => {
obj[name] = Number(req.body[name]);
return obj;
}, {});
if (getScore(validatedAttributes) > initAttributesPoints || attributes.map(name => validatedAttributes[name]).some(value => value > 18 || value < 7)) {
return error(req, res, 'Bad form', "Character creation corrupted");
} else if (maxCharactersNumber <= await Character.countDocuments({ user: req.session.user._id })) {
return error(req, res, 'Too many characters', "You are not allowed to create one more character.");
}
await Character.create({
user: req.session.user._id,
name: req.body.name,
avatar: req.body.avatar,
attributes: validatedAttributes
});
res.redirect('/characters');
});
module.exports = router;
\ No newline at end of file
.ui.card.fluid
.content
img.right.floated.mini.image.ui(src="/media/avatars/"+character.avatar, alt="Avatar")
.header= character.name
.meta
.date Created on #{character.birthDate.toDateString()}
.ui.tiny.progress.yellow.progress.action-points(data-total=maxActionPoints, data-value=character.actionPoints)
.bar
.label #{character.actionPoints} action points
.content
.ui.label(class=character.attributes.strength<=8 ? "orange" : character.attributes.strength>=12 ? "green" : "" )
| Strength
.detail= character.attributes.strength
.ui.label(class=character.attributes.constitution<=8 ? "orange" : character.attributes.constitution>=12 ? "green" : "" )
| Constitution
.detail= character.attributes.constitution
.ui.label(class=character.attributes.dexterity<=8 ? "orange" : character.attributes.dexterity>=12 ? "green" : "" )
| Dexterity
.detail= character.attributes.dexterity
.ui.label(class=character.attributes.intelligence<=8 ? "orange" : character.attributes.intelligence>=12 ? "green" : "" )
| Intelligence
.detail= character.attributes.intelligence
.ui.label(class=character.attributes.wisdom<=8 ? "orange" : character.attributes.wisdom>=12 ? "green" : "" )
| Wisdom
.detail= character.attributes.wisdom
.ui.label(class=character.attributes.charisma<=8 ? "orange" : character.attributes.charisma>=12 ? "green" : "" )
| Charisma
.detail= character.attributes.charisma
extends base.pug
block main
.ui.cards
each character in characters
include character_summary.pug
button.ui.basic.teal.labeled.icon.button(onClick="$('.ui.modal').modal('show');")
| Create character
i.add.icon
.ui.modal
i.close.icon
.ui.header Create a new character
.ui.image.content
.ui.medium.image
img#avatar(src="/media/avatars/fazzlemare_by_charro_art_d8etbfa-pre.jpg", alt="Avatar")
.description
form.ui.form#create-character(name="create-character", action="/characters/create", method="post")
.ui.header Details
.ui.field
input#name(type="text", name="name", placeholder="name")
.ui.field
select#avatar-select.ui.selection.dropdown(name="avatar", onChange="changeAvatar($('select').dropdown('get value'))")
each avatar in avatars
option(value=avatar)= avatar
.ui.header Attributes:&nbsp
span#available-points= initAttributesPoints
| &nbsppoints remaining
.ui.grid
each attribute in ['strength', 'constitution', 'dexterity', 'intelligence', 'wisdom', 'charisma']
.eight.wide.column
.ui.segment
.ui.horizontal.statistic
.value(id=attribute) 10
.label= attribute
button.ui.button.orange.icon.circular.left.floated(type="button", onClick=`reduceAttribute('${attribute}')`)
i.minus.icon
button.ui.button.teal.icon.circular.right.floated(type="button", onClick=`augmentAttribute('${attribute}')`)
i.add.icon
.ui.bottom.attached.progress(id=attribute+"-bar")
.bar
.actions
button.ui.basic.orange.button.labeled.icon(type="reset", onClick="$('.ui.modal').modal('hide');")
i.close.icon
| Cancel
button.ui.teal.labeled.icon.button(type="submit", onClick="createCharacter()")
i.check.icon
| Create
script $('.ui.dropdown').dropdown();
script $('.ui.progress').progress({ total: 20, value: 10 });
script let initAttributesPoints = #{initAttributesPoints};
script(src="/media/script.js")
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment