You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
7.8 KiB
309 lines
7.8 KiB
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)
|