Beginning to add DB backend
This commit is contained in:
commit
acb3621146
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Python
|
||||||
|
*.py[co]
|
||||||
|
|
||||||
|
# Vim
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Virtualenv
|
||||||
|
bin
|
||||||
|
data
|
||||||
|
include
|
||||||
|
lib
|
||||||
|
lib64
|
||||||
|
__pycache__
|
||||||
|
share
|
||||||
|
pyvenv.cfg
|
26
acks/__init__.py
Normal file
26
acks/__init__.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
def create_app():
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
# Prep the database
|
||||||
|
from acks.models import db
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///../data/acks.db'
|
||||||
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
db.init_app(app)
|
||||||
|
|
||||||
|
# Load our views
|
||||||
|
from acks.views import default_views
|
||||||
|
app.register_blueprint(default_views)
|
||||||
|
|
||||||
|
from acks.npc.views import npc_views
|
||||||
|
app.register_blueprint(npc_views)
|
||||||
|
|
||||||
|
# Load our CLI commands
|
||||||
|
from acks.commands import default_cli
|
||||||
|
app.cli.add_command(default_cli)
|
||||||
|
|
||||||
|
from acks.npc.commands import npc_cli
|
||||||
|
app.cli.add_command(npc_cli)
|
||||||
|
|
||||||
|
return app
|
13
acks/commands.py
Normal file
13
acks/commands.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import click
|
||||||
|
from flask.cli import AppGroup
|
||||||
|
|
||||||
|
from acks.models import db
|
||||||
|
|
||||||
|
default_cli = AppGroup('acks')
|
||||||
|
|
||||||
|
@default_cli.command('initdb')
|
||||||
|
def initialize_database():
|
||||||
|
from acks import models
|
||||||
|
from acks.npc import models
|
||||||
|
db.create_all()
|
||||||
|
|
10
acks/models.py
Normal file
10
acks/models.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
class BaseModel(db.Model):
|
||||||
|
__abstract__ = True
|
||||||
|
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
created_at = db.Column(db.DateTime)
|
184
acks/npc/commands.py
Normal file
184
acks/npc/commands.py
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import click
|
||||||
|
from flask.cli import AppGroup
|
||||||
|
|
||||||
|
from ..models import db
|
||||||
|
|
||||||
|
|
||||||
|
npc_cli = AppGroup('npc')
|
||||||
|
|
||||||
|
@npc_cli.command('create classes')
|
||||||
|
def create_classes():
|
||||||
|
from .models import CharacterClass
|
||||||
|
|
||||||
|
classes = []
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Elven Nightblade',
|
||||||
|
bucket = 'Demi-Human',
|
||||||
|
prime_requisite = 'D+I',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 11,
|
||||||
|
armour_modifier = -4,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 2,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 0,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Elven Spellsword',
|
||||||
|
bucket = 'Demi-Human',
|
||||||
|
prime_requisite = 'S+I',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 10,
|
||||||
|
armour_modifier = -4,
|
||||||
|
melee_light = 0,
|
||||||
|
melee_medium = 1,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 0,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Explorer',
|
||||||
|
bucket = 'Campaign',
|
||||||
|
prime_requisite = 'S+D',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = -3,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 1,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 0,
|
||||||
|
ranged_heavy = 1
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Bladedancer',
|
||||||
|
bucket = 'Campaign',
|
||||||
|
prime_requisite = 'W+D',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = -2,
|
||||||
|
melee_light = 0,
|
||||||
|
melee_medium = 1,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 0,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Cleric',
|
||||||
|
bucket = 'Core',
|
||||||
|
prime_requisite = 'WIS',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = 0,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 3,
|
||||||
|
melee_heavy = 1,
|
||||||
|
ranged_light = 1,
|
||||||
|
ranged_heavy = 3
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Fighter',
|
||||||
|
bucket = 'Core',
|
||||||
|
prime_requisite = 'STR',
|
||||||
|
hit_die_size = 8,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = 1,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 4,
|
||||||
|
melee_heavy = 1,
|
||||||
|
ranged_light = 1,
|
||||||
|
ranged_heavy = 1
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Thief',
|
||||||
|
bucket = 'Core',
|
||||||
|
prime_requisite = 'DEX',
|
||||||
|
hit_die_size = 4,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = -6,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 1,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 1,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Mage',
|
||||||
|
bucket = 'Core',
|
||||||
|
prime_requisite = 'INT',
|
||||||
|
hit_die_size = 4,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = -8,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 0,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 0,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Assassin',
|
||||||
|
bucket = 'Campaign',
|
||||||
|
prime_requisite = 'S+D',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = -6,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 2,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 1,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Bard',
|
||||||
|
bucket = 'Campaign',
|
||||||
|
prime_requisite = 'D+H',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 14,
|
||||||
|
armour_modifier = -3,
|
||||||
|
melee_light = 1,
|
||||||
|
melee_medium = 2,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 1,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Dwarven Vaultguard',
|
||||||
|
bucket = 'Demi-Human',
|
||||||
|
prime_requisite = 'STR',
|
||||||
|
hit_die_size = 8,
|
||||||
|
maximum_level = 13,
|
||||||
|
armour_modifier = -1,
|
||||||
|
melee_light = 0,
|
||||||
|
melee_medium = 3,
|
||||||
|
melee_heavy = 1,
|
||||||
|
ranged_light = 1,
|
||||||
|
ranged_heavy = 1
|
||||||
|
))
|
||||||
|
|
||||||
|
classes.append(CharacterClass(
|
||||||
|
name = 'Dwarven Craftpriest',
|
||||||
|
bucket = 'Demi-Human',
|
||||||
|
prime_requisite = 'WIS',
|
||||||
|
hit_die_size = 6,
|
||||||
|
maximum_level = 10,
|
||||||
|
armour_modifier = -2,
|
||||||
|
melee_light = 0,
|
||||||
|
melee_medium = 1,
|
||||||
|
melee_heavy = 0,
|
||||||
|
ranged_light = 1,
|
||||||
|
ranged_heavy = 0
|
||||||
|
))
|
||||||
|
|
||||||
|
db.session.bulk_save_objects(classes)
|
||||||
|
db.session.commit()
|
23
acks/npc/models.py
Normal file
23
acks/npc/models.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from ..models import db, BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class CharacterClass(BaseModel):
|
||||||
|
__tablename__ = 'character_class'
|
||||||
|
|
||||||
|
name = db.Column(db.String(50), unique=True, nullable=False)
|
||||||
|
bucket = db.Column(db.String(50))
|
||||||
|
|
||||||
|
prime_requisite = db.Column(db.String(3))
|
||||||
|
hit_die_size = db.Column(db.Integer)
|
||||||
|
maximum_level = db.Column(db.Integer)
|
||||||
|
|
||||||
|
armour_modifier = db.Column(db.Integer)
|
||||||
|
melee_light = db.Column(db.Integer)
|
||||||
|
melee_medium = db.Column(db.Integer)
|
||||||
|
melee_heavy = db.Column(db.Integer)
|
||||||
|
ranged_light = db.Column(db.Integer)
|
||||||
|
ranged_heavy = db.Column(db.Integer)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '<CharacterClass {0}>'.format(self.name)
|
309
acks/npc/npc_party.py
Normal file
309
acks/npc/npc_party.py
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
from random import randint
|
||||||
|
|
||||||
|
|
||||||
|
def number_encountered():
|
||||||
|
return (randint(1, 4) + 2)
|
||||||
|
|
||||||
|
def npc_class():
|
||||||
|
roll = (randint(1, 6) + randint(1, 6) + randint(1, 6))
|
||||||
|
if roll == 3 or roll == 4:
|
||||||
|
return 'Elven Nightblade'
|
||||||
|
elif roll == 5:
|
||||||
|
return 'Elven Spellsword'
|
||||||
|
elif roll == 6:
|
||||||
|
return 'Explorer'
|
||||||
|
elif roll == 7:
|
||||||
|
return 'Bladedancer'
|
||||||
|
elif roll == 8:
|
||||||
|
return 'Cleric'
|
||||||
|
elif roll == 9 or roll == 10 or roll == 11:
|
||||||
|
return 'Fighter'
|
||||||
|
elif roll == 12:
|
||||||
|
return 'Thief'
|
||||||
|
elif roll == 13:
|
||||||
|
return 'Mage'
|
||||||
|
elif roll == 14:
|
||||||
|
return 'Assassin'
|
||||||
|
elif roll == 15:
|
||||||
|
return 'Bard'
|
||||||
|
elif roll == 16:
|
||||||
|
return 'Dwarven Vaultguard'
|
||||||
|
elif roll == 17 or roll == 18:
|
||||||
|
return 'Dwarven Craftpriest'
|
||||||
|
|
||||||
|
def npc_alignment():
|
||||||
|
roll = randint(1, 6)
|
||||||
|
if roll == 1 or roll == 2:
|
||||||
|
return 'Lawful'
|
||||||
|
elif roll == 3 or roll == 4 or roll == 5:
|
||||||
|
return 'Neutral'
|
||||||
|
elif roll == 6:
|
||||||
|
return 'Chaotic'
|
||||||
|
|
||||||
|
def npc_baselevel(base_level):
|
||||||
|
roll = randint(1, 6)
|
||||||
|
mod = 0
|
||||||
|
if roll == 1:
|
||||||
|
mod = -2
|
||||||
|
elif roll == 2:
|
||||||
|
mod = -1
|
||||||
|
elif roll == 3 or roll == 4:
|
||||||
|
mod = 0
|
||||||
|
elif roll == 5:
|
||||||
|
mod = 1
|
||||||
|
elif roll == 6:
|
||||||
|
mod = 2
|
||||||
|
|
||||||
|
base_level += mod
|
||||||
|
if base_level < 1:
|
||||||
|
base_level = 1
|
||||||
|
|
||||||
|
return base_level
|
||||||
|
|
||||||
|
def npc_abilities():
|
||||||
|
return [(randint(1, 6) + randint(1, 6) + randint(1, 6)) for x in range(0,6)]
|
||||||
|
|
||||||
|
def attribute_mod(atr):
|
||||||
|
mod = 0
|
||||||
|
|
||||||
|
if atr <= 3: mod = -3
|
||||||
|
if atr >= 4 and atr <= 5: mod = -2
|
||||||
|
if atr >= 6 and atr <= 8: mod = -1
|
||||||
|
if atr >= 9 and atr <= 12: mod = 0
|
||||||
|
if atr >= 13 and atr <= 15: mod = 1
|
||||||
|
if atr >= 16 and atr <= 17: mod = 2
|
||||||
|
if atr >= 18: mod = 3
|
||||||
|
|
||||||
|
return mod
|
||||||
|
|
||||||
|
|
||||||
|
npc_class_data = {
|
||||||
|
'Elven Nightblade': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': -4,
|
||||||
|
'melee': [0, 2, 1],
|
||||||
|
'ranged': [0, 0, 1]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Elven Spellsword': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': -4,
|
||||||
|
'melee': [0, 1, 0],
|
||||||
|
'ranged': [0, 0, 1]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Explorer': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': -3,
|
||||||
|
'melee': [0, 1, 1],
|
||||||
|
'ranged': [0, 1, 2]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Bladedancer': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': -2,
|
||||||
|
'melee': [0, 1, 0],
|
||||||
|
'ranged': [0, 0, 1]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Cleric': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': 0,
|
||||||
|
'melee': [1, 3, 1],
|
||||||
|
'ranged': [1, 3, 4]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Fighter': {
|
||||||
|
'hd': [1, 8],
|
||||||
|
'armour': 1,
|
||||||
|
'melee': [1, 4, 1],
|
||||||
|
'ranged': [1, 1, 4],
|
||||||
|
},
|
||||||
|
|
||||||
|
'Thief': {
|
||||||
|
'hd': [1, 4],
|
||||||
|
'armour': -6,
|
||||||
|
'melee': [0, 1, 1],
|
||||||
|
'ranged': [1, 0, 6]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Mage': {
|
||||||
|
'hd': [1, 4],
|
||||||
|
'armour': -8,
|
||||||
|
'melee': [0, 0, 1],
|
||||||
|
'ranged': [0, 0, 1]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Assassin': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': -6,
|
||||||
|
'melee': [0, 2, 1],
|
||||||
|
'ranged': [1, 0, 5]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Bard': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': -3,
|
||||||
|
'melee': [0, 2, 1],
|
||||||
|
'ranged': [1, 0, 4]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Dwarven Vaultguard': {
|
||||||
|
'hd': [1, 8],
|
||||||
|
'armour': -1,
|
||||||
|
'melee': [1, 3, 0],
|
||||||
|
'ranged': [1, 1, 6]
|
||||||
|
},
|
||||||
|
|
||||||
|
'Dwarven Craftpriest': {
|
||||||
|
'hd': [1, 6],
|
||||||
|
'armour': -2,
|
||||||
|
'melee': [0, 1, 0],
|
||||||
|
'ranged': [1, 0, 5]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
npc_armour_list = [
|
||||||
|
['Clothing Only', 0, 0],
|
||||||
|
['Hide and Fur Armour', 10, 1],
|
||||||
|
['Leather Armour', 20, 2],
|
||||||
|
['Ring Mail Armour', 30, 3],
|
||||||
|
['Scale Mail Armour', 30, 3],
|
||||||
|
['Chain Mail Armour', 40, 4],
|
||||||
|
['Banded Plate', 50, 5],
|
||||||
|
['Lamellar Armour', 50, 5],
|
||||||
|
['Plate Armour', 60, 6],
|
||||||
|
]
|
||||||
|
|
||||||
|
npc_melee_weapons_data = {
|
||||||
|
'light': [
|
||||||
|
['Club', 1, '1d4'],
|
||||||
|
['Dagger', 3, '1d4'],
|
||||||
|
['Sap', 1, '1d4'],
|
||||||
|
['Staff (1h)', 1, '1d4'],
|
||||||
|
['Staff (2h)', 1, '1d6'],
|
||||||
|
['Whip', 5, '1d2']
|
||||||
|
],
|
||||||
|
'medium': [
|
||||||
|
['Battle Axe (1h)', 7, '1d6'],
|
||||||
|
['Battle Axe (2h)', 7, '1d8'],
|
||||||
|
['Hand Axe', 4, '1d6'],
|
||||||
|
['Flail (1h)', 5, '1d6'],
|
||||||
|
['Flail (2h)', 5, '1d8'],
|
||||||
|
['Mace (1h)', 5, '1d6'],
|
||||||
|
['Mace (2h)', 5, '1d8'],
|
||||||
|
['War Hammer (1h)', 5, '1d6'],
|
||||||
|
['War Hammer (2h)', 5, '1d8'],
|
||||||
|
['Spear (1h)', 3, '1d6'],
|
||||||
|
['Spear (2h)', 3, '1d8'],
|
||||||
|
['Short Sword', 7, '1d6'],
|
||||||
|
['Sword (1h)', 10, '1d6'],
|
||||||
|
['Sword (2h)', 10, '1d8']
|
||||||
|
],
|
||||||
|
'heavy': [
|
||||||
|
['Great Axe (2h)', 10, '1d10'],
|
||||||
|
['Morning Star (2h)', 10, '1d10'],
|
||||||
|
['Pole Arm (2h)', 7, '1d10'],
|
||||||
|
['Two-Handed Sword (2h)', 15, '1d10']
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
npc_ranged_weapons_data = {
|
||||||
|
'light': [
|
||||||
|
['Crossbow', 30, '1d6'],
|
||||||
|
['Shortbow', 3, '1d6'],
|
||||||
|
['Javelin', 1, '1d6'],
|
||||||
|
],
|
||||||
|
'heavy': [
|
||||||
|
['Arbalest', 50, '1d8'],
|
||||||
|
['Composite Bow', 40, '1d6'],
|
||||||
|
['Longbow', 7, '1d6'],
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
def select_melee_weapon(guild):
|
||||||
|
melee = npc_class_data[guild]['melee']
|
||||||
|
weapons = []
|
||||||
|
for x in range(0, melee[0]):
|
||||||
|
weapons.extend(npc_melee_weapons_data['heavy'])
|
||||||
|
for x in range(0, melee[1]):
|
||||||
|
weapons.extend(npc_melee_weapons_data['medium'])
|
||||||
|
for x in range(0, melee[2]):
|
||||||
|
weapons.extend(npc_melee_weapons_data['light'])
|
||||||
|
|
||||||
|
selection = randint(0, len(weapons) - 1)
|
||||||
|
return weapons[selection]
|
||||||
|
|
||||||
|
def select_ranged_weapon(guild):
|
||||||
|
ranged = npc_class_data[guild]['ranged']
|
||||||
|
weapons = []
|
||||||
|
for x in range(0, ranged[0]):
|
||||||
|
weapons.extend(npc_ranged_weapons_data['light'])
|
||||||
|
for x in range(0, ranged[1]):
|
||||||
|
weapons.extend(npc_ranged_weapons_data['heavy'])
|
||||||
|
for x in range(0, ranged[2]):
|
||||||
|
weapons.append(None)
|
||||||
|
|
||||||
|
selection = randint(0, len(weapons) - 1)
|
||||||
|
return weapons[selection]
|
||||||
|
|
||||||
|
def generate_npc(base_level):
|
||||||
|
attributes = npc_abilities()
|
||||||
|
|
||||||
|
npc = {}
|
||||||
|
npc['guild'] = npc_class()
|
||||||
|
npc['level'] = npc_baselevel(base_level)
|
||||||
|
npc['str'] = attributes[0]
|
||||||
|
npc['int'] = attributes[1]
|
||||||
|
npc['wis'] = attributes[2]
|
||||||
|
npc['dex'] = attributes[3]
|
||||||
|
npc['con'] = attributes[4]
|
||||||
|
npc['chr'] = attributes[5]
|
||||||
|
|
||||||
|
npc['hp'] = 0
|
||||||
|
conmod = attribute_mod(npc['con'])
|
||||||
|
for x in range(0, npc['level']):
|
||||||
|
hitdice = [randint(1, npc_class_data[npc['guild']]['hd'][1]) for x in range(0, npc_class_data[npc['guild']]['hd'][0])]
|
||||||
|
for die in hitdice:
|
||||||
|
die += conmod
|
||||||
|
if die < 1:
|
||||||
|
die = 1
|
||||||
|
npc['hp'] += die
|
||||||
|
|
||||||
|
armourval = randint(0, len(npc_armour_list) - 1) + npc_class_data[npc['guild']]['armour']
|
||||||
|
if armourval < 0:
|
||||||
|
armourval = 0
|
||||||
|
if armourval > len(npc_armour_list) - 1:
|
||||||
|
armourval = len(npc_armour_list) - 1
|
||||||
|
npc['armour'] = npc_armour_list[armourval]
|
||||||
|
npc['melee'] = select_melee_weapon(npc['guild'])
|
||||||
|
npc['ranged'] = select_ranged_weapon(npc['guild'])
|
||||||
|
|
||||||
|
return npc
|
||||||
|
|
||||||
|
def create_party(base_level):
|
||||||
|
party_size = number_encountered()
|
||||||
|
return [generate_npc(base_level) for x in range(0, party_size)]
|
||||||
|
|
||||||
|
def print_party(party):
|
||||||
|
def print_npc(npc):
|
||||||
|
print('Level {0} NPC, {1}, {2} HP'.format(npc['level'], npc['guild'], npc['hp']))
|
||||||
|
print('{0} Str, {1} Int, {2} Wis, {3} Dex, {4} Con, {5} Chr'.format(
|
||||||
|
npc['str'], npc['int'], npc['wis'],
|
||||||
|
npc['dex'], npc['con'], npc['chr']
|
||||||
|
))
|
||||||
|
print('Armour Class: {0} - {1}, {2}gp'.format(npc['armour'][2], npc['armour'][0], npc['armour'][1]))
|
||||||
|
print('{:^16} - {:^10} - {:^10} - {:^10}'.format('Weapon', 'Gold', 'Throw Mod', 'Damage'))
|
||||||
|
print('-------------------------------------------------------')
|
||||||
|
print('{:^16} | {:^10} | {:^10} | {:^10}'.format(npc['melee'][0], npc['melee'][1], 0, npc['melee'][2]))
|
||||||
|
if npc['ranged']:
|
||||||
|
print('{:^16} | {:^10} | {:^10} | {:^10}'.format(npc['ranged'][0], npc['ranged'][1], 0, npc['ranged'][2]))
|
||||||
|
print('\n')
|
||||||
|
|
||||||
|
for npc in party:
|
||||||
|
print_npc(npc)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
party = create_party(2)
|
||||||
|
print_party(party)
|
122
acks/npc/templates/generate_npc_party.html
Normal file
122
acks/npc/templates/generate_npc_party.html
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}NPC Party Generation{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div>
|
||||||
|
<label for="base_level">Base level of party to generate: </label>
|
||||||
|
<input type="number" name="base_level" id="base_level" default="1">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button onclick="generateParty();">Generate</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
{% if party %}
|
||||||
|
<h3>NPC Party of Size {{ party | length }}</h3>
|
||||||
|
|
||||||
|
<div class="uk-grid-medium uk-grid-match" uk-grid>
|
||||||
|
{% for npc in party %}
|
||||||
|
<div class="acks-npc-card">
|
||||||
|
<div class="uk-card uk-card-body uk-card-default">
|
||||||
|
<h4 class="uk-card-title">{{ npc.guild }}</h4>
|
||||||
|
<div class="uk-card-badge uk-label">Level {{ npc.level }}</div>
|
||||||
|
<div class="uk-flex uk-flex-around uk-text-center uk-margin-bottom">
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.hp }}</div>
|
||||||
|
<div>HP</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.armour[2] }}</div>
|
||||||
|
<div>AC</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uk-flex uk-flex-around stat-block">
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.str }}</div>
|
||||||
|
<div>Str</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.int }}</div>
|
||||||
|
<div>Int</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.wis }}</div>
|
||||||
|
<div>Wis</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.dex }}</div>
|
||||||
|
<div>Dex</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.con }}</div>
|
||||||
|
<div>Con</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div>{{ npc.chr }}</div>
|
||||||
|
<div>Chr</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table class="uk-table uk-table-hover uk-table-small item-table">
|
||||||
|
<thead>
|
||||||
|
<tr> <th>Name</th><th>Worth</th><th>Thr</th><th>Dmg</th> </tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{{ npc.melee[0] }}</td>
|
||||||
|
<td>{{ npc.melee[1] }}gp</td>
|
||||||
|
<td>0</td>
|
||||||
|
<td>{{ npc.melee[2] }}</td>
|
||||||
|
</tr>
|
||||||
|
{% if npc.ranged %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ npc.ranged[0] }}</td>
|
||||||
|
<td>{{ npc.ranged[1] }}gp</td>
|
||||||
|
<td>0</td>
|
||||||
|
<td>{{ npc.ranged[2] }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ npc.armour[0] }}</td>
|
||||||
|
<td>{{ npc.armour[1] }}gp</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table.item-table, table.item-table th {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
div.stat-block > div {
|
||||||
|
text-align: center;
|
||||||
|
padding: 3px;
|
||||||
|
width: 26px;
|
||||||
|
}
|
||||||
|
div.stat-block > div > div:first-child {
|
||||||
|
font-weight: bold;
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
div.stat-block > div > div:last-child {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
div.acks-npc-card {
|
||||||
|
width: 370px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function generateParty() {
|
||||||
|
let bl = document.querySelector('#base_level').value;
|
||||||
|
window.location = "/npcparty/" + bl.toString();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
19
acks/npc/views.py
Normal file
19
acks/npc/views.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from flask import current_app, Blueprint, render_template
|
||||||
|
|
||||||
|
from .npc_party import create_party
|
||||||
|
|
||||||
|
|
||||||
|
npc_views = Blueprint(
|
||||||
|
'npc_views',
|
||||||
|
__name__,
|
||||||
|
template_folder='templates',
|
||||||
|
url_prefix='/npc'
|
||||||
|
)
|
||||||
|
|
||||||
|
@npc_views.route('/party')
|
||||||
|
@npc_views.route('/party/<int:base_level>')
|
||||||
|
def generate_npc_party(base_level=None):
|
||||||
|
party = None
|
||||||
|
if base_level:
|
||||||
|
party = create_party(base_level)
|
||||||
|
return render_template('generate_npc_party.html', party=party)
|
29
acks/templates/base.html
Normal file
29
acks/templates/base.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{% block title %}{% endblock %} - Atr0phy ACKS</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" contents="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.2.0/css/uikit.min.css" integrity="sha256-5YtK9j+Nl/245lAkSjrIs600d6edKTevi+3JYdjuHhY=" crossorigin="anonymous" />
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/uikit/3.2.0/js/uikit.min.js" integrity="sha256-rhLALrRmAQVu/OxzVDpQaiHAEMxiRSN8h8RDydUEh2g=" crossorigin="anonymous"></script>
|
||||||
|
{% block head %} {% endblock %}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="uk-navbar-container" uk-navbar>
|
||||||
|
<div class="uk-navbar-left">
|
||||||
|
<a href="" class="uk-navbar-item uk-logo">Atr0phy ACKS</a>
|
||||||
|
</div>
|
||||||
|
<div class="uk-navbar-center">
|
||||||
|
<ul class="uk-navbar-nav">
|
||||||
|
<li><a href="/handbook">Handbook</a></li>
|
||||||
|
<li class="uk-active"><a href="/npc/party">NPC Party</a></li>
|
||||||
|
<li><a href="">Treasure</a></li>
|
||||||
|
<li><a href="">Henchmen</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="uk-container">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
acks/templates/handbook.html
Normal file
24
acks/templates/handbook.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}ACKS Handbook{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div id="frame-container">
|
||||||
|
<iframe id="handbook-frame" src="https://atr0phy.net/acks/handbook"/>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<style>
|
||||||
|
#frame-container {
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
height: 85vh;
|
||||||
|
flex-direction: column:
|
||||||
|
}
|
||||||
|
#handbook-frame {
|
||||||
|
flex-grow: 1;
|
||||||
|
border: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
11
acks/templates/index.html
Normal file
11
acks/templates/index.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}ACKS Toolset Home{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block head %}
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
12
acks/views.py
Normal file
12
acks/views.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from flask import current_app, Blueprint, render_template
|
||||||
|
|
||||||
|
|
||||||
|
default_views = Blueprint('default_views', __name__, url_prefix='/')
|
||||||
|
|
||||||
|
@default_views.route('/')
|
||||||
|
def index():
|
||||||
|
return render_template('index.html')
|
||||||
|
|
||||||
|
@default_views.route('/handbook')
|
||||||
|
def handbook():
|
||||||
|
return render_template('handbook.html')
|
18
requirements.txt
Normal file
18
requirements.txt
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
ansi2html==1.5.2
|
||||||
|
cryptography==1.7.1
|
||||||
|
culour==0.1
|
||||||
|
enum34==1.1.6
|
||||||
|
idna==2.2
|
||||||
|
ipaddress==1.0.17
|
||||||
|
keyring==10.1
|
||||||
|
keyrings.alt==1.3
|
||||||
|
pudb==2018.1
|
||||||
|
pyasn1==0.1.9
|
||||||
|
pycrypto==2.6.1
|
||||||
|
Pygments==2.3.1
|
||||||
|
pygobject==3.22.0
|
||||||
|
pyxdg==0.25
|
||||||
|
SecretStorage==2.3.1
|
||||||
|
six==1.12.0
|
||||||
|
urwid==2.0.1
|
||||||
|
virtualenv==16.6.1
|
7
start.py
Normal file
7
start.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from acks import create_app
|
||||||
|
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run()
|
Loading…
x
Reference in New Issue
Block a user