Compare commits
18 Commits
Author | SHA1 | Date | |
---|---|---|---|
7a06e8a5c9 | |||
b4d6616cb4 | |||
aaef4dd896 | |||
a3c6509862 | |||
c2fe34e7a6 | |||
46176b2782 | |||
b7f13500a6 | |||
bd8b098b35 | |||
71d3f777bf | |||
157163672c | |||
a043117ec7 | |||
791a7d6b67 | |||
2ce5088471 | |||
ebb7bfe3d6 | |||
16959dd52e | |||
ccebf8dc1f | |||
a2364e1252 | |||
d961e130e0 |
20
README.md
20
README.md
@ -1,6 +1,20 @@
|
||||
|
||||
<h2><em>Lethal Fantasy RPG</em> for Foundry Virtual TableTop</h2>
|
||||
## Lethal Fantasy RPG for Foundry Virtual TableTop
|
||||
|
||||
<div align="center">
|
||||
The Official game system for playing Lethal Fantasy TTRPG: The Role Playing Game on FoundryVTT. This fully functional system is the foundational framework to build your game.
|
||||
|
||||
</div>
|
||||
This product's format, programming code, and presentation is copyrighted by Lethal Fantasy Games LLC.
|
||||
|
||||
This system & product are used with permission granted as part of the partnership agreement between Foundry Gaming LLC and Lethal Fantasy Games LLC. It uses the following trademarks and/or copyrights:
|
||||
|
||||
© 2025 Lethal Fantasy Games. Content copyright Ted McClintock, Lethal Fantasy Games LLC. All Rights Reserved. Lethal Fantasy® is a Registered Trademark of Lethal Fantasy Games LLC. All Rights Reserved.
|
||||
|
||||
Lethal Fantasy Games is ©2025 Lethal Fantasy Games, LLC. All rights reserved. Lethal Fantasy, Lethal Fantasy Games, and their associated logos are trademarks of Lethal Fantasy Games, LLC. https://lethalfantasy.com/
|
||||
|
||||
For inquiries on developing content for this ruleset please contact Lethalted@lethalfantasy.com
|
||||
|
||||
## Community
|
||||
|
||||
Please join our Discord server Lethal Fantasy games https://discord.gg/UDvnnyvreV
|
||||
|
||||
It's the place to ask questions on how to use the system, make feature request and follow the development of the system.
|
1
assets/icons/broken-heart.svg
Normal file
1
assets/icons/broken-heart.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M373.47 25.5c-33.475-.064-67.614 13.444-94.44 43.156l37.22 145.156-33.437.032 35.343 132.093-116.718-188.375 50.03 5.375L202.5 47.312C120.437-1.43 4.756 40.396 8.5 158.156c4.402 138.44 191.196 184.6 247.406 331.625 59.376-147.035 251.26-184.33 246.656-331.624-2.564-82.042-64.6-132.532-129.093-132.656z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 506 B |
@ -4,7 +4,7 @@
|
||||
}
|
||||
@font-face {
|
||||
font-family: "BaskervilleBold";
|
||||
src: url("../fonts/baskerville-bold.ttf") format("truetype");
|
||||
src: url("../assets/fonts/baskerville-bold.ttf") format("truetype");
|
||||
}
|
||||
:root {
|
||||
--font-primary: "TimesNewRoman", serif;
|
||||
@ -13,6 +13,16 @@
|
||||
--font-secondary: "BaskervilleBold", serif;
|
||||
--logo-standard: url("../assets/ui/lf_logo_small_02.webp");
|
||||
}
|
||||
.initiative-area {
|
||||
min-width: 8rem;
|
||||
max-width: 8rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.initiative-area input {
|
||||
min-width: 3rem;
|
||||
max-width: 3rem;
|
||||
}
|
||||
#logo {
|
||||
content: var(--logo-standard);
|
||||
width: 50px;
|
||||
@ -229,6 +239,10 @@ i.lethalfantasy {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.lethalfantasy .character-main .character-characteristics .character-characteristic span {
|
||||
min-width: 2.2rem;
|
||||
max-width: 2.2rem;
|
||||
}
|
||||
.lethalfantasy .character-main .character-characteristics .character-characteristic .rollable:hover,
|
||||
.lethalfantasy .character-main .character-characteristics .character-characteristic .rollable:focus {
|
||||
text-shadow: 0 0 8px var(--color-shadow-primary);
|
||||
@ -342,22 +356,22 @@ i.lethalfantasy {
|
||||
.lethalfantasy .character-main .character-characteristic-edit {
|
||||
min-width: 160px;
|
||||
}
|
||||
.lethalfantasy .tab.character-biography .biodata {
|
||||
.lethalfantasy .tab.character-biography .main-div .biodata {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-biography .biodata .biodata-elem {
|
||||
.lethalfantasy .tab.character-biography .main-div .biodata .biodata-elem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-biography .biodata .biodata-elem .item-img {
|
||||
.lethalfantasy .tab.character-biography .main-div .biodata .biodata-elem .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
.lethalfantasy .tab.character-biography .biodata .biodata-elem .name {
|
||||
.lethalfantasy .tab.character-biography .main-div .biodata .biodata-elem .name {
|
||||
min-width: 8rem;
|
||||
}
|
||||
.lethalfantasy .character-biography prose-mirror.inactive {
|
||||
@ -366,345 +380,345 @@ i.lethalfantasy {
|
||||
.lethalfantasy .character-biography prose-mirror.active {
|
||||
min-height: 150px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills {
|
||||
.lethalfantasy .tab.character-skills .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills legend a {
|
||||
.lethalfantasy .tab.character-skills .main-div legend a {
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
padding-left: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .skills {
|
||||
.lethalfantasy .tab.character-skills .main-div .skills {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .skills .skill {
|
||||
.lethalfantasy .tab.character-skills .main-div .skills .skill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .skills .skill .item-img {
|
||||
.lethalfantasy .tab.character-skills .main-div .skills .skill .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .skills .skill .name {
|
||||
.lethalfantasy .tab.character-skills .main-div .skills .skill .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .gifts {
|
||||
.lethalfantasy .tab.character-skills .main-div .gifts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .gifts .gift {
|
||||
.lethalfantasy .tab.character-skills .main-div .gifts .gift {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .gifts .gift .item-img {
|
||||
.lethalfantasy .tab.character-skills .main-div .gifts .gift .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .gifts .gift .name {
|
||||
.lethalfantasy .tab.character-skills .main-div .gifts .gift .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .vulnerabilities {
|
||||
.lethalfantasy .tab.character-skills .main-div .vulnerabilities {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .vulnerabilities .vulnerability {
|
||||
.lethalfantasy .tab.character-skills .main-div .vulnerabilities .vulnerability {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .vulnerabilities .vulnerability .item-img {
|
||||
.lethalfantasy .tab.character-skills .main-div .vulnerabilities .vulnerability .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.character-skills .vulnerabilities .vulnerability .name {
|
||||
.lethalfantasy .tab.character-skills .main-div .vulnerabilities .vulnerability .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment {
|
||||
.lethalfantasy .tab.character-equipment .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment legend a {
|
||||
.lethalfantasy .tab.character-equipment .main-div legend a {
|
||||
font-size: calc(var(--font-size-standard) * 1.4);
|
||||
padding-left: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment .moneys {
|
||||
.lethalfantasy .tab.character-equipment .main-div .moneys {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment .equipments {
|
||||
.lethalfantasy .tab.character-equipment .main-div .equipments {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment .equipments .equipment {
|
||||
.lethalfantasy .tab.character-equipment .main-div .equipments .equipment {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment .equipments .equipment .item-img {
|
||||
.lethalfantasy .tab.character-equipment .main-div .equipments .equipment .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment .equipments .equipment .name {
|
||||
.lethalfantasy .tab.character-equipment .main-div .equipments .equipment .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-equipment .equipments .name {
|
||||
.lethalfantasy .tab.character-equipment .main-div .equipments .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat {
|
||||
.lethalfantasy .tab.character-combat .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat legend a {
|
||||
.lethalfantasy .tab.character-combat .main-div legend a {
|
||||
font-size: calc(var(--font-size-standard) * 1.4);
|
||||
padding-left: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail .input {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail .input {
|
||||
min-width: 2.5rem;
|
||||
max-width: 2.5rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail button {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail button {
|
||||
min-width: 9rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail .armor-hp {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail .armor-hp {
|
||||
margin-right: 4px;
|
||||
min-width: 10rem;
|
||||
max-width: 10rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail .armor-hp .name {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail .armor-hp .name {
|
||||
min-width: 6rem;
|
||||
max-width: 6rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail .armor-hp .input {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail .armor-hp .input {
|
||||
min-width: 2.5rem;
|
||||
max-width: 2.5rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail .granted {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail .granted {
|
||||
min-width: 8rem;
|
||||
max-width: 8rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .combat-details .combat-detail .granted .input {
|
||||
.lethalfantasy .tab.character-combat .main-div .combat-details .combat-detail .granted .input {
|
||||
min-width: 2.5rem;
|
||||
max-width: 2.5rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .wounds {
|
||||
.lethalfantasy .tab.character-combat .main-div .wounds {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .wounds .wound {
|
||||
.lethalfantasy .tab.character-combat .main-div .wounds .wound {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .wounds .wound .wound-description {
|
||||
.lethalfantasy .tab.character-combat .main-div .wounds .wound .wound-description {
|
||||
min-width: 14rem;
|
||||
max-width: 14rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .wounds .wound .wound-duration {
|
||||
.lethalfantasy .tab.character-combat .main-div .wounds .wound .wound-duration {
|
||||
min-width: 3rem;
|
||||
max-width: 3rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .wounds .wound .wound-value {
|
||||
.lethalfantasy .tab.character-combat .main-div .wounds .wound .wound-value {
|
||||
min-width: 3rem;
|
||||
max-width: 3rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .wounds .wound .item-img {
|
||||
.lethalfantasy .tab.character-combat .main-div .wounds .wound .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .wounds .wound .name {
|
||||
.lethalfantasy .tab.character-combat .main-div .wounds .wound .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .weapons {
|
||||
.lethalfantasy .tab.character-combat .main-div .weapons {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .weapons .weapon {
|
||||
.lethalfantasy .tab.character-combat .main-div .weapons .weapon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .weapons .weapon .item-img {
|
||||
.lethalfantasy .tab.character-combat .main-div .weapons .weapon .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .weapons .weapon .name {
|
||||
.lethalfantasy .tab.character-combat .main-div .weapons .weapon .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .weapons .weapon .attack-icons a {
|
||||
.lethalfantasy .tab.character-combat .main-div .weapons .weapon .attack-icons a {
|
||||
margin-left: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .armors {
|
||||
.lethalfantasy .tab.character-combat .main-div .armors {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .armors .armor {
|
||||
.lethalfantasy .tab.character-combat .main-div .armors .armor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .armors .armor .item-img {
|
||||
.lethalfantasy .tab.character-combat .main-div .armors .armor .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .armors .name {
|
||||
.lethalfantasy .tab.character-combat .main-div .armors .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .armors .item-detail {
|
||||
.lethalfantasy .tab.character-combat .main-div .armors .item-detail {
|
||||
min-width: 2rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .shields {
|
||||
.lethalfantasy .tab.character-combat .main-div .shields {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
min-width: 20rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .shields .shield {
|
||||
.lethalfantasy .tab.character-combat .main-div .shields .shield {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .shields .shield .item-img {
|
||||
.lethalfantasy .tab.character-combat .main-div .shields .shield .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px 0 0 0;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .shields .item-detail {
|
||||
.lethalfantasy .tab.character-combat .main-div .shields .item-detail {
|
||||
min-width: 2.5rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-combat .shields .name {
|
||||
.lethalfantasy .tab.character-combat .main-div .shields .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells {
|
||||
.lethalfantasy .tab.character-spells .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells legend a {
|
||||
.lethalfantasy .tab.character-spells .main-div legend a {
|
||||
font-size: calc(var(--font-size-standard) * 1.4);
|
||||
padding-left: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spell-details {
|
||||
.lethalfantasy .tab.character-spells .main-div .spell-details {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spell-details .spell-detail {
|
||||
.lethalfantasy .tab.character-spells .main-div .spell-details .spell-detail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spell-details .spell-detail button {
|
||||
.lethalfantasy .tab.character-spells .main-div .spell-details .spell-detail button {
|
||||
min-width: 10rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spell-details .spell-detail .armor-hp {
|
||||
.lethalfantasy .tab.character-spells .main-div .spell-details .spell-detail .armor-hp {
|
||||
min-width: 12rem;
|
||||
max-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spell-details .spell-detail .armor-hp .input {
|
||||
.lethalfantasy .tab.character-spells .main-div .spell-details .spell-detail .armor-hp .input {
|
||||
flex: 0;
|
||||
min-width: 3rem;
|
||||
max-width: 3rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spells {
|
||||
.lethalfantasy .tab.character-spells .main-div .spells {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
min-width: 18rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spells .spell {
|
||||
.lethalfantasy .tab.character-spells .main-div .spells .spell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spells .spell .item-img {
|
||||
.lethalfantasy .tab.character-spells .main-div .spells .spell .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells .spells .spell .name {
|
||||
.lethalfantasy .tab.character-spells .main-div .spells .spell .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells prose-mirror.inactive {
|
||||
.lethalfantasy .tab.character-spells .main-div prose-mirror.inactive {
|
||||
min-height: 40px;
|
||||
}
|
||||
.lethalfantasy .tab.character-spells prose-mirror.active {
|
||||
.lethalfantasy .tab.character-spells .main-div prose-mirror.active {
|
||||
min-height: 150px;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles {
|
||||
.lethalfantasy .tab.character-miracles .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles legend a {
|
||||
.lethalfantasy .tab.character-miracles .main-div legend a {
|
||||
font-size: calc(var(--font-size-standard) * 1.4);
|
||||
padding-left: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracle-details {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracle-details {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracle-details .miracle-detail {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracle-details .miracle-detail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracle-details .miracle-detail button {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracle-details .miracle-detail button {
|
||||
min-width: 10rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracle-details .miracle-detail .armor-hp {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracle-details .miracle-detail .armor-hp {
|
||||
min-width: 20rem;
|
||||
max-width: 20rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracle-details .miracle-detail .armor-hp .input {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracle-details .miracle-detail .armor-hp .input {
|
||||
min-width: 3rem;
|
||||
max-width: 3rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracles {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracles {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 4px;
|
||||
min-width: 18rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracles .miracle {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracles .miracle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracles .miracle .item-img {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracles .miracle .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles .miracles .miracle .name {
|
||||
.lethalfantasy .tab.character-miracles .main-div .miracles .miracle .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles prose-mirror.inactive {
|
||||
.lethalfantasy .tab.character-miracles .main-div prose-mirror.inactive {
|
||||
min-height: 40px;
|
||||
}
|
||||
.lethalfantasy .tab.character-miracles prose-mirror.active {
|
||||
.lethalfantasy .tab.character-miracles .main-div prose-mirror.active {
|
||||
min-height: 150px;
|
||||
}
|
||||
.lethalfantasy .monster-content {
|
||||
@ -848,6 +862,10 @@ i.lethalfantasy {
|
||||
text-shadow: 0 0 8px var(--color-shadow-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
.lethalfantasy .monster-main .monster-characteristics .monster-characteristic span {
|
||||
min-width: 2.2rem;
|
||||
max-width: 2.2rem;
|
||||
}
|
||||
.lethalfantasy .monster-main .monster-characteristics .monster-characteristic .form-group {
|
||||
flex: 1;
|
||||
padding-left: 4px;
|
||||
@ -960,17 +978,17 @@ i.lethalfantasy {
|
||||
.lethalfantasy .monster-main .monster-characteristic-edit {
|
||||
min-width: 200px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-biography .biodata {
|
||||
.lethalfantasy .tab.monster-biography .main-div .biodata {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-biography .biodata .biodata-elem {
|
||||
.lethalfantasy .tab.monster-biography .main-div .biodata .biodata-elem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-biography .biodata .biodata-elem .name {
|
||||
.lethalfantasy .tab.monster-biography .main-div .biodata .biodata-elem .name {
|
||||
min-width: 8rem;
|
||||
}
|
||||
.lethalfantasy .monster-biography prose-mirror.inactive {
|
||||
@ -979,63 +997,63 @@ i.lethalfantasy {
|
||||
.lethalfantasy .monster-biography prose-mirror.active {
|
||||
min-height: 150px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills {
|
||||
.lethalfantasy .tab.monster-skills .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills legend a {
|
||||
.lethalfantasy .tab.monster-skills .main-div legend a {
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
padding-left: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .skills {
|
||||
.lethalfantasy .tab.monster-skills .main-div .skills {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .skills .skill {
|
||||
.lethalfantasy .tab.monster-skills .main-div .skills .skill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .skills .skill .item-img {
|
||||
.lethalfantasy .tab.monster-skills .main-div .skills .skill .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .skills .skill .name {
|
||||
.lethalfantasy .tab.monster-skills .main-div .skills .skill .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .gifts {
|
||||
.lethalfantasy .tab.monster-skills .main-div .gifts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .gifts .gift {
|
||||
.lethalfantasy .tab.monster-skills .main-div .gifts .gift {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .gifts .gift .item-img {
|
||||
.lethalfantasy .tab.monster-skills .main-div .gifts .gift .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .gifts .gift .name {
|
||||
.lethalfantasy .tab.monster-skills .main-div .gifts .gift .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .vulnerabilities {
|
||||
.lethalfantasy .tab.monster-skills .main-div .vulnerabilities {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .vulnerabilities .vulnerability {
|
||||
.lethalfantasy .tab.monster-skills .main-div .vulnerabilities .vulnerability {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .vulnerabilities .vulnerability .item-img {
|
||||
.lethalfantasy .tab.monster-skills .main-div .vulnerabilities .vulnerability .item-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
.lethalfantasy .tab.monster-skills .vulnerabilities .vulnerability .name {
|
||||
.lethalfantasy .tab.monster-skills .main-div .vulnerabilities .vulnerability .name {
|
||||
min-width: 12rem;
|
||||
}
|
||||
.lethalfantasy .tab.monster-equipment {
|
||||
@ -1951,6 +1969,18 @@ i.lethalfantasy {
|
||||
.lethalfantasy-roll-dialog fieldset {
|
||||
padding: 4px;
|
||||
}
|
||||
.lethalfantasy-roll-dialog .goto-token-button {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
margin-left: 0.5rem;
|
||||
max-width: 8rem;
|
||||
background-color: var(--color-dark-6);
|
||||
color: var(--color-dark-2);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
.lethalfantasy-range-defense-dialog {
|
||||
width: 18rem;
|
||||
}
|
||||
@ -2058,22 +2088,39 @@ i.lethalfantasy {
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
text-shadow: 0 0 10px var(--color-shadow-primary);
|
||||
}
|
||||
#lethalfantasy-application-manager {
|
||||
display: flex;
|
||||
font-family: var(--font-primary);
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
color: var(--color-dark-1);
|
||||
#token-hud .hp-loss-wrap {
|
||||
position: absolute;
|
||||
left: 75px;
|
||||
display: none;
|
||||
top: 50%;
|
||||
width: 48px;
|
||||
text-align: start;
|
||||
overflow-y: auto;
|
||||
}
|
||||
#token-hud .hp-loss-wrap-col1 {
|
||||
transform: translate(-200%, -50%);
|
||||
}
|
||||
#token-hud .hp-loss-wrap-col2 {
|
||||
transform: translate(-300%, -50%);
|
||||
}
|
||||
#token-hud .hp-loss-wrap-col3 {
|
||||
transform: translate(-400%, -50%);
|
||||
}
|
||||
#token-hud .hp-loss-hud-active {
|
||||
display: block;
|
||||
}
|
||||
#token-hud .hp-loss-hud-disabled {
|
||||
display: none;
|
||||
}
|
||||
#token-hud .hud-loss-hp-button-select {
|
||||
max-width: 40px;
|
||||
background-image: var(--background-image-base);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
#lethalfantasy-application-manager .lethalfantasy-table {
|
||||
margin: 1rem;
|
||||
background: none;
|
||||
padding: 0;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
width: max-content;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
#lethalfantasy-application-manager .lethalfantasy-table .player {
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
#token-hud .hp-loss-wrap .hud-loss-hp-button-select {
|
||||
padding-left: 8px;
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
10
lang/en.json
10
lang/en.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"COMBAT": {
|
||||
"Round": "Second",
|
||||
"Round": "Second {round}",
|
||||
"Rounds": "Seconds",
|
||||
"RoundNext": "Next second"
|
||||
},
|
||||
@ -281,6 +281,7 @@
|
||||
}
|
||||
},
|
||||
"Label": {
|
||||
"gotoToken": "Go to token",
|
||||
"combatAction": "Combat action",
|
||||
"currentAction": "Current ongoing action",
|
||||
"selectAction": "Select an action",
|
||||
@ -288,6 +289,7 @@
|
||||
"spell-attack": "Spell - Attack",
|
||||
"miracle-power": "Miracle - Power",
|
||||
"miracle-attack": "Miracle - Attack",
|
||||
"spell": "Spell",
|
||||
"will":"Will",
|
||||
"dodge":"Dodge",
|
||||
"toughness":"Toughness",
|
||||
@ -489,11 +491,11 @@
|
||||
"rollTypeNotFound": "Roll type not found",
|
||||
"skillNotFound": "Skill not found",
|
||||
"messageProgressionOK": "{name} can perform his action !",
|
||||
"messageLethargyOK": "Lethargy ended. <br>{name} can perform a new action !",
|
||||
"messageLethargyKO": "Lethargy stil ongoing ...",
|
||||
"messageLethargyOK": "{spellName} : Lethargy ended ( dice result {roll}). <br>{name} can perform a new action !",
|
||||
"messageLethargyKO": "{spellName} : Lethargy still ongoing ... ( dice result : {roll} )",
|
||||
"messageProgressionKO": "{name} can't attack this second.",
|
||||
"messageProgressionOKMonster": "{name} can attack this second with {weapon}.",
|
||||
"messageProgressionKOMonster": "{name} can't attack this second."
|
||||
"messageProgressionKOMonster": "{name} can't attack this second (dice result {roll})."
|
||||
},
|
||||
"Opponent": {
|
||||
"FIELDS": {}
|
||||
|
@ -11,12 +11,12 @@ import * as models from "./module/models/_module.mjs"
|
||||
import * as documents from "./module/documents/_module.mjs"
|
||||
import * as applications from "./module/applications/_module.mjs"
|
||||
|
||||
import { LethalFantasyCombatTracker, LethalFantasyCombat} from "./module/applications/combat.mjs"
|
||||
import { LethalFantasyCombatTracker, LethalFantasyCombat } from "./module/applications/combat.mjs"
|
||||
import { Macros } from "./module/macros.mjs"
|
||||
import { setupTextEnrichers } from "./module/enrichers.mjs"
|
||||
import { default as LethalFantasyUtils } from "./module/utils.mjs"
|
||||
|
||||
export class ClassCounter{static printHello(){console.log("Hello")}static sendJsonPostRequest(e,s){const t={method:"POST",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(s)};return fetch(e,t).then((e=>{if(!e.ok)throw new Error("La requête a échoué avec le statut "+e.status);return e.json()})).catch((e=>{throw console.error("Erreur envoi de la requête:",e),e}))}static registerUsageCount(e=game.system.id,s={}){if(game.user.isGM){game.settings.register(e,"world-key",{name:"Unique world key",scope:"world",config:!1,default:"",type:String});let t=game.settings.get(e,"world-key");null!=t&&""!=t&&"NONE"!=t&&"none"!=t.toLowerCase()||(t=foundry.utils.randomID(32),game.settings.set(e,"world-key",t));let a={name:e,system:game.system.id,worldKey:t,version:game.system.version,language:game.settings.get("core","language"),remoteAddr:game.data.addresses.remote,nbInstalledModules:game.modules.size,nbActiveModules:game.modules.filter((e=>e.active)).length,nbPacks:game.world.packs.size,nbUsers:game.users.size,nbScenes:game.scenes.size,nbActors:game.actors.size,nbPlaylist:game.playlists.size,nbTables:game.tables.size,nbCards:game.cards.size,optionsData:s,foundryVersion:`${game.release.generation}.${game.release.build}`};this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php",a)}}}
|
||||
export class ClassCounter { static printHello() { console.log("Hello") } static sendJsonPostRequest(e, s) { const t = { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(s) }; return fetch(e, t).then((e => { if (!e.ok) throw new Error("La requête a échoué avec le statut " + e.status); return e.json() })).catch((e => { throw console.error("Erreur envoi de la requête:", e), e })) } static registerUsageCount(e = game.system.id, s = {}) { if (game.user.isGM) { game.settings.register(e, "world-key", { name: "Unique world key", scope: "world", config: !1, default: "", type: String }); let t = game.settings.get(e, "world-key"); null != t && "" != t && "NONE" != t && "none" != t.toLowerCase() || (t = foundry.utils.randomID(32), game.settings.set(e, "world-key", t)); let a = { name: e, system: game.system.id, worldKey: t, version: game.system.version, language: game.settings.get("core", "language"), remoteAddr: game.data.addresses.remote, nbInstalledModules: game.modules.size, nbActiveModules: game.modules.filter((e => e.active)).length, nbPacks: game.world.packs.size, nbUsers: game.users.size, nbScenes: game.scenes.size, nbActors: game.actors.size, nbPlaylist: game.playlists.size, nbTables: game.tables.size, nbCards: game.cards.size, optionsData: s, foundryVersion: `${game.release.generation}.${game.release.build}` }; this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php", a) } } }
|
||||
|
||||
Hooks.once("init", function () {
|
||||
console.info("Lethal Fantasy RPG | Initializing System")
|
||||
@ -55,20 +55,20 @@ Hooks.once("init", function () {
|
||||
}
|
||||
|
||||
// Register sheet application classes
|
||||
Actors.unregisterSheet("core", ActorSheet)
|
||||
Actors.registerSheet("lethalFantasy", applications.LethalFantasyCharacterSheet, { types: ["character"], makeDefault: true })
|
||||
Actors.registerSheet("lethalFantasy", applications.LethalFantasyMonsterSheet, { types: ["monster"], makeDefault: true })
|
||||
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet)
|
||||
foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyCharacterSheet, { types: ["character"], makeDefault: true })
|
||||
foundry.documents.collections.Actors.registerSheet("lethalFantasy", applications.LethalFantasyMonsterSheet, { types: ["monster"], makeDefault: true })
|
||||
|
||||
Items.unregisterSheet("core", ItemSheet)
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasySkillSheet, { types: ["skill"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasyGiftSheet, { types: ["gift"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasyVulnerabilitySheet, { types: ["vulnerability"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasyWeaponSheet, { types: ["weapon"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasySpellSheet, { types: ["spell"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasyArmorSheet, { types: ["armor"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasyShieldSheet, { types: ["shield"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasyEquipmentSheet, { types: ["equipment"], makeDefault: true })
|
||||
Items.registerSheet("lethalFantasy", applications.LethalFantasyMiracleSheet, { types: ["miracle"], makeDefault: true })
|
||||
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ActorSheet)
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasySkillSheet, { types: ["skill"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyGiftSheet, { types: ["gift"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyVulnerabilitySheet, { types: ["vulnerability"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyWeaponSheet, { types: ["weapon"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasySpellSheet, { types: ["spell"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyArmorSheet, { types: ["armor"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyShieldSheet, { types: ["shield"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyEquipmentSheet, { types: ["equipment"], makeDefault: true })
|
||||
foundry.documents.collections.Items.registerSheet("lethalFantasy", applications.LethalFantasyMiracleSheet, { types: ["miracle"], makeDefault: true })
|
||||
|
||||
// Other Document Configuration
|
||||
CONFIG.ChatMessage.documentClass = documents.LethalFantasyChatMessage
|
||||
@ -89,12 +89,13 @@ Hooks.once("init", function () {
|
||||
|
||||
setupTextEnrichers()
|
||||
LethalFantasyUtils.registerHandlebarsHelpers()
|
||||
LethalFantasyUtils.setHookListeners()
|
||||
|
||||
console.info("LETHAL FANTASY | System Initialized")
|
||||
})
|
||||
|
||||
/**
|
||||
* Perform one-time configuration of system configuration objects.
|
||||
* Perform one-time configuration of system configuration objects.f
|
||||
*/
|
||||
function preLocalizeConfig() {
|
||||
const localizeConfigObject = (obj, keys) => {
|
||||
@ -104,11 +105,6 @@ function preLocalizeConfig() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CONFIG.Dice.rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
|
||||
// localizeConfigObject(SYSTEM.ACTION.TAG_CATEGORIES, ["label"])
|
||||
// localizeConfigObject(CONFIG.Dice.rollModes, ["label"])
|
||||
}
|
||||
|
||||
Hooks.once("ready", function () {
|
||||
@ -117,6 +113,7 @@ Hooks.once("ready", function () {
|
||||
if (!SYSTEM.DEV_MODE) {
|
||||
registerWorldCount("lethalFantasy")
|
||||
}
|
||||
|
||||
_showUserGuide()
|
||||
|
||||
/**
|
||||
@ -129,7 +126,12 @@ Hooks.once("ready", function () {
|
||||
}
|
||||
})
|
||||
|
||||
Hooks.on("renderChatMessage", (message, html, data) => {
|
||||
// Test if version below 13
|
||||
let hookName = "renderChatMessage"
|
||||
if (foundry.utils.isNewerVersion(game.version, "12.0",)) {
|
||||
hookName = "renderChatMessageHTML"
|
||||
}
|
||||
Hooks.on(hookName, (message, html, data) => {
|
||||
const typeMessage = data.message.flags.lethalFantasy?.typeMessage
|
||||
// Message de demande de jet de dés
|
||||
if (typeMessage === "askRoll") {
|
||||
@ -152,7 +154,7 @@ Hooks.on("renderChatMessage", (message, html, data) => {
|
||||
}
|
||||
})
|
||||
|
||||
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
||||
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
||||
LethalFantasyUtils.pushCombatOptions(html, options);
|
||||
});
|
||||
|
||||
@ -181,4 +183,4 @@ async function registerWorldCount(registerKey) {
|
||||
console.log("No usage log ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,54 @@
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class LethalFantasyCombatTracker extends CombatTracker {
|
||||
export class LethalFantasyCombatTracker extends foundry.applications.sidebar.tabs.CombatTracker {
|
||||
|
||||
async getData(options) {
|
||||
let data = await super.getData(options);
|
||||
for (let u of data.turns) {
|
||||
static PARTS = {
|
||||
"header": {
|
||||
"template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-header-v2.hbs"
|
||||
},
|
||||
"tracker": {
|
||||
"template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-v2.hbs"
|
||||
},
|
||||
"footer": {
|
||||
"template": "systems/fvtt-lethal-fantasy/templates/combat-tracker-footer-v2.hbs"
|
||||
}
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = foundry.utils.mergeObject(super.DEFAULT_OPTIONS, {
|
||||
actions: {
|
||||
initiativePlus: LethalFantasyCombatTracker.#initiativePlus,
|
||||
initiativeMinus: LethalFantasyCombatTracker.#initiativeMinus,
|
||||
},
|
||||
});
|
||||
|
||||
async _prepareContext(options) {
|
||||
let data = await super._prepareContext(options);
|
||||
console?.log("Combat Tracker Data", data);
|
||||
/*for (let u of data.turns) {
|
||||
let c = game.combat.combatants.get(u.id);
|
||||
u.progressionCount = c.system.progressionCount
|
||||
u.isMonster = c.actor.type === "monster"
|
||||
}
|
||||
console.log("Combat Data", data);
|
||||
console.log("Combat Data", data);*/
|
||||
return data;
|
||||
}
|
||||
|
||||
static #initiativePlus(ev) {
|
||||
ev.preventDefault();
|
||||
let cId = ev.target.closest(".combatant").dataset.combatantId;
|
||||
let c = game.combat.combatants.get(cId);
|
||||
c.update({ 'initiative': c.initiative + 1 });
|
||||
console.log("Initiative Plus");
|
||||
}
|
||||
|
||||
static #initiativeMinus(ev) {
|
||||
ev.preventDefault();
|
||||
let cId = ev.target.closest(".combatant").dataset.combatantId;
|
||||
let c = game.combat.combatants.get(cId);
|
||||
let newInit = Math.max(c.initiative - 1, 0);
|
||||
c.update({ 'initiative': newInit });
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
// Display Combat settings
|
||||
@ -21,7 +57,6 @@ export class LethalFantasyCombatTracker extends CombatTracker {
|
||||
let cId = ev.currentTarget.closest(".combatant").dataset.combatantId;
|
||||
let c = game.combat.combatants.get(cId);
|
||||
c.update({ 'initiative': c.initiative + 1 });
|
||||
console.log("Initiative Plus");
|
||||
});
|
||||
|
||||
html.find(".initiative-minus").click(ev => {
|
||||
@ -138,7 +173,6 @@ export class LethalFantasyCombat extends Combat {
|
||||
}
|
||||
|
||||
async nextRound() {
|
||||
console.log('NEXT ROUND')
|
||||
this.turnsDone = false
|
||||
|
||||
let turn = this.turn === null ? null : 0; // Preserve the fact that it's no-one's turn currently.
|
||||
@ -161,14 +195,13 @@ export class LethalFantasyCombat extends Combat {
|
||||
}
|
||||
|
||||
for (let c of this.combatants) {
|
||||
if ( nextRound >= c.initiative) {
|
||||
c.update({ 'system.progressionCount': c.system.progressionCount + 1 });
|
||||
if (nextRound >= c.initiative) {
|
||||
let user = game.users.find(u => u.active && u.character && u.character.id === c.actor.id);
|
||||
if (user?.hasPlayerOwner) {
|
||||
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", progressionCount: c.system.progressionCount+1, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
|
||||
game.socket.emit(`system.${SYSTEM.id}`, { type: "rollProgressionDice", progressionCount: c.system.progressionCount + 1, actorId: c.actor.id, combatId: this.id, combatantId: c.id });
|
||||
} else {
|
||||
user = game.users.find(u => u.active && u.isGM);
|
||||
c.actor.system.rollProgressionDice(this.id, c.id, c.system.progressionCount+1);
|
||||
c.actor.system.rollProgressionDice(this.id, c.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ export default class LethalFantasyArmorSheet extends LethalFantasyItemSheet {
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin(
|
||||
actor: this.document,
|
||||
system: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true }),
|
||||
isEditMode: this.isEditMode,
|
||||
isPlayMode: this.isPlayMode,
|
||||
isEditable: this.isEditable,
|
||||
@ -100,7 +100,7 @@ export default class LethalFantasyActorSheet extends HandlebarsApplicationMixin(
|
||||
dragover: this._onDragOver.bind(this),
|
||||
drop: this._onDrop.bind(this),
|
||||
}
|
||||
return new DragDrop(d)
|
||||
return new foundry.applications.ux.DragDrop.implementation(d)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -58,22 +58,25 @@ export default class LethalFantasyItemSheet extends HandlebarsApplicationMixin(f
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = {
|
||||
let context = await super._prepareContext()
|
||||
const contextLocal = {
|
||||
fields: this.document.schema.fields,
|
||||
systemFields: this.document.system.schema.fields,
|
||||
item: this.document,
|
||||
system: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true }),
|
||||
isEditMode: this.isEditMode,
|
||||
isPlayMode: this.isPlayMode,
|
||||
isEditable: this.isEditable,
|
||||
}
|
||||
context = mergeObject(context, contextLocal)
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||
}
|
||||
|
||||
|
@ -90,9 +90,6 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
return context
|
||||
}
|
||||
|
||||
_generateTooltip(type, target) {
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _preparePartContext(partId, context) {
|
||||
const doc = this.document
|
||||
@ -127,8 +124,8 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
break
|
||||
case "biography":
|
||||
context.tab = context.tabs.biography
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.notes, { async: true })
|
||||
break
|
||||
}
|
||||
return context
|
||||
@ -143,18 +140,17 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
if (!this.isEditable || !this.isEditMode) return
|
||||
const data = TextEditor.getDragEventData(event)
|
||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
|
||||
|
||||
// Handle different data types
|
||||
switch (data.type) {
|
||||
case "Item":
|
||||
const item = await fromUuid(data.uuid)
|
||||
return this._onDropItem(item)
|
||||
if (data.type === "Item") {
|
||||
const item = await fromUuid(data.uuid)
|
||||
return this._onDropItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
static async #onRangedAttackDefense(event, target) {
|
||||
const hasTarget = false
|
||||
// Future use : const hasTarget = false
|
||||
|
||||
let roll = await LethalFantasyRoll.promptRangedDefense({
|
||||
actorId: this.actor.id,
|
||||
@ -250,6 +246,7 @@ export default class LethalFantasyCharacterSheet extends LethalFantasyActorSheet
|
||||
|
||||
async _onRoll(event, target) {
|
||||
if (this.isEditMode) return
|
||||
console.log("Roll event", event)
|
||||
const rollType = event.target.dataset.rollType
|
||||
let rollKey = event.target.dataset.rollKey;
|
||||
let rollDice = event.target.dataset?.rollDice;
|
||||
|
@ -22,7 +22,7 @@ export default class LethalFantasyEquipmentSheet extends LethalFantasyItemSheet
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export default class LethalFantasyGiftSheet extends LethalFantasyItemSheet {
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export default class LethalFantasyMiracleSheet extends LethalFantasyItemSheet {
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
|
||||
|
@ -63,9 +63,6 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet {
|
||||
return context
|
||||
}
|
||||
|
||||
_generateTooltip(type, target) {
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _preparePartContext(partId, context) {
|
||||
const doc = this.document
|
||||
@ -78,8 +75,8 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet {
|
||||
break
|
||||
case "biography":
|
||||
context.tab = context.tabs.biography
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.notes, { async: true })
|
||||
break
|
||||
}
|
||||
return context
|
||||
@ -166,71 +163,8 @@ export default class LethalFantasyMonsterSheet extends LethalFantasyActorSheet {
|
||||
async _onRoll(event, target) {
|
||||
if (this.isEditMode) return
|
||||
const rollType = event.target.dataset.rollType
|
||||
let rollTarget
|
||||
let rollKey = event.target.dataset.rollKey
|
||||
switch (rollType) {
|
||||
case "monster-attack":
|
||||
case "monster-defense":
|
||||
case "monster-damage":
|
||||
rollTarget = foundry.utils.duplicate(this.document.system.attacks[rollKey])
|
||||
rollTarget.rollKey = rollKey
|
||||
break
|
||||
case "monster-skill":
|
||||
rollTarget = foundry.utils.duplicate(this.document.system.resists[rollKey])
|
||||
rollTarget.rollKey = rollKey
|
||||
break
|
||||
case "save":
|
||||
rollTarget = foundry.utils.duplicate(this.document.system.saves[rollKey])
|
||||
rollTarget.rollKey = rollKey
|
||||
rollTarget.rollDice = event.target.dataset?.rollDice
|
||||
break
|
||||
case "weapon-damage-small":
|
||||
case "weapon-damage-medium":
|
||||
case "weapon-attack":
|
||||
case "weapon-defense":
|
||||
let weapon = this.actor.items.find((i) => i.type === "weapon" && i.id === rollKey)
|
||||
let skill
|
||||
let skills = this.actor.items.filter((i) => i.type === "skill" && i.name.toLowerCase() === weapon.name.toLowerCase())
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
||||
} else {
|
||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.name.toLowerCase().replace(" skill", "") === weapon.name.toLowerCase())
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
||||
} else {
|
||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass === weapon.system.weaponClass)
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 0.5)
|
||||
} else {
|
||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass.includes(SYSTEM.WEAPON_CATEGORIES[weapon.system.weaponClass]))
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 0.25)
|
||||
} else {
|
||||
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!weapon || !skill) {
|
||||
console.error("Weapon or skill not found", weapon, skill)
|
||||
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
||||
return
|
||||
}
|
||||
rollTarget = skill
|
||||
rollTarget.weapon = weapon
|
||||
rollTarget.weaponSkillModifier = skill.weaponSkillModifier
|
||||
rollTarget.rollKey = rollKey
|
||||
rollTarget.combat = foundry.utils.duplicate(this.actor.system.combat)
|
||||
break
|
||||
default:
|
||||
ui.notifications.error(game.i18n.localize("LETHALFANTASY.Notifications.rollTypeNotFound") + String(rollType))
|
||||
break
|
||||
}
|
||||
|
||||
// In all cases
|
||||
console.log(rollTarget)
|
||||
await this.document.system.roll(rollType, rollTarget)
|
||||
let rollDice = event.target.dataset?.rollDice || "0"
|
||||
this.actor.system.prepareMonsterRoll(rollType, rollKey, rollDice)
|
||||
}
|
||||
// #endregion
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export default class LethalFantasyShieldSheet extends LethalFantasyItemSheet {
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export default class LethalFantasySkillSheet extends LethalFantasyItemSheet {
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export default class LethalFantasySpellSheet extends LethalFantasyItemSheet {
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ export default class LethalFantasyVulnerabilitySheet extends LethalFantasyItemSh
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
|
@ -18,11 +18,11 @@ export default class LethalFantasyWeaponSheet extends LethalFantasyItemSheet {
|
||||
template: "systems/fvtt-lethal-fantasy/templates/weapon.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
|
||||
|
@ -44,20 +44,13 @@ export const MONEY = {
|
||||
}
|
||||
|
||||
export const MORTAL_CHOICES = {
|
||||
"mankind": {label: "Mankind", value: "Mankind", defenseBonus: 0},
|
||||
"elf": {label: "Elf", value: "Elf", defenseBonus: 0},
|
||||
"dwarf": {label: "Dwarf", value: "Dwarf", defenseBonus: 0},
|
||||
"halfelf": {label: "Half-Elf", value: "Half-Elf", defenseBonus: 0},
|
||||
"halforc": {label: "Half-Orc", value: "Half-Orc", defenseBonus: 0},
|
||||
"gnome": {label: "Gnome", value: "Gnome", defenseBonus: 2},
|
||||
"shirefolk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
|
||||
"Elf": {label: "Elf", value: "Elf", defenseBonus: 0},
|
||||
"Half-orc": {label: "Half-Orc", value: "Half-Orc", defenseBonus: 0},
|
||||
"Dwarf": {label: "Dwarf", value: "Dwarf", defenseBonus: 0},
|
||||
"Half-elf": {label: "Half-Elf", value: "Half-Elf", defenseBonus: 0},
|
||||
"Gnome": {label: "Gnome", value: "Gnome", defenseBonus: 2},
|
||||
"Shire Folk": {label: "Shire Folk", value: "Shire Folk", defenseBonus: 2},
|
||||
"Mankind": {label: "Human", value: "Human", defenseBonus: 0},
|
||||
"mankind": {label: "Mankind", id: "mankind", defenseBonus: 0},
|
||||
"elf": {label: "Elf", id: "elf", defenseBonus: 0},
|
||||
"dwarf": {label: "Dwarf", id: "dwarf", defenseBonus: 0},
|
||||
"halfelf": {label: "Half-Elf", id: "halfelf", defenseBonus: 0},
|
||||
"halforc": {label: "Half-Orc", id: "halforc", defenseBonus: 0},
|
||||
"gnome": {label: "Gnome", id: "gnome", defenseBonus: 2},
|
||||
"halflings": {label: "Halflings", id: "halflings", defenseBonus: 2}
|
||||
}
|
||||
|
||||
export const FAVOR_CHOICES = {
|
||||
@ -96,7 +89,7 @@ export const RANGE_CHOICES = {
|
||||
"extreme": {label: "Extreme (+20)", value: "+20"},
|
||||
"beyondskill": {label: "Beyond Skill (+25)", value: "+25"}
|
||||
}
|
||||
|
||||
|
||||
export const ATTACKER_AIM_CHOICES = {
|
||||
"simple": {label: "Simple (+0)", value: "0"},
|
||||
"careful": {label: "Careful (-4)", value: "-4"},
|
||||
@ -119,7 +112,7 @@ export const INITIATIVE_DICE_CHOICES_PER_CLASS = {
|
||||
{ "name": "Aware of the enemy, can hear them but not see (2D4)", "value": "2D4" },
|
||||
{ "name": "Aware and know exactly where the enemy is (2D3)", "value": "2D3" }
|
||||
],
|
||||
"fighter": [
|
||||
"fighter": [
|
||||
{ "name": "Asleep or totally distracted (1D12)", "value": "1D12" },
|
||||
{ "name": "Awake but unsuspecting (1D8)", "value": "1D8" },
|
||||
{ "name": "Declared Ready on Alert (1D6)", "value": "1D6" },
|
||||
@ -163,7 +156,7 @@ export const CHAR_CLASSES = {
|
||||
"rogue": "Rogue",
|
||||
"ranger": "Ranger",
|
||||
"cleric": "Cleric",
|
||||
"magicuser": "Magic User"
|
||||
"magicuser": "Magic User"
|
||||
}
|
||||
|
||||
export const CHAR_CLASSES_DEFINES = {
|
||||
@ -176,7 +169,7 @@ export const CHAR_CLASSES_DEFINES = {
|
||||
}
|
||||
|
||||
export const DICE_VALUES = {
|
||||
"d3": "D3",
|
||||
"d3": "D3",
|
||||
"d4": "D4",
|
||||
"d6": "D6",
|
||||
"d8": "D8",
|
||||
@ -191,7 +184,8 @@ export const CHARACTERISTIC_DEFENSE = [ "int", "wis", "dex" ]
|
||||
export const CHARACTERISTIC_DAMAGE = [ "str" ]
|
||||
|
||||
export const DEFENSE_DICE_VALUES = {
|
||||
"d3": "D3",
|
||||
"0": "0",
|
||||
"d3": "D3",
|
||||
"d4": "D4",
|
||||
"d6": "D6",
|
||||
"d8": "D8",
|
||||
@ -280,7 +274,7 @@ export const SYSTEM = {
|
||||
id: SYSTEM_ID,
|
||||
CHARACTERISTICS: CHARACTER.CHARACTERISTICS,
|
||||
CHARACTERISTICS_TABLES: CHARACTERISTICS.TABLES,
|
||||
CHARACTERISTICS_MAJOR: CHARACTERISTICS.MAJOR,
|
||||
CHARACTERISTICS_MAJOR: CHARACTERISTICS.MAJOR,
|
||||
MONSTER_CHARACTERISTICS: MONSTER.MONSTER_CHARACTERISTICS,
|
||||
MONSTER_RESIST: MONSTER.MONSTER_RESIST,
|
||||
MONSTER_SAVES: MONSTER.MONSTER_SAVES,
|
||||
|
@ -41,6 +41,7 @@ export default class LethalFantasyActor extends Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************************************/
|
||||
getBestWeaponClassSkill(skills, rollType, multiplier = 1.0) {
|
||||
let maxValue = 0
|
||||
let goodSkill = skills[0]
|
||||
@ -68,6 +69,16 @@ export default class LethalFantasyActor extends Actor {
|
||||
return goodSkill
|
||||
}
|
||||
|
||||
/* *************************************************/
|
||||
async applyDamage(hpLoss) {
|
||||
let hp = this.system.hp.value + hpLoss
|
||||
if (hp < 0) {
|
||||
hp = 0
|
||||
}
|
||||
this.update({ "system.hp.value": hp })
|
||||
}
|
||||
|
||||
/* *************************************************/
|
||||
async prepareRoll(rollType, rollKey, rollDice ) {
|
||||
console.log("Preparing roll", rollType, rollKey, rollDice)
|
||||
let rollTarget
|
||||
|
@ -221,9 +221,13 @@ export default class LethalFantasyRoll extends Roll {
|
||||
hasChangeDice = false
|
||||
options.rollTarget.value = options.rollTarget.actorModifiers.levelSpellModifier + options.rollTarget.actorModifiers.intSpellModifier
|
||||
options.rollTarget.charModifier = options.rollTarget.actorModifiers.intSpellModifier
|
||||
hasStaticModifier = true // options.rollType === "spell-power"
|
||||
hasModifier = true //options.rollType !== "spell-attack"
|
||||
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
||||
hasStaticModifier = options.rollType === "spell-power"
|
||||
//hasModifier = options.rollType !== "spell-attack"
|
||||
if (hasStaticModifier) {
|
||||
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
||||
} else {
|
||||
options.rollTarget.staticModifier = 0
|
||||
}
|
||||
|
||||
} else if (options.rollType === "miracle" || options.rollType === "miracle-attack" || options.rollType === "miracle-power") {
|
||||
hasD30 = true
|
||||
@ -234,9 +238,13 @@ export default class LethalFantasyRoll extends Roll {
|
||||
hasChangeDice = false
|
||||
options.rollTarget.value = options.rollTarget.actorModifiers.levelMiracleModifier + options.rollTarget.actorModifiers.chaMiracleModifier
|
||||
options.rollTarget.charModifier = options.rollTarget.actorModifiers.chaMiracleModifier
|
||||
hasStaticModifier = true // options.rollType === "spell-power"
|
||||
hasModifier = true // options.rollType !== "miracle-attack"
|
||||
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
||||
hasStaticModifier = options.rollType === "miracle-power"
|
||||
//hasModifier = options.rollType !== "miracle-attack"
|
||||
if (hasStaticModifier) {
|
||||
options.rollTarget.staticModifier = options.rollTarget.actorLevel
|
||||
} else {
|
||||
options.rollTarget.staticModifier = 0
|
||||
}
|
||||
|
||||
} else if (options.rollType === "shield-roll") {
|
||||
hasD30 = false
|
||||
@ -284,7 +292,9 @@ export default class LethalFantasyRoll extends Roll {
|
||||
hasModifier = false
|
||||
}
|
||||
|
||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
console.log("Roll mode", rollModes)
|
||||
|
||||
const fieldRollMode = new foundry.data.fields.StringField({
|
||||
choices: rollModes,
|
||||
blank: false,
|
||||
@ -302,6 +312,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
rollType: options.rollType,
|
||||
rollTarget: options.rollTarget,
|
||||
rollName: options.rollName,
|
||||
actorName: options.actorName,
|
||||
rollModes,
|
||||
hasModifier,
|
||||
hasFavor,
|
||||
@ -320,18 +331,22 @@ export default class LethalFantasyRoll extends Roll {
|
||||
favor: "none",
|
||||
targetName
|
||||
}
|
||||
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-dialog.hbs", dialogContext)
|
||||
|
||||
const title = LethalFantasyRoll.createTitle(options.rollType, options.rollTarget)
|
||||
let position = game.user.getFlag(SYSTEM.id, "roll-dialog-pos") || { top: -1, left: -1 }
|
||||
const label = game.i18n.localize("LETHALFANTASY.Roll.roll")
|
||||
const rollContext = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: title },
|
||||
window: { title: "Roll dialog" },
|
||||
classes: ["lethalfantasy"],
|
||||
content,
|
||||
position,
|
||||
buttons: [
|
||||
{
|
||||
label: label,
|
||||
callback: (event, button, dialog) => {
|
||||
console.log("Roll context", event, button, dialog)
|
||||
let position = dialog.position
|
||||
game.user.setFlag(SYSTEM.id, "roll-dialog-pos", foundry.utils.duplicate(position))
|
||||
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
||||
if (input.name) obj[input.name] = input.value
|
||||
return obj
|
||||
@ -343,6 +358,15 @@ export default class LethalFantasyRoll extends Roll {
|
||||
actions: {
|
||||
"selectGranted": (event, button, dialog) => {
|
||||
hasGrantedDice = true
|
||||
},
|
||||
"gotoToken" : (event, button, dialog) => {
|
||||
let tokenId = $(button).data("tokenId")
|
||||
let token = canvas.tokens?.get(tokenId)
|
||||
if (token) {
|
||||
canvas.animatePan({ x: token.x, y: token.y, duration: 200 })
|
||||
canvas.tokens.releaseAll();
|
||||
token.control({ releaseOthers: true });
|
||||
}
|
||||
}
|
||||
},
|
||||
rejectClose: false // Click on Close button will not launch an error
|
||||
@ -373,7 +397,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
if (hasStaticModifier) {
|
||||
modifierFormula += ` + ${options.rollTarget.staticModifier}`
|
||||
}
|
||||
modifierFormula += ` + ${options.rollTarget.charModifier}`
|
||||
// modifierFormula += ` + ${options.rollTarget.charModifier}`
|
||||
let sign = fullModifier < 0 ? "-" : "+"
|
||||
if (hasExplode) {
|
||||
titleFormula = `${dice}E ${sign} ${modifierFormula}`
|
||||
@ -543,8 +567,9 @@ export default class LethalFantasyRoll extends Roll {
|
||||
return rollBase
|
||||
}
|
||||
|
||||
/* ***********************************************************/
|
||||
static async promptInitiative(options = {}) {
|
||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const fieldRollMode = new foundry.data.fields.StringField({
|
||||
choices: rollModes,
|
||||
blank: false,
|
||||
@ -567,7 +592,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
}
|
||||
console.log("CTX", dialogContext)
|
||||
|
||||
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-initiative-dialog.hbs", dialogContext)
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-initiative-dialog.hbs", dialogContext)
|
||||
|
||||
const label = game.i18n.localize("LETHALFANTASY.Label.initiative")
|
||||
const rollContext = await foundry.applications.api.DialogV2.wait({
|
||||
@ -603,9 +628,10 @@ export default class LethalFantasyRoll extends Roll {
|
||||
|
||||
}
|
||||
|
||||
/* ***********************************************************/
|
||||
static async promptCombatAction(options = {}) {
|
||||
|
||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const fieldRollMode = new foundry.data.fields.StringField({
|
||||
choices: rollModes,
|
||||
blank: false,
|
||||
@ -619,6 +645,8 @@ export default class LethalFantasyRoll extends Roll {
|
||||
}
|
||||
let currentAction = combatant.getFlag(SYSTEM.id, "currentAction")
|
||||
|
||||
let position = game.user.getFlag(SYSTEM.id, "combat-action-dialog-pos") || { top: -1, left: -1 }
|
||||
|
||||
let dialogContext = {
|
||||
progressionDiceId: "",
|
||||
fieldRollMode,
|
||||
@ -627,7 +655,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
...options
|
||||
}
|
||||
|
||||
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/combat-action-dialog.hbs", dialogContext)
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-lethal-fantasy/templates/combat-action-dialog.hbs", dialogContext)
|
||||
|
||||
let buttons = []
|
||||
if (currentAction) {
|
||||
@ -636,33 +664,45 @@ export default class LethalFantasyRoll extends Roll {
|
||||
action: "roll",
|
||||
label: "Roll progression dice",
|
||||
callback: (event, button, dialog) => {
|
||||
let pos = $('#combat-action-dialog').position()
|
||||
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||
return "rollProgressionDice"
|
||||
},
|
||||
})
|
||||
} else if (currentAction.type === "spell" || currentAction.type === "miracle") {
|
||||
let label = ""
|
||||
if ( currentAction.spellStatus === "castingTime") {
|
||||
if (currentAction.spellStatus === "castingTime") {
|
||||
let pos = $('#combat-action-dialog').position()
|
||||
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||
label = "Wait casting time"
|
||||
}
|
||||
if ( currentAction.spellStatus === "toBeCasted") {
|
||||
if (currentAction.spellStatus === "toBeCasted") {
|
||||
let pos = $('#combat-action-dialog').position()
|
||||
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||
label = "Cast spell/miracle"
|
||||
}
|
||||
if ( currentAction.spellStatus === "lethargy") {
|
||||
if (currentAction.spellStatus === "lethargy") {
|
||||
let pos = $('#combat-action-dialog').position()
|
||||
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", pos)
|
||||
label = "Roll lethargy dice"
|
||||
}
|
||||
buttons.push({
|
||||
action: "roll",
|
||||
label: label,
|
||||
callback: (event, button, dialog) => {
|
||||
return "rollLethargyDice"
|
||||
},
|
||||
})
|
||||
action: "roll",
|
||||
label: label,
|
||||
callback: (event, button, dialog) => {
|
||||
let pos = $('#combat-action-dialog').position()
|
||||
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", foundry.utils.duplicate(pos))
|
||||
return "rollLethargyDice"
|
||||
},
|
||||
})
|
||||
}
|
||||
} else {
|
||||
buttons.push({
|
||||
action: "roll",
|
||||
label: "Select action",
|
||||
callback: (event, button, dialog) => {
|
||||
let pos = $('#combat-action-dialog').position()
|
||||
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", foundry.utils.duplicate(pos))
|
||||
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
||||
if (input.name) obj[input.name] = input.value
|
||||
return obj
|
||||
@ -676,13 +716,17 @@ export default class LethalFantasyRoll extends Roll {
|
||||
action: "cancel",
|
||||
label: "Other action, not listed here",
|
||||
callback: (event, button, dialog) => {
|
||||
let pos = $('#combat-action-dialog').position()
|
||||
game.user.setFlag(SYSTEM.id, "combat-action-dialog-pos", foundry.utils.duplicate(pos))
|
||||
return null;
|
||||
}
|
||||
})
|
||||
|
||||
let rollContext = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Combat Action Dialog" },
|
||||
id: "combat-action-dialog",
|
||||
classes: ["lethalfantasy"],
|
||||
position,
|
||||
content,
|
||||
buttons,
|
||||
rejectClose: false // Click on Close button will not launch an error
|
||||
@ -723,7 +767,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
actionItem.spellStatus = "castingTime"
|
||||
// Set the flag on the combatant
|
||||
await combatant.setFlag(SYSTEM.id, "currentAction", actionItem)
|
||||
let message = `${combatant.name} action : ${selectedItem.name}, start rolling progression dice`
|
||||
let message = `${combatant.name} action : ${selectedItem.name}, start rolling progression dice or casting time`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||
rollContext = (actionItem.type == "weapon") ? "rollProgressionDice" : "rollLethargyDice" // Set the roll context to rollProgressionDice
|
||||
currentAction = actionItem
|
||||
@ -731,15 +775,16 @@ export default class LethalFantasyRoll extends Roll {
|
||||
|
||||
if (currentAction) {
|
||||
if (rollContext === "rollLethargyDice") {
|
||||
if ( currentAction.spellStatus === "castingTime") {
|
||||
if ( currentAction.castingTime < currentAction.system.castingTime) {
|
||||
let message = `Casting time : ${currentAction.name}, count : ${currentAction.castingTime}/${currentAction.system.castingTime}`
|
||||
if (currentAction.spellStatus === "castingTime") {
|
||||
let time = currentAction.type === "spell" ? currentAction.system.castingTime : currentAction.system.prayerTime
|
||||
if (currentAction.castingTime < time) {
|
||||
let message = `Casting time : ${currentAction.name}, count : ${currentAction.castingTime}/${time}`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||
currentAction.castingTime += 1
|
||||
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
||||
return
|
||||
} else {
|
||||
let message = `Spell ${currentAction.name} ready to be cast on next second !`
|
||||
let message = `Spell/Miracle ${currentAction.name} ready to be cast on next second !`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||
currentAction.castingTime = 1
|
||||
currentAction.spellStatus = "toBeCasted"
|
||||
@ -747,8 +792,8 @@ export default class LethalFantasyRoll extends Roll {
|
||||
return
|
||||
}
|
||||
}
|
||||
if ( currentAction.spellStatus === "toBeCasted") {
|
||||
combatant.actor.prepareRoll( (currentAction.type === "spell") ? "spell-attack" : "miracle-attack" , currentAction._id)
|
||||
if (currentAction.spellStatus === "toBeCasted") {
|
||||
combatant.actor.prepareRoll((currentAction.type === "spell") ? "spell-attack" : "miracle-attack", currentAction._id)
|
||||
if (currentAction.type === "spell") {
|
||||
currentAction.spellStatus = "lethargy"
|
||||
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
||||
@ -758,26 +803,29 @@ export default class LethalFantasyRoll extends Roll {
|
||||
}
|
||||
return
|
||||
}
|
||||
if ( currentAction.spellStatus === "lethargy") {
|
||||
if (currentAction.spellStatus === "lethargy") {
|
||||
// Roll lethargy dice
|
||||
let dice = LethalFantasyUtils.getLethargyDice(currentAction.system.level)
|
||||
let roll = new Roll(dice)
|
||||
await roll.evaluate()
|
||||
if (game?.dice3d) {
|
||||
await game.dice3d.showForRoll(roll)
|
||||
}
|
||||
let max = roll.dice[0].faces - 1
|
||||
let toCompare = Math.min(options.rollProgressionCount, max)
|
||||
let toCompare = Math.min(currentAction.progressionCount, max)
|
||||
if (roll.total <= toCompare) {
|
||||
// Notify that the player can act now with a chat message
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyOK", { name: combatant.actor.name, weapon: currentAction.name, roll: roll.total })
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyOK", { name: combatant.actor.name, spellName: currentAction.name, roll: roll.total })
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||
// Update the combatant progression count
|
||||
await combatant.setFlag(SYSTEM.id, "currentAction", "")
|
||||
// Display the action selection window again
|
||||
combatant.actor.system.rollProgressionDice(options.combatId, options.combatantId )
|
||||
combatant.actor.system.rollProgressionDice(options.combatId, options.combatantId)
|
||||
} else {
|
||||
// Notify that the player cannot act now with a chat message
|
||||
currentAction.progressionCount += 1
|
||||
combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyKO", { name: combatant.actor.name, weapon: currentAction.name, roll: roll.total })
|
||||
await combatant.setFlag(SYSTEM.id, "currentAction", foundry.utils.duplicate(currentAction))
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageLethargyKO", { name: combatant.actor.name, spellName: currentAction.name, roll: roll.total })
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: combatant.actor }) })
|
||||
}
|
||||
}
|
||||
@ -839,181 +887,10 @@ export default class LethalFantasyRoll extends Roll {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static async promptProgressionDice(options = {}) {
|
||||
|
||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const fieldRollMode = new foundry.data.fields.StringField({
|
||||
choices: rollModes,
|
||||
blank: false,
|
||||
default: "public",
|
||||
})
|
||||
let dialogContext = {
|
||||
progressionDiceId: "",
|
||||
fieldRollMode,
|
||||
rollModes,
|
||||
...options
|
||||
}
|
||||
|
||||
const content = await renderTemplate("systems/fvtt-lethal-fantasy/templates/roll-progression-dice-dialog.hbs", dialogContext)
|
||||
|
||||
const label = game.i18n.localize("LETHALFANTASY.Label.rollProgressionDice")
|
||||
const rollContext = await foundry.applications.api.DialogV2.wait({
|
||||
window: { title: "Progression Roll" },
|
||||
classes: ["lethalfantasy"],
|
||||
content,
|
||||
buttons: [
|
||||
{
|
||||
action: "roll",
|
||||
label: "Roll Progression Dice or Continue Loading",
|
||||
callback: (event, button, dialog) => {
|
||||
const output = Array.from(button.form.elements).reduce((obj, input) => {
|
||||
if (input.name) obj[input.name] = input.value
|
||||
return obj
|
||||
}, {})
|
||||
return output
|
||||
},
|
||||
},
|
||||
{
|
||||
action: "cast",
|
||||
label: "Cast a spell",
|
||||
callback: (event, button, dialog) => {
|
||||
return "casting"
|
||||
},
|
||||
},
|
||||
{
|
||||
action: "cancel",
|
||||
label: "Other action, no progression dice",
|
||||
callback: (event, button, dialog) => {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
],
|
||||
rejectClose: false // Click on Close button will not launch an error
|
||||
})
|
||||
|
||||
console.log("RollContext", dialogContext, rollContext)
|
||||
let combat = game.combats.get(options.combatId)
|
||||
let actor = game.actors.get(options.actorId)
|
||||
|
||||
if (rollContext === "casting") {
|
||||
combat.setCasting(options.combatantId)
|
||||
let message = `Starting casting a spell !`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
||||
return
|
||||
}
|
||||
|
||||
if (rollContext === null || !rollContext?.progressionDiceId) {
|
||||
c.resetCasting(options.combatantId)
|
||||
combat.resetProgression(options.combatantId)
|
||||
let message = `${actor.name} : Other action, progression reset`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Get the weapons from the actor items
|
||||
let rangedMode
|
||||
let searchId = rollContext.progressionDiceId
|
||||
if (searchId.match("simpleAim")) {
|
||||
searchId = searchId.replace("simpleAim", "")
|
||||
rangedMode = "simpleAim"
|
||||
}
|
||||
if (searchId.match("carefulAim")) {
|
||||
searchId = searchId.replace("carefulAim", "")
|
||||
rangedMode = "carefulAim"
|
||||
}
|
||||
if (searchId.match("focusedAim")) {
|
||||
searchId = searchId.replace("focusedAim", "")
|
||||
rangedMode = "focusedAim"
|
||||
}
|
||||
|
||||
if (searchId.match("spell")) {
|
||||
searchId = searchId.replace("spell", "")
|
||||
let spell = actor.items.find(i => i.type === "spell" && i.id === searchId)
|
||||
let dice = LethalFantasyUtils.getLethargyDice(spell.system.level)
|
||||
if (combat.isCasting(options.combatantId)) {
|
||||
if (options.rollProgressionCount <= spell.system.castingTime) {
|
||||
let message = `Spell casting time : ${spell.name}, count : ${options.rollProgressionCount}/${spell.system.castingTime}`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
||||
return
|
||||
}
|
||||
if (options.rollProgressionCount > spell.system.castingTime) {
|
||||
let message = `Spell ${spell.name} has been cast !`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
||||
combat.resetCasting(options.combatantId)
|
||||
combat.resetProgression(options.combatantId)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
let formula = dice
|
||||
let roll = new Roll(formula)
|
||||
await roll.evaluate()
|
||||
let max = roll.dice[0].faces - 1
|
||||
let toCompare = Math.min(options.rollProgressionCount, max)
|
||||
let message
|
||||
if (roll.total > toCompare) {
|
||||
message = `Spell Lethargy ongoing ... (${roll.total}/${toCompare}, spell level ${spell.system.level})`
|
||||
} else {
|
||||
combat.resetProgression(options.combatantId)
|
||||
message = `Spell Lethargy ended ! (${roll.total}/${toCompare}, spell level ${spell.system.level})<br>${actor.name} can return to normal actions.`
|
||||
}
|
||||
let msg = await roll.toMessage({ flavor: message }, { rollMode: rollContext.visibility })
|
||||
if (game?.dice3d) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let weapon = actor.items.find(i => i.type === "weapon" && i.id === searchId)
|
||||
let formula = weapon.system.combatProgressionDice
|
||||
|
||||
let rangedLoad
|
||||
if (rangedMode) {
|
||||
let toSplit = weapon.system.speed[rangedMode]
|
||||
let split = toSplit.split("+")
|
||||
rangedLoad = Number(split[0]) || 0
|
||||
formula = split[1]
|
||||
console.log("Ranged Mode", rangedMode, rangedLoad, formula, options.rollProgressionCount)
|
||||
}
|
||||
|
||||
if (rangedLoad && options.rollProgressionCount <= rangedLoad) {
|
||||
let message = `Ranged weapon ${weapon.name} is loading, loading count : ${options.rollProgressionCount}/${rangedLoad}`
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
||||
return
|
||||
}
|
||||
|
||||
let isMonster = actor.type === "monster"
|
||||
// Get the dice and roll it if
|
||||
let roll = new Roll(formula)
|
||||
await roll.evaluate()
|
||||
|
||||
let max = roll.dice[0].faces - 1
|
||||
max = Math.min(options.rollProgressionCount, max)
|
||||
let msg = await roll.toMessage({ flavor: `Progression Roll for ${weapon.name}, progression count : ${options.rollProgressionCount}/${max}` }, { rollMode: rollContext.visibility })
|
||||
if (game?.dice3d) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
||||
}
|
||||
|
||||
if (roll.total <= max) {
|
||||
// Notify that the player can act now with a chat message
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionOK", { isMonster, name: actor.name, weapon: weapon.name, roll: roll.total })
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
||||
// Update the combatant progression count
|
||||
let combat = game.combats.get(options.combatId)
|
||||
let combatant = combat.combatants.get(options.combatantId)
|
||||
combatant.update({ 'system.progressionCount': 0 })
|
||||
} else {
|
||||
// Notify that the player cannot act now with a chat message
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionKO", { isMonster, name: actor.name, weapon: weapon.name, roll: roll.total })
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: actor }) })
|
||||
}
|
||||
}
|
||||
|
||||
/* ***********************************************************/
|
||||
static async promptRangedDefense(rollTarget) {
|
||||
|
||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes); // v12 : Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const fieldRollMode = new foundry.data.fields.StringField({
|
||||
choices: rollModes,
|
||||
blank: false,
|
||||
@ -1176,7 +1053,7 @@ export default class LethalFantasyRoll extends Roll {
|
||||
async render(chatOptions = {}) {
|
||||
let chatData = await this._getChatCardData(chatOptions.isPrivate)
|
||||
console.log("ChatData", chatData)
|
||||
return await renderTemplate(this.constructor.CHAT_TEMPLATE, chatData)
|
||||
return await foundry.applications.handlebars.renderTemplate(this.constructor.CHAT_TEMPLATE, chatData)
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -174,6 +174,31 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["LETHALFANTASY.Character"]
|
||||
|
||||
static migrateData(data) {
|
||||
if (data?.biodata?.mortal) {
|
||||
if (!SYSTEM.MORTAL_CHOICES[data.biodata.mortal]) {
|
||||
for (let key in SYSTEM.MORTAL_CHOICES) {
|
||||
let mortal = SYSTEM.MORTAL_CHOICES[key]
|
||||
if ( mortal.label.toLowerCase() === data.biodata.mortal.toLowerCase()) {
|
||||
data.biodata.mortal = mortal.id
|
||||
}
|
||||
if ( data.biodata.mortal.toLowerCase().includes("shire")) {
|
||||
data.biodata.mortal = "halflings"
|
||||
}
|
||||
if ( data.biodata.mortal.toLowerCase().includes("human")) {
|
||||
data.biodata.mortal = "mankind"
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!SYSTEM.MORTAL_CHOICES[data.biodata.mortal]) {
|
||||
console.warn("Lethal Fantasy | Migrate data: Mortal not found, forced to mankind", data.biodata.mortal)
|
||||
data.biodata.mortal = "mankind"
|
||||
}
|
||||
}
|
||||
|
||||
return super.migrateData(data)
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
let grit = 0
|
||||
@ -275,7 +300,7 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
||||
actorName: this.parent.name,
|
||||
actorImage: this.parent.img,
|
||||
combatId,
|
||||
combatantId ,
|
||||
combatantId,
|
||||
actorClass,
|
||||
maxInit,
|
||||
})
|
||||
@ -298,8 +323,17 @@ export default class LethalFantasyCharacter extends foundry.abstract.TypeDataMod
|
||||
if (this.biodata.magicUser || this.biodata.clericUser) {
|
||||
let spells = this.parent.items.filter(i => i.type === "spell" || i.type === "miracle")
|
||||
for (let s of spells) {
|
||||
let dice = LethalFantasyUtils.getLethargyDice(s.system.level)
|
||||
weaponsChoices.push({ id: s.id, name: `${s.name} (Time: ${s.system.castingTime}, Lethargy: ${dice})`, combatProgressionDice: `${s.system.castingTime}+${dice}` })
|
||||
let title = ""
|
||||
let formula = ""
|
||||
if (s.type === "spell") {
|
||||
let dice = LethalFantasyUtils.getLethargyDice(s.system.level)
|
||||
title = `${s.name} (Casting time: ${s.system.castingTime}, Lethargy: ${dice})`
|
||||
formula = `${s.system.castingTime}+${dice}`
|
||||
} else {
|
||||
title = `${s.name} (Prayer time: ${s.system.prayerTime})`
|
||||
formula = `${s.system.prayerTime}`
|
||||
}
|
||||
weaponsChoices.push({ id: s.id, name: title, combatProgressionDice: formula })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,12 +76,16 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
}
|
||||
return new fields.SchemaField(schema, { label })
|
||||
}
|
||||
// Add 4 attackFields in an attack schema
|
||||
// Add 4 attackFields in an attack schema
|
||||
schema.attacks = new fields.SchemaField({
|
||||
attack1: attackField("1"),
|
||||
attack2: attackField("2"),
|
||||
attack3: attackField("3"),
|
||||
attack4: attackField("4"),
|
||||
attack5: attackField("5"),
|
||||
attack6: attackField("6"),
|
||||
attack7: attackField("7"),
|
||||
attack8: attackField("8")
|
||||
})
|
||||
|
||||
schema.perception = new fields.SchemaField({
|
||||
@ -145,6 +149,74 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
||||
}
|
||||
|
||||
async prepareMonsterRoll(rollType, rollKey, rollDice = undefined, tokenId = undefined) {
|
||||
let rollTarget
|
||||
switch (rollType) {
|
||||
case "monster-attack":
|
||||
case "monster-defense":
|
||||
case "monster-damage":
|
||||
rollTarget = foundry.utils.duplicate(this.attacks[rollKey])
|
||||
rollTarget.rollKey = rollKey
|
||||
break
|
||||
case "monster-skill":
|
||||
rollTarget = foundry.utils.duplicate(this.resists[rollKey])
|
||||
rollTarget.rollKey = rollKey
|
||||
break
|
||||
case "save":
|
||||
rollTarget = foundry.utils.duplicate(this.saves[rollKey])
|
||||
rollTarget.rollKey = rollKey
|
||||
rollTarget.rollDice = rollDice
|
||||
break
|
||||
case "weapon-damage-small":
|
||||
case "weapon-damage-medium":
|
||||
case "weapon-attack":
|
||||
case "weapon-defense":
|
||||
let weapon = this.actor.items.find((i) => i.type === "weapon" && i.id === rollKey)
|
||||
let skill
|
||||
let skills = this.actor.items.filter((i) => i.type === "skill" && i.name.toLowerCase() === weapon.name.toLowerCase())
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
||||
} else {
|
||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.name.toLowerCase().replace(" skill", "") === weapon.name.toLowerCase())
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
|
||||
} else {
|
||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass === weapon.system.weaponClass)
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 0.5)
|
||||
} else {
|
||||
skills = this.actor.items.filter((i) => i.type === "skill" && i.system.weaponClass.includes(SYSTEM.WEAPON_CATEGORIES[weapon.system.weaponClass]))
|
||||
if (skills.length > 0) {
|
||||
skill = this.getBestWeaponClassSkill(skills, rollType, 0.25)
|
||||
} else {
|
||||
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!weapon || !skill) {
|
||||
console.error("Weapon or skill not found", weapon, skill)
|
||||
ui.notifications.warn(game.i18n.localize("LETHALFANTASY.Notifications.skillNotFound"))
|
||||
return
|
||||
}
|
||||
rollTarget = skill
|
||||
rollTarget.weapon = weapon
|
||||
rollTarget.weaponSkillModifier = skill.weaponSkillModifier
|
||||
rollTarget.rollKey = rollKey
|
||||
rollTarget.combat = foundry.utils.duplicate(this.combat)
|
||||
break
|
||||
default:
|
||||
ui.notifications.error(game.i18n.localize("LETHALFANTASY.Notifications.rollTypeNotFound") + String(rollType))
|
||||
break
|
||||
}
|
||||
|
||||
// In all cases
|
||||
rollTarget.tokenId = tokenId
|
||||
console.log(rollTarget)
|
||||
await this.roll(rollType, rollTarget)
|
||||
}
|
||||
|
||||
async rollInitiative(combatId = undefined, combatantId = undefined) {
|
||||
const hasTarget = false
|
||||
|
||||
@ -164,9 +236,9 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
await roll.toMessage({}, { rollMode: roll.options.rollMode })
|
||||
}
|
||||
|
||||
async rollProgressionDice(combatId, combatantId, rollProgressionCount) {
|
||||
async rollProgressionDice(combatId, combatantId) {
|
||||
|
||||
const rollModes = Object.fromEntries(Object.entries(CONFIG.Dice.rollModes).map(([key, value]) => [key, game.i18n.localize(value)]))
|
||||
const rollModes = foundry.utils.duplicate(CONFIG.Dice.rollModes)
|
||||
const fieldRollMode = new foundry.data.fields.StringField({
|
||||
choices: rollModes,
|
||||
blank: false,
|
||||
@ -175,7 +247,8 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
|
||||
let roll = new Roll("1D8")
|
||||
await roll.evaluate()
|
||||
let max = rollProgressionCount
|
||||
let combatant = game.combats.get(combatId)?.combatants?.get(combatantId)
|
||||
|
||||
let msg = await roll.toMessage({ flavor: `Progression Roll for ${this.parent.name}` } )
|
||||
if (game?.dice3d) {
|
||||
await game.dice3d.waitFor3DAnimationByMessageID(msg.id)
|
||||
@ -188,14 +261,19 @@ export default class LethalFantasyMonster extends foundry.abstract.TypeDataModel
|
||||
hasAttack = true
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionOKMonster", { isMonster: true, name: this.parent.name, weapon: attack.name, roll: roll.total })
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: this.parent }) })
|
||||
let token = combatant?.token
|
||||
this.prepareMonsterRoll("monster-attack", key, undefined, token?.id)
|
||||
if ( token?.object ) {
|
||||
token.object?.control({releaseOthers: true});
|
||||
return canvas.animatePan(token.object.center);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasAttack) {
|
||||
let message = game.i18n.format("LETHALFANTASY.Notifications.messageProgressionKOMonster", { isMonster: true, name: this.parent.name, roll: roll.total })
|
||||
ChatMessage.create({ content: message, speaker: ChatMessage.getSpeaker({ actor: this.parent }) })
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ export default class LethalFantasyShield extends foundry.abstract.TypeDataModel
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.defense = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.SHIELD_DEFENSE_DICE})
|
||||
schema.movementreduction = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.hascover = new fields.BooleanField({ required: true, initial: false })
|
||||
schema.hascover = new fields.BooleanField({ required: true, initial: false })
|
||||
|
||||
schema.standing = new fields.SchemaField({
|
||||
min: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
|
@ -9,33 +9,33 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE })
|
||||
schema.weaponClass = new fields.StringField({ required: true, initial: "shortblade", choices: SYSTEM.WEAPON_CLASS })
|
||||
|
||||
schema.damageType = new fields.SchemaField({
|
||||
|
||||
schema.damageType = new fields.SchemaField({
|
||||
typeP: new fields.BooleanField(),
|
||||
typeB: new fields.BooleanField(),
|
||||
typeS: new fields.BooleanField()
|
||||
})
|
||||
schema.damage = new fields.SchemaField({
|
||||
schema.damage = new fields.SchemaField({
|
||||
damageS: new fields.StringField({required: true, initial: ""}),
|
||||
damageM: new fields.StringField({required: true, initial: ""})
|
||||
})
|
||||
schema.applyStrengthDamageBonus = new fields.BooleanField({ required: true, initial: true })
|
||||
|
||||
|
||||
schema.hands = new fields.StringField({ required: true, initial: "1", choices: {"1": "1", "2": "2"} })
|
||||
schema.isAgile = new fields.BooleanField({ required: true, initial: false })
|
||||
|
||||
|
||||
schema.defenseMax = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.secondsToAttack = new fields.StringField({required: true, initial: ""})
|
||||
schema.combatProgressionDice = new fields.StringField({required: true, initial: "d4", choices: SYSTEM.COMBAT_PROGRESSION_DICE})
|
||||
|
||||
schema.speed = new fields.SchemaField({
|
||||
schema.speed = new fields.SchemaField({
|
||||
simpleAim: new fields.StringField({required: true, initial: ""}),
|
||||
carefulAim: new fields.StringField({required: true, initial: ""}),
|
||||
focusedAim: new fields.StringField({required: true, initial: ""})
|
||||
})
|
||||
|
||||
schema.defense = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
schema.weaponRange = new fields.SchemaField({
|
||||
schema.weaponRange = new fields.SchemaField({
|
||||
pointBlank: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
short: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
medium: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
@ -44,7 +44,7 @@ export default class LethalFantasySkill extends foundry.abstract.TypeDataModel {
|
||||
outOfSkill: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
})
|
||||
|
||||
schema.bonuses = new fields.SchemaField({
|
||||
schema.bonuses = new fields.SchemaField({
|
||||
attackBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
damageBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }),
|
||||
defenseBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 })
|
||||
|
@ -18,6 +18,51 @@ export default class LethalFantasyUtils {
|
||||
options.push({ name: "Reset Progression", condition: true, icon: '<i class="fas fa-rotate-right"></i>', callback: target => { game.combat.resetProgression(target.data('combatant-id')); } })
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static setHookListeners() {
|
||||
|
||||
Hooks.on('renderTokenHUD', async (hud, html, token) => {
|
||||
const lossHPButton = await foundry.applications.handlebars.renderTemplate('systems/fvtt-lethal-fantasy/templates/loss-hp-hud.hbs', {} )
|
||||
$(html).find('div.left').append(lossHPButton);
|
||||
$(html).find('img.lethal-hp-loss-hud').click((event) => {
|
||||
event.preventDefault();
|
||||
let hpMenu = $(html).find('.hp-loss-wrap')[0]
|
||||
if (hpMenu.classList.contains("hp-loss-hud-disabled")) {
|
||||
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-disabled');
|
||||
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-disabled');
|
||||
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-disabled');
|
||||
} else {
|
||||
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
|
||||
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
|
||||
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
|
||||
}
|
||||
})
|
||||
$(html).find('.loss-hp-hud-click').click((event) => {
|
||||
event.preventDefault();
|
||||
let hpLoss = event.currentTarget.dataset.hpValue;
|
||||
if (token) {
|
||||
let tokenFull = canvas.tokens.placeables.find( t => t.id === token._id);
|
||||
console.log(tokenFull, token)
|
||||
let actor = tokenFull.actor;
|
||||
actor.applyDamage(Number(hpLoss));
|
||||
$(html).find('.hp-loss-wrap')[0].classList.remove('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[0].classList.add('hp-loss-hud-disabled');
|
||||
$(html).find('.hp-loss-wrap')[1].classList.remove('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[1].classList.add('hp-loss-hud-disabled');
|
||||
$(html).find('.hp-loss-wrap')[2].classList.remove('hp-loss-hud-active');
|
||||
$(html).find('.hp-loss-wrap')[2].classList.add('hp-loss-hud-disabled');
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static handleSocketEvent(msg = {}) {
|
||||
console.log(`handleSocketEvent !`, msg)
|
||||
let actor
|
||||
|
Binary file not shown.
BIN
packs-system/lf-equipment/000323.ldb
Normal file
BIN
packs-system/lf-equipment/000323.ldb
Normal file
Binary file not shown.
@ -1 +1 @@
|
||||
MANIFEST-000219
|
||||
MANIFEST-000348
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/21-17:09:30.765172 7f5dceffd6c0 Recovering log #217
|
||||
2025/04/21-17:09:30.774995 7f5dceffd6c0 Delete type=3 #215
|
||||
2025/04/21-17:09:30.775106 7f5dceffd6c0 Delete type=0 #217
|
||||
2025/04/21-17:40:19.481504 7f5dcd3ff6c0 Level-0 table #222: started
|
||||
2025/04/21-17:40:19.481549 7f5dcd3ff6c0 Level-0 table #222: 0 bytes OK
|
||||
2025/04/21-17:40:19.518709 7f5dcd3ff6c0 Delete type=0 #220
|
||||
2025/04/21-17:40:19.572101 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 0 : 0; will stop at (end)
|
||||
2025/04/21-17:40:19.634424 7f5dcd3ff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-16:36:11.138560 7f53e4df86c0 Recovering log #346
|
||||
2025/05/29-16:36:11.150394 7f53e4df86c0 Delete type=3 #344
|
||||
2025/05/29-16:36:11.150472 7f53e4df86c0 Delete type=0 #346
|
||||
2025/05/29-18:48:12.764595 7f53df3ff6c0 Level-0 table #351: started
|
||||
2025/05/29-18:48:12.764652 7f53df3ff6c0 Level-0 table #351: 0 bytes OK
|
||||
2025/05/29-18:48:12.777058 7f53df3ff6c0 Delete type=0 #349
|
||||
2025/05/29-18:48:12.800778 7f53df3ff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-18:48:12.800877 7f53df3ff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/17-17:21:12.564483 7f5c837fe6c0 Recovering log #213
|
||||
2025/04/17-17:21:12.575284 7f5c837fe6c0 Delete type=3 #211
|
||||
2025/04/17-17:21:12.575342 7f5c837fe6c0 Delete type=0 #213
|
||||
2025/04/17-17:34:42.493086 7f5c81bff6c0 Level-0 table #218: started
|
||||
2025/04/17-17:34:42.493111 7f5c81bff6c0 Level-0 table #218: 0 bytes OK
|
||||
2025/04/17-17:34:42.499036 7f5c81bff6c0 Delete type=0 #216
|
||||
2025/04/17-17:34:42.518959 7f5c81bff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 0 : 0; will stop at (end)
|
||||
2025/04/17-17:34:42.519032 7f5c81bff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!znm6T1ef4qQI8BX7' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-18:45:28.754313 7f53737fe6c0 Recovering log #342
|
||||
2025/05/22-18:45:28.804653 7f53737fe6c0 Delete type=3 #340
|
||||
2025/05/22-18:45:28.804783 7f53737fe6c0 Delete type=0 #342
|
||||
2025/05/22-19:43:04.046497 7f53723ff6c0 Level-0 table #347: started
|
||||
2025/05/22-19:43:04.046522 7f53723ff6c0 Level-0 table #347: 0 bytes OK
|
||||
2025/05/22-19:43:04.084205 7f53723ff6c0 Delete type=0 #345
|
||||
2025/05/22-19:43:04.153359 7f53723ff6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-19:43:04.153400 7f53723ff6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
|
||||
|
Binary file not shown.
BIN
packs-system/lf-equipment/MANIFEST-000348
Normal file
BIN
packs-system/lf-equipment/MANIFEST-000348
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs-system/lf-gifts/000322.ldb
Normal file
BIN
packs-system/lf-gifts/000322.ldb
Normal file
Binary file not shown.
@ -1 +1 @@
|
||||
MANIFEST-000218
|
||||
MANIFEST-000347
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/21-17:09:30.778463 7f5dcdffb6c0 Recovering log #216
|
||||
2025/04/21-17:09:30.789411 7f5dcdffb6c0 Delete type=3 #214
|
||||
2025/04/21-17:09:30.789468 7f5dcdffb6c0 Delete type=0 #216
|
||||
2025/04/21-17:40:19.406720 7f5dcd3ff6c0 Level-0 table #221: started
|
||||
2025/04/21-17:40:19.406774 7f5dcd3ff6c0 Level-0 table #221: 0 bytes OK
|
||||
2025/04/21-17:40:19.446347 7f5dcd3ff6c0 Delete type=0 #219
|
||||
2025/04/21-17:40:19.572073 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
2025/04/21-17:40:19.572119 7f5dcd3ff6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-16:36:11.158130 7f53e5dfa6c0 Recovering log #345
|
||||
2025/05/29-16:36:11.168794 7f53e5dfa6c0 Delete type=3 #343
|
||||
2025/05/29-16:36:11.168968 7f53e5dfa6c0 Delete type=0 #345
|
||||
2025/05/29-18:48:12.777345 7f53df3ff6c0 Level-0 table #350: started
|
||||
2025/05/29-18:48:12.777387 7f53df3ff6c0 Level-0 table #350: 0 bytes OK
|
||||
2025/05/29-18:48:12.788225 7f53df3ff6c0 Delete type=0 #348
|
||||
2025/05/29-18:48:12.800802 7f53df3ff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-18:48:12.800914 7f53df3ff6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/17-17:21:12.578876 7f5c82ffd6c0 Recovering log #212
|
||||
2025/04/17-17:21:12.589060 7f5c82ffd6c0 Delete type=3 #210
|
||||
2025/04/17-17:21:12.589120 7f5c82ffd6c0 Delete type=0 #212
|
||||
2025/04/17-17:34:42.486913 7f5c81bff6c0 Level-0 table #217: started
|
||||
2025/04/17-17:34:42.486964 7f5c81bff6c0 Level-0 table #217: 0 bytes OK
|
||||
2025/04/17-17:34:42.492952 7f5c81bff6c0 Delete type=0 #215
|
||||
2025/04/17-17:34:42.518936 7f5c81bff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
2025/04/17-17:34:42.519016 7f5c81bff6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-18:45:28.835173 7f5373fff6c0 Recovering log #341
|
||||
2025/05/22-18:45:28.894795 7f5373fff6c0 Delete type=3 #339
|
||||
2025/05/22-18:45:28.894867 7f5373fff6c0 Delete type=0 #341
|
||||
2025/05/22-19:43:04.009442 7f53723ff6c0 Level-0 table #346: started
|
||||
2025/05/22-19:43:04.009522 7f53723ff6c0 Level-0 table #346: 0 bytes OK
|
||||
2025/05/22-19:43:04.046375 7f53723ff6c0 Delete type=0 #344
|
||||
2025/05/22-19:43:04.153344 7f53723ff6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-19:43:04.153392 7f53723ff6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!zjvGljrLk5SshC9D' @ 0 : 0; will stop at (end)
|
||||
|
Binary file not shown.
BIN
packs-system/lf-gifts/MANIFEST-000347
Normal file
BIN
packs-system/lf-gifts/MANIFEST-000347
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs-system/lf-skills/000322.ldb
Normal file
BIN
packs-system/lf-skills/000322.ldb
Normal file
Binary file not shown.
@ -1 +1 @@
|
||||
MANIFEST-000218
|
||||
MANIFEST-000347
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/21-17:09:30.749204 7f5dce7fc6c0 Recovering log #216
|
||||
2025/04/21-17:09:30.759893 7f5dce7fc6c0 Delete type=3 #214
|
||||
2025/04/21-17:09:30.760044 7f5dce7fc6c0 Delete type=0 #216
|
||||
2025/04/21-17:40:19.292988 7f5dcd3ff6c0 Level-0 table #221: started
|
||||
2025/04/21-17:40:19.293026 7f5dcd3ff6c0 Level-0 table #221: 0 bytes OK
|
||||
2025/04/21-17:40:19.329102 7f5dcd3ff6c0 Delete type=0 #219
|
||||
2025/04/21-17:40:19.406586 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
2025/04/21-17:40:19.406620 7f5dcd3ff6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-16:36:11.123463 7f53e55f96c0 Recovering log #345
|
||||
2025/05/29-16:36:11.133586 7f53e55f96c0 Delete type=3 #343
|
||||
2025/05/29-16:36:11.133663 7f53e55f96c0 Delete type=0 #345
|
||||
2025/05/29-18:48:12.753680 7f53df3ff6c0 Level-0 table #350: started
|
||||
2025/05/29-18:48:12.753732 7f53df3ff6c0 Level-0 table #350: 0 bytes OK
|
||||
2025/05/29-18:48:12.764334 7f53df3ff6c0 Delete type=0 #348
|
||||
2025/05/29-18:48:12.800724 7f53df3ff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-18:48:12.800854 7f53df3ff6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/17-17:21:12.549824 7f5c827fc6c0 Recovering log #212
|
||||
2025/04/17-17:21:12.560061 7f5c827fc6c0 Delete type=3 #210
|
||||
2025/04/17-17:21:12.560203 7f5c827fc6c0 Delete type=0 #212
|
||||
2025/04/17-17:34:42.505447 7f5c81bff6c0 Level-0 table #217: started
|
||||
2025/04/17-17:34:42.505471 7f5c81bff6c0 Level-0 table #217: 0 bytes OK
|
||||
2025/04/17-17:34:42.518767 7f5c81bff6c0 Delete type=0 #215
|
||||
2025/04/17-17:34:42.518998 7f5c81bff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
2025/04/17-17:34:42.519066 7f5c81bff6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-18:45:28.668409 7f5378bfa6c0 Recovering log #341
|
||||
2025/05/22-18:45:28.725273 7f5378bfa6c0 Delete type=3 #339
|
||||
2025/05/22-18:45:28.725349 7f5378bfa6c0 Delete type=0 #341
|
||||
2025/05/22-19:43:04.084321 7f53723ff6c0 Level-0 table #346: started
|
||||
2025/05/22-19:43:04.084343 7f53723ff6c0 Level-0 table #346: 0 bytes OK
|
||||
2025/05/22-19:43:04.122081 7f53723ff6c0 Delete type=0 #344
|
||||
2025/05/22-19:43:04.153372 7f53723ff6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-19:43:04.153416 7f53723ff6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
|
||||
|
Binary file not shown.
BIN
packs-system/lf-skills/MANIFEST-000347
Normal file
BIN
packs-system/lf-skills/MANIFEST-000347
Normal file
Binary file not shown.
BIN
packs-system/lf-spells-miracles/000022.ldb
Normal file
BIN
packs-system/lf-spells-miracles/000022.ldb
Normal file
Binary file not shown.
1
packs-system/lf-spells-miracles/CURRENT
Normal file
1
packs-system/lf-spells-miracles/CURRENT
Normal file
@ -0,0 +1 @@
|
||||
MANIFEST-000047
|
0
packs-system/lf-spells-miracles/LOCK
Normal file
0
packs-system/lf-spells-miracles/LOCK
Normal file
8
packs-system/lf-spells-miracles/LOG
Normal file
8
packs-system/lf-spells-miracles/LOG
Normal file
@ -0,0 +1,8 @@
|
||||
2025/05/29-16:36:11.187985 7f53e4df86c0 Recovering log #45
|
||||
2025/05/29-16:36:11.199498 7f53e4df86c0 Delete type=3 #43
|
||||
2025/05/29-16:36:11.199566 7f53e4df86c0 Delete type=0 #45
|
||||
2025/05/29-18:48:12.801134 7f53df3ff6c0 Level-0 table #50: started
|
||||
2025/05/29-18:48:12.801185 7f53df3ff6c0 Level-0 table #50: 0 bytes OK
|
||||
2025/05/29-18:48:12.810101 7f53df3ff6c0 Delete type=0 #48
|
||||
2025/05/29-18:48:12.859825 7f53df3ff6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-18:48:12.859922 7f53df3ff6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
|
8
packs-system/lf-spells-miracles/LOG.old
Normal file
8
packs-system/lf-spells-miracles/LOG.old
Normal file
@ -0,0 +1,8 @@
|
||||
2025/05/22-18:45:28.985810 7f5372ffd6c0 Recovering log #41
|
||||
2025/05/22-18:45:29.040662 7f5372ffd6c0 Delete type=3 #39
|
||||
2025/05/22-18:45:29.040742 7f5372ffd6c0 Delete type=0 #41
|
||||
2025/05/22-19:43:04.281148 7f53723ff6c0 Level-0 table #46: started
|
||||
2025/05/22-19:43:04.281205 7f53723ff6c0 Level-0 table #46: 0 bytes OK
|
||||
2025/05/22-19:43:04.315875 7f53723ff6c0 Delete type=0 #44
|
||||
2025/05/22-19:43:04.316126 7f53723ff6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-19:43:04.366588 7f53723ff6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
|
BIN
packs-system/lf-spells-miracles/MANIFEST-000047
Normal file
BIN
packs-system/lf-spells-miracles/MANIFEST-000047
Normal file
Binary file not shown.
Binary file not shown.
BIN
packs-system/lf-vulnerabilities/000322.ldb
Normal file
BIN
packs-system/lf-vulnerabilities/000322.ldb
Normal file
Binary file not shown.
0
packs-system/lf-vulnerabilities/000349.log
Normal file
0
packs-system/lf-vulnerabilities/000349.log
Normal file
@ -1 +1 @@
|
||||
MANIFEST-000218
|
||||
MANIFEST-000347
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/21-17:09:30.792733 7f5dcf7fe6c0 Recovering log #216
|
||||
2025/04/21-17:09:30.802787 7f5dcf7fe6c0 Delete type=3 #214
|
||||
2025/04/21-17:09:30.802873 7f5dcf7fe6c0 Delete type=0 #216
|
||||
2025/04/21-17:40:19.329256 7f5dcd3ff6c0 Level-0 table #221: started
|
||||
2025/04/21-17:40:19.329290 7f5dcd3ff6c0 Level-0 table #221: 0 bytes OK
|
||||
2025/04/21-17:40:19.360850 7f5dcd3ff6c0 Delete type=0 #219
|
||||
2025/04/21-17:40:19.406600 7f5dcd3ff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
2025/04/21-17:40:19.406634 7f5dcd3ff6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-16:36:11.172412 7f53e55f96c0 Recovering log #345
|
||||
2025/05/29-16:36:11.183464 7f53e55f96c0 Delete type=3 #343
|
||||
2025/05/29-16:36:11.183540 7f53e55f96c0 Delete type=0 #345
|
||||
2025/05/29-18:48:12.788378 7f53df3ff6c0 Level-0 table #350: started
|
||||
2025/05/29-18:48:12.788406 7f53df3ff6c0 Level-0 table #350: 0 bytes OK
|
||||
2025/05/29-18:48:12.800425 7f53df3ff6c0 Delete type=0 #348
|
||||
2025/05/29-18:48:12.800827 7f53df3ff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
2025/05/29-18:48:12.800943 7f53df3ff6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
|
@ -1,8 +1,8 @@
|
||||
2025/04/17-17:21:12.592168 7f5c83fff6c0 Recovering log #212
|
||||
2025/04/17-17:21:12.602692 7f5c83fff6c0 Delete type=3 #210
|
||||
2025/04/17-17:21:12.602743 7f5c83fff6c0 Delete type=0 #212
|
||||
2025/04/17-17:34:42.499156 7f5c81bff6c0 Level-0 table #217: started
|
||||
2025/04/17-17:34:42.499188 7f5c81bff6c0 Level-0 table #217: 0 bytes OK
|
||||
2025/04/17-17:34:42.505329 7f5c81bff6c0 Delete type=0 #215
|
||||
2025/04/17-17:34:42.518977 7f5c81bff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
2025/04/17-17:34:42.519047 7f5c81bff6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-18:45:28.912541 7f5378bfa6c0 Recovering log #341
|
||||
2025/05/22-18:45:28.969080 7f5378bfa6c0 Delete type=3 #339
|
||||
2025/05/22-18:45:28.969151 7f5378bfa6c0 Delete type=0 #341
|
||||
2025/05/22-19:43:04.122198 7f53723ff6c0 Level-0 table #346: started
|
||||
2025/05/22-19:43:04.122219 7f53723ff6c0 Level-0 table #346: 0 bytes OK
|
||||
2025/05/22-19:43:04.153184 7f53723ff6c0 Delete type=0 #344
|
||||
2025/05/22-19:43:04.153383 7f53723ff6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
2025/05/22-19:43:04.153407 7f53723ff6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
|
||||
|
Binary file not shown.
BIN
packs-system/lf-vulnerabilities/MANIFEST-000347
Normal file
BIN
packs-system/lf-vulnerabilities/MANIFEST-000347
Normal file
Binary file not shown.
@ -1,21 +0,0 @@
|
||||
#lethalfantasy-application-manager {
|
||||
display: flex;
|
||||
|
||||
font-family: var(--font-primary);
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
color: var(--color-dark-1);
|
||||
background-image: var(--background-image-base);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.lethalfantasy-table {
|
||||
margin: 1rem;
|
||||
background: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
.player {
|
||||
font-size: calc(var(--font-size-standard) * 1);
|
||||
}
|
||||
}
|
||||
}
|
@ -93,6 +93,10 @@
|
||||
.character-characteristic {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
span {
|
||||
min-width: 2.2rem;
|
||||
max-width: 2.2rem;
|
||||
}
|
||||
.rollable:hover,
|
||||
.rollable:focus {
|
||||
text-shadow: 0 0 8px var(--color-shadow-primary);
|
||||
@ -108,7 +112,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.character-challenges {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -218,7 +222,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab.character-biography {
|
||||
.tab.character-biography .main-div{
|
||||
.biodata {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
@ -248,7 +252,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab.character-skills {
|
||||
.tab.character-skills .main-div{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
legend {
|
||||
@ -310,7 +314,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab.character-equipment {
|
||||
.tab.character-equipment .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
legend {
|
||||
@ -349,7 +353,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab.character-combat {
|
||||
.tab.character-combat .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
legend {
|
||||
@ -497,7 +501,7 @@
|
||||
|
||||
}
|
||||
|
||||
.tab.character-spells {
|
||||
.tab.character-spells .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
legend {
|
||||
@ -558,7 +562,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab.character-miracles {
|
||||
.tab.character-miracles .main-div {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
legend {
|
||||
|
@ -5,6 +5,5 @@
|
||||
|
||||
@font-face {
|
||||
font-family: "BaskervilleBold";
|
||||
src: url("../fonts/baskerville-bold.ttf") format("truetype");
|
||||
src: url("../assets/fonts/baskerville-bold.ttf") format("truetype");
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
@import "weapon.less";
|
||||
@import "armor.less";
|
||||
@import "spell.less";
|
||||
@import "vulnerability.less";
|
||||
@import "vulnerability.less";
|
||||
@import "chat.less";
|
||||
@import "equipment.less";
|
||||
@import "shield.less";
|
||||
@ -18,4 +18,4 @@
|
||||
}
|
||||
|
||||
@import "roll.less";
|
||||
@import "application-manager.less";
|
||||
@import "hud.less";
|
||||
|
@ -6,6 +6,17 @@
|
||||
--logo-standard: url("../assets/ui/lf_logo_small_02.webp");
|
||||
}
|
||||
|
||||
.initiative-area {
|
||||
min-width: 8rem;
|
||||
max-width: 8rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
input {
|
||||
min-width: 3rem;
|
||||
max-width: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
#logo {
|
||||
content: var(--logo-standard);
|
||||
width: 50px;
|
||||
|
43
styles/hud.less
Normal file
43
styles/hud.less
Normal file
@ -0,0 +1,43 @@
|
||||
#token-hud .hp-loss-wrap {
|
||||
position: absolute;
|
||||
left: 75px;
|
||||
display: none;
|
||||
top: 50%;
|
||||
width: 48px;
|
||||
text-align: start;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#token-hud .hp-loss-wrap-col1 {
|
||||
transform: translate(-200%, -50%);
|
||||
}
|
||||
|
||||
#token-hud .hp-loss-wrap-col2 {
|
||||
transform: translate(-300%, -50%);
|
||||
}
|
||||
|
||||
#token-hud .hp-loss-wrap-col3 {
|
||||
transform: translate(-400%, -50%);
|
||||
}
|
||||
|
||||
#token-hud .hp-loss-hud-active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#token-hud .hp-loss-hud-disabled {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#token-hud .hud-loss-hp-button-select {
|
||||
max-width: 40px;
|
||||
background-image: var(--background-image-base);
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
width: max-content;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#token-hud .hp-loss-wrap .hud-loss-hp-button-select {
|
||||
padding-left: 8px;
|
||||
font-size: 0.7rem;
|
||||
}
|
@ -19,12 +19,12 @@
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.monster-pc {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex: 1;
|
||||
|
||||
|
||||
|
||||
.monster-hp {
|
||||
display: flex;
|
||||
@ -99,6 +99,10 @@
|
||||
text-shadow: 0 0 8px var(--color-shadow-primary);
|
||||
cursor: pointer;
|
||||
}
|
||||
span {
|
||||
min-width: 2.2rem;
|
||||
max-width: 2.2rem;
|
||||
}
|
||||
.form-group {
|
||||
flex: 1;
|
||||
padding-left: 4px;
|
||||
@ -223,7 +227,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab.monster-biography {
|
||||
.tab.monster-biography .main-div {
|
||||
.biodata {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
@ -248,7 +252,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.tab.monster-skills {
|
||||
.tab.monster-skills .main-div{
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
legend {
|
||||
@ -462,4 +466,3 @@
|
||||
min-height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,19 @@
|
||||
fieldset {
|
||||
padding: 4px;
|
||||
}
|
||||
.goto-token-button {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
align-content: center;
|
||||
margin-left: 0.5rem;
|
||||
max-width: 8rem;
|
||||
background-color: var(--color-dark-6);
|
||||
color: var(--color-dark-2);
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.lethalfantasy-range-defense-dialog {
|
||||
@ -24,7 +37,7 @@
|
||||
select {
|
||||
margin-left: 0.5rem;
|
||||
min-width: 10rem;
|
||||
max-width: 10rem;
|
||||
max-width: 10rem;
|
||||
}
|
||||
.field-section {
|
||||
display: flex;
|
||||
@ -34,13 +47,13 @@
|
||||
.field-name {
|
||||
width:4rem;
|
||||
min-width: 4rem;
|
||||
max-width: 4rem;
|
||||
max-width: 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dialog-form {
|
||||
.form-footer {
|
||||
.form-footer {
|
||||
button {
|
||||
min-width: 14rem;
|
||||
min-height: 3.2rem;
|
||||
|
14
system.json
14
system.json
@ -6,7 +6,7 @@
|
||||
"download": "#{DOWNLOAD}#",
|
||||
"url": "#{URL}#",
|
||||
"license": "LICENSE",
|
||||
"version": "12.0.35",
|
||||
"version": "13.0.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Uberwald",
|
||||
@ -14,8 +14,8 @@
|
||||
}
|
||||
],
|
||||
"compatibility": {
|
||||
"minimum": "12",
|
||||
"verified": "12"
|
||||
"minimum": "13",
|
||||
"verified": "13"
|
||||
},
|
||||
"esmodules": ["lethal-fantasy.mjs"],
|
||||
"styles": ["css/fvtt-lethal-fantasy.css"],
|
||||
@ -82,6 +82,14 @@
|
||||
"system": "fvtt-lethal-fantasy",
|
||||
"path": "packs-system/lf-vulnerabilities",
|
||||
"type": "Item"
|
||||
},
|
||||
{
|
||||
"name": "lf-spells-miracles",
|
||||
"banner": "",
|
||||
"label": "Spells & Miracles",
|
||||
"system": "fvtt-lethal-fantasy",
|
||||
"path": "packs-system/lf-spells-miracles",
|
||||
"type": "Item"
|
||||
}
|
||||
],
|
||||
"flags": {
|
||||
|
@ -1,4 +1,5 @@
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
||||
<div class="main-div">
|
||||
|
||||
<fieldset>
|
||||
<legend>{{localize "LETHALFANTASY.Label.biodata"}}</legend>
|
||||
@ -92,5 +93,5 @@
|
||||
<legend>{{localize "LETHALFANTASY.Label.notes"}}</legend>
|
||||
{{formInput systemFields.notes enriched=enrichedNotes value=system.notes name="system.notes" toggled=true}}
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</section>
|
@ -1,10 +1,11 @@
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="combat" data-group="sheet">
|
||||
<div class="main-div">
|
||||
|
||||
<fieldset>
|
||||
<legend>{{localize "LETHALFANTASY.Label.combatDetails"}}</legend>
|
||||
<div class="combat-details">
|
||||
<div class="combat-detail">
|
||||
|
||||
|
||||
<button class="action" data-action="rangedAttackDefense">
|
||||
{{localize "LETHALFANTASY.Label.rangedAttackDefense"}}
|
||||
</button>
|
||||
@ -155,5 +156,6 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
<div>
|
||||
|
||||
</section>
|
@ -1,4 +1,5 @@
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
||||
<div class="main-div">
|
||||
|
||||
<fieldset>
|
||||
<legend>{{localize "LETHALFANTASY.Label.money"}}</legend>
|
||||
@ -31,5 +32,5 @@
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
|
||||
</div>
|
||||
</section>
|
@ -81,16 +81,16 @@
|
||||
<div class="character-save">
|
||||
<span class="name">
|
||||
<a class="rollable" data-roll-type="save" data-roll-key="contagion"><i
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
{{localize "LETHALFANTASY.Label.saves.contagion"}}
|
||||
</a>
|
||||
</span>
|
||||
{{formField systemFields.saves.fields.contagion.fields.value value=system.saves.contagion.value
|
||||
disabled=true}}
|
||||
|
||||
|
||||
<span class="name">
|
||||
<a class="rollable" data-roll-type="save" data-roll-key="poison"><i
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
{{localize "LETHALFANTASY.Label.saves.poison"}}
|
||||
</a>
|
||||
</span>
|
||||
@ -99,18 +99,18 @@
|
||||
|
||||
<span class="name-pain">
|
||||
<a class="rollable" data-roll-type="save" data-roll-key="pain" data-roll-dice="D12"><i
|
||||
class="lf-roll-small fa-solid fa-dice-d12"></i>
|
||||
class="lf-roll-small fa-solid fa-dice-d12"></i>
|
||||
{{localize "LETHALFANTASY.Label.saves.pain"}}
|
||||
</a>
|
||||
</span>
|
||||
<span class="name-pain">
|
||||
<span class="name-pain">
|
||||
<a class="rollable" data-roll-type="save" data-roll-key="pain" data-roll-dice="D20"><i
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
{{localize "LETHALFANTASY.Label.saves.pain"}}
|
||||
</a>
|
||||
</span>
|
||||
{{formField systemFields.saves.fields.pain.fields.value value=system.saves.pain.value disabled=true}}
|
||||
|
||||
|
||||
<span data-tooltip="Pain save if wound exceeds">
|
||||
{{formField systemFields.hp.fields.painDamage value=system.hp.painDamage disabled=isPlayMode tooltip="Pain Damage"}}
|
||||
</span>
|
||||
@ -174,14 +174,14 @@
|
||||
<fieldset class="character-characteristics character-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
|
||||
<legend>{{localize "LETHALFANTASY.Label.characteristics"}}</legend>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.str"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.str"}}</span>
|
||||
{{formField systemFields.characteristics.fields.str.fields.value value=system.characteristics.str.value
|
||||
disabled=isPlayMode data-char-id="str" }}
|
||||
{{formField systemFields.characteristics.fields.str.fields.percent value=system.characteristics.str.percent
|
||||
disabled=isPlayMode type="number"}}
|
||||
</div>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.int"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.int"}}</span>
|
||||
{{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value
|
||||
disabled=isPlayMode data-char-id="int" }}
|
||||
|
||||
@ -189,7 +189,7 @@
|
||||
disabled=isPlayMode type="number" }}
|
||||
</div>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.wis"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.wis"}}</span>
|
||||
{{formField systemFields.characteristics.fields.wis.fields.value value=system.characteristics.wis.value
|
||||
disabled=isPlayMode data-char-id="wis" }}
|
||||
|
||||
@ -197,7 +197,7 @@
|
||||
disabled=isPlayMode type="number"}}
|
||||
</div>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.dex"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.dex"}}</span>
|
||||
{{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value
|
||||
disabled=isPlayMode data-char-id="wis" }}
|
||||
|
||||
@ -205,7 +205,7 @@
|
||||
disabled=isPlayMode type="number" }}
|
||||
</div>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.con"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.con"}}</span>
|
||||
{{formField systemFields.characteristics.fields.con.fields.value value=system.characteristics.con.value
|
||||
disabled=isPlayMode data-char-id="con" }}
|
||||
|
||||
@ -213,7 +213,7 @@
|
||||
disabled=isPlayMode type="number"}}
|
||||
</div>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.cha"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.cha"}}</span>
|
||||
{{formField systemFields.characteristics.fields.cha.fields.value value=system.characteristics.cha.value
|
||||
disabled=isPlayMode data-char-id="cha" }}
|
||||
|
||||
@ -221,7 +221,7 @@
|
||||
disabled=isPlayMode type="number"}}
|
||||
</div>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.luc"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.luc"}}</span>
|
||||
{{formField systemFields.characteristics.fields.luc.fields.value value=system.characteristics.luc.value
|
||||
disabled=isPlayMode data-char-id="luc" }}
|
||||
|
||||
@ -229,7 +229,7 @@
|
||||
disabled=isPlayMode type="number"}}
|
||||
</div>
|
||||
<div class="character-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.app"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.app"}}</span>
|
||||
{{formField systemFields.characteristics.fields.app.fields.value value=system.characteristics.app.value
|
||||
disabled=isPlayMode data-char-id="app" }}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
||||
<div class="main-div">
|
||||
|
||||
<fieldset>
|
||||
<legend>{{localize "LETHALFANTASY.Label.divinityPoints"}}</legend>
|
||||
@ -46,5 +47,6 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
</section>
|
@ -1,4 +1,5 @@
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="skills" data-group="sheet">
|
||||
<div class="main-div">
|
||||
|
||||
<fieldset>
|
||||
<legend data-tooltip="{{localize " LETHALFANTASY.Tooltip.skills"}}" data-tooltip-direction="UP">{{localize
|
||||
@ -68,5 +69,5 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</section>
|
@ -1,19 +1,21 @@
|
||||
<section class="tab character-{{tab.id}} {{tab.cssClass}}" data-tab="{{tab.id}}" data-group="{{tab.group}}">
|
||||
<div class="main-div">
|
||||
|
||||
<fieldset>
|
||||
<legend>{{localize "LETHALFANTASY.Label.aetherPoints"}}</legend>
|
||||
<div class="spell-details">
|
||||
<div class="spell-detail">
|
||||
<span >Current</span>
|
||||
{{formField systemFields.aetherPoints.fields.value value=system.aetherPoints.value localize=true}}
|
||||
<a data-action="aetherPointsPlus"><i class="fa-solid fa-hexagon-plus"></i></a>
|
||||
<a data-action="aetherPointsMinus"><i class="fa-solid fa-hexagon-minus"></i></a>
|
||||
<fieldset>
|
||||
<legend>{{localize "LETHALFANTASY.Label.aetherPoints"}}</legend>
|
||||
<div class="spell-details">
|
||||
<div class="spell-detail">
|
||||
<span>Current</span>
|
||||
{{formField systemFields.aetherPoints.fields.value value=system.aetherPoints.value localize=true}}
|
||||
<a data-action="aetherPointsPlus"><i class="fa-solid fa-hexagon-plus"></i></a>
|
||||
<a data-action="aetherPointsMinus"><i class="fa-solid fa-hexagon-minus"></i></a>
|
||||
|
||||
<span >Max</span>
|
||||
{{formField systemFields.aetherPoints.fields.max value=system.aetherPoints.max localize=true disabled=isPlayMode}}
|
||||
<span>Max</span>
|
||||
{{formField systemFields.aetherPoints.fields.max value=system.aetherPoints.max localize=true
|
||||
disabled=isPlayMode}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
@ -22,9 +24,9 @@
|
||||
data-action="createSpell"></i></a>{{/if}}</legend>
|
||||
<div class="spells">
|
||||
{{#each spells as |item|}}
|
||||
<div class="spell" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true" >
|
||||
<div class="spell" data-item-id="{{item.id}}" data-item-uuid="{{item.uuid}}" data-drag="true">
|
||||
<img class="item-img" src="{{item.img}}" data-tooltip="{{item.name}}" />
|
||||
<div class="name" >
|
||||
<div class="name">
|
||||
{{item.name}}
|
||||
</div>
|
||||
|
||||
@ -46,5 +48,5 @@
|
||||
{{/each}}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
</div>
|
||||
</section>
|
@ -1,7 +1,7 @@
|
||||
<div class="lethalfantasy-combat-action-dialog">
|
||||
|
||||
<fieldSet class="">
|
||||
<legend>{{localize "LETHALFANTASY.Label.combatAction"}}</legend>
|
||||
<legend>{{localize "LETHALFANTASY.Label.combatAction"}} for {{actorName}}</legend>
|
||||
|
||||
{{#if currentAction}}
|
||||
<label>{{localize "LETHALFANTASY.Label.currentAction"}} : {{currentAction.name}}</label>
|
||||
@ -18,7 +18,7 @@
|
||||
<fieldSet>
|
||||
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
|
||||
<select name="visibility">
|
||||
{{selectOptions rollModes selected=visibility}}
|
||||
{{selectOptions rollModes selected=visibility localize=true}}
|
||||
</select>
|
||||
</fieldSet>
|
||||
|
||||
|
39
templates/combat-tracker-footer-v2.hbs
Normal file
39
templates/combat-tracker-footer-v2.hbs
Normal file
@ -0,0 +1,39 @@
|
||||
<nav class="combat-controls" data-tooltip-direction="UP">
|
||||
{{~#if hasCombat~}}
|
||||
|
||||
{{!-- GM Controls --}}
|
||||
{{#if user.isGM}}
|
||||
{{#if combat.round}}
|
||||
<!-- <button type="button" class="inline-control combat-control icon fa-solid fa-backward-step"
|
||||
data-action="previousRound" data-tooltip aria-label="{{ localize "COMBAT.RoundPrev" }}"></button>
|
||||
<button type="button" class="inline-control combat-control icon fa-solid fa-arrow-left" data-action="previousTurn"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.TurnPrev" }}"></button> -->
|
||||
<button type="button" class="combat-control combat-control-lg" data-action="endCombat">
|
||||
<i class="fa-solid fa-xmark" inert></i>
|
||||
<span>{{ localize "COMBAT.End" }}</span>
|
||||
</button>
|
||||
|
||||
<!-- <button type="button" class="inline-control combat-control icon fa-solid fa-arrow-right" data-action="nextTurn"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.TurnNext" }}"></button> -->
|
||||
<button type="button" class="inline-control combat-control icon fa-solid fa-forward-step" data-action="nextRound"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.RoundNext" }}"></button>
|
||||
{{else}}
|
||||
<button type="button" class="combat-control combat-control-lg" data-action="startCombat">
|
||||
<i class="fa-solid fa-swords" inert></i>
|
||||
<span>{{ localize "COMBAT.Begin" }}</span>
|
||||
</button>
|
||||
{{/if}}
|
||||
|
||||
{{!-- Active Player Controls --}}
|
||||
{{else if control}}
|
||||
<!-- <button type="button" class="inline-control combat-control icon fa-solid fa-arrow-left" data-action="previousTurn"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.TurnPrev" }}"></button>
|
||||
<button type="button" class="combat-control combat-control-lg" data-action="nextTurn">
|
||||
<i class="fa-solid fa-check"></i>
|
||||
<span>{{ localize "COMBAT.TurnEnd" }}</span>
|
||||
</button>
|
||||
<button type="button" class="inline-control combat-control icon fa-solid fa-arrow-right" data-action="nextTurn"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.TurnNext" }}"></button> -->
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</nav>
|
92
templates/combat-tracker-header-v2.hbs
Normal file
92
templates/combat-tracker-header-v2.hbs
Normal file
@ -0,0 +1,92 @@
|
||||
<header class="combat-tracker-header">
|
||||
|
||||
{{!-- Encounter Controls --}}
|
||||
{{#if user.isGM}}
|
||||
<nav class="encounters {{ css }}" aria-label="{{ localize "COMBAT.NavLabel" }}">
|
||||
|
||||
{{!-- Cycle Display --}}
|
||||
{{#if displayCycle}}
|
||||
<button type="button" class="inline-control icon fa-solid fa-plus" data-action="createCombat"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.Create" }}"></button>
|
||||
|
||||
<div class="cycle-combats">
|
||||
<button type="button" class="inline-control icon fa-solid fa-caret-left" data-action="cycleCombat"
|
||||
{{#if previousId}}data-combat-id="{{ previousId }}" {{else}}disabled{{/if}}
|
||||
data-tooltip aria-label="{{ localize "COMBAT.EncounterPrevious" }}"></button>
|
||||
<div class="encounter-count">
|
||||
<span class="value">{{ currentIndex }}</span>
|
||||
<span class="separator">/</span>
|
||||
<span class="max">{{ combats.length }}</span>
|
||||
</div>
|
||||
<button type="button" class="inline-control icon fa-solid fa-caret-right" data-action="cycleCombat"
|
||||
{{#if nextId}}data-combat-id="{{ nextId }}" {{else}}disabled{{/if}}
|
||||
data-tooltip aria-label="{{ localize "COMBAT.EncounterNext" }}"></button>
|
||||
</div>
|
||||
|
||||
<button type="button" class="inline-control icon fa-solid fa-gear" data-action="trackerSettings"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.Settings" }}"></button>
|
||||
|
||||
{{!-- Tabbed Display --}}
|
||||
{{else if combats.length}}
|
||||
<button type="button" class="inline-control icon fa-solid fa-plus" data-action="createCombat"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.Create" }}"></button>
|
||||
{{#each combats}}
|
||||
<button type="button" class="inline-control {{#if active}}active{{/if}}" data-action="cycleCombat"
|
||||
data-combat-id="{{ id }}">
|
||||
{{ label }}
|
||||
</button>
|
||||
{{/each}}
|
||||
<button type="button" class="inline-control icon fa-solid fa-gear" data-action="trackerSettings"
|
||||
data-tooltip aria-label="{{ localize "COMBAT.Settings" }}"></button>
|
||||
|
||||
{{!-- No Combats --}}
|
||||
{{else}}
|
||||
<button type="button" class="combat-control-lg" data-action="createCombat">
|
||||
<i class="fa-solid fa-plus" inert></i>
|
||||
<span>{{ localize "COMBAT.Create" }}</span>
|
||||
</button>
|
||||
|
||||
{{/if}}
|
||||
</nav>
|
||||
{{/if}}
|
||||
|
||||
<div class="encounter-controls {{#if hasCombat}}combat{{/if}}">
|
||||
|
||||
{{!-- Bulk Rolls --}}
|
||||
<div class="control-buttons left flexrow">
|
||||
{{#if user.isGM}}
|
||||
<button type="button" class="inline-control combat-control icon fa-solid fa-users" data-action="rollAll"
|
||||
{{#unless combat.turns.length}}disabled{{/unless}} data-tooltip="COMBAT.RollAll"
|
||||
aria-label="{{ localize "COMBAT.RollAll" }}"></button>
|
||||
<button type="button" class="inline-control combat-control icon fa-solid fa-users-cog" data-action="rollNPC"
|
||||
{{#unless combat.turns.length}}disabled{{/unless}} data-tooltip="COMBAT.RollNPC"
|
||||
aria-label="{{ localize "COMBAT.RollNPC" }}"></button>
|
||||
{{else}}
|
||||
<div class="spacer"></div>
|
||||
<div class="spacer"></div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{!-- Combat Status --}}
|
||||
<strong class="encounter-title">
|
||||
{{#if combats.length}}
|
||||
{{#if combat.round}}
|
||||
{{ localize "COMBAT.Round" round=combat.round }}
|
||||
{{else}}
|
||||
{{ localize "COMBAT.NotStarted" }}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
{{ localize "COMBAT.None" }}
|
||||
{{/if}}
|
||||
</strong>
|
||||
|
||||
{{!-- Combat Controls --}}
|
||||
<div class="control-buttons right flexrow">
|
||||
<div class="spacer"></div>
|
||||
<button type="button" class="encounter-context-menu inline-control combat-control icon fa-solid fa-ellipsis-vertical"
|
||||
{{#unless (and user.isGM hasCombat)}}disabled{{/unless}}></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</header>
|
81
templates/combat-tracker-v2.hbs
Normal file
81
templates/combat-tracker-v2.hbs
Normal file
@ -0,0 +1,81 @@
|
||||
<ol class="combat-tracker plain">
|
||||
{{#each turns}}
|
||||
<li class="combatant {{ css }}" data-combatant-id="{{ id }}" data-action="activateCombatant">
|
||||
{{!-- TODO: Targets --}}
|
||||
|
||||
{{!-- Image --}}
|
||||
<img class="token-image" src="{{ img }}" alt="{{ name }}" loading="lazy">
|
||||
|
||||
{{!-- Name & Controls --}}
|
||||
<div class="token-name">
|
||||
<strong class="name">{{ name }}</strong>
|
||||
<div class="combatant-controls">
|
||||
{{#if @root.user.isGM}}
|
||||
<button type="button" class="inline-control combatant-control icon fa-solid fa-eye-slash {{#if hidden}}active{{/if}}"
|
||||
data-action="toggleHidden" data-tooltip aria-label="{{ localize "COMBAT.ToggleVis" }}"></button>
|
||||
<button type="button" class="inline-control combatant-control icon fa-solid fa-skull {{#if isDefeated}}active{{/if}}"
|
||||
data-action="toggleDefeated" data-tooltip
|
||||
aria-label="{{ localize "COMBAT.ToggleDead" }}"></button>
|
||||
{{/if}}
|
||||
{{#if canPing}}
|
||||
<button type="button" class="inline-control combatant-control icon fa-solid fa-bullseye-arrow"
|
||||
data-action="pingCombatant" data-tooltip
|
||||
aria-label="{{ localize "COMBAT.PingCombatant" }}"></button>
|
||||
{{/if}}
|
||||
{{#unless @root.user.isGM}}
|
||||
<button type="button" class="inline-control combatant-control icon fa-solid fa-arrows-to-eye"
|
||||
data-action="panToCombatant" data-tooltip
|
||||
aria-label="{{ localize "COMBAT.PanToCombatant" }}"></button>
|
||||
{{/unless}}
|
||||
{{!-- TODO: Target Control --}}
|
||||
<div class="token-effects" data-tooltip-html="{{ effects.tooltip }}">
|
||||
{{#each effects.icons}}
|
||||
<img class="token-effect" src="{{ img }}" alt="{{ name }}">
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Resource --}}
|
||||
{{#if resource includeZero=true}}
|
||||
<div class="token-resource">
|
||||
<span class="resource">{{ resource }}</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{!-- Initiative --}}
|
||||
<div class="token-initiative initiative-area">
|
||||
{{#if initiative includeZero=true}}
|
||||
|
||||
{{!-- Decimal Initiative --}}
|
||||
{{#if @root.hasDecimals}}
|
||||
<span>{{ initiative }}</span>
|
||||
|
||||
{{!-- Simple Initiative --}}
|
||||
{{else}}
|
||||
<input type="text" class="initiative-input" inputmode="numeric" pattern="^[+=\-]?\d*" value="{{ initiative }}"
|
||||
aria-label="{{ localize "COMBAT.InitiativeScore" }}" {{#unless @root.user.isGM}}readonly{{/unless}}>
|
||||
|
||||
{{/if}}
|
||||
|
||||
{{#if isOwner}}
|
||||
<a data-action="initiativePlus" class="initiative-plus" data-combatant-id="{{this.id}}"><i class="fa-solid fa-hexagon-plus"></i></a>
|
||||
<a data-action="initiativeMinus" class="initiative-minus" data-combatant-id="{{this.id}}"><i class="fa-solid fa-hexagon-minus"></i></a>
|
||||
{{/if}}
|
||||
|
||||
{{#if isMonster}}
|
||||
<span class="initiative">-</span>
|
||||
{{else}}
|
||||
<span class="initiative" data-tooltip="Current max. progression counter">{{progressionCount}}</span>
|
||||
{{/if}}
|
||||
|
||||
{{!-- Roll Initiative --}}
|
||||
{{else if isOwner}}
|
||||
<button type="button" class="combatant-control roll" data-action="rollInitiative" data-tooltip
|
||||
aria-label="{{ localize "COMBAT.InitiativeRoll" }}"
|
||||
style="--initiative-icon: url('{{ @root.initiativeIcon.icon }}'); --initiative-icon-hover: url('{{ @root.initiativeIcon.hover }}');"></button>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
29
templates/loss-hp-hud.hbs
Normal file
29
templates/loss-hp-hud.hbs
Normal file
@ -0,0 +1,29 @@
|
||||
<div class="control-icon" data-action="lethal-loss-hp-hud">
|
||||
<img class="lethal-hp-loss-hud" src="systems/fvtt-lethal-fantasy/assets/icons/broken-heart.svg"
|
||||
width="36" height="36" title="Open token journal" />
|
||||
|
||||
<div class="hp-loss-wrap hp-loss-wrap-col1 hp-loss-hud-disabled">
|
||||
{{#for -10 0 1}}
|
||||
<button class="hud-loss-hp-button-select loss-hp-hud-click " data-hp-value="{{this}}" >
|
||||
<span class="">{{this}}</span>
|
||||
</button>
|
||||
{{/for}}
|
||||
</div>
|
||||
|
||||
<div class="hp-loss-wrap hp-loss-wrap-col2 hp-loss-hud-disabled">
|
||||
{{#for -20 -10 1}}
|
||||
<button class="hud-loss-hp-button-select loss-hp-hud-click " data-hp-value="{{this}}" >
|
||||
<span class="">{{this}}</span>
|
||||
</button>
|
||||
{{/for}}
|
||||
</div>
|
||||
|
||||
<div class="hp-loss-wrap hp-loss-wrap-col3 hp-loss-hud-disabled">
|
||||
{{#for -30 -20 1}}
|
||||
<button class="hud-loss-hp-button-select loss-hp-hud-click " data-hp-value="{{this}}" >
|
||||
<span class="">{{this}}</span>
|
||||
</button>
|
||||
{{/for}}
|
||||
</div>
|
||||
|
||||
</div>
|
@ -62,16 +62,16 @@
|
||||
<div class="monster-save">
|
||||
<span class="name">
|
||||
<a class="rollable" data-roll-type="save" data-roll-key="contagion"><i
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
{{localize "LETHALFANTASY.Label.saves.contagion"}}
|
||||
</a>
|
||||
</span>
|
||||
{{formField systemFields.saves.fields.contagion.fields.value value=system.saves.contagion.value
|
||||
disabled=isPlayMode}}
|
||||
|
||||
|
||||
<span class="name">
|
||||
<a class="rollable" data-roll-type="save" data-roll-key="poison"><i
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
{{localize "LETHALFANTASY.Label.saves.poison"}}
|
||||
</a>
|
||||
</span>
|
||||
@ -80,7 +80,7 @@
|
||||
|
||||
<span class="name">
|
||||
<a class="rollable" data-roll-type="save" data-roll-key="paincourage" data-roll-dice="D20" data-tooltip="Pain/Courage check on wound of..."><i
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
class="lf-roll-small fa-solid fa-dice-d20"></i>
|
||||
{{localize "LETHALFANTASY.Label.saves.paincourage"}}
|
||||
</a>
|
||||
</span>
|
||||
@ -91,7 +91,7 @@
|
||||
</span>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@ -157,7 +157,7 @@
|
||||
<fieldset class="monster-characteristics monster-characteristics-{{ifThen isPlayMode 'play' 'edit'}}">
|
||||
<legend>{{localize "LETHALFANTASY.Label.characteristics"}}</legend>
|
||||
<div class="monster-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.int"}}
|
||||
<span>x{{localize "LETHALFANTASY.Label.int"}}</span>
|
||||
{{formField systemFields.characteristics.fields.int.fields.value value=system.characteristics.int.value
|
||||
disabled=isPlayMode data-char-id="int" }}
|
||||
|
||||
@ -165,7 +165,7 @@
|
||||
disabled=isPlayMode type="number" }}
|
||||
</div>
|
||||
<div class="monster-characteristic">
|
||||
{{localize "LETHALFANTASY.Label.dex"}}
|
||||
<span>{{localize "LETHALFANTASY.Label.dex"}}</span>
|
||||
{{formField systemFields.characteristics.fields.dex.fields.value value=system.characteristics.dex.value
|
||||
disabled=isPlayMode data-char-id="wis" }}
|
||||
|
||||
|
@ -1,79 +0,0 @@
|
||||
<section>
|
||||
{{!log "opponent sheet" this}}
|
||||
<div class="opponent-header">
|
||||
<img class="opponent-img" src="{{actor.img}}" data-edit="img" data-action="editImage" data-tooltip="{{actor.name}}" />
|
||||
{{formInput fields.name value=source.name}}
|
||||
<a class="control" data-action="toggleSheet" data-tooltip="TENEBRIS.ToggleSheet" data-tooltip-direction="UP">
|
||||
<i class="fa-solid fa-user-{{ifThen isPlayMode 'lock' 'pen'}}"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div class="opponent-main">
|
||||
<div class="opponent-gauche">
|
||||
<fieldset class="opponent-caracteristiques">
|
||||
<legend>{{localize "TENEBRIS.Character.Label.caracteristiques"}}</legend>
|
||||
{{formField systemFields.dv value=system.dv disabled=isPlayMode}}
|
||||
{{formField systemFields.pv.fields.value value=system.pv.value}}
|
||||
{{formField systemFields.pv.fields.max value=system.pv.max disabled=isPlayMode}}
|
||||
{{formField systemFields.armure value=system.armure disabled=isPlayMode}}
|
||||
{{formField systemFields.malus value=system.malus disabled=isPlayMode}}
|
||||
{{formField systemFields.actions value=system.actions disabled=isPlayMode}}
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="opponent-attacks">
|
||||
<legend>{{localize "TENEBRIS.Character.Label.attaques"}}
|
||||
{{#if isEditMode}}<a class="action" data-tooltip="{{localize 'TENEBRIS.Tooltip.addAttack'}}" data-tooltip-direction="UP"><i
|
||||
class="fas fa-plus"
|
||||
data-action="createAttack"
|
||||
></i></a>{{/if}}</legend>
|
||||
{{#each attacks as |attack|}}
|
||||
<div class="opponent-attack" data-drag="true" data-drag-type="attack" data-roll-value="{{attack.system.degats}}" data-roll-target="{{attack.name}}">
|
||||
<div class="attack-name">
|
||||
<a
|
||||
class="rollable"
|
||||
data-item-id="{{attack.id}}"
|
||||
data-item-name="{{attack.name}}"
|
||||
data-action="roll"
|
||||
data-roll-type="attack"
|
||||
data-roll-value="{{attack.system.degats}}"
|
||||
>{{attack.system.degats}}</a>
|
||||
(<span data-tooltip="{{attack.system.toolTip}}">{{attack.name}}</span>)
|
||||
</div>
|
||||
{{#if @root.isEditMode}}
|
||||
<div class="controls">
|
||||
<a data-tooltip="{{localize 'TENEBRIS.Edit'}}" data-action="edit" data-item-id="{{attack.id}}" data-item-uuid="{{attack.uuid}}"><i class="fas fa-edit"></i></a>
|
||||
<a data-tooltip="{{localize 'TENEBRIS.Delete'}}" data-action="delete" data-item-id="{{attack.id}}" data-item-uuid="{{attack.uuid}}"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</fieldset>
|
||||
|
||||
{{#if (or isEditMode (and isPlayMode hasSpells))}}
|
||||
<fieldset class="opponent-spells">
|
||||
<legend>{{localize "TENEBRIS.Label.spells"}}{{#if isEditMode}}<a class="action" data-tooltip="{{localize "TENEBRIS.Tooltip.addSpell"}}" data-tooltip-direction="UP"><i class="fas fa-plus" data-action="createSpell"></i></a>{{/if}}</legend>
|
||||
{{#each spells as |spell|}}
|
||||
<div class="opponent-spell">
|
||||
<div class="name" data-tooltip="{{{spell.system.description}}}">
|
||||
{{spell.name}}
|
||||
</div>
|
||||
{{#if @root.isEditMode}}
|
||||
<div class="controls">
|
||||
<a data-tooltip="{{localize 'TENEBRIS.Edit'}}" data-action="edit" data-item-id="{{spell.id}}" data-item-uuid="{{spell.uuid}}"><i class="fas fa-edit"></i></a>
|
||||
<a data-tooltip="{{localize 'TENEBRIS.Delete'}}" data-action="delete" data-item-id="{{spell.id}}" data-item-uuid="{{spell.uuid}}"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each}}
|
||||
</fieldset>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="opponent-droite">
|
||||
<fieldset class="opponent-description">
|
||||
<legend>{{localize "TENEBRIS.Label.description"}}</legend>
|
||||
{{formInput systemFields.description enriched=enrichedDescription value=system.description name="system.description" toggled=true compact=true}}
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
@ -26,7 +26,7 @@
|
||||
|
||||
<div class="field-section">
|
||||
<span class="field-name">Range :</span>
|
||||
|
||||
|
||||
<select name="range" data-tooltip-direction="UP">
|
||||
{{selectOptions rangeChoices selected=range}}
|
||||
</select>
|
||||
@ -34,7 +34,7 @@
|
||||
|
||||
<div class="field-section">
|
||||
<span class="field-name">Aim :</span>
|
||||
|
||||
|
||||
<select name="attackerAim" data-tooltip-direction="UP">
|
||||
{{selectOptions attackerAimChoices selected=attackerAim}}
|
||||
</select>
|
||||
@ -45,7 +45,7 @@
|
||||
<fieldSet>
|
||||
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
|
||||
<select name="visibility">
|
||||
{{selectOptions rollModes selected=visibility}}
|
||||
{{selectOptions rollModes selected=visibility localize=true}}
|
||||
</select>
|
||||
</fieldSet>
|
||||
|
||||
|
@ -1,13 +1,19 @@
|
||||
<div class="lethalfantasy-roll-dialog">
|
||||
|
||||
<fieldSet class="">
|
||||
<legend>{{localize (concat "LETHALFANTASY.Label." rollType)}}</legend>
|
||||
<legend>{{localize (concat "LETHALFANTASY.Label." rollType)}} - {{actorName}}</legend>
|
||||
|
||||
{{#if rollTarget.tokenId}}
|
||||
<div class="dialog-save">
|
||||
<a class="goto-token-button" data-action="gotoToken" data-token-id="{{rollTarget.tokenId}}">{{localize "LETHALFANTASY.Label.gotoToken"}} </a>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if (match rollType "attack")}}
|
||||
<div class="dialog-save">Attack roll !</div>
|
||||
<div class="dialog-save">Attack roll ! - {{rollTarget.name}}</div>
|
||||
{{/if}}
|
||||
{{#if (match rollType "defense")}}
|
||||
<div class="dialog-save">Defense roll !</div>
|
||||
<div class="dialog-save">Defense roll ! - {{rollTarget.name}}</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if hasModifier}}
|
||||
@ -19,7 +25,7 @@
|
||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.baseModifier"}} : {{rollTarget.charModifier}}</div>
|
||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.weapon"}} : {{rollTarget.weapon.name}}</div>
|
||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.skill"}} : {{rollTarget.name}}</div>
|
||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.skillBonus"}} : {{rollTarget.weaponSkillModifier}}</div>
|
||||
<div class="dialog-save">{{localize "LETHALFANTASY.Label.skillBonus"}} : {{rollTarget.weaponSkillModifier}}</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if (match rollType "attack")}}
|
||||
@ -29,16 +35,16 @@
|
||||
{{/if}}
|
||||
{{#if (match rollType "defense")}}
|
||||
<div class="dialog-save">Add Granted Defense Dice
|
||||
<input type="checkbox" data-action="selectGranted" name="granted" >
|
||||
<input type="checkbox" data-action="selectGranted" name="granted" >
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (match rollType "damage")}}
|
||||
<div class="dialog-save">Add Granted Damage Dice
|
||||
<input type="checkbox" data-action="selectGranted" name="granted" >
|
||||
<input type="checkbox" data-action="selectGranted" name="granted" >
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if rollTarget.staticModifier}}
|
||||
{{#if rollTarget.staticModifier}}
|
||||
<div class="dialog-save">Static modifier : +{{rollTarget.staticModifier}}</div>
|
||||
{{/if}}
|
||||
|
||||
@ -84,7 +90,9 @@
|
||||
<fieldSet>
|
||||
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
|
||||
<select name="visibility">
|
||||
{{selectOptions rollModes selected=visibility}}
|
||||
{{selectOptions rollModes selected=visibility localize=true}}
|
||||
</select>
|
||||
</fieldSet>
|
||||
|
||||
|
||||
</div>
|
@ -13,8 +13,8 @@
|
||||
<fieldSet>
|
||||
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
|
||||
<select name="visibility">
|
||||
{{selectOptions rollModes selected=visibility}}
|
||||
{{selectOptions rollModes selected=visibility localize=true}}
|
||||
</select>
|
||||
</fieldSet>
|
||||
|
||||
|
||||
</div>
|
@ -13,8 +13,8 @@
|
||||
<fieldSet>
|
||||
<legend>{{localize "LETHALFANTASY.Roll.visibility"}}</legend>
|
||||
<select name="visibility">
|
||||
{{selectOptions rollModes selected=visibility}}
|
||||
{{selectOptions rollModes selected=visibility localize=true}}
|
||||
</select>
|
||||
</fieldSet>
|
||||
|
||||
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user