This commit is contained in:
Dennis Kerschus 2024-02-19 09:41:36 +01:00
commit 14f63c00a4
5 changed files with 700 additions and 0 deletions

476
input.txt Normal file
View File

@ -0,0 +1,476 @@
View all chat entries for this game »
Dennis:
24 + 4 19 + 4
20/60
Gauntlets of Midnight (+14)
30
Divine
21 + 4 31 + 4
20/60
Gauntlets of Midnight (+14)
20
Divine
32 + 2 26 + 2
20/60
Gauntlets of Midnight (+14)
29
Divine
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Zarkull against AC 27
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 44 | 29
Damage: 91bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Revered Ancient Vampire Spellcaster Bites at Healem All The Empowered against AC 28
Bite (Bat or Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 37 | 37
Damage: 51piercing + 51necrotic
The target's hit point maximum is reduced by an amount equal to the necrotic damage taken, and the vampire regains hit points equal to that amount. The reduction lasts until the target finishes a long rest. The target dies if this effect reduces its hit point maximum to 0. A humanoid slain in this way and then buried in the ground rises the following night as a vampire spawn under the vampire's control
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Zarkull against AC 27
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 28 | 35
Revered Ancient Vampire Spellcaster Claws at Zarkull against AC 27
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 41 | 39
Damage: 111bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Almighty GM (GM):
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 38 | 38
Damage: 67bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Revered Ancient Vampire Spellcaster Claws at Healem All The Empowered against AC 28
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 44 | 33
Damage: 94bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Healem All:
29 + 4 30 + 4
CONSTITUTION SAVE (12)
15 + 2 17 + 2
CONSTITUTION SAVE (12)
Almighty GM (GM) The night seems to go on forever
Almighty GM (GM):Web of Lilith
Almighty GM (GM) A huge spider web covers the area, all movement for the party is considered difficult terrain. This last one turn. Additionally, a random party member becomes entangled in the web and is incapcitated (until web is removed)
Almighty GM (GM):rolling 1d4
(
1
)
=1
Gynther halftooth:
16 + -2 21 + -2
arm of dawn, dormant (+14)
10
Great Weapon Master
23
Slashing
27 + -1 33 + -1
arm of dawn, dormant (+14)
10
Great Weapon Master
16 + 16
Slashing
16 + -1 19 + -1
arm of dawn, dormant (+14)
10
Great Weapon Master
18
Slashing
18 + -4 25 + -4
arm of dawn, dormant (+14)
10
Great Weapon Master
14
Slashing
32 + -3 19 + -3
arm of dawn, dormant (+14)
10
Great Weapon Master
16 + 8
Slashing
Almighty GM (GM):Revered Ancient Vampire Spellcaster Bites at Zarkull against AC 27
Bite (Bat or Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 41 | 33
Damage: 35piercing + 35necrotic
The target's hit point maximum is reduced by an amount equal to the necrotic damage taken, and the vampire regains hit points equal to that amount. The reduction lasts until the target finishes a long rest. The target dies if this effect reduces its hit point maximum to 0. A humanoid slain in this way and then buried in the ground rises the following night as a vampire spawn under the vampire's control
Revered Ancient Vampire Spellcaster Claws at Zarkull against AC 27
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 40 | 36
Damage: 91bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Gynther halftooth against AC 28
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 44 | 38
Damage: 92bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Revered Ancient Vampire Spellcaster Claws at Gynther halftooth against AC 28
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 35 | 33
Damage: 76bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 29 | 39
Gynther halftooth:
17 + -2 19 + -2
arm of dawn, dormant (+14)
10
Great Weapon Master
14
Slashing
24 + -3 21 + -3
arm of dawn, dormant (+14)
10
Great Weapon Master
21
Slashing
17 + -3 26 + -3
arm of dawn, dormant (+14)
10
Great Weapon Master
19
Slashing
28 + -3 20 + -3
arm of dawn, dormant (+14)
10
Great Weapon Master
11
Slashing
28 + -3 30 + -3
arm of dawn, dormant (+14)
10
Great Weapon Master
17
Slashing
Jonas:
37 + 2 35 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
47
Slashing
39
Radiant
23 + 4 30 + 4
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
45
Slashing
37
Radiant
24 + 4 23 + 4
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
50
Slashing
45
Radiant
25 + 2 27 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
37
Slashing
31
Radiant
23 + 4 23 + 4
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
57
Slashing
35
Radiant
36 + 2 33 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
43
Slashing
37
Radiant
Jonas:
35 + 2 28 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
59
Slashing
43
Radiant
38 + 1 32 + 1
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
50 + 20
Slashing
41 + 68
Radiant
32 + 2 31 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
55
Slashing
54
Radiant
26 + 4 23 + 4
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
38
Slashing
45
Radiant
29 + 2 38 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
49 + 24
Slashing
47 + 63
Radiant
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 30 | 32
Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 27 | 40
Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 44 | 29
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 32 | 37
Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 40 | 40
Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 41 | 44
Almighty GM (GM):
Damage: 92bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Damage: 83bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Gynther halftooth:
30 + -2 24 + -2
arm of dawn, dormant (+14)
10
Great Weapon Master
14
Slashing
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Mehtahl Whint against AC 35
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 44 | 40
Damage: 105bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Gynther halftooth:
25 + -4 31 + -4
arm of dawn, dormant (+14)
10
Great Weapon Master
20
Slashing
27 + -3 34 + -3
arm of dawn, dormant (+14)
10
Great Weapon Master
12 + 10
Slashing
31 + -1 28 + -1
arm of dawn, dormant (+14)
10
Great Weapon Master
11
Slashing
18 + -2 22 + -2
arm of dawn, dormant (+14)
10
Great Weapon Master
18
Slashing
34 + -3 20 + -3
arm of dawn, dormant (+14)
10
Great Weapon Master
21 + 5
Slashing
15 + -1 31 + -1
arm of dawn, dormant (+14)
10
Great Weapon Master
16
Slashing
Almighty GM (GM):Revered Ancient Vampire Spellcaster Claws at Gynther halftooth against AC 28
Unarmed Strike (Vampire Form Only)
Revered Ancient Vampire Spellcaster
Attack: 39 | 43
Damage: 77bludgeoning
Instead of dealing damage, the vampire can grapple the target, escape DC 28
Jonas:
24 + 4 41 + 4
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
50 + 25
Slashing
35 + 59
Radiant
42 + 2 31 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
46 + 26
Slashing
43 + 74
Radiant
40 + 2 26 + 2
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
53 + 38
Slashing
39 + 63
Radiant
31 + 3 26 + 3
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
42
Slashing
32
Radiant
25 + 4 27 + 4
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
48
Slashing
46
Radiant
28 + 1 38 + 1
Sword of Eternal Sunshine (+22)
On a hit:
Heals wielder for 25 hp
On a crit:
Heals a nearby ally for 25 hp
On kill:
Embrace of Darkness on wielder
46 + 34
Slashing
38 + 71
Radiant
Almighty GM (GM) The night seems to go on forever
Almighty GM (GM):Swarm of Bats
Almighty GM (GM) Bats! Bats! Bat's everywhere. Everyone in the party are attacked by bats, each taking damage
Almighty GM (GM):rolling 3d6
(
1
+
2
+
3
)
=6
What's New?
jan. 2024
The redesigned toolbar has leveled up and is ready for the final battle: serving all Roll20 users! Opt in to the Beta Features toggle if you'd like to keep testing features like Page Folders and the New Compendium Search.
Learn More
Chat Tips
Type these chat commands into the text box below then press the Enter key.
Dice Rolls
/roll 1d20 or /r 1d20
/gmroll 2d6>5 or /gr 2d6>5
Whisper a Player or Character
/w name message
/w gm message

2
requirements.txt Normal file
View File

@ -0,0 +1,2 @@
Flask
flask-WTF

172
roll20ChatParserMain.py Normal file
View File

@ -0,0 +1,172 @@
import os
import re
from typing import List
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField
from wtforms import DecimalField, RadioField, SelectField, TextAreaField, FileField, IntegerField
from wtforms.validators import InputRequired,DataRequired,length
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secretkey'
class MyForm(FlaskForm):
chatTekst = TextAreaField('Chat tekst', validators=[InputRequired()])
ac = IntegerField(label='Ac', validators=[InputRequired()])
advantage = BooleanField(label='Har advantage')
class Action:
def __init__(self) -> None:
self.Dam=[]
self.curActionValue=0
self.actionCounter=0
self.hit=[]
self.targetAc=0
self.advantage=0
def addActionValue(self,actionValue):
self.curActionValue=actionValue
def setActionTypeToDam(self,DamType):
self.Dam.append([self.actionCounter,self.curActionValue,DamType])
def setActionTypeToDam(self,value,DamType):
self.Dam.append([self.actionCounter,value,DamType])
def setActionTypeToHit(self,rul):
if(rul==1):
self.actionCounter=self.actionCounter+1
self.hit.append([self.actionCounter,rul,self.curActionValue])
def setActionTypeToHit(self,value,rul):
self.hit.append([self.actionCounter,rul,value])
def setTargetAc(self,ac):
self.targetAc=ac
def setWithAdvantage(self,advantage):
self.advantage=advantage
def getDamForHit(self):
dam=dict()
hits=False
if(self.advantage==False):
if(self.hit[0][2]>self.targetAc): #actioncounter styre hvilket rul er tale om
hits=1
if(self.advantage==True):
if(self.hit[0][2]>self.targetAc or self.hit[1][2]>self.targetAc): #actioncounter styre hvilket rul er tale om
hits=1
if(hits==1):
for d in self.Dam:
if(dam.get(d[2])==None):
dam[d[2]]=d[1]
else:
dam[d[2]]=dam[d[2]]+d[1]
return dam
damTypes=["Slashing","Radiant","Great Weapon Master","Divine","Holy Weapon","Great Weapon Master/Radiant"]
con=0
def incContext():
res=0
if(con==0):
con=1
res=1
con=con+1
if(con>2):
con=1
res=1
def getContext():
return con
def isItTheRightContext(c,line):
res=0
return res
def checkIfCounts(line):
estCon=0
if(re.match("(^_?[0-9]+){1}( \+ [0-9]+)?( [0-9]+( \+ [0-9])*)?", line)):
print("match : " + line)
estCon=1 # attackroll eller dam
return estCon
def getAllDamage(runder):
dam=dict()
dam['Samlet']=0
for r in runder:
print(r)
damage = r.getDamForHit()
for d in damage:
print(d)
if(dam.get(d)==None):
dam[d]=damage[d]
dam['Samlet']=dam['Samlet']+damage[d]
else:
dam[d]=dam[d]+damage[d]
dam['Samlet']=dam['Samlet']+damage[d]
return dam
def parseText(runder,lines,ac,advantage):
line=None
for nextLine in lines:
nextLine=nextLine.strip()
if(line==None):
line=nextLine
continue
print(line)
c=checkIfCounts(line)
if(c==1):
if(nextLine in damTypes):
c=2 # damage
else:
c=1 # to hit
if(c==1):
curAction=Action()
curAction.setTargetAc(ac)
curAction.setWithAdvantage(advantage)
h=line.split(" ")
if(h[0].rfind("+")>-1 or h[0].rfind("-")>-1):
if(h[0].rfind("+")>-1):
curAction.setActionTypeToHit(int(h[0].split("+")[0])+int(h[0].split("+")[1]),1)
else:
curAction.setActionTypeToHit(int(h[0].split("-")[0])-int(h[0].split("-")[1]),1)
else:
curAction.setActionTypeToHit(h[0])
if(h[1].rfind("+")>-1 or h[1].rfind("-")>-1):
if(h[1].rfind("+")>-1):
curAction.setActionTypeToHit(int(h[1].split("+")[0])+int(h[1].split("+")[1]),2)
else:
curAction.setActionTypeToHit(int(h[1].split("-")[0])-int(h[1].split("-")[1]),2)
else:
curAction.setActionTypeToHit(h[1],2)
runder.append(curAction)
if(c==2):
if(len(runder)==0):
continue
curAction=runder[len(runder)-1]
if(line.rfind("+")>-1 or line.rfind("-")>-1):
if(line.rfind("+")>-1):
curAction.setActionTypeToDam(int(line.split("+")[0])+int(line.split("+")[1]),nextLine)
else:
curAction.setActionTypeToDam(int(line.split("-")[0])+int(line.split("-")[1]),nextLine)
else:
curAction.setActionTypeToDam(int(line),nextLine)
line=nextLine
@app.route('/', methods=['GET', 'POST'])
def main():
form = MyForm()
runder: List[Action] = list()
if form.validate_on_submit():
parseText(runder,form.chatTekst.data.splitlines(),form.ac.data, form.advantage.data)
dam=getAllDamage(runder)
return render_template('index.html', dam=dam, form=form)
if __name__ == '__main__':
app.run()

17
templates/index.html Normal file
View File

@ -0,0 +1,17 @@
<html>
<head>
<title>Templating in Flask</title>
</head>
<body>
<h1>Dam {{ dam }} !</h1>
<p>Welcome to the world of Flask!</p>
<form method="post" action="/" enctype="multipart/form-data">
{{ form.csrf_token }}
<p>{{ form.ac.label }} {{ form.ac() }}</p>
<p>{{ form.advantage.label }} {{ form.advantage }}</p>
<p>{{ form.chatTekst.label }} {{ form.chatTekst(rows='40',cols='60') }}</p>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>

33
tmp.txt Normal file
View File

@ -0,0 +1,33 @@
from env import *
from flask import Flask, render_template
def create_app(test_config=None):
# create and configure the app
FlowAnalyserMain = Flask(__name__, instance_relative_config=True)
#app.config.from_mapping(
## SECRET_KEY='dev',
# DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
#)
if test_config is None:
# load the instance config, if it exists, when not testing
# FlowAnalyserMain.config.from_pyfile('config.py', silent=True)
else:
# load the test config if passed in
# FlowAnalyserMain.config.from_mapping(test_config)
# ensure the instance folder exists
@FlowAnalyserMain.context_processor
def inject_debug():
return dict(debug=FlowAnalyserMain.debug)
# a simple page that says hello
@FlowAnalyserMain.route('/')
def hello():
return FlowTest.test()
FlowAnalyserMain=create_app()