#spell #dnd #pdf-document #text-document #field-value #spellbook

dnd_spellbook_maker

用于创建类似于第五版 D&D 官方源书法术描述的 pdf 文档的库

1 个不稳定版本

0.1.0 2024年2月15日

#479 in 文本处理

MIT 许可证

235KB
3.5K SLoC

dnd_spellbook_maker

创建类似于第五版 D&D 官方源书法术描述的 pdf 文档的库。

文档在 https://docs.rs/dnd_spellbook_maker

快速入门

Cargo.toml 依赖关系

dnd_spellbook_maker = "0.1.0"

或者

dnd_spellbook_maker = { git = "https://github.com/ChandlerJayCalkins/dnd_spellbook_maker" }

示例程序

此程序创建一本法术书。它假设它所在的目录具有此存储库中相同的 "spells"、"fonts" 和 "img" 文件夹及其所有内容。

use dnd_spellbook_maker;

fn main()
{
	// Spellbook's name
	let spellbook_name = "A Spellcaster's Spellbook";
	// Vec of spells that will be added to spellbook
	let mut spell_list = Vec::new();
	// Vec of paths to spell files that will be read from
	let spell_paths = vec!
	[
		"spells/players_handbook/prestidigitation.spell",
		"spells/players_handbook/mending.spell",
		"spells/players_handbook/mage_hand.spell",
		"spells/players_handbook/fire_bolt.spell",
		"spells/strixhaven/silvery_barbs.spell",
		"spells/players_handbook/color_spray.spell",
		"spells/players_handbook/magic_missile.spell",
		"spells/xanathars_guide_to_everything/ice_knife.spell",
		"spells/players_handbook/mage_armor.spell",
		"spells/players_handbook/unseen_servant.spell",
		"spells/players_handbook/detect_magic.spell",
		"spells/players_handbook/alarm.spell",
		"spells/players_handbook/cloud_of_daggers.spell",
		"spells/players_handbook/scorching_ray.spell"
	];
	// Attempt to loop through each spell file and convert it into a spell struct
	for path in spell_paths
	{
		println!("{}", path);
		// Convert spell file into spell struct and add it to spell_list vec
		spell_list.push(dnd_spellbook_maker::spells::Spell::from_file(path).unwrap());
	}
	// File paths to the fonts needed
	let font_paths = dnd_spellbook_maker::FontPaths
	{
		regular: String::from("fonts/Bookman/Bookman-Regular.otf"),
		bold: String::from("fonts/Bookman/Bookman-Bold.otf"),
		italic: String::from("fonts/Bookman/Bookman-Italic.otf"),
		bold_italic: String::from("fonts/Bookman/Bookman-BoldItalic.otf")
	};
	// Parameters for determining the size of the page and the text margins on the page
	let page_size_data = dnd_spellbook_maker::PageSizeData::new
	(
		210.0, 297.0, 10.0, 10.0, 10.0, 10.0
	).unwrap();
	// Parameters for determining page number behavior
	let page_number_data = dnd_spellbook_maker::PageNumberData::new
	(
		true, false, 1, 5.0, 4.0
	).unwrap();
	// Parameters for determining font sizes, the tab amount, and newline amounts
	let font_size_data = dnd_spellbook_maker::FontSizeData::new
	(
		32.0, 24.0, 12.0, 7.5, 12.0, 8.0, 5.0
	).unwrap();
	// Colors for each type of text
	let text_colors = dnd_spellbook_maker::TextColors
	{
		title_color: (0, 0, 0),
		header_color: (115, 26, 26),
		body_color: (0, 0, 0)
	};
	// Scalars used to convert the size of fonts from rusttype font units to printpdf millimeters (Mm)
	let font_scalars = dnd_spellbook_maker::FontScalars::new
	(
		0.475, 0.51, 0.48, 0.515
	).unwrap();
	// Parameters for table margins / padding and off-row color / scaling
	let table_options = dnd_spellbook_maker::TableOptions::new
	(
		16.0, 10.0, 8.0, 4.0, 12.0, 0.1075, 4.0, (213, 209, 224)
	).unwrap();
	// File path to the background image
	let background_path = "img/parchment.jpg";
	// Image transform data for the background image
	let background_transform = dnd_spellbook_maker::ImageTransform
	{
		translate_x: Some(dnd_spellbook_maker::Mm(0.0)),
		translate_y: Some(dnd_spellbook_maker::Mm(0.0)),
		scale_x: Some(1.95),
		scale_y: Some(2.125),
		..Default::default()
	};
	// Creates the spellbook
	let doc = dnd_spellbook_maker::generate_spellbook
	(
		spellbook_name, &spell_list, &font_paths, &page_size_data,
		&Some(page_number_data), &font_size_data, &text_colors, &font_scalars,
		&table_options, &Some((background_path, &background_transform))
	).unwrap();
	// Saves the spellbook to a pdf document
	let _ = dnd_spellbook_maker::save_spellbook(doc, "Spellbook.pdf");
}

设置

此库需要字体文件才能工作,以便它可以在文档中添加文本。将背景图片添加到法术书的每一页是可选的,但如果需要,则需要手动提供。

字体

需要将四个字体文件提供给 generate_spellbook() 函数的其中一个结构参数。所需的字体文件必须是 .otf.ttf 文件。构成字体的四个所需字体文件是

  • 常规字体
  • 粗体字体
  • 斜体字体
  • 粗斜体字体

背景图片

可以添加背景图片到法术书的每一页,但这不是必需的。图片通过 printpdf crate 添加到法术书的每一页,该 crate 在向 pdf 页面层添加图片时存在错误。如果您遇到图片未正确添加到页面或根本未添加的故障,请尝试将图片转换为不同类型(例如,从 .jpg.png 或反之,等等)。

法术

要使用 generate_spellbook() 函数创建法术书,需要一个 Spell 对象的 vec。法术对象通常应从法术文件中创建。如果您想创建自己的,以下源材料书籍中提供了每个法术的法术文件的结构详细信息

  • 玩家手册
  • 一切指南
  • 塔莎的魔法锅
  • 斯特里克斯文法:混乱课程。

法术文件

拼写文件是纯文本文件,字段主要通过换行符分隔。拼写文件中的每个字段对应于 Spell 结构体中的一个字段。字段如下:

  • 名称:
  • 等级:
  • 学派:
  • 是否是仪式:
  • 施法时间:
  • 范围:
  • 是否有V成分:
  • 是否有S成分:
  • M成分:
  • 持续时间:
  • 描述:
  • 升级描述:

这些字段在拼写文件中不需要任何特定的顺序。只需用行分隔即可。

字段

名称

名称:

魔法的名称。可以是单行上的任何字符串(不需要用引号包围)。

示例

名称:酸溅

名称:火球

NAME:奇怪

等级

等级:

魔法的等级。范围是从0到9的整数。等级0代表咒语。

示例

等级: 3

等级: 9

LEVEL: 0

学派

学派:

魔法的魔法学派。可以是以下值之一

  • 禁咒
  • 咒法
  • 占卜
  • 附魔
  • 召唤
  • 幻术
  • necromancy
  • 变形

示例

学派:召唤

学派:幻术

SCHOOL:nEcRoMaNcY

仪式

是否是仪式:

魔法是否是仪式。必须是 truefalse。或者,这个字段可以直接放在拼写文件中,没有冒号或值来表示 true,或者根本不在拼写文件中放置,表示 false

示例

is_ritual: trueis_ritual

is_ritual: false 或文件中不包含该字段。

施法时间

施法时间:

施放这个魔法所需的时间。可以是以下值之一

  • seconds 必须后跟一个非负整数。
  • actions 必须后跟一个非负整数。
  • bonusaction
  • reaction 必须后跟一行文字,用引号括起来。
  • minutes 必须后跟一个非负整数。
  • hours 必须后跟一个非负整数。
  • days 必须后跟一个非负整数。
  • weeks 必须后跟一个非负整数。
  • months 必须后跟一个非负整数。
  • years 必须后跟一个非负整数。
  • special

示例

施法时间:actions1

施法时间:bonusaction

CASTING_TIME:分钟10

cAsTiNg_TiMe: REACTION "当看到一只生物在60英尺内成功投掷攻击骰时你采取的行动"

范围

范围:

这个魔法可以针对的事物距离/区域。可以是以下值之一

  • self 这个值可以可选地后跟一个AOE(区域效果)值(AOE的详细信息见下文)。
  • touch
  • 距离值(距离的详细信息见下文)。
  • sight
  • 无限
  • special

AOE(区域效果)值定义了一个体积形状,魔法的效应就在其中发生。它们可以是以下值之一

  • line 必须后跟一个距离值(距离的详细信息见下文)。
  • cone 必须后跟一个距离值。
  • cube 必须后跟一个距离值。
  • sphere 必须后跟一个距离值。
  • hemisphere 必须后跟一个距离值。
  • cylinder 必须后跟两个距离值,第一个代表其半径,第二个代表其高度。

距离值是自我解释的。它们由一个正整数和一个表示该距离测量单位的字符串定义。有效的距离值包括

  • feet 必须后跟一个非负整数。
  • miles 必须后跟一个非负整数。

示例

范围:feet120

范围: 自我

RaNgE: self锥形英尺15

范围: self圆柱英尺15feet60

ranGe:special

V / S 组件

has_v_component: / has_s_component:

这两个字段确定咒语是否具有言语/姿势成分。必须是 truefalse。或者,这些字段可以直接放在咒语文件中,不包含任何冒号或值以表示 true,或者根本不放在咒语文件中以表示 false

示例

has_v_component: truehas_v_component

has_v_component: false 或文件中不包含该字段。

has_s_component: truehas_s_component

has_s_component: false 或文件中不包含该字段。

M 成分

M成分:

咒语的材料成分。如果咒语有材料成分,其值应为一行文本,位于引号内。如果咒语没有任何材料成分,其值应为 none 或可以不包含该字段在咒语文件中以达到相同的效果。

示例

M成分: "一根绳子和一些木头"

m_components: none 或文件中不包含该字段。

持续时间

duration: 咒语持续的时间长度。可以是以下值之一

  • 瞬间
  • seconds 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • rounds 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • minutes 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • hours 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • days 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • weeks 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • months 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • years 必须后跟一个非负整数。该整数也可以后跟值 concentration 如果此咒语需要集中注意力。
  • dispelledortriggered 如果法术需要集中注意力,可以跟随着值 concentration
  • untildispelled 如果法术需要集中注意力,可以跟随着值 concentration
  • 永久
  • special 如果法术需要集中注意力,可以跟随着值 concentration

示例

持续时间:回合1

持续时间:分钟10集中注意力

dUrAtIoN:untildispelledortriggered

持续时间:untildispelled Concentration

持续时间:永久

描述

描述:

描述法术作用内容的文本。此字段的值必须是包含在引号中的文本,可以跨多行。如果一行在引号之前结束,而你希望描述文本不在此处结束,可以在引号前放置一个转义反斜杠(例如:\\)以防止引号提前结束文本。如果在你放置的第一个转义反斜杠之前再放置一个(例如:\\\\),则文本中会出现一个反斜杠作为最后一个字符,并且引号将正常结束该行,依此类推。

法术描述也可以包含字体变化、项目符号和表格,就像在《玩家手册》中一样。

文本最初使用提供给 generate_spellbook() 函数的常规字体,但可以在以下这些字体标签之间切换

  • <r> 用于常规字体
  • <b> 用于粗体字体
  • <i> 用于斜体字体
  • <bi><ib> 用于粗斜体字体

一旦检测到任何这些令牌,接下来的文本将使用该标签的字体。标签必须是单独的令牌才能被检测到(被空白字符包围)。

示例

描述: "此文本为常规字体 <bi>,此文本为粗斜体字体 <b>,此字体为粗体 <r>,现在又回到常规字体。"

描述: "<i> 此文本最初为斜体 <r>,然后变为常规。"

要进行项目符号,只需在文本中的行或段落开始处使用破折号 - 或项目符号字符

示例

description: "This is normal text on the first paragraph.
This is new text on a new second paragraph.
This is the third paragraph.
- This is the first bullet point in a series of them.
- This is the second bullet point.
- This is the third bullet point.
And now it's back to regular non-bullet-point text in the last paragraph."
DeScRiPtIoN: "This is some normal text in a paragraph.
• <bi> This is some bold-italic text in a bullet point.
• This is some more bold- italic text in another bullet point.
• <r> This text is back to regular font in a third bullet point.
This text is back to normal paragraph form."

在描述中插入表格,需要使用多个标签。第一个是 <table> 标签,它应该位于每个表格的开始和结束处。第二个是 <title> 标签,用于定义表格的标题。这个标签是可选的,但如果使用,它必须与打开的 <table> 标签在同一行上,并且必须包围表格的标题文本。接下来是列分隔符 |,它用于分隔行内的单个单元格。最后是 <row> 标签,用于标记新行的开始。这个标签对于第一行,即标题行或列标题行,不是必需的。

示例

description: "This is some text in normal paragraph form.
<table> <title> This is a table <title>
Column A | Column B
<row> 1 | Red
<row> 2 | Green
<row> 3 | Blue
<table>
And here's some more text because why not."
description: "Here is a table with 3 columns but no title.
<table>
1 | 2 | 3
<row> A | Black | Black
<row> B | Black | White
<row> C | White | Black
<row> D | White | White
<table>"

提升描述

升级描述:

描述文本,说明你在更高等级施放法术时的效果。遵循与 description: 字段相同的规则,但如果没有提升描述,它可以有一个值为 none,或者根本不包含在法术文件中,以达到相同的效果。

示例

upcast_description: "This is an upcast description <b> with some font changes <r>.
- Here are some bullet points too
- A second bullet point
Some more text.
<table> <title> Here's a table too <title>
A | B | C
<row> 1 | 2 | 3
<row> 4 | 5 | 6
<table>"

upcast_description: none 或在文件中不包含该字段。

自定义字段

字段 level:school:casting_time:range:duration: 都有受控的值,只有少数几种有效的值类型。这种控制措施可以覆盖所有这些字段,允许用户将任何文本注入到法术页面上这些字段中。这可以通过将这些字段的值设置为单行中的文本,并用引号括起来来实现,就像非空的 m_components: 值一样。

示例

等级: "10级"

学派: "技术魔法"

施法时间: "1个动作或8小时"

完整示例

name: Fireball
level: 3
school: evocation
casting_time: actions 1
range: feet 150
has_v_component
has_s_component
m_components: "a tiny ball of bat guano and sulfur"
duration: instant
description: "A bright streak flashes from your pointing finger to a point you choose within range and then blossoms with a low roar into an explosion of flame. Each creature in a 20-foot-radius sphere centered on that point must make a Dexterity saving throw. A target takes 8d6 fire damage on a failed save, or half as much damage on a successful one.
The fire spreads around corners. It ignites flammable objects in the area that aren't being worn or carried."
upcast_description: "When you cast this spell using a spell slot of 4th level or higher, the damage increases by 1d6 for each slot level above 3rd."
name: Counterspell
level: 3
school: abjuration
casting_time: reaction "which you take when you see a creature within 60 feet of you casting a spell"
range: feet 60
has_s_component
duration: instant
description: "You attempt to interrupt a creature in the process of casting a spell. If the creature is casting a spell of 3rd level or lower, its spell fails and has no effect. If it is casting a spell of 4th level or higher, make an ability check using your spellcasting ability. The DC equals 10 + the spell's level. On a success, the creature's spell fails and has no effect."
name: Antipathy/Sympathy
level: 8
school: enchantment
casting_time: hours 1
range: feet 60
has_v_component
has_s_component
m_components: "either a lump of alum soaked in vinegar for the <i> antipathy <r> effect or a drop of honey for the <i> sympathy <r> effect"
duration: days 10
description: "This spell attracts or repels creatures of your choice. You target something within range, either a Huge or smaller object or creature or an area that is no larger than a 200-foot cube. Then specify a kind of intelligent creature, such as red dragons, goblins, or vampires. You invest the target with an aura that either attracts or repels the specified creatures for the duration. Choose antipathy or sympathy as the aura's effect.
<bi> Antipathy. <r> The enchantment causes creatures of the kind you designated to feel an intense urge to leave the area and avoid the target. When such a creature can see the target or comes within 60 feet of it, the creature must succeed on a Wisdom saving throw or become frightened. The creature remains frightened while it can see the target or is within 60 feet of it. While frightened by the target, the creature must use its movement to move to the nearest safe spot from which it can't see the target. If the creature moves more than 60 feet from the target and can't see it, the creature is no longer frightened, but the creature becomes frightened again if it regains sight of the target or moves within 60 feet of it.
<bi> Sympathy. <r> The enchantment causes the specified creatures to feel an intense urge to approach the target while within 60 feet of it or able to see it. When such a creature can see the target or comes within 60 feet of it, the creature must succeed on a Wisdom saving throw or use its movement on each of its turns to enter the area or move within reach of the target. When the creature has done so, it can't willingly move away from the target.
If the target damages or otherwise harms an affected creature, the affected creature can make a Wisdom saving throw to end the effect, as described below.
<bi> Ending the Effect. <r> If an affected creature ends its turn while not within 60 feet of the target or able to see it, the creature makes a Wisdom saving throw. On a successful save, the creature is no longer affected by the target and recognizes the feeling of repugnance or attraction as magical. In addition, a creature affected by the spell is allowed another Wisdom saving throw every 24 hours while the spell persists.
A creature that successfully saves against this effect is immune to it for 1 minute, after which time it can be affected again."
name: Thunderclap
level: 0
school: evocation
casting_time: actions 1
range: feet 5
has_s_component
duration: instant
description: "You create a burst of thunderous sound that can be heard up to 100 feet away. Each creature within range, other than you, must succeed on a Constitution saving throw or take 1d6 thunder damage.
The spell's damage increases by 1d6 when you reach 5th level (2d6), 11th level (3d6), and 17th level (4d6)."
name: Leomund's Tiny Hut
level: 3
school: evocation
is_ritual
casting_time: minutes 1
range: self hemisphere feet 10
has_v_component
has_s_component
m_components: "a small crystal bead"
duration: hours 8
description: "A 10-foot-radius immobile dome of force springs into existence around and above you and remains stationary for the duration. The spell ends if you leave its area.
Nine creatures of Medium size or smaller can fit inside the dome with you. The spell fails if its area includes a larger creature or more than nine creatures. Creatures and objects within the dome when you cast this spell can move through it freely. All other creatures and objects are barred from passing through it. Spells and other magical effects can't extend through the dome or be cast through it. The atmosphere inside the space is comfortable and dry, regardless of the weather outside.
Until the spell ends, you can command the interior to become dimly lit or dark. The dome is opaque from the outside, of any color you choose, but it is transparent from the inside."
name: Prestidigitation
level: 0
school: transmutation
casting_time: actions 1
range: feet 10
has_v_component
has_s_component
duration: hours 1
description: "This spell is a minor magical trick that novice spellcasters use for practice. You create one of the following magical effects within range:
- You create an instantaneous, harmless sensory effect, such as a shower of sparks, a puff of wind, faint musical notes, or an odd odor.
- You instantaneously light or snuff out a candle, a torch, or a small campfire.
- You instantaneously clean or soil an object no larger than 1 cubic foot.
- You chill, warm, or flavor up to 1 cubic foot of nonliving material for 1 hour.
- You make a color, a small mark, or a symbol appear on an object or a surface for 1 hour.
- You create a nonmagical trinket or an illusory image that can fit in your hand and that lasts until the end of your next turn.
If you cast this spell multiple times, you can have up to three of its non-instantaneous effects active at a time, and you can dismiss such an effect as an action."
name: Control Weather
level: 8
school: transmutation
casting_time: minutes 10
range: self sphere miles 5
has_v_component
has_s_component
m_components: "burning incense and bits of earth and wood mixed in water"
duration: hours 8 concentration
description: "You take control of the weather within 5 miles of you for the duration. You must be outdoors to cast this spell. Moving to a place where you don't have a clear path to the sky ends the spell early.
When you cast the spell, you change the current weather conditions, which are determined by the DM based on the climate and season. You can change precipitation, temperature, and wind. It takes 1d4 × 10 minutes for the new conditions to take effect. Once they do so, you can change the conditions again. When the spell ends, the weather gradually returns to normal. When you change the weather conditions, find a current condition on the following tables and change its stage by one, up or down. When changing the wind, you can change its direction.
<table> <title> Precipitation <title>
Stage | Condition
<row> 1 | Clear
<row> 2 | Light Clouds
<row> 3 | Overcast or ground fog
<row> 4 | Rain, hail, or snow
<row> 5 | Torrential rain, driving hail, or blizzard
<table>
<table> <title> Temperature <title>
Stage | Condition
<row> 1 | Unbearable heat
<row> 2 | Hot
<row> 3 | Warm
<row> 4 | Cool
<row> 5 | Cold
<row> 6 | Arctic cold
<table>
<table> <title> Wind <title>
Stage | Condition
<row> 1 | Calm
<row> 2 | Moderate wind
<row> 3 | Strong wind
<row> 4 | Gale
<row> 5 | Storm
<table>"
name: Control Flames
level: 0
school: transmutation
casting_time: actions 1
range: feet 60
has_s_component
duration: "Instantaneous or 1 hour (see below)"
description: "You choose a nonmagical flame that you can see within range and that fits within a 5-foot cube. You affect it in one of the following ways:
- You instantaneously expand the flame 5 feet in one direction, provided that wood or other fuel is present in the new location.
- You instantaneously extinguish the flames within the cube.
- You double or halve the area of bright light and dim light cast by the flame, change its color, or both. The change lasts for 1 hour.
- You cause simple shapes—such as the vague form of a creature, an inanimate object, or a location—to appear within the flames and animate as you like. The shapes last for 1 hour.
If you cast this spell multiple times, you can have up to three non-instantaneous effects created by it active at a time, and you can dismiss such an effect as an action."

依赖关系

30MB
~247K SLoC