Browse Source

Add monster functionality, but still needs HTML work

master
Josh Gordon 3 years ago
parent
commit
080cb0d9dc
  1. 3
      Monsters/apocrypha.txt
  2. 5
      Monsters/matryoshka.txt
  3. 7
      Monsters/pirate_skirmisher.txt
  4. 8
      Monsters/reverse_mimic.txt
  5. 7
      app/items.py
  6. 110
      app/monsters.py
  7. 6
      app/routes.py
  8. 1
      app/templates/index.html
  9. 16
      app/templates/monsters.html

3
Monsters/apocrypha.txt

@ -18,8 +18,7 @@ Int: 2
Wis: 8
Cha: 6
Sense: Darkvision 60ft
Sense: Passive Perception 9
Senses: Darkvision 60ft,Passive Perception 9
Descript {
Apocrypha resemble regular books, generally of the large dusty tome variety, although with several key differences.

5
Monsters/matryoshka.txt

@ -1,7 +1,7 @@
Matryoshka
----------
CR 7
CR: 7
Size: Special (values given here are for large)
Type: Construct
@ -18,8 +18,7 @@ Int: 10
Wis: 10
Cha: 10
Sense: Darkvision 60ft
Sense: Passive Perception 10
Senses: Darkvision 60ft, Passive Perception 10
Resist: Magic
Immune: Nonmagic Physical

7
Monsters/pirate_skirmisher.txt

@ -1,7 +1,7 @@
Pirate Skirmisher
-----------------
CR 1/2
CR: 1/2
Size: Medium
Type: Humanoid
@ -18,8 +18,7 @@ Int: 8
Wis: 10
Cha: 9
Sense: Vision 60ft
Sense: Passive Perception 10
Senses: Vision 60ft, Passive Perception 10
Descript {
Your average pirate crewmember. Loyal to the captain as long as they're paid, and willing to plunder and pillage.
@ -42,7 +41,7 @@ Actions {
}
}
Note {
Notes {
You need to go to town with the voices for these guys.
Use a large crew for a pirate ship also. These guys are not very strong, but the pistols add up.

8
Monsters/reverse_mimic.txt

@ -1,7 +1,7 @@
Reverse Mimic
-------------
CR ?
CR: ?
Size: Medium
Type: Monstrosity
@ -18,8 +18,7 @@ Int: 10
Wis: 13
Cha: 8
Sense: Darkvision 60ft
Sense: Passive Perception 11
Senses: Darkvision 60ft, Passive Perception 11
Immune: acid
@ -35,6 +34,9 @@ Actions {
Damage 1d8+3
}
Transform {
Hit 0
Reach 0
Damage 0
Special {
Select an inanimate object of size at most medium. Over the course of the next 10 minutes, the object transforms to appear like one creature you have seen before. You determine the pose and expression of the creature, however it cannot move. This lasts for 24 hours.
}

7
app/items.py

@ -1,4 +1,5 @@
import glob
from monsters import Monster
def parse_headers(spell_text):
"""Takes in the 'tail' part of a spell file"""
@ -41,3 +42,9 @@ def get_worlds():
world_list.append(fname.split("/")[-1])
return world_list
def get_monsters():
monster_list = []
for fname in glob.glob("../Monsters/*"):
m = Monster(fname)
monster_list.append(m)
return monster_list

110
app/monsters.py

@ -0,0 +1,110 @@
MONSTER_PROPS = ["CR","Size","Type","Align","AC","HP","Speed","Str","Dex","Con","Int","Wis","Cha","Senses","Resist","Immune","Weak"] #properties must appear in this order... for now
def getProperty(strs,prop):
lineData = strs[0].split(":")
if lineData[0] == prop:
return lineData[1]
return None
class MonsterAction(object):
def __init__(self):
self.name = ""
self.hit = ""
self.reach = -1
self.damage = ""
self.special = ""
def parse(self,text):
#assumes first line is first opening brace of action
#and last line is last closing brace of action
lines = [line.strip() for line in text.split("\n") if line]
self.name = lines[0][:-1].strip()
self.hit = lines[1].split(" ")[1:]
self.reach = lines[2].split(" ")[1]
self.damage = lines[3].split(" ")[1]
if len(lines) > 4:
if "Special" in lines[4]:
i = 1
while not "}" in lines[i]:
self.special += lines[i] + "\n"
i += 1
def __str__(self):
return str(self.__dict__)
class Monster(object):
def __init__(self,fpath):
with open(fpath,'r') as f:
text = list(filter(bool,f.read().split("\n")))
self.name = text.pop(0)
text.pop(0) #clear ------
for p in MONSTER_PROPS:
prop = getProperty(text,p)
if prop:
text.pop(0)
setattr(self,p,prop)
#now for brace parsing
self.descript = ""
if "Descript" in text[0]:
text.pop(0)
while not "}" in text[0]:
self.descript += text[0] + "\n"
text.pop(0)
text.pop(0) #remove last }
if "Actions" in text[0]:
self.actions = []
#print("Debug: parsing actions")
text.pop(0)
parenCount = 1
actionBuffer = ""
while parenCount >= 1:
actionBuffer += text[0]+"\n"
if "{" in text[0]:
parenCount += 1
#print("Upping paren count")
if "}" in text[0]:
parenCount -= 1
#print("Downing paren count")
if parenCount == 1:
#print("Making action")
a = MonsterAction()
a.parse(actionBuffer)
self.actions.append(a)
#print("Made action out of")
#print(''.join(actionBuffer))
actionBuffer = ""
#print("Reading line")
text.pop(0)
#we do not need to remove last brace here, as it is consumed by the loop this time
if "Notes" in text[0]:
text.pop(0)
self.notes = ""
while not "}" in text[0]:
self.notes += text[0] + "\n"
text.pop(0)
text.pop(0) #remove last }
if len(text) > 0:
print("Unparsed: ")
print(text)
def __str__(self):
return str(self.__dict__).replace("\',","\'\n")
#driver code
#m = Monster("../Monsters/reverse_mimic.txt")
#print(m)
#m = Monster("../Monsters/apocrypha.txt")
#print(m)
#m = Monster("../Monsters/matryoshka.txt")
#print(m)
#m = Monster("../Monsters/pirate_skirmisher.txt")
#print(m)

6
app/routes.py

@ -2,7 +2,7 @@ import sys
from flask import Flask, render_template, request, redirect
from items import get_items, get_worlds
from items import get_items, get_worlds, get_monsters
from random import choice, sample
@ -154,5 +154,9 @@ bucket_route('characters', 'Characters')
bucket_route('spells', 'Spells')
bucket_route('feats', 'Feats')
@app.route("/monsters")
def render_monsters():
return render_template('monsters.html',monsters=get_monsters())
if __name__ == "__main__":
app.run()

1
app/templates/index.html

@ -19,6 +19,7 @@
<li><a href="/characters">Characters</a></li>
<li><a href="/spells">Spells</a></li>
<li><a href="/feats">Feats</a></li>
<li><a href="/monsters">Monsters</a></li>
</ul>
</nav>

16
app/templates/monsters.html

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block content %}
<h2>Monsters</h2>
<ul class="headlist special">
<li><a href="monsters/random">Random</a></li>
</ul>
<ul class="headlist">
{% for monster in monsters %}
<li><a href="#{{monster.name}}">{{monster.name}}</a> {% if not loop.last %} &middot; {% endif %} </li>
{% endfor %}
</ul>
{% endblock %}
Loading…
Cancel
Save