ddb_ruby 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4250 @@
1
+ # This code may look unusually verbose for Ruby (and it is), but
2
+ # it performs some subtle and complex validation of JSON data.
3
+ #
4
+ # To parse this JSON, add 'dry-struct' and 'dry-types' gems, then do:
5
+ #
6
+ # top_level = TopLevel.from_json! "{…}"
7
+ # puts top_level.optional_class_features.first
8
+ #
9
+ # If from_json! succeeds, the value returned matches the schema.
10
+
11
+ require 'json'
12
+ require 'dry-types'
13
+ require 'dry-struct'
14
+
15
+ module DdbRuby
16
+ module FifthEdition
17
+ module Types
18
+ include Dry.Types(default: :nominal)
19
+
20
+ Integer = Coercible::Integer
21
+ Bool = Coercible::Bool
22
+ Hash = Coercible::Hash
23
+ String = Coercible::String
24
+ Double = Coercible::Float | Coercible::Integer
25
+ SaveSuccessDescription = Coercible::String.enum("", "half damage")
26
+ Name = Coercible::String.enum("Ammunition", "Finesse", "Golgari Swarm", "Heavy", "Light", "Loading", "Range", "Reach", "Selesnya Conclave", "Thrown", "Two-Handed", "Versatile")
27
+ Username = Coercible::String.enum("afstanton", "hXcMike", "trillianh85")
28
+ DurationUnit = Coercible::String.enum("Day", "Hour", "Minute", "Round", "Special")
29
+ DurationType = Coercible::String.enum("Concentration", "Instantaneous", "Time")
30
+ BackgroundType = Coercible::String.enum("advantage", "bonus", "carrying-capacity", "damage", "disadvantage", "eldritch-blast", "expertise", "ignore", "immunity", "language", "natural-weapon", "proficiency", "protection", "resistance", "set", "set-base", "size", "stealth-disadvantage", "vulnerability")
31
+ BackgroundFriendlyTypeName = Coercible::String.enum("Advantage", "Bonus", "Carrying Capacity", "Damage", "Disadvantage", "Eldritch Blast", "Expertise", "Ignore", "Immunity", "Language", "Natural Weapon", "Proficiency", "Protection", "Resistance", "Set", "Set Base", "Size", "Stealth Disadvantage", "Vulnerability")
32
+ AoeType = Coercible::String.enum("Cone", "Cube", "Cylinder", "Line", "Sphere", "Square")
33
+ Origin = Coercible::String.enum("Ranged", "Self", "Sight", "Touch")
34
+ ScaleType = Coercible::String.enum("characterlevel", "spelllevel", "spellscale")
35
+ School = Coercible::String.enum("Abjuration", "Conjuration", "Divination", "Enchantment", "Evocation", "Illusion", "Necromancy", "Transmutation")
36
+ EntityType = Coercible::String.enum("class-feature", "racial-trait")
37
+ PrerequisiteMappingFriendlyTypeName = Coercible::String.enum("Ability Score", "Custom Value", "Proficiency", "Race", "Size")
38
+ PrerequisiteMappingType = Coercible::String.enum("ability-score", "custom-value", "proficiency", "race", "size")
39
+ AttunementDescription = Coercible::String.enum("druid or ranger", "", "Spellcaster", "Warlock", "wizard")
40
+ DamageType = Coercible::String.enum("Bludgeoning", "Piercing", "Slashing")
41
+ FilterType = Coercible::String.enum("Armor", "Other Gear", "Potion", "Ring", "Rod", "Wand", "Weapon", "Wondrous item")
42
+ Rarity = Coercible::String.enum("Common", "Rare", "Uncommon", "Very Rare")
43
+ SubType = Coercible::String.enum("Adventuring Gear", "Ammunition", "Arcane Focus", "Druidic Focus", "Holy Symbol", "Potion", "Tool")
44
+ Tag = Coercible::String.enum("Buff", "Combat", "Communication", "Consumable", "Container", "Control", "Creation", "Damage", "Deception", "Detection", "Exploration", "Eyewear", "Focus", "Handwear", "Headwear", "Healing", "Instrument", "Jewelry", "Movement", "Outerwear", "Social", "Utility", "Warding")
45
+ ProvidedFrom = Coercible::String.enum("database", "storage")
46
+ AdditionalDescription = Coercible::String.enum("does not require material components", "Doesn't require any components", "", "the hand is invisible")
47
+ Restriction = Coercible::String.enum("Doesn't require concentration", "")
48
+ StatusSlug = Coercible::String.enum("active")
49
+ end
50
+
51
+ class Activation < Dry::Struct
52
+ attribute :activation_time, Types::Integer.optional
53
+ attribute :activation_type, Types::Integer.optional
54
+
55
+ def self.from_dynamic!(d)
56
+ d = Types::Hash[d]
57
+ new(
58
+ activation_time: d.fetch("activationTime"),
59
+ activation_type: d.fetch("activationType"),
60
+ )
61
+ end
62
+
63
+ def self.from_json!(json)
64
+ from_dynamic!(JSON.parse(json))
65
+ end
66
+
67
+ def to_dynamic
68
+ {
69
+ "activationTime" => activation_time,
70
+ "activationType" => activation_type,
71
+ }
72
+ end
73
+
74
+ def to_json(options = nil)
75
+ JSON.generate(to_dynamic, options)
76
+ end
77
+ end
78
+
79
+ class Die < Dry::Struct
80
+ attribute :dice_count, Types::Integer.optional
81
+ attribute :dice_value, Types::Integer.optional
82
+ attribute :dice_multiplier, Types::Integer.optional
83
+ attribute :fixed_value, Types::Integer.optional
84
+ attribute :dice_string, Types::String.optional
85
+
86
+ def self.from_dynamic!(d)
87
+ d = Types::Hash[d]
88
+ new(
89
+ dice_count: d.fetch("diceCount"),
90
+ dice_value: d.fetch("diceValue"),
91
+ dice_multiplier: d.fetch("diceMultiplier"),
92
+ fixed_value: d.fetch("fixedValue"),
93
+ dice_string: d.fetch("diceString"),
94
+ )
95
+ end
96
+
97
+ def self.from_json!(json)
98
+ from_dynamic!(JSON.parse(json))
99
+ end
100
+
101
+ def to_dynamic
102
+ {
103
+ "diceCount" => dice_count,
104
+ "diceValue" => dice_value,
105
+ "diceMultiplier" => dice_multiplier,
106
+ "fixedValue" => fixed_value,
107
+ "diceString" => dice_string,
108
+ }
109
+ end
110
+
111
+ def to_json(options = nil)
112
+ JSON.generate(to_dynamic, options)
113
+ end
114
+ end
115
+
116
+ class ClassLimitedUse < Dry::Struct
117
+ attribute :limited_use_name, Types::Nil
118
+ attribute :stat_modifier_uses_id, Types::Integer.optional
119
+ attribute :reset_type, Types::Integer.optional
120
+ attribute :number_used, Types::Integer
121
+ attribute :min_number_consumed, Types::Integer.optional
122
+ attribute :max_number_consumed, Types::Integer
123
+ attribute :max_uses, Types::Integer
124
+ attribute :operator, Types::Integer.optional
125
+ attribute :use_proficiency_bonus, Types::Bool
126
+ attribute :proficiency_bonus_operator, Types::Integer.optional
127
+ attribute :reset_dice, Types::Nil
128
+
129
+ def self.from_dynamic!(d)
130
+ d = Types::Hash[d]
131
+ new(
132
+ limited_use_name: d.fetch("name"),
133
+ stat_modifier_uses_id: d.fetch("statModifierUsesId"),
134
+ reset_type: d.fetch("resetType"),
135
+ number_used: d.fetch("numberUsed"),
136
+ min_number_consumed: d.fetch("minNumberConsumed"),
137
+ max_number_consumed: d.fetch("maxNumberConsumed"),
138
+ max_uses: d.fetch("maxUses"),
139
+ operator: d.fetch("operator"),
140
+ use_proficiency_bonus: d.fetch("useProficiencyBonus"),
141
+ proficiency_bonus_operator: d.fetch("proficiencyBonusOperator"),
142
+ reset_dice: d.fetch("resetDice"),
143
+ )
144
+ end
145
+
146
+ def self.from_json!(json)
147
+ from_dynamic!(JSON.parse(json))
148
+ end
149
+
150
+ def to_dynamic
151
+ {
152
+ "name" => limited_use_name,
153
+ "statModifierUsesId" => stat_modifier_uses_id,
154
+ "resetType" => reset_type,
155
+ "numberUsed" => number_used,
156
+ "minNumberConsumed" => min_number_consumed,
157
+ "maxNumberConsumed" => max_number_consumed,
158
+ "maxUses" => max_uses,
159
+ "operator" => operator,
160
+ "useProficiencyBonus" => use_proficiency_bonus,
161
+ "proficiencyBonusOperator" => proficiency_bonus_operator,
162
+ "resetDice" => reset_dice,
163
+ }
164
+ end
165
+
166
+ def to_json(options = nil)
167
+ JSON.generate(to_dynamic, options)
168
+ end
169
+ end
170
+
171
+ class Range1 < Dry::Struct
172
+ attribute :range, Types::Integer.optional
173
+ attribute :long_range, Types::Integer.optional
174
+ attribute :aoe_type, Types::Integer.optional
175
+ attribute :aoe_size, Types::Integer.optional
176
+ attribute :has_aoe_special_description, Types::Bool
177
+ attribute :minimum_range, Types::Nil
178
+
179
+ def self.from_dynamic!(d)
180
+ d = Types::Hash[d]
181
+ new(
182
+ range: d.fetch("range"),
183
+ long_range: d.fetch("longRange"),
184
+ aoe_type: d.fetch("aoeType"),
185
+ aoe_size: d.fetch("aoeSize"),
186
+ has_aoe_special_description: d.fetch("hasAoeSpecialDescription"),
187
+ minimum_range: d.fetch("minimumRange"),
188
+ )
189
+ end
190
+
191
+ def self.from_json!(json)
192
+ from_dynamic!(JSON.parse(json))
193
+ end
194
+
195
+ def to_dynamic
196
+ {
197
+ "range" => range,
198
+ "longRange" => long_range,
199
+ "aoeType" => aoe_type,
200
+ "aoeSize" => aoe_size,
201
+ "hasAoeSpecialDescription" => has_aoe_special_description,
202
+ "minimumRange" => minimum_range,
203
+ }
204
+ end
205
+
206
+ def to_json(options = nil)
207
+ JSON.generate(to_dynamic, options)
208
+ end
209
+ end
210
+
211
+ module SaveSuccessDescription
212
+ Empty = ""
213
+ HalfDamage = "half damage"
214
+ end
215
+
216
+ class ActionsClass < Dry::Struct
217
+ attribute :component_id, Types::Integer
218
+ attribute :component_type_id, Types::Integer
219
+ attribute :id, Types::String
220
+ attribute :entity_type_id, Types::String
221
+ attribute :limited_use, ClassLimitedUse.optional
222
+ attribute :class_name, Types::String
223
+ attribute :description, Types::String.optional
224
+ attribute :snippet, Types::String
225
+ attribute :ability_modifier_stat_id, Types::Integer.optional
226
+ attribute :on_miss_description, Types::String.optional
227
+ attribute :save_fail_description, Types::String.optional
228
+ attribute :save_success_description, Types::SaveSuccessDescription.optional
229
+ attribute :save_stat_id, Types::Integer.optional
230
+ attribute :fixed_save_dc, Types::Integer.optional
231
+ attribute :attack_type_range, Types::Integer.optional
232
+ attribute :action_type, Types::Integer
233
+ attribute :attack_subtype, Types::Integer.optional
234
+ attribute :dice, Die.optional
235
+ attribute :value, Types::Integer.optional
236
+ attribute :damage_type_id, Types::Integer.optional
237
+ attribute :is_martial_arts, Types::Bool
238
+ attribute :is_proficient, Types::Bool
239
+ attribute :spell_range_type, Types::Integer.optional
240
+ attribute :display_as_attack, Types::Bool.optional
241
+ attribute :range, Range1
242
+ attribute :activation, Activation
243
+ attribute :number_of_targets, Types::Nil
244
+ attribute :fixed_to_hit, Types::Nil
245
+ attribute :ammunition, Types::Nil
246
+
247
+ def self.from_dynamic!(d)
248
+ d = Types::Hash[d]
249
+ new(
250
+ component_id: d.fetch("componentId"),
251
+ component_type_id: d.fetch("componentTypeId"),
252
+ id: d.fetch("id"),
253
+ entity_type_id: d.fetch("entityTypeId"),
254
+ limited_use: d.fetch("limitedUse") ? ClassLimitedUse.from_dynamic!(d.fetch("limitedUse")) : nil,
255
+ class_name: d.fetch("name"),
256
+ description: d.fetch("description"),
257
+ snippet: d.fetch("snippet"),
258
+ ability_modifier_stat_id: d.fetch("abilityModifierStatId"),
259
+ on_miss_description: d.fetch("onMissDescription"),
260
+ save_fail_description: d.fetch("saveFailDescription"),
261
+ save_success_description: d.fetch("saveSuccessDescription"),
262
+ save_stat_id: d.fetch("saveStatId"),
263
+ fixed_save_dc: d.fetch("fixedSaveDc"),
264
+ attack_type_range: d.fetch("attackTypeRange"),
265
+ action_type: d.fetch("actionType"),
266
+ attack_subtype: d.fetch("attackSubtype"),
267
+ dice: d.fetch("dice") ? Die.from_dynamic!(d.fetch("dice")) : nil,
268
+ value: d.fetch("value"),
269
+ damage_type_id: d.fetch("damageTypeId"),
270
+ is_martial_arts: d.fetch("isMartialArts"),
271
+ is_proficient: d.fetch("isProficient"),
272
+ spell_range_type: d.fetch("spellRangeType"),
273
+ display_as_attack: d.fetch("displayAsAttack"),
274
+ range: Range1.from_dynamic!(d.fetch("range")),
275
+ activation: Activation.from_dynamic!(d.fetch("activation")),
276
+ number_of_targets: d.fetch("numberOfTargets"),
277
+ fixed_to_hit: d.fetch("fixedToHit"),
278
+ ammunition: d.fetch("ammunition"),
279
+ )
280
+ end
281
+
282
+ def self.from_json!(json)
283
+ from_dynamic!(JSON.parse(json))
284
+ end
285
+
286
+ def to_dynamic
287
+ {
288
+ "componentId" => component_id,
289
+ "componentTypeId" => component_type_id,
290
+ "id" => id,
291
+ "entityTypeId" => entity_type_id,
292
+ "limitedUse" => limited_use&.to_dynamic,
293
+ "name" => class_name,
294
+ "description" => description,
295
+ "snippet" => snippet,
296
+ "abilityModifierStatId" => ability_modifier_stat_id,
297
+ "onMissDescription" => on_miss_description,
298
+ "saveFailDescription" => save_fail_description,
299
+ "saveSuccessDescription" => save_success_description,
300
+ "saveStatId" => save_stat_id,
301
+ "fixedSaveDc" => fixed_save_dc,
302
+ "attackTypeRange" => attack_type_range,
303
+ "actionType" => action_type,
304
+ "attackSubtype" => attack_subtype,
305
+ "dice" => dice&.to_dynamic,
306
+ "value" => value,
307
+ "damageTypeId" => damage_type_id,
308
+ "isMartialArts" => is_martial_arts,
309
+ "isProficient" => is_proficient,
310
+ "spellRangeType" => spell_range_type,
311
+ "displayAsAttack" => display_as_attack,
312
+ "range" => range.to_dynamic,
313
+ "activation" => activation.to_dynamic,
314
+ "numberOfTargets" => number_of_targets,
315
+ "fixedToHit" => fixed_to_hit,
316
+ "ammunition" => ammunition,
317
+ }
318
+ end
319
+
320
+ def to_json(options = nil)
321
+ JSON.generate(to_dynamic, options)
322
+ end
323
+ end
324
+
325
+ class Actions < Dry::Struct
326
+ attribute :race, Types.Array(ActionsClass)
327
+ attribute :actions_class, Types.Array(ActionsClass)
328
+ attribute :background, Types::Nil
329
+ attribute :item, Types::Nil
330
+ attribute :feat, Types.Array(ActionsClass)
331
+
332
+ def self.from_dynamic!(d)
333
+ d = Types::Hash[d]
334
+ new(
335
+ race: d.fetch("race").map { |x| ActionsClass.from_dynamic!(x) },
336
+ actions_class: d.fetch("class").map { |x| ActionsClass.from_dynamic!(x) },
337
+ background: d.fetch("background"),
338
+ item: d.fetch("item"),
339
+ feat: d.fetch("feat").map { |x| ActionsClass.from_dynamic!(x) },
340
+ )
341
+ end
342
+
343
+ def self.from_json!(json)
344
+ from_dynamic!(JSON.parse(json))
345
+ end
346
+
347
+ def to_dynamic
348
+ {
349
+ "race" => race.map { |x| x.to_dynamic },
350
+ "class" => actions_class.map { |x| x.to_dynamic },
351
+ "background" => background,
352
+ "item" => item,
353
+ "feat" => feat.map { |x| x.to_dynamic },
354
+ }
355
+ end
356
+
357
+ def to_json(options = nil)
358
+ JSON.generate(to_dynamic, options)
359
+ end
360
+ end
361
+
362
+ class Bond < Dry::Struct
363
+ attribute :id, Types::Integer
364
+ attribute :description, Types::String
365
+ attribute :dice_roll, Types::Integer
366
+
367
+ def self.from_dynamic!(d)
368
+ d = Types::Hash[d]
369
+ new(
370
+ id: d.fetch("id"),
371
+ description: d.fetch("description"),
372
+ dice_roll: d.fetch("diceRoll"),
373
+ )
374
+ end
375
+
376
+ def self.from_json!(json)
377
+ from_dynamic!(JSON.parse(json))
378
+ end
379
+
380
+ def to_dynamic
381
+ {
382
+ "id" => id,
383
+ "description" => description,
384
+ "diceRoll" => dice_roll,
385
+ }
386
+ end
387
+
388
+ def to_json(options = nil)
389
+ JSON.generate(to_dynamic, options)
390
+ end
391
+ end
392
+
393
+ class FeatList < Dry::Struct
394
+ attribute :id, Types::Integer
395
+ attribute :feat_list_name, Types::String
396
+ attribute :feat_ids, Types.Array(Types::Integer)
397
+
398
+ def self.from_dynamic!(d)
399
+ d = Types::Hash[d]
400
+ new(
401
+ id: d.fetch("id"),
402
+ feat_list_name: d.fetch("name"),
403
+ feat_ids: d.fetch("featIds"),
404
+ )
405
+ end
406
+
407
+ def self.from_json!(json)
408
+ from_dynamic!(JSON.parse(json))
409
+ end
410
+
411
+ def to_dynamic
412
+ {
413
+ "id" => id,
414
+ "name" => feat_list_name,
415
+ "featIds" => feat_ids,
416
+ }
417
+ end
418
+
419
+ def to_json(options = nil)
420
+ JSON.generate(to_dynamic, options)
421
+ end
422
+ end
423
+
424
+ module Name
425
+ Ammunition = "Ammunition"
426
+ Finesse = "Finesse"
427
+ GolgariSwarm = "Golgari Swarm"
428
+ Heavy = "Heavy"
429
+ Light = "Light"
430
+ Loading = "Loading"
431
+ Range = "Range"
432
+ Reach = "Reach"
433
+ SelesnyaConclave = "Selesnya Conclave"
434
+ Thrown = "Thrown"
435
+ TwoHanded = "Two-Handed"
436
+ Versatile = "Versatile"
437
+ end
438
+
439
+ class Organization < Dry::Struct
440
+ attribute :id, Types::Integer
441
+ attribute :organization_name, Types::Name
442
+ attribute :description, Types::String
443
+ attribute :notes, Types::String.optional.optional
444
+
445
+ def self.from_dynamic!(d)
446
+ d = Types::Hash[d]
447
+ new(
448
+ id: d.fetch("id"),
449
+ organization_name: d.fetch("name"),
450
+ description: d.fetch("description"),
451
+ notes: d["notes"],
452
+ )
453
+ end
454
+
455
+ def self.from_json!(json)
456
+ from_dynamic!(JSON.parse(json))
457
+ end
458
+
459
+ def to_dynamic
460
+ {
461
+ "id" => id,
462
+ "name" => organization_name,
463
+ "description" => description,
464
+ "notes" => notes,
465
+ }
466
+ end
467
+
468
+ def to_json(options = nil)
469
+ JSON.generate(to_dynamic, options)
470
+ end
471
+ end
472
+
473
+ class Source < Dry::Struct
474
+ attribute :source_id, Types::Integer
475
+ attribute :page_number, Types::Integer.optional
476
+ attribute :source_type, Types::Integer
477
+
478
+ def self.from_dynamic!(d)
479
+ d = Types::Hash[d]
480
+ new(
481
+ source_id: d.fetch("sourceId"),
482
+ page_number: d.fetch("pageNumber"),
483
+ source_type: d.fetch("sourceType"),
484
+ )
485
+ end
486
+
487
+ def self.from_json!(json)
488
+ from_dynamic!(JSON.parse(json))
489
+ end
490
+
491
+ def to_dynamic
492
+ {
493
+ "sourceId" => source_id,
494
+ "pageNumber" => page_number,
495
+ "sourceType" => source_type,
496
+ }
497
+ end
498
+
499
+ def to_json(options = nil)
500
+ JSON.generate(to_dynamic, options)
501
+ end
502
+ end
503
+
504
+ class CharacteristicsBackgroundClass < Dry::Struct
505
+ attribute :id, Types::Integer
506
+ attribute :entity_type_id, Types::Integer
507
+ attribute :definition_key, Types::String
508
+ attribute :definition_name, Types::String
509
+ attribute :description, Types::String
510
+ attribute :snippet, Types::String
511
+ attribute :short_description, Types::String
512
+ attribute :skill_proficiencies_description, Types::String
513
+ attribute :tool_proficiencies_description, Types::String
514
+ attribute :languages_description, Types::String
515
+ attribute :equipment_description, Types::String
516
+ attribute :feature_name, Types::String
517
+ attribute :feature_description, Types::String
518
+ attribute :avatar_url, Types::Nil
519
+ attribute :large_avatar_url, Types::Nil
520
+ attribute :suggested_characteristics_description, Types::String
521
+ attribute :suggested_proficiencies, Types::Nil
522
+ attribute :suggested_languages, Types::Nil
523
+ attribute :organization, Organization.optional
524
+ attribute :contracts_description, Types::String
525
+ attribute :spells_pre_description, Types::String
526
+ attribute :spells_post_description, Types::String
527
+ attribute :personality_traits, Types.Array(Bond)
528
+ attribute :ideals, Types.Array(Bond)
529
+ attribute :bonds, Types.Array(Bond)
530
+ attribute :flaws, Types.Array(Bond)
531
+ attribute :is_homebrew, Types::Bool
532
+ attribute :sources, Types.Array(Source)
533
+ attribute :spell_list_ids, Types.Array(Types::Integer)
534
+ attribute :feat_list, FeatList.optional
535
+
536
+ def self.from_dynamic!(d)
537
+ d = Types::Hash[d]
538
+ new(
539
+ id: d.fetch("id"),
540
+ entity_type_id: d.fetch("entityTypeId"),
541
+ definition_key: d.fetch("definitionKey"),
542
+ definition_name: d.fetch("name"),
543
+ description: d.fetch("description"),
544
+ snippet: d.fetch("snippet"),
545
+ short_description: d.fetch("shortDescription"),
546
+ skill_proficiencies_description: d.fetch("skillProficienciesDescription"),
547
+ tool_proficiencies_description: d.fetch("toolProficienciesDescription"),
548
+ languages_description: d.fetch("languagesDescription"),
549
+ equipment_description: d.fetch("equipmentDescription"),
550
+ feature_name: d.fetch("featureName"),
551
+ feature_description: d.fetch("featureDescription"),
552
+ avatar_url: d.fetch("avatarUrl"),
553
+ large_avatar_url: d.fetch("largeAvatarUrl"),
554
+ suggested_characteristics_description: d.fetch("suggestedCharacteristicsDescription"),
555
+ suggested_proficiencies: d.fetch("suggestedProficiencies"),
556
+ suggested_languages: d.fetch("suggestedLanguages"),
557
+ organization: d.fetch("organization") ? Organization.from_dynamic!(d.fetch("organization")) : nil,
558
+ contracts_description: d.fetch("contractsDescription"),
559
+ spells_pre_description: d.fetch("spellsPreDescription"),
560
+ spells_post_description: d.fetch("spellsPostDescription"),
561
+ personality_traits: d.fetch("personalityTraits").map { |x| Bond.from_dynamic!(x) },
562
+ ideals: d.fetch("ideals").map { |x| Bond.from_dynamic!(x) },
563
+ bonds: d.fetch("bonds").map { |x| Bond.from_dynamic!(x) },
564
+ flaws: d.fetch("flaws").map { |x| Bond.from_dynamic!(x) },
565
+ is_homebrew: d.fetch("isHomebrew"),
566
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
567
+ spell_list_ids: d.fetch("spellListIds"),
568
+ feat_list: d.fetch("featList") ? FeatList.from_dynamic!(d.fetch("featList")) : nil,
569
+ )
570
+ end
571
+
572
+ def self.from_json!(json)
573
+ from_dynamic!(JSON.parse(json))
574
+ end
575
+
576
+ def to_dynamic
577
+ {
578
+ "id" => id,
579
+ "entityTypeId" => entity_type_id,
580
+ "definitionKey" => definition_key,
581
+ "name" => definition_name,
582
+ "description" => description,
583
+ "snippet" => snippet,
584
+ "shortDescription" => short_description,
585
+ "skillProficienciesDescription" => skill_proficiencies_description,
586
+ "toolProficienciesDescription" => tool_proficiencies_description,
587
+ "languagesDescription" => languages_description,
588
+ "equipmentDescription" => equipment_description,
589
+ "featureName" => feature_name,
590
+ "featureDescription" => feature_description,
591
+ "avatarUrl" => avatar_url,
592
+ "largeAvatarUrl" => large_avatar_url,
593
+ "suggestedCharacteristicsDescription" => suggested_characteristics_description,
594
+ "suggestedProficiencies" => suggested_proficiencies,
595
+ "suggestedLanguages" => suggested_languages,
596
+ "organization" => organization&.to_dynamic,
597
+ "contractsDescription" => contracts_description,
598
+ "spellsPreDescription" => spells_pre_description,
599
+ "spellsPostDescription" => spells_post_description,
600
+ "personalityTraits" => personality_traits.map { |x| x.to_dynamic },
601
+ "ideals" => ideals.map { |x| x.to_dynamic },
602
+ "bonds" => bonds.map { |x| x.to_dynamic },
603
+ "flaws" => flaws.map { |x| x.to_dynamic },
604
+ "isHomebrew" => is_homebrew,
605
+ "sources" => sources.map { |x| x.to_dynamic },
606
+ "spellListIds" => spell_list_ids,
607
+ "featList" => feat_list&.to_dynamic,
608
+ }
609
+ end
610
+
611
+ def to_json(options = nil)
612
+ JSON.generate(to_dynamic, options)
613
+ end
614
+ end
615
+
616
+ class CustomBackground < Dry::Struct
617
+ attribute :id, Types::Integer
618
+ attribute :entity_type_id, Types::Integer
619
+ attribute :custom_background_name, Types::String.optional
620
+ attribute :description, Types::Nil
621
+ attribute :features_background, CharacteristicsBackgroundClass.optional
622
+ attribute :characteristics_background, CharacteristicsBackgroundClass.optional
623
+ attribute :features_background_definition_id, Types::Nil
624
+ attribute :characteristics_background_definition_id, Types::Nil
625
+ attribute :background_type, Types::Integer.optional
626
+
627
+ def self.from_dynamic!(d)
628
+ d = Types::Hash[d]
629
+ new(
630
+ id: d.fetch("id"),
631
+ entity_type_id: d.fetch("entityTypeId"),
632
+ custom_background_name: d.fetch("name"),
633
+ description: d.fetch("description"),
634
+ features_background: d.fetch("featuresBackground") ? CharacteristicsBackgroundClass.from_dynamic!(d.fetch("featuresBackground")) : nil,
635
+ characteristics_background: d.fetch("characteristicsBackground") ? CharacteristicsBackgroundClass.from_dynamic!(d.fetch("characteristicsBackground")) : nil,
636
+ features_background_definition_id: d.fetch("featuresBackgroundDefinitionId"),
637
+ characteristics_background_definition_id: d.fetch("characteristicsBackgroundDefinitionId"),
638
+ background_type: d.fetch("backgroundType"),
639
+ )
640
+ end
641
+
642
+ def self.from_json!(json)
643
+ from_dynamic!(JSON.parse(json))
644
+ end
645
+
646
+ def to_dynamic
647
+ {
648
+ "id" => id,
649
+ "entityTypeId" => entity_type_id,
650
+ "name" => custom_background_name,
651
+ "description" => description,
652
+ "featuresBackground" => features_background&.to_dynamic,
653
+ "characteristicsBackground" => characteristics_background&.to_dynamic,
654
+ "featuresBackgroundDefinitionId" => features_background_definition_id,
655
+ "characteristicsBackgroundDefinitionId" => characteristics_background_definition_id,
656
+ "backgroundType" => background_type,
657
+ }
658
+ end
659
+
660
+ def to_json(options = nil)
661
+ JSON.generate(to_dynamic, options)
662
+ end
663
+ end
664
+
665
+ class TopLevelBackground < Dry::Struct
666
+ attribute :has_custom_background, Types::Bool
667
+ attribute :definition, CharacteristicsBackgroundClass.optional
668
+ attribute :definition_id, Types::Nil
669
+ attribute :custom_background, CustomBackground
670
+
671
+ def self.from_dynamic!(d)
672
+ d = Types::Hash[d]
673
+ new(
674
+ has_custom_background: d.fetch("hasCustomBackground"),
675
+ definition: d.fetch("definition") ? CharacteristicsBackgroundClass.from_dynamic!(d.fetch("definition")) : nil,
676
+ definition_id: d.fetch("definitionId"),
677
+ custom_background: CustomBackground.from_dynamic!(d.fetch("customBackground")),
678
+ )
679
+ end
680
+
681
+ def self.from_json!(json)
682
+ from_dynamic!(JSON.parse(json))
683
+ end
684
+
685
+ def to_dynamic
686
+ {
687
+ "hasCustomBackground" => has_custom_background,
688
+ "definition" => definition&.to_dynamic,
689
+ "definitionId" => definition_id,
690
+ "customBackground" => custom_background.to_dynamic,
691
+ }
692
+ end
693
+
694
+ def to_json(options = nil)
695
+ JSON.generate(to_dynamic, options)
696
+ end
697
+ end
698
+
699
+ class Stat < Dry::Struct
700
+ attribute :id, Types::Integer
701
+ attribute :stat_name, Types::Nil
702
+ attribute :value, Types::Integer.optional
703
+
704
+ def self.from_dynamic!(d)
705
+ d = Types::Hash[d]
706
+ new(
707
+ id: d.fetch("id"),
708
+ stat_name: d.fetch("name"),
709
+ value: d.fetch("value"),
710
+ )
711
+ end
712
+
713
+ def self.from_json!(json)
714
+ from_dynamic!(JSON.parse(json))
715
+ end
716
+
717
+ def to_dynamic
718
+ {
719
+ "id" => id,
720
+ "name" => stat_name,
721
+ "value" => value,
722
+ }
723
+ end
724
+
725
+ def to_json(options = nil)
726
+ JSON.generate(to_dynamic, options)
727
+ end
728
+ end
729
+
730
+ class Character < Dry::Struct
731
+ attribute :user_id, Types::Integer
732
+ attribute :username, Types::String
733
+ attribute :character_id, Types::Integer
734
+ attribute :character_name, Types::String
735
+ attribute :character_url, Types::String
736
+ attribute :avatar_url, Types::String.optional
737
+ attribute :privacy_type, Types::Integer
738
+ attribute :campaign_id, Types::Nil
739
+ attribute :is_assigned, Types::Bool
740
+
741
+ def self.from_dynamic!(d)
742
+ d = Types::Hash[d]
743
+ new(
744
+ user_id: d.fetch("userId"),
745
+ username: d.fetch("username"),
746
+ character_id: d.fetch("characterId"),
747
+ character_name: d.fetch("characterName"),
748
+ character_url: d.fetch("characterUrl"),
749
+ avatar_url: d.fetch("avatarUrl"),
750
+ privacy_type: d.fetch("privacyType"),
751
+ campaign_id: d.fetch("campaignId"),
752
+ is_assigned: d.fetch("isAssigned"),
753
+ )
754
+ end
755
+
756
+ def self.from_json!(json)
757
+ from_dynamic!(JSON.parse(json))
758
+ end
759
+
760
+ def to_dynamic
761
+ {
762
+ "userId" => user_id,
763
+ "username" => username,
764
+ "characterId" => character_id,
765
+ "characterName" => character_name,
766
+ "characterUrl" => character_url,
767
+ "avatarUrl" => avatar_url,
768
+ "privacyType" => privacy_type,
769
+ "campaignId" => campaign_id,
770
+ "isAssigned" => is_assigned,
771
+ }
772
+ end
773
+
774
+ def to_json(options = nil)
775
+ JSON.generate(to_dynamic, options)
776
+ end
777
+ end
778
+
779
+ module Username
780
+ Afstanton = "afstanton"
781
+ HXcMike = "hXcMike"
782
+ Trillianh85 = "trillianh85"
783
+ end
784
+
785
+ class Campaign < Dry::Struct
786
+ attribute :id, Types::Integer
787
+ attribute :campaign_name, Types::String
788
+ attribute :description, Types::String
789
+ attribute :link, Types::String
790
+ attribute :public_notes, Types::String
791
+ attribute :dm_user_id, Types::Integer
792
+ attribute :dm_username, Types::Username
793
+ attribute :characters, Types.Array(Character)
794
+
795
+ def self.from_dynamic!(d)
796
+ d = Types::Hash[d]
797
+ new(
798
+ id: d.fetch("id"),
799
+ campaign_name: d.fetch("name"),
800
+ description: d.fetch("description"),
801
+ link: d.fetch("link"),
802
+ public_notes: d.fetch("publicNotes"),
803
+ dm_user_id: d.fetch("dmUserId"),
804
+ dm_username: d.fetch("dmUsername"),
805
+ characters: d.fetch("characters").map { |x| Character.from_dynamic!(x) },
806
+ )
807
+ end
808
+
809
+ def self.from_json!(json)
810
+ from_dynamic!(JSON.parse(json))
811
+ end
812
+
813
+ def to_dynamic
814
+ {
815
+ "id" => id,
816
+ "name" => campaign_name,
817
+ "description" => description,
818
+ "link" => link,
819
+ "publicNotes" => public_notes,
820
+ "dmUserId" => dm_user_id,
821
+ "dmUsername" => dm_username,
822
+ "characters" => characters.map { |x| x.to_dynamic },
823
+ }
824
+ end
825
+
826
+ def to_json(options = nil)
827
+ JSON.generate(to_dynamic, options)
828
+ end
829
+ end
830
+
831
+ class CharacterValue < Dry::Struct
832
+ attribute :type_id, Types::Integer
833
+ attribute :value, Types::Integer
834
+ attribute :notes, Types::Nil
835
+ attribute :value_id, Types::String
836
+ attribute :value_type_id, Types::String
837
+ attribute :context_id, Types::Nil
838
+ attribute :context_type_id, Types::Nil
839
+
840
+ def self.from_dynamic!(d)
841
+ d = Types::Hash[d]
842
+ new(
843
+ type_id: d.fetch("typeId"),
844
+ value: d.fetch("value"),
845
+ notes: d.fetch("notes"),
846
+ value_id: d.fetch("valueId"),
847
+ value_type_id: d.fetch("valueTypeId"),
848
+ context_id: d.fetch("contextId"),
849
+ context_type_id: d.fetch("contextTypeId"),
850
+ )
851
+ end
852
+
853
+ def self.from_json!(json)
854
+ from_dynamic!(JSON.parse(json))
855
+ end
856
+
857
+ def to_dynamic
858
+ {
859
+ "typeId" => type_id,
860
+ "value" => value,
861
+ "notes" => notes,
862
+ "valueId" => value_id,
863
+ "valueTypeId" => value_type_id,
864
+ "contextId" => context_id,
865
+ "contextTypeId" => context_type_id,
866
+ }
867
+ end
868
+
869
+ def to_json(options = nil)
870
+ JSON.generate(to_dynamic, options)
871
+ end
872
+ end
873
+
874
+ class ChoicesBackground < Dry::Struct
875
+ attribute :component_id, Types::Integer
876
+ attribute :component_type_id, Types::Integer
877
+ attribute :id, Types::String
878
+ attribute :parent_choice_id, Types::String.optional
879
+ attribute :background_type, Types::Integer
880
+ attribute :sub_type, Types::Integer.optional
881
+ attribute :option_value, Types::Integer.optional
882
+ attribute :label, Types::String.optional
883
+ attribute :is_optional, Types::Bool
884
+ attribute :is_infinite, Types::Bool
885
+ attribute :default_subtypes, Types.Array(Types::String)
886
+ attribute :display_order, Types::Integer.optional
887
+ attribute :background_options, Types.Array(Types::Any)
888
+ attribute :option_ids, Types.Array(Types::Integer)
889
+
890
+ def self.from_dynamic!(d)
891
+ d = Types::Hash[d]
892
+ new(
893
+ component_id: d.fetch("componentId"),
894
+ component_type_id: d.fetch("componentTypeId"),
895
+ id: d.fetch("id"),
896
+ parent_choice_id: d.fetch("parentChoiceId"),
897
+ background_type: d.fetch("type"),
898
+ sub_type: d.fetch("subType"),
899
+ option_value: d.fetch("optionValue"),
900
+ label: d.fetch("label"),
901
+ is_optional: d.fetch("isOptional"),
902
+ is_infinite: d.fetch("isInfinite"),
903
+ default_subtypes: d.fetch("defaultSubtypes"),
904
+ display_order: d.fetch("displayOrder"),
905
+ background_options: d.fetch("options"),
906
+ option_ids: d.fetch("optionIds"),
907
+ )
908
+ end
909
+
910
+ def self.from_json!(json)
911
+ from_dynamic!(JSON.parse(json))
912
+ end
913
+
914
+ def to_dynamic
915
+ {
916
+ "componentId" => component_id,
917
+ "componentTypeId" => component_type_id,
918
+ "id" => id,
919
+ "parentChoiceId" => parent_choice_id,
920
+ "type" => background_type,
921
+ "subType" => sub_type,
922
+ "optionValue" => option_value,
923
+ "label" => label,
924
+ "isOptional" => is_optional,
925
+ "isInfinite" => is_infinite,
926
+ "defaultSubtypes" => default_subtypes,
927
+ "displayOrder" => display_order,
928
+ "options" => background_options,
929
+ "optionIds" => option_ids,
930
+ }
931
+ end
932
+
933
+ def to_json(options = nil)
934
+ JSON.generate(to_dynamic, options)
935
+ end
936
+ end
937
+
938
+ class Option < Dry::Struct
939
+ attribute :id, Types::Integer
940
+ attribute :label, Types::String
941
+ attribute :description, Types::String.optional
942
+
943
+ def self.from_dynamic!(d)
944
+ d = Types::Hash[d]
945
+ new(
946
+ id: d.fetch("id"),
947
+ label: d.fetch("label"),
948
+ description: d.fetch("description"),
949
+ )
950
+ end
951
+
952
+ def self.from_json!(json)
953
+ from_dynamic!(JSON.parse(json))
954
+ end
955
+
956
+ def to_dynamic
957
+ {
958
+ "id" => id,
959
+ "label" => label,
960
+ "description" => description,
961
+ }
962
+ end
963
+
964
+ def to_json(options = nil)
965
+ JSON.generate(to_dynamic, options)
966
+ end
967
+ end
968
+
969
+ class ChoiceDefinition < Dry::Struct
970
+ attribute :id, Types::String
971
+ attribute :choice_definition_options, Types.Array(Option)
972
+
973
+ def self.from_dynamic!(d)
974
+ d = Types::Hash[d]
975
+ new(
976
+ id: d.fetch("id"),
977
+ choice_definition_options: d.fetch("options").map { |x| Option.from_dynamic!(x) },
978
+ )
979
+ end
980
+
981
+ def self.from_json!(json)
982
+ from_dynamic!(JSON.parse(json))
983
+ end
984
+
985
+ def to_dynamic
986
+ {
987
+ "id" => id,
988
+ "options" => choice_definition_options.map { |x| x.to_dynamic },
989
+ }
990
+ end
991
+
992
+ def to_json(options = nil)
993
+ JSON.generate(to_dynamic, options)
994
+ end
995
+ end
996
+
997
+ class DefinitionKeyNameMap < Dry::Struct
998
+ attribute :feat_1212493, Types::String.optional
999
+
1000
+ def self.from_dynamic!(d)
1001
+ d = Types::Hash[d]
1002
+ new(
1003
+ feat_1212493: d["feat:1212493"],
1004
+ )
1005
+ end
1006
+
1007
+ def self.from_json!(json)
1008
+ from_dynamic!(JSON.parse(json))
1009
+ end
1010
+
1011
+ def to_dynamic
1012
+ {
1013
+ "feat:1212493" => feat_1212493,
1014
+ }
1015
+ end
1016
+
1017
+ def to_json(options = nil)
1018
+ JSON.generate(to_dynamic, options)
1019
+ end
1020
+ end
1021
+
1022
+ class Choices < Dry::Struct
1023
+ attribute :race, Types.Array(ChoicesBackground)
1024
+ attribute :choices_class, Types.Array(ChoicesBackground)
1025
+ attribute :background, Types.Array(ChoicesBackground)
1026
+ attribute :item, Types::Nil
1027
+ attribute :feat, Types.Array(ChoicesBackground)
1028
+ attribute :choice_definitions, Types.Array(ChoiceDefinition)
1029
+ attribute :definition_key_name_map, DefinitionKeyNameMap
1030
+
1031
+ def self.from_dynamic!(d)
1032
+ d = Types::Hash[d]
1033
+ new(
1034
+ race: d.fetch("race").map { |x| ChoicesBackground.from_dynamic!(x) },
1035
+ choices_class: d.fetch("class").map { |x| ChoicesBackground.from_dynamic!(x) },
1036
+ background: d.fetch("background").map { |x| ChoicesBackground.from_dynamic!(x) },
1037
+ item: d.fetch("item"),
1038
+ feat: d.fetch("feat").map { |x| ChoicesBackground.from_dynamic!(x) },
1039
+ choice_definitions: d.fetch("choiceDefinitions").map { |x| ChoiceDefinition.from_dynamic!(x) },
1040
+ definition_key_name_map: DefinitionKeyNameMap.from_dynamic!(d.fetch("definitionKeyNameMap")),
1041
+ )
1042
+ end
1043
+
1044
+ def self.from_json!(json)
1045
+ from_dynamic!(JSON.parse(json))
1046
+ end
1047
+
1048
+ def to_dynamic
1049
+ {
1050
+ "race" => race.map { |x| x.to_dynamic },
1051
+ "class" => choices_class.map { |x| x.to_dynamic },
1052
+ "background" => background.map { |x| x.to_dynamic },
1053
+ "item" => item,
1054
+ "feat" => feat.map { |x| x.to_dynamic },
1055
+ "choiceDefinitions" => choice_definitions.map { |x| x.to_dynamic },
1056
+ "definitionKeyNameMap" => definition_key_name_map.to_dynamic,
1057
+ }
1058
+ end
1059
+
1060
+ def to_json(options = nil)
1061
+ JSON.generate(to_dynamic, options)
1062
+ end
1063
+ end
1064
+
1065
+ class HigherLevelDefinition < Dry::Struct
1066
+ attribute :level, Types::Integer.optional
1067
+ attribute :type_id, Types::Integer
1068
+ attribute :dice, Die.optional
1069
+ attribute :value, Types::Integer.optional
1070
+ attribute :details, Types::String
1071
+
1072
+ def self.from_dynamic!(d)
1073
+ d = Types::Hash[d]
1074
+ new(
1075
+ level: d.fetch("level"),
1076
+ type_id: d.fetch("typeId"),
1077
+ dice: d.fetch("dice") ? Die.from_dynamic!(d.fetch("dice")) : nil,
1078
+ value: d.fetch("value"),
1079
+ details: d.fetch("details"),
1080
+ )
1081
+ end
1082
+
1083
+ def self.from_json!(json)
1084
+ from_dynamic!(JSON.parse(json))
1085
+ end
1086
+
1087
+ def to_dynamic
1088
+ {
1089
+ "level" => level,
1090
+ "typeId" => type_id,
1091
+ "dice" => dice&.to_dynamic,
1092
+ "value" => value,
1093
+ "details" => details,
1094
+ }
1095
+ end
1096
+
1097
+ def to_json(options = nil)
1098
+ JSON.generate(to_dynamic, options)
1099
+ end
1100
+ end
1101
+
1102
+ class AtHigherLevels < Dry::Struct
1103
+ attribute :higher_level_definitions, Types.Array(HigherLevelDefinition)
1104
+ attribute :additional_attacks, Types.Array(Types::Any)
1105
+ attribute :additional_targets, Types.Array(Types::Any)
1106
+ attribute :area_of_effect, Types.Array(Types::Any)
1107
+ attribute :duration, Types.Array(Types::Any)
1108
+ attribute :creatures, Types.Array(Types::Any)
1109
+ attribute :special, Types.Array(Types::Any)
1110
+ attribute :points, Types.Array(Types::Any)
1111
+ attribute :range, Types.Array(Types::Any)
1112
+
1113
+ def self.from_dynamic!(d)
1114
+ d = Types::Hash[d]
1115
+ new(
1116
+ higher_level_definitions: d.fetch("higherLevelDefinitions").map { |x| HigherLevelDefinition.from_dynamic!(x) },
1117
+ additional_attacks: d.fetch("additionalAttacks"),
1118
+ additional_targets: d.fetch("additionalTargets"),
1119
+ area_of_effect: d.fetch("areaOfEffect"),
1120
+ duration: d.fetch("duration"),
1121
+ creatures: d.fetch("creatures"),
1122
+ special: d.fetch("special"),
1123
+ points: d.fetch("points"),
1124
+ range: d.fetch("range"),
1125
+ )
1126
+ end
1127
+
1128
+ def self.from_json!(json)
1129
+ from_dynamic!(JSON.parse(json))
1130
+ end
1131
+
1132
+ def to_dynamic
1133
+ {
1134
+ "higherLevelDefinitions" => higher_level_definitions.map { |x| x.to_dynamic },
1135
+ "additionalAttacks" => additional_attacks,
1136
+ "additionalTargets" => additional_targets,
1137
+ "areaOfEffect" => area_of_effect,
1138
+ "duration" => duration,
1139
+ "creatures" => creatures,
1140
+ "special" => special,
1141
+ "points" => points,
1142
+ "range" => range,
1143
+ }
1144
+ end
1145
+
1146
+ def to_json(options = nil)
1147
+ JSON.generate(to_dynamic, options)
1148
+ end
1149
+ end
1150
+
1151
+ module DurationUnit
1152
+ Day = "Day"
1153
+ Hour = "Hour"
1154
+ Minute = "Minute"
1155
+ Round = "Round"
1156
+ Special = "Special"
1157
+ end
1158
+
1159
+ class DefinitionCondition < Dry::Struct
1160
+ attribute :condition_type, Types::Integer
1161
+ attribute :condition_id, Types::Integer
1162
+ attribute :condition_duration, Types::Integer
1163
+ attribute :duration_unit, Types::DurationUnit
1164
+ attribute :exception, Types::String
1165
+
1166
+ def self.from_dynamic!(d)
1167
+ d = Types::Hash[d]
1168
+ new(
1169
+ condition_type: d.fetch("type"),
1170
+ condition_id: d.fetch("conditionId"),
1171
+ condition_duration: d.fetch("conditionDuration"),
1172
+ duration_unit: d.fetch("durationUnit"),
1173
+ exception: d.fetch("exception"),
1174
+ )
1175
+ end
1176
+
1177
+ def self.from_json!(json)
1178
+ from_dynamic!(JSON.parse(json))
1179
+ end
1180
+
1181
+ def to_dynamic
1182
+ {
1183
+ "type" => condition_type,
1184
+ "conditionId" => condition_id,
1185
+ "conditionDuration" => condition_duration,
1186
+ "durationUnit" => duration_unit,
1187
+ "exception" => exception,
1188
+ }
1189
+ end
1190
+
1191
+ def to_json(options = nil)
1192
+ JSON.generate(to_dynamic, options)
1193
+ end
1194
+ end
1195
+
1196
+ module DurationType
1197
+ Concentration = "Concentration"
1198
+ Instantaneous = "Instantaneous"
1199
+ Time = "Time"
1200
+ end
1201
+
1202
+ class DefinitionDuration < Dry::Struct
1203
+ attribute :duration_interval, Types::Integer
1204
+ attribute :duration_unit, Types::DurationUnit.optional
1205
+ attribute :duration_type, Types::DurationType
1206
+
1207
+ def self.from_dynamic!(d)
1208
+ d = Types::Hash[d]
1209
+ new(
1210
+ duration_interval: d.fetch("durationInterval"),
1211
+ duration_unit: d.fetch("durationUnit"),
1212
+ duration_type: d.fetch("durationType"),
1213
+ )
1214
+ end
1215
+
1216
+ def self.from_json!(json)
1217
+ from_dynamic!(JSON.parse(json))
1218
+ end
1219
+
1220
+ def to_dynamic
1221
+ {
1222
+ "durationInterval" => duration_interval,
1223
+ "durationUnit" => duration_unit,
1224
+ "durationType" => duration_type,
1225
+ }
1226
+ end
1227
+
1228
+ def to_json(options = nil)
1229
+ JSON.generate(to_dynamic, options)
1230
+ end
1231
+ end
1232
+
1233
+ module BackgroundType
1234
+ Advantage = "advantage"
1235
+ Bonus = "bonus"
1236
+ CarryingCapacity = "carrying-capacity"
1237
+ Damage = "damage"
1238
+ Disadvantage = "disadvantage"
1239
+ EldritchBlast = "eldritch-blast"
1240
+ Expertise = "expertise"
1241
+ Ignore = "ignore"
1242
+ Immunity = "immunity"
1243
+ Language = "language"
1244
+ NaturalWeapon = "natural-weapon"
1245
+ Proficiency = "proficiency"
1246
+ Protection = "protection"
1247
+ Resistance = "resistance"
1248
+ Set = "set"
1249
+ SetBase = "set-base"
1250
+ Size = "size"
1251
+ StealthDisadvantage = "stealth-disadvantage"
1252
+ Vulnerability = "vulnerability"
1253
+ end
1254
+
1255
+ class BackgroundDuration < Dry::Struct
1256
+ attribute :duration_interval, Types::Integer
1257
+ attribute :duration_unit, Types::DurationUnit
1258
+
1259
+ def self.from_dynamic!(d)
1260
+ d = Types::Hash[d]
1261
+ new(
1262
+ duration_interval: d.fetch("durationInterval"),
1263
+ duration_unit: d.fetch("durationUnit"),
1264
+ )
1265
+ end
1266
+
1267
+ def self.from_json!(json)
1268
+ from_dynamic!(JSON.parse(json))
1269
+ end
1270
+
1271
+ def to_dynamic
1272
+ {
1273
+ "durationInterval" => duration_interval,
1274
+ "durationUnit" => duration_unit,
1275
+ }
1276
+ end
1277
+
1278
+ def to_json(options = nil)
1279
+ JSON.generate(to_dynamic, options)
1280
+ end
1281
+ end
1282
+
1283
+ module BackgroundFriendlyTypeName
1284
+ Advantage = "Advantage"
1285
+ Bonus = "Bonus"
1286
+ CarryingCapacity = "Carrying Capacity"
1287
+ Damage = "Damage"
1288
+ Disadvantage = "Disadvantage"
1289
+ EldritchBlast = "Eldritch Blast"
1290
+ Expertise = "Expertise"
1291
+ Ignore = "Ignore"
1292
+ Immunity = "Immunity"
1293
+ Language = "Language"
1294
+ NaturalWeapon = "Natural Weapon"
1295
+ Proficiency = "Proficiency"
1296
+ Protection = "Protection"
1297
+ Resistance = "Resistance"
1298
+ Set = "Set"
1299
+ SetBase = "Set Base"
1300
+ Size = "Size"
1301
+ StealthDisadvantage = "Stealth Disadvantage"
1302
+ Vulnerability = "Vulnerability"
1303
+ end
1304
+
1305
+ class ItemElement < Dry::Struct
1306
+ attribute :fixed_value, Types::Integer.optional
1307
+ attribute :id, Types::String
1308
+ attribute :entity_id, Types::Integer.optional
1309
+ attribute :entity_type_id, Types::Integer.optional
1310
+ attribute :background_type, Types::BackgroundType
1311
+ attribute :sub_type, Types::String
1312
+ attribute :dice, Die.optional
1313
+ attribute :restriction, Types::String.optional
1314
+ attribute :stat_id, Types::Integer.optional
1315
+ attribute :requires_attunement, Types::Bool
1316
+ attribute :duration, BackgroundDuration.optional
1317
+ attribute :friendly_type_name, Types::BackgroundFriendlyTypeName
1318
+ attribute :friendly_subtype_name, Types::String
1319
+ attribute :is_granted, Types::Bool
1320
+ attribute :bonus_types, Types.Array(Types::Any)
1321
+ attribute :value, Types::Integer.optional
1322
+ attribute :available_to_multiclass, Types::Bool.optional
1323
+ attribute :modifier_type_id, Types::Integer
1324
+ attribute :modifier_sub_type_id, Types::Integer
1325
+ attribute :component_id, Types::Integer
1326
+ attribute :component_type_id, Types::Integer
1327
+ attribute :die, Die.optional
1328
+ attribute :count, Types::Integer.optional
1329
+ attribute :duration_unit, Types::Nil.optional
1330
+ attribute :use_primary_stat, Types::Bool.optional
1331
+ attribute :at_higher_levels, AtHigherLevels.optional
1332
+
1333
+ def self.from_dynamic!(d)
1334
+ d = Types::Hash[d]
1335
+ new(
1336
+ fixed_value: d.fetch("fixedValue"),
1337
+ id: d.fetch("id"),
1338
+ entity_id: d.fetch("entityId"),
1339
+ entity_type_id: d.fetch("entityTypeId"),
1340
+ background_type: d.fetch("type"),
1341
+ sub_type: d.fetch("subType"),
1342
+ dice: d.fetch("dice") ? Die.from_dynamic!(d.fetch("dice")) : nil,
1343
+ restriction: d.fetch("restriction"),
1344
+ stat_id: d.fetch("statId"),
1345
+ requires_attunement: d.fetch("requiresAttunement"),
1346
+ duration: d.fetch("duration") ? BackgroundDuration.from_dynamic!(d.fetch("duration")) : nil,
1347
+ friendly_type_name: d.fetch("friendlyTypeName"),
1348
+ friendly_subtype_name: d.fetch("friendlySubtypeName"),
1349
+ is_granted: d.fetch("isGranted"),
1350
+ bonus_types: d.fetch("bonusTypes"),
1351
+ value: d.fetch("value"),
1352
+ available_to_multiclass: d.fetch("availableToMulticlass"),
1353
+ modifier_type_id: d.fetch("modifierTypeId"),
1354
+ modifier_sub_type_id: d.fetch("modifierSubTypeId"),
1355
+ component_id: d.fetch("componentId"),
1356
+ component_type_id: d.fetch("componentTypeId"),
1357
+ die: d["die"] ? Die.from_dynamic!(d["die"]) : nil,
1358
+ count: d["count"],
1359
+ duration_unit: d["durationUnit"],
1360
+ use_primary_stat: d["usePrimaryStat"],
1361
+ at_higher_levels: d["atHigherLevels"] ? AtHigherLevels.from_dynamic!(d["atHigherLevels"]) : nil,
1362
+ )
1363
+ end
1364
+
1365
+ def self.from_json!(json)
1366
+ from_dynamic!(JSON.parse(json))
1367
+ end
1368
+
1369
+ def to_dynamic
1370
+ {
1371
+ "fixedValue" => fixed_value,
1372
+ "id" => id,
1373
+ "entityId" => entity_id,
1374
+ "entityTypeId" => entity_type_id,
1375
+ "type" => background_type,
1376
+ "subType" => sub_type,
1377
+ "dice" => dice&.to_dynamic,
1378
+ "restriction" => restriction,
1379
+ "statId" => stat_id,
1380
+ "requiresAttunement" => requires_attunement,
1381
+ "duration" => duration&.to_dynamic,
1382
+ "friendlyTypeName" => friendly_type_name,
1383
+ "friendlySubtypeName" => friendly_subtype_name,
1384
+ "isGranted" => is_granted,
1385
+ "bonusTypes" => bonus_types,
1386
+ "value" => value,
1387
+ "availableToMulticlass" => available_to_multiclass,
1388
+ "modifierTypeId" => modifier_type_id,
1389
+ "modifierSubTypeId" => modifier_sub_type_id,
1390
+ "componentId" => component_id,
1391
+ "componentTypeId" => component_type_id,
1392
+ "die" => die&.to_dynamic,
1393
+ "count" => count,
1394
+ "durationUnit" => duration_unit,
1395
+ "usePrimaryStat" => use_primary_stat,
1396
+ "atHigherLevels" => at_higher_levels&.to_dynamic,
1397
+ }
1398
+ end
1399
+
1400
+ def to_json(options = nil)
1401
+ JSON.generate(to_dynamic, options)
1402
+ end
1403
+ end
1404
+
1405
+ module AoeType
1406
+ Cone = "Cone"
1407
+ Cube = "Cube"
1408
+ Cylinder = "Cylinder"
1409
+ Line = "Line"
1410
+ Sphere = "Sphere"
1411
+ Square = "Square"
1412
+ end
1413
+
1414
+ module Origin
1415
+ Ranged = "Ranged"
1416
+ Self = "Self"
1417
+ Sight = "Sight"
1418
+ Touch = "Touch"
1419
+ end
1420
+
1421
+ class DefinitionRange < Dry::Struct
1422
+ attribute :origin, Types::Origin
1423
+ attribute :range_value, Types::Integer.optional
1424
+ attribute :aoe_type, Types::AoeType.optional
1425
+ attribute :aoe_value, Types::Integer.optional
1426
+
1427
+ def self.from_dynamic!(d)
1428
+ d = Types::Hash[d]
1429
+ new(
1430
+ origin: d.fetch("origin"),
1431
+ range_value: d.fetch("rangeValue"),
1432
+ aoe_type: d.fetch("aoeType"),
1433
+ aoe_value: d.fetch("aoeValue"),
1434
+ )
1435
+ end
1436
+
1437
+ def self.from_json!(json)
1438
+ from_dynamic!(JSON.parse(json))
1439
+ end
1440
+
1441
+ def to_dynamic
1442
+ {
1443
+ "origin" => origin,
1444
+ "rangeValue" => range_value,
1445
+ "aoeType" => aoe_type,
1446
+ "aoeValue" => aoe_value,
1447
+ }
1448
+ end
1449
+
1450
+ def to_json(options = nil)
1451
+ JSON.generate(to_dynamic, options)
1452
+ end
1453
+ end
1454
+
1455
+ module ScaleType
1456
+ Characterlevel = "characterlevel"
1457
+ Spelllevel = "spelllevel"
1458
+ Spellscale = "spellscale"
1459
+ end
1460
+
1461
+ module School
1462
+ Abjuration = "Abjuration"
1463
+ Conjuration = "Conjuration"
1464
+ Divination = "Divination"
1465
+ Enchantment = "Enchantment"
1466
+ Evocation = "Evocation"
1467
+ Illusion = "Illusion"
1468
+ Necromancy = "Necromancy"
1469
+ Transmutation = "Transmutation"
1470
+ end
1471
+
1472
+ class SpellDefinition < Dry::Struct
1473
+ attribute :id, Types::Integer
1474
+ attribute :definition_key, Types::String
1475
+ attribute :definition_name, Types::String
1476
+ attribute :level, Types::Integer
1477
+ attribute :school, Types::School
1478
+ attribute :duration, DefinitionDuration
1479
+ attribute :activation, Activation
1480
+ attribute :range, DefinitionRange
1481
+ attribute :as_part_of_weapon_attack, Types::Bool
1482
+ attribute :description, Types::String
1483
+ attribute :snippet, Types::String
1484
+ attribute :concentration, Types::Bool
1485
+ attribute :ritual, Types::Bool
1486
+ attribute :range_area, Types::Nil
1487
+ attribute :damage_effect, Types::Nil
1488
+ attribute :components, Types.Array(Types::Integer)
1489
+ attribute :components_description, Types::String
1490
+ attribute :save_dc_ability_id, Types::Integer.optional
1491
+ attribute :healing, Types::Nil
1492
+ attribute :healing_dice, Types.Array(Types::Any)
1493
+ attribute :temp_hp_dice, Types.Array(Types::Any)
1494
+ attribute :attack_type, Types::Integer.optional
1495
+ attribute :can_cast_at_higher_level, Types::Bool
1496
+ attribute :is_homebrew, Types::Bool
1497
+ attribute :version, Types::String.optional
1498
+ attribute :source_id, Types::Nil
1499
+ attribute :source_page_number, Types::Integer.optional
1500
+ attribute :requires_saving_throw, Types::Bool
1501
+ attribute :requires_attack_roll, Types::Bool
1502
+ attribute :at_higher_levels, AtHigherLevels
1503
+ attribute :modifiers, Types.Array(ItemElement)
1504
+ attribute :conditions, Types.Array(DefinitionCondition)
1505
+ attribute :tags, Types.Array(Types::String)
1506
+ attribute :casting_time_description, Types::String
1507
+ attribute :scale_type, Types::ScaleType.optional
1508
+ attribute :sources, Types.Array(Source)
1509
+ attribute :spell_groups, Types.Array(Types::Integer)
1510
+
1511
+ def self.from_dynamic!(d)
1512
+ d = Types::Hash[d]
1513
+ new(
1514
+ id: d.fetch("id"),
1515
+ definition_key: d.fetch("definitionKey"),
1516
+ definition_name: d.fetch("name"),
1517
+ level: d.fetch("level"),
1518
+ school: d.fetch("school"),
1519
+ duration: DefinitionDuration.from_dynamic!(d.fetch("duration")),
1520
+ activation: Activation.from_dynamic!(d.fetch("activation")),
1521
+ range: DefinitionRange.from_dynamic!(d.fetch("range")),
1522
+ as_part_of_weapon_attack: d.fetch("asPartOfWeaponAttack"),
1523
+ description: d.fetch("description"),
1524
+ snippet: d.fetch("snippet"),
1525
+ concentration: d.fetch("concentration"),
1526
+ ritual: d.fetch("ritual"),
1527
+ range_area: d.fetch("rangeArea"),
1528
+ damage_effect: d.fetch("damageEffect"),
1529
+ components: d.fetch("components"),
1530
+ components_description: d.fetch("componentsDescription"),
1531
+ save_dc_ability_id: d.fetch("saveDcAbilityId"),
1532
+ healing: d.fetch("healing"),
1533
+ healing_dice: d.fetch("healingDice"),
1534
+ temp_hp_dice: d.fetch("tempHpDice"),
1535
+ attack_type: d.fetch("attackType"),
1536
+ can_cast_at_higher_level: d.fetch("canCastAtHigherLevel"),
1537
+ is_homebrew: d.fetch("isHomebrew"),
1538
+ version: d.fetch("version"),
1539
+ source_id: d.fetch("sourceId"),
1540
+ source_page_number: d.fetch("sourcePageNumber"),
1541
+ requires_saving_throw: d.fetch("requiresSavingThrow"),
1542
+ requires_attack_roll: d.fetch("requiresAttackRoll"),
1543
+ at_higher_levels: AtHigherLevels.from_dynamic!(d.fetch("atHigherLevels")),
1544
+ modifiers: d.fetch("modifiers").map { |x| ItemElement.from_dynamic!(x) },
1545
+ conditions: d.fetch("conditions").map { |x| DefinitionCondition.from_dynamic!(x) },
1546
+ tags: d.fetch("tags"),
1547
+ casting_time_description: d.fetch("castingTimeDescription"),
1548
+ scale_type: d.fetch("scaleType"),
1549
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
1550
+ spell_groups: d.fetch("spellGroups"),
1551
+ )
1552
+ end
1553
+
1554
+ def self.from_json!(json)
1555
+ from_dynamic!(JSON.parse(json))
1556
+ end
1557
+
1558
+ def to_dynamic
1559
+ {
1560
+ "id" => id,
1561
+ "definitionKey" => definition_key,
1562
+ "name" => definition_name,
1563
+ "level" => level,
1564
+ "school" => school,
1565
+ "duration" => duration.to_dynamic,
1566
+ "activation" => activation.to_dynamic,
1567
+ "range" => range.to_dynamic,
1568
+ "asPartOfWeaponAttack" => as_part_of_weapon_attack,
1569
+ "description" => description,
1570
+ "snippet" => snippet,
1571
+ "concentration" => concentration,
1572
+ "ritual" => ritual,
1573
+ "rangeArea" => range_area,
1574
+ "damageEffect" => damage_effect,
1575
+ "components" => components,
1576
+ "componentsDescription" => components_description,
1577
+ "saveDcAbilityId" => save_dc_ability_id,
1578
+ "healing" => healing,
1579
+ "healingDice" => healing_dice,
1580
+ "tempHpDice" => temp_hp_dice,
1581
+ "attackType" => attack_type,
1582
+ "canCastAtHigherLevel" => can_cast_at_higher_level,
1583
+ "isHomebrew" => is_homebrew,
1584
+ "version" => version,
1585
+ "sourceId" => source_id,
1586
+ "sourcePageNumber" => source_page_number,
1587
+ "requiresSavingThrow" => requires_saving_throw,
1588
+ "requiresAttackRoll" => requires_attack_roll,
1589
+ "atHigherLevels" => at_higher_levels.to_dynamic,
1590
+ "modifiers" => modifiers.map { |x| x.to_dynamic },
1591
+ "conditions" => conditions.map { |x| x.to_dynamic },
1592
+ "tags" => tags,
1593
+ "castingTimeDescription" => casting_time_description,
1594
+ "scaleType" => scale_type,
1595
+ "sources" => sources.map { |x| x.to_dynamic },
1596
+ "spellGroups" => spell_groups,
1597
+ }
1598
+ end
1599
+
1600
+ def to_json(options = nil)
1601
+ JSON.generate(to_dynamic, options)
1602
+ end
1603
+ end
1604
+
1605
+ class Spell < Dry::Struct
1606
+ attribute :override_save_dc, Types::Nil
1607
+ attribute :limited_use, Types::Nil
1608
+ attribute :id, Types::Integer
1609
+ attribute :entity_type_id, Types::Integer
1610
+ attribute :definition, SpellDefinition
1611
+ attribute :definition_id, Types::Integer
1612
+ attribute :prepared, Types::Bool
1613
+ attribute :counts_as_known_spell, Types::Bool
1614
+ attribute :uses_spell_slot, Types::Bool
1615
+ attribute :cast_at_level, Types::Nil
1616
+ attribute :always_prepared, Types::Bool
1617
+ attribute :restriction, Types::Nil
1618
+ attribute :spell_casting_ability_id, Types::Nil
1619
+ attribute :display_as_attack, Types::Nil
1620
+ attribute :additional_description, Types::Nil
1621
+ attribute :cast_only_as_ritual, Types::Bool
1622
+ attribute :ritual_casting_type, Types::Nil
1623
+ attribute :range, DefinitionRange
1624
+ attribute :activation, Activation
1625
+ attribute :base_level_at_will, Types::Bool
1626
+ attribute :at_will_limited_use_level, Types::Nil
1627
+ attribute :is_signature_spell, Types::Nil
1628
+ attribute :component_id, Types::Integer
1629
+ attribute :component_type_id, Types::Integer
1630
+ attribute :spell_list_id, Types::Integer.optional
1631
+
1632
+ def self.from_dynamic!(d)
1633
+ d = Types::Hash[d]
1634
+ new(
1635
+ override_save_dc: d.fetch("overrideSaveDc"),
1636
+ limited_use: d.fetch("limitedUse"),
1637
+ id: d.fetch("id"),
1638
+ entity_type_id: d.fetch("entityTypeId"),
1639
+ definition: SpellDefinition.from_dynamic!(d.fetch("definition")),
1640
+ definition_id: d.fetch("definitionId"),
1641
+ prepared: d.fetch("prepared"),
1642
+ counts_as_known_spell: d.fetch("countsAsKnownSpell"),
1643
+ uses_spell_slot: d.fetch("usesSpellSlot"),
1644
+ cast_at_level: d.fetch("castAtLevel"),
1645
+ always_prepared: d.fetch("alwaysPrepared"),
1646
+ restriction: d.fetch("restriction"),
1647
+ spell_casting_ability_id: d.fetch("spellCastingAbilityId"),
1648
+ display_as_attack: d.fetch("displayAsAttack"),
1649
+ additional_description: d.fetch("additionalDescription"),
1650
+ cast_only_as_ritual: d.fetch("castOnlyAsRitual"),
1651
+ ritual_casting_type: d.fetch("ritualCastingType"),
1652
+ range: DefinitionRange.from_dynamic!(d.fetch("range")),
1653
+ activation: Activation.from_dynamic!(d.fetch("activation")),
1654
+ base_level_at_will: d.fetch("baseLevelAtWill"),
1655
+ at_will_limited_use_level: d.fetch("atWillLimitedUseLevel"),
1656
+ is_signature_spell: d.fetch("isSignatureSpell"),
1657
+ component_id: d.fetch("componentId"),
1658
+ component_type_id: d.fetch("componentTypeId"),
1659
+ spell_list_id: d.fetch("spellListId"),
1660
+ )
1661
+ end
1662
+
1663
+ def self.from_json!(json)
1664
+ from_dynamic!(JSON.parse(json))
1665
+ end
1666
+
1667
+ def to_dynamic
1668
+ {
1669
+ "overrideSaveDc" => override_save_dc,
1670
+ "limitedUse" => limited_use,
1671
+ "id" => id,
1672
+ "entityTypeId" => entity_type_id,
1673
+ "definition" => definition.to_dynamic,
1674
+ "definitionId" => definition_id,
1675
+ "prepared" => prepared,
1676
+ "countsAsKnownSpell" => counts_as_known_spell,
1677
+ "usesSpellSlot" => uses_spell_slot,
1678
+ "castAtLevel" => cast_at_level,
1679
+ "alwaysPrepared" => always_prepared,
1680
+ "restriction" => restriction,
1681
+ "spellCastingAbilityId" => spell_casting_ability_id,
1682
+ "displayAsAttack" => display_as_attack,
1683
+ "additionalDescription" => additional_description,
1684
+ "castOnlyAsRitual" => cast_only_as_ritual,
1685
+ "ritualCastingType" => ritual_casting_type,
1686
+ "range" => range.to_dynamic,
1687
+ "activation" => activation.to_dynamic,
1688
+ "baseLevelAtWill" => base_level_at_will,
1689
+ "atWillLimitedUseLevel" => at_will_limited_use_level,
1690
+ "isSignatureSpell" => is_signature_spell,
1691
+ "componentId" => component_id,
1692
+ "componentTypeId" => component_type_id,
1693
+ "spellListId" => spell_list_id,
1694
+ }
1695
+ end
1696
+
1697
+ def to_json(options = nil)
1698
+ JSON.generate(to_dynamic, options)
1699
+ end
1700
+ end
1701
+
1702
+ class ClassSpell < Dry::Struct
1703
+ attribute :entity_type_id, Types::Integer
1704
+ attribute :character_class_id, Types::Integer
1705
+ attribute :spells, Types.Array(Spell)
1706
+
1707
+ def self.from_dynamic!(d)
1708
+ d = Types::Hash[d]
1709
+ new(
1710
+ entity_type_id: d.fetch("entityTypeId"),
1711
+ character_class_id: d.fetch("characterClassId"),
1712
+ spells: d.fetch("spells").map { |x| Spell.from_dynamic!(x) },
1713
+ )
1714
+ end
1715
+
1716
+ def self.from_json!(json)
1717
+ from_dynamic!(JSON.parse(json))
1718
+ end
1719
+
1720
+ def to_dynamic
1721
+ {
1722
+ "entityTypeId" => entity_type_id,
1723
+ "characterClassId" => character_class_id,
1724
+ "spells" => spells.map { |x| x.to_dynamic },
1725
+ }
1726
+ end
1727
+
1728
+ def to_json(options = nil)
1729
+ JSON.generate(to_dynamic, options)
1730
+ end
1731
+ end
1732
+
1733
+ class CreatureRule < Dry::Struct
1734
+ attribute :creature_group_id, Types::Integer
1735
+ attribute :monster_type_id, Types::Integer
1736
+ attribute :max_challenge_rating_id, Types::Integer
1737
+ attribute :level_divisor, Types::Nil
1738
+ attribute :monster_ids, Types.Array(Types::Any)
1739
+ attribute :movement_ids, Types.Array(Types::Integer)
1740
+ attribute :size_ids, Types.Array(Types::Any)
1741
+
1742
+ def self.from_dynamic!(d)
1743
+ d = Types::Hash[d]
1744
+ new(
1745
+ creature_group_id: d.fetch("creatureGroupId"),
1746
+ monster_type_id: d.fetch("monsterTypeId"),
1747
+ max_challenge_rating_id: d.fetch("maxChallengeRatingId"),
1748
+ level_divisor: d.fetch("levelDivisor"),
1749
+ monster_ids: d.fetch("monsterIds"),
1750
+ movement_ids: d.fetch("movementIds"),
1751
+ size_ids: d.fetch("sizeIds"),
1752
+ )
1753
+ end
1754
+
1755
+ def self.from_json!(json)
1756
+ from_dynamic!(JSON.parse(json))
1757
+ end
1758
+
1759
+ def to_dynamic
1760
+ {
1761
+ "creatureGroupId" => creature_group_id,
1762
+ "monsterTypeId" => monster_type_id,
1763
+ "maxChallengeRatingId" => max_challenge_rating_id,
1764
+ "levelDivisor" => level_divisor,
1765
+ "monsterIds" => monster_ids,
1766
+ "movementIds" => movement_ids,
1767
+ "sizeIds" => size_ids,
1768
+ }
1769
+ end
1770
+
1771
+ def to_json(options = nil)
1772
+ JSON.generate(to_dynamic, options)
1773
+ end
1774
+ end
1775
+
1776
+ class DisplayConfiguration < Dry::Struct
1777
+ attribute :racialtrait, Types::Integer
1778
+ attribute :language, Types::Integer
1779
+ attribute :abilityscore, Types::Integer
1780
+ attribute :classfeature, Types::Integer
1781
+
1782
+ def self.from_dynamic!(d)
1783
+ d = Types::Hash[d]
1784
+ new(
1785
+ racialtrait: d.fetch("RACIALTRAIT"),
1786
+ language: d.fetch("LANGUAGE"),
1787
+ abilityscore: d.fetch("ABILITYSCORE"),
1788
+ classfeature: d.fetch("CLASSFEATURE"),
1789
+ )
1790
+ end
1791
+
1792
+ def self.from_json!(json)
1793
+ from_dynamic!(JSON.parse(json))
1794
+ end
1795
+
1796
+ def to_dynamic
1797
+ {
1798
+ "RACIALTRAIT" => racialtrait,
1799
+ "LANGUAGE" => language,
1800
+ "ABILITYSCORE" => abilityscore,
1801
+ "CLASSFEATURE" => classfeature,
1802
+ }
1803
+ end
1804
+
1805
+ def to_json(options = nil)
1806
+ JSON.generate(to_dynamic, options)
1807
+ end
1808
+ end
1809
+
1810
+ module EntityType
1811
+ ClassFeature = "class-feature"
1812
+ RacialTrait = "racial-trait"
1813
+ end
1814
+
1815
+ class InfusionRule < Dry::Struct
1816
+ attribute :level, Types::Integer
1817
+ attribute :choice_key, Types::String
1818
+
1819
+ def self.from_dynamic!(d)
1820
+ d = Types::Hash[d]
1821
+ new(
1822
+ level: d.fetch("level"),
1823
+ choice_key: d.fetch("choiceKey"),
1824
+ )
1825
+ end
1826
+
1827
+ def self.from_json!(json)
1828
+ from_dynamic!(JSON.parse(json))
1829
+ end
1830
+
1831
+ def to_dynamic
1832
+ {
1833
+ "level" => level,
1834
+ "choiceKey" => choice_key,
1835
+ }
1836
+ end
1837
+
1838
+ def to_json(options = nil)
1839
+ JSON.generate(to_dynamic, options)
1840
+ end
1841
+ end
1842
+
1843
+ class LevelScale < Dry::Struct
1844
+ attribute :id, Types::Integer
1845
+ attribute :level, Types::Integer
1846
+ attribute :description, Types::String
1847
+ attribute :dice, Die.optional
1848
+ attribute :fixed_value, Types::Integer.optional
1849
+
1850
+ def self.from_dynamic!(d)
1851
+ d = Types::Hash[d]
1852
+ new(
1853
+ id: d.fetch("id"),
1854
+ level: d.fetch("level"),
1855
+ description: d.fetch("description"),
1856
+ dice: d.fetch("dice") ? Die.from_dynamic!(d.fetch("dice")) : nil,
1857
+ fixed_value: d.fetch("fixedValue"),
1858
+ )
1859
+ end
1860
+
1861
+ def self.from_json!(json)
1862
+ from_dynamic!(JSON.parse(json))
1863
+ end
1864
+
1865
+ def to_dynamic
1866
+ {
1867
+ "id" => id,
1868
+ "level" => level,
1869
+ "description" => description,
1870
+ "dice" => dice&.to_dynamic,
1871
+ "fixedValue" => fixed_value,
1872
+ }
1873
+ end
1874
+
1875
+ def to_json(options = nil)
1876
+ JSON.generate(to_dynamic, options)
1877
+ end
1878
+ end
1879
+
1880
+ class LimitedUseElement < Dry::Struct
1881
+ attribute :level, Types::Nil
1882
+ attribute :uses, Types::Integer
1883
+
1884
+ def self.from_dynamic!(d)
1885
+ d = Types::Hash[d]
1886
+ new(
1887
+ level: d.fetch("level"),
1888
+ uses: d.fetch("uses"),
1889
+ )
1890
+ end
1891
+
1892
+ def self.from_json!(json)
1893
+ from_dynamic!(JSON.parse(json))
1894
+ end
1895
+
1896
+ def to_dynamic
1897
+ {
1898
+ "level" => level,
1899
+ "uses" => uses,
1900
+ }
1901
+ end
1902
+
1903
+ def to_json(options = nil)
1904
+ JSON.generate(to_dynamic, options)
1905
+ end
1906
+ end
1907
+
1908
+ class ClassFeatureDefinition < Dry::Struct
1909
+ attribute :id, Types::Integer
1910
+ attribute :definition_key, Types::String
1911
+ attribute :entity_type_id, Types::Integer
1912
+ attribute :display_order, Types::Integer.optional
1913
+ attribute :definition_name, Types::String
1914
+ attribute :description, Types::String
1915
+ attribute :snippet, Types::String.optional
1916
+ attribute :activation, Types::Nil
1917
+ attribute :multi_class_description, Types::String.optional
1918
+ attribute :required_level, Types::Integer.optional
1919
+ attribute :is_sub_class_feature, Types::Bool.optional
1920
+ attribute :limited_use, Types.Array(LimitedUseElement).optional
1921
+ attribute :hide_in_builder, Types::Bool
1922
+ attribute :hide_in_sheet, Types::Bool
1923
+ attribute :source_id, Types::Integer
1924
+ attribute :source_page_number, Types::Integer.optional
1925
+ attribute :creature_rules, Types.Array(CreatureRule)
1926
+ attribute :level_scales, Types.Array(LevelScale).optional
1927
+ attribute :infusion_rules, Types.Array(InfusionRule).optional
1928
+ attribute :spell_list_ids, Types.Array(Types::Integer)
1929
+ attribute :class_id, Types::Integer.optional
1930
+ attribute :feature_type, Types::Integer
1931
+ attribute :sources, Types.Array(Source)
1932
+ attribute :affected_feature_definition_keys, Types.Array(Types::Any)
1933
+ attribute :entity_type, Types::EntityType
1934
+ attribute :entity_id, Types::String
1935
+ attribute :is_called_out, Types::Bool.optional
1936
+ attribute :entity_race_id, Types::Integer.optional
1937
+ attribute :entity_race_type_id, Types::Integer.optional
1938
+ attribute :display_configuration, DisplayConfiguration.optional
1939
+
1940
+ def self.from_dynamic!(d)
1941
+ d = Types::Hash[d]
1942
+ new(
1943
+ id: d.fetch("id"),
1944
+ definition_key: d.fetch("definitionKey"),
1945
+ entity_type_id: d.fetch("entityTypeId"),
1946
+ display_order: d.fetch("displayOrder"),
1947
+ definition_name: d.fetch("name"),
1948
+ description: d.fetch("description"),
1949
+ snippet: d.fetch("snippet"),
1950
+ activation: d.fetch("activation"),
1951
+ multi_class_description: d["multiClassDescription"],
1952
+ required_level: d.fetch("requiredLevel"),
1953
+ is_sub_class_feature: d["isSubClassFeature"],
1954
+ limited_use: d["limitedUse"]&.map { |x| LimitedUseElement.from_dynamic!(x) },
1955
+ hide_in_builder: d.fetch("hideInBuilder"),
1956
+ hide_in_sheet: d.fetch("hideInSheet"),
1957
+ source_id: d.fetch("sourceId"),
1958
+ source_page_number: d.fetch("sourcePageNumber"),
1959
+ creature_rules: d.fetch("creatureRules").map { |x| CreatureRule.from_dynamic!(x) },
1960
+ level_scales: d["levelScales"]&.map { |x| LevelScale.from_dynamic!(x) },
1961
+ infusion_rules: d["infusionRules"]&.map { |x| InfusionRule.from_dynamic!(x) },
1962
+ spell_list_ids: d.fetch("spellListIds"),
1963
+ class_id: d["classId"],
1964
+ feature_type: d.fetch("featureType"),
1965
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
1966
+ affected_feature_definition_keys: d.fetch("affectedFeatureDefinitionKeys"),
1967
+ entity_type: d.fetch("entityType"),
1968
+ entity_id: d.fetch("entityID"),
1969
+ is_called_out: d["isCalledOut"],
1970
+ entity_race_id: d["entityRaceId"],
1971
+ entity_race_type_id: d["entityRaceTypeId"],
1972
+ display_configuration: d["displayConfiguration"] ? DisplayConfiguration.from_dynamic!(d["displayConfiguration"]) : nil,
1973
+ )
1974
+ end
1975
+
1976
+ def self.from_json!(json)
1977
+ from_dynamic!(JSON.parse(json))
1978
+ end
1979
+
1980
+ def to_dynamic
1981
+ {
1982
+ "id" => id,
1983
+ "definitionKey" => definition_key,
1984
+ "entityTypeId" => entity_type_id,
1985
+ "displayOrder" => display_order,
1986
+ "name" => definition_name,
1987
+ "description" => description,
1988
+ "snippet" => snippet,
1989
+ "activation" => activation,
1990
+ "multiClassDescription" => multi_class_description,
1991
+ "requiredLevel" => required_level,
1992
+ "isSubClassFeature" => is_sub_class_feature,
1993
+ "limitedUse" => limited_use&.map { |x| x.to_dynamic },
1994
+ "hideInBuilder" => hide_in_builder,
1995
+ "hideInSheet" => hide_in_sheet,
1996
+ "sourceId" => source_id,
1997
+ "sourcePageNumber" => source_page_number,
1998
+ "creatureRules" => creature_rules.map { |x| x.to_dynamic },
1999
+ "levelScales" => level_scales&.map { |x| x.to_dynamic },
2000
+ "infusionRules" => infusion_rules&.map { |x| x.to_dynamic },
2001
+ "spellListIds" => spell_list_ids,
2002
+ "classId" => class_id,
2003
+ "featureType" => feature_type,
2004
+ "sources" => sources.map { |x| x.to_dynamic },
2005
+ "affectedFeatureDefinitionKeys" => affected_feature_definition_keys,
2006
+ "entityType" => entity_type,
2007
+ "entityID" => entity_id,
2008
+ "isCalledOut" => is_called_out,
2009
+ "entityRaceId" => entity_race_id,
2010
+ "entityRaceTypeId" => entity_race_type_id,
2011
+ "displayConfiguration" => display_configuration&.to_dynamic,
2012
+ }
2013
+ end
2014
+
2015
+ def to_json(options = nil)
2016
+ JSON.generate(to_dynamic, options)
2017
+ end
2018
+ end
2019
+
2020
+ class ClassClassFeature < Dry::Struct
2021
+ attribute :definition, ClassFeatureDefinition
2022
+ attribute :level_scale, LevelScale.optional
2023
+
2024
+ def self.from_dynamic!(d)
2025
+ d = Types::Hash[d]
2026
+ new(
2027
+ definition: ClassFeatureDefinition.from_dynamic!(d.fetch("definition")),
2028
+ level_scale: d.fetch("levelScale") ? LevelScale.from_dynamic!(d.fetch("levelScale")) : nil,
2029
+ )
2030
+ end
2031
+
2032
+ def self.from_json!(json)
2033
+ from_dynamic!(JSON.parse(json))
2034
+ end
2035
+
2036
+ def to_dynamic
2037
+ {
2038
+ "definition" => definition.to_dynamic,
2039
+ "levelScale" => level_scale&.to_dynamic,
2040
+ }
2041
+ end
2042
+
2043
+ def to_json(options = nil)
2044
+ JSON.generate(to_dynamic, options)
2045
+ end
2046
+ end
2047
+
2048
+ class DefinitionClassFeature < Dry::Struct
2049
+ attribute :id, Types::Integer
2050
+ attribute :class_feature_name, Types::String
2051
+ attribute :prerequisite, Types::Nil
2052
+ attribute :description, Types::String
2053
+ attribute :required_level, Types::Integer
2054
+ attribute :display_order, Types::Integer
2055
+
2056
+ def self.from_dynamic!(d)
2057
+ d = Types::Hash[d]
2058
+ new(
2059
+ id: d.fetch("id"),
2060
+ class_feature_name: d.fetch("name"),
2061
+ prerequisite: d.fetch("prerequisite"),
2062
+ description: d.fetch("description"),
2063
+ required_level: d.fetch("requiredLevel"),
2064
+ display_order: d.fetch("displayOrder"),
2065
+ )
2066
+ end
2067
+
2068
+ def self.from_json!(json)
2069
+ from_dynamic!(JSON.parse(json))
2070
+ end
2071
+
2072
+ def to_dynamic
2073
+ {
2074
+ "id" => id,
2075
+ "name" => class_feature_name,
2076
+ "prerequisite" => prerequisite,
2077
+ "description" => description,
2078
+ "requiredLevel" => required_level,
2079
+ "displayOrder" => display_order,
2080
+ }
2081
+ end
2082
+
2083
+ def to_json(options = nil)
2084
+ JSON.generate(to_dynamic, options)
2085
+ end
2086
+ end
2087
+
2088
+ module PrerequisiteMappingFriendlyTypeName
2089
+ AbilityScore = "Ability Score"
2090
+ CustomValue = "Custom Value"
2091
+ Proficiency = "Proficiency"
2092
+ Race = "Race"
2093
+ Size = "Size"
2094
+ end
2095
+
2096
+ module PrerequisiteMappingType
2097
+ AbilityScore = "ability-score"
2098
+ CustomValue = "custom-value"
2099
+ Proficiency = "proficiency"
2100
+ Race = "race"
2101
+ Size = "size"
2102
+ end
2103
+
2104
+ class PrerequisiteMapping < Dry::Struct
2105
+ attribute :id, Types::Integer
2106
+ attribute :entity_id, Types::Integer.optional
2107
+ attribute :entity_type_id, Types::Integer.optional
2108
+ attribute :prerequisite_mapping_type, Types::PrerequisiteMappingType
2109
+ attribute :sub_type, Types::String
2110
+ attribute :value, Types::Integer.optional
2111
+ attribute :friendly_type_name, Types::PrerequisiteMappingFriendlyTypeName
2112
+ attribute :friendly_sub_type_name, Types::String
2113
+
2114
+ def self.from_dynamic!(d)
2115
+ d = Types::Hash[d]
2116
+ new(
2117
+ id: d.fetch("id"),
2118
+ entity_id: d.fetch("entityId"),
2119
+ entity_type_id: d.fetch("entityTypeId"),
2120
+ prerequisite_mapping_type: d.fetch("type"),
2121
+ sub_type: d.fetch("subType"),
2122
+ value: d.fetch("value"),
2123
+ friendly_type_name: d.fetch("friendlyTypeName"),
2124
+ friendly_sub_type_name: d.fetch("friendlySubTypeName"),
2125
+ )
2126
+ end
2127
+
2128
+ def self.from_json!(json)
2129
+ from_dynamic!(JSON.parse(json))
2130
+ end
2131
+
2132
+ def to_dynamic
2133
+ {
2134
+ "id" => id,
2135
+ "entityId" => entity_id,
2136
+ "entityTypeId" => entity_type_id,
2137
+ "type" => prerequisite_mapping_type,
2138
+ "subType" => sub_type,
2139
+ "value" => value,
2140
+ "friendlyTypeName" => friendly_type_name,
2141
+ "friendlySubTypeName" => friendly_sub_type_name,
2142
+ }
2143
+ end
2144
+
2145
+ def to_json(options = nil)
2146
+ JSON.generate(to_dynamic, options)
2147
+ end
2148
+ end
2149
+
2150
+ class Prerequisite < Dry::Struct
2151
+ attribute :description, Types::String
2152
+ attribute :prerequisite_mappings, Types.Array(PrerequisiteMapping)
2153
+
2154
+ def self.from_dynamic!(d)
2155
+ d = Types::Hash[d]
2156
+ new(
2157
+ description: d.fetch("description"),
2158
+ prerequisite_mappings: d.fetch("prerequisiteMappings").map { |x| PrerequisiteMapping.from_dynamic!(x) },
2159
+ )
2160
+ end
2161
+
2162
+ def self.from_json!(json)
2163
+ from_dynamic!(JSON.parse(json))
2164
+ end
2165
+
2166
+ def to_dynamic
2167
+ {
2168
+ "description" => description,
2169
+ "prerequisiteMappings" => prerequisite_mappings.map { |x| x.to_dynamic },
2170
+ }
2171
+ end
2172
+
2173
+ def to_json(options = nil)
2174
+ JSON.generate(to_dynamic, options)
2175
+ end
2176
+ end
2177
+
2178
+ class SpellRules < Dry::Struct
2179
+ attribute :multi_class_spell_slot_divisor, Types::Integer
2180
+ attribute :is_ritual_spell_caster, Types::Bool
2181
+ attribute :level_cantrips_known_maxes, Types.Array(Types::Integer)
2182
+ attribute :level_spell_known_maxes, Types.Array(Types::Integer)
2183
+ attribute :level_spell_slots, Types.Array(Types.Array(Types::Integer))
2184
+ attribute :multi_class_spell_slot_rounding, Types::Integer
2185
+
2186
+ def self.from_dynamic!(d)
2187
+ d = Types::Hash[d]
2188
+ new(
2189
+ multi_class_spell_slot_divisor: d.fetch("multiClassSpellSlotDivisor"),
2190
+ is_ritual_spell_caster: d.fetch("isRitualSpellCaster"),
2191
+ level_cantrips_known_maxes: d.fetch("levelCantripsKnownMaxes"),
2192
+ level_spell_known_maxes: d.fetch("levelSpellKnownMaxes"),
2193
+ level_spell_slots: d.fetch("levelSpellSlots"),
2194
+ multi_class_spell_slot_rounding: d.fetch("multiClassSpellSlotRounding"),
2195
+ )
2196
+ end
2197
+
2198
+ def self.from_json!(json)
2199
+ from_dynamic!(JSON.parse(json))
2200
+ end
2201
+
2202
+ def to_dynamic
2203
+ {
2204
+ "multiClassSpellSlotDivisor" => multi_class_spell_slot_divisor,
2205
+ "isRitualSpellCaster" => is_ritual_spell_caster,
2206
+ "levelCantripsKnownMaxes" => level_cantrips_known_maxes,
2207
+ "levelSpellKnownMaxes" => level_spell_known_maxes,
2208
+ "levelSpellSlots" => level_spell_slots,
2209
+ "multiClassSpellSlotRounding" => multi_class_spell_slot_rounding,
2210
+ }
2211
+ end
2212
+
2213
+ def to_json(options = nil)
2214
+ JSON.generate(to_dynamic, options)
2215
+ end
2216
+ end
2217
+
2218
+ class SubclassDefinitionClass < Dry::Struct
2219
+ attribute :id, Types::Integer
2220
+ attribute :definition_key, Types::String
2221
+ attribute :definition_name, Types::String
2222
+ attribute :description, Types::String
2223
+ attribute :equipment_description, Types::String.optional
2224
+ attribute :parent_class_id, Types::Integer.optional
2225
+ attribute :avatar_url, Types::String.optional
2226
+ attribute :large_avatar_url, Types::String.optional
2227
+ attribute :portrait_avatar_url, Types::String.optional
2228
+ attribute :more_details_url, Types::String
2229
+ attribute :spell_casting_ability_id, Types::Integer.optional
2230
+ attribute :sources, Types.Array(Source)
2231
+ attribute :class_features, Types.Array(DefinitionClassFeature)
2232
+ attribute :hit_dice, Types::Integer
2233
+ attribute :wealth_dice, Die.optional
2234
+ attribute :can_cast_spells, Types::Bool
2235
+ attribute :knows_all_spells, Types::Bool.optional
2236
+ attribute :spell_prepare_type, Types::Integer.optional
2237
+ attribute :spell_container_name, Types::String.optional
2238
+ attribute :source_page_number, Types::Integer.optional
2239
+ attribute :subclass_definition, Types::Nil
2240
+ attribute :is_homebrew, Types::Bool
2241
+ attribute :primary_abilities, Types.Array(Types::Integer).optional
2242
+ attribute :spell_rules, SpellRules.optional
2243
+ attribute :prerequisites, Types.Array(Prerequisite).optional
2244
+
2245
+ def self.from_dynamic!(d)
2246
+ d = Types::Hash[d]
2247
+ new(
2248
+ id: d.fetch("id"),
2249
+ definition_key: d.fetch("definitionKey"),
2250
+ definition_name: d.fetch("name"),
2251
+ description: d.fetch("description"),
2252
+ equipment_description: d.fetch("equipmentDescription"),
2253
+ parent_class_id: d.fetch("parentClassId"),
2254
+ avatar_url: d.fetch("avatarUrl"),
2255
+ large_avatar_url: d.fetch("largeAvatarUrl"),
2256
+ portrait_avatar_url: d.fetch("portraitAvatarUrl"),
2257
+ more_details_url: d.fetch("moreDetailsUrl"),
2258
+ spell_casting_ability_id: d.fetch("spellCastingAbilityId"),
2259
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
2260
+ class_features: d.fetch("classFeatures").map { |x| DefinitionClassFeature.from_dynamic!(x) },
2261
+ hit_dice: d.fetch("hitDice"),
2262
+ wealth_dice: d.fetch("wealthDice") ? Die.from_dynamic!(d.fetch("wealthDice")) : nil,
2263
+ can_cast_spells: d.fetch("canCastSpells"),
2264
+ knows_all_spells: d.fetch("knowsAllSpells"),
2265
+ spell_prepare_type: d.fetch("spellPrepareType"),
2266
+ spell_container_name: d.fetch("spellContainerName"),
2267
+ source_page_number: d.fetch("sourcePageNumber"),
2268
+ subclass_definition: d.fetch("subclassDefinition"),
2269
+ is_homebrew: d.fetch("isHomebrew"),
2270
+ primary_abilities: d.fetch("primaryAbilities"),
2271
+ spell_rules: d.fetch("spellRules") ? SpellRules.from_dynamic!(d.fetch("spellRules")) : nil,
2272
+ prerequisites: d.fetch("prerequisites")&.map { |x| Prerequisite.from_dynamic!(x) },
2273
+ )
2274
+ end
2275
+
2276
+ def self.from_json!(json)
2277
+ from_dynamic!(JSON.parse(json))
2278
+ end
2279
+
2280
+ def to_dynamic
2281
+ {
2282
+ "id" => id,
2283
+ "definitionKey" => definition_key,
2284
+ "name" => definition_name,
2285
+ "description" => description,
2286
+ "equipmentDescription" => equipment_description,
2287
+ "parentClassId" => parent_class_id,
2288
+ "avatarUrl" => avatar_url,
2289
+ "largeAvatarUrl" => large_avatar_url,
2290
+ "portraitAvatarUrl" => portrait_avatar_url,
2291
+ "moreDetailsUrl" => more_details_url,
2292
+ "spellCastingAbilityId" => spell_casting_ability_id,
2293
+ "sources" => sources.map { |x| x.to_dynamic },
2294
+ "classFeatures" => class_features.map { |x| x.to_dynamic },
2295
+ "hitDice" => hit_dice,
2296
+ "wealthDice" => wealth_dice&.to_dynamic,
2297
+ "canCastSpells" => can_cast_spells,
2298
+ "knowsAllSpells" => knows_all_spells,
2299
+ "spellPrepareType" => spell_prepare_type,
2300
+ "spellContainerName" => spell_container_name,
2301
+ "sourcePageNumber" => source_page_number,
2302
+ "subclassDefinition" => subclass_definition,
2303
+ "isHomebrew" => is_homebrew,
2304
+ "primaryAbilities" => primary_abilities,
2305
+ "spellRules" => spell_rules&.to_dynamic,
2306
+ "prerequisites" => prerequisites&.map { |x| x.to_dynamic },
2307
+ }
2308
+ end
2309
+
2310
+ def to_json(options = nil)
2311
+ JSON.generate(to_dynamic, options)
2312
+ end
2313
+ end
2314
+
2315
+ class TopLevelClass < Dry::Struct
2316
+ attribute :id, Types::Integer
2317
+ attribute :entity_type_id, Types::Integer
2318
+ attribute :level, Types::Integer
2319
+ attribute :is_starting_class, Types::Bool
2320
+ attribute :hit_dice_used, Types::Integer
2321
+ attribute :definition_id, Types::Integer
2322
+ attribute :subclass_definition_id, Types::Nil
2323
+ attribute :definition, SubclassDefinitionClass
2324
+ attribute :subclass_definition, SubclassDefinitionClass.optional
2325
+ attribute :class_features, Types.Array(ClassClassFeature)
2326
+
2327
+ def self.from_dynamic!(d)
2328
+ d = Types::Hash[d]
2329
+ new(
2330
+ id: d.fetch("id"),
2331
+ entity_type_id: d.fetch("entityTypeId"),
2332
+ level: d.fetch("level"),
2333
+ is_starting_class: d.fetch("isStartingClass"),
2334
+ hit_dice_used: d.fetch("hitDiceUsed"),
2335
+ definition_id: d.fetch("definitionId"),
2336
+ subclass_definition_id: d.fetch("subclassDefinitionId"),
2337
+ definition: SubclassDefinitionClass.from_dynamic!(d.fetch("definition")),
2338
+ subclass_definition: d.fetch("subclassDefinition") ? SubclassDefinitionClass.from_dynamic!(d.fetch("subclassDefinition")) : nil,
2339
+ class_features: d.fetch("classFeatures").map { |x| ClassClassFeature.from_dynamic!(x) },
2340
+ )
2341
+ end
2342
+
2343
+ def self.from_json!(json)
2344
+ from_dynamic!(JSON.parse(json))
2345
+ end
2346
+
2347
+ def to_dynamic
2348
+ {
2349
+ "id" => id,
2350
+ "entityTypeId" => entity_type_id,
2351
+ "level" => level,
2352
+ "isStartingClass" => is_starting_class,
2353
+ "hitDiceUsed" => hit_dice_used,
2354
+ "definitionId" => definition_id,
2355
+ "subclassDefinitionId" => subclass_definition_id,
2356
+ "definition" => definition.to_dynamic,
2357
+ "subclassDefinition" => subclass_definition&.to_dynamic,
2358
+ "classFeatures" => class_features.map { |x| x.to_dynamic },
2359
+ }
2360
+ end
2361
+
2362
+ def to_json(options = nil)
2363
+ JSON.generate(to_dynamic, options)
2364
+ end
2365
+ end
2366
+
2367
+ class TopLevelCondition < Dry::Struct
2368
+ attribute :id, Types::Integer
2369
+ attribute :level, Types::Integer
2370
+
2371
+ def self.from_dynamic!(d)
2372
+ d = Types::Hash[d]
2373
+ new(
2374
+ id: d.fetch("id"),
2375
+ level: d.fetch("level"),
2376
+ )
2377
+ end
2378
+
2379
+ def self.from_json!(json)
2380
+ from_dynamic!(JSON.parse(json))
2381
+ end
2382
+
2383
+ def to_dynamic
2384
+ {
2385
+ "id" => id,
2386
+ "level" => level,
2387
+ }
2388
+ end
2389
+
2390
+ def to_json(options = nil)
2391
+ JSON.generate(to_dynamic, options)
2392
+ end
2393
+ end
2394
+
2395
+ class Configuration < Dry::Struct
2396
+ attribute :starting_equipment_type, Types::Integer.optional
2397
+ attribute :ability_score_type, Types::Integer.optional
2398
+ attribute :show_help_text, Types::Bool
2399
+
2400
+ def self.from_dynamic!(d)
2401
+ d = Types::Hash[d]
2402
+ new(
2403
+ starting_equipment_type: d.fetch("startingEquipmentType"),
2404
+ ability_score_type: d.fetch("abilityScoreType"),
2405
+ show_help_text: d.fetch("showHelpText"),
2406
+ )
2407
+ end
2408
+
2409
+ def self.from_json!(json)
2410
+ from_dynamic!(JSON.parse(json))
2411
+ end
2412
+
2413
+ def to_dynamic
2414
+ {
2415
+ "startingEquipmentType" => starting_equipment_type,
2416
+ "abilityScoreType" => ability_score_type,
2417
+ "showHelpText" => show_help_text,
2418
+ }
2419
+ end
2420
+
2421
+ def to_json(options = nil)
2422
+ JSON.generate(to_dynamic, options)
2423
+ end
2424
+ end
2425
+
2426
+ class Currencies < Dry::Struct
2427
+ attribute :cp, Types::Integer
2428
+ attribute :sp, Types::Integer
2429
+ attribute :gp, Types::Integer
2430
+ attribute :ep, Types::Integer
2431
+ attribute :pp, Types::Integer
2432
+
2433
+ def self.from_dynamic!(d)
2434
+ d = Types::Hash[d]
2435
+ new(
2436
+ cp: d.fetch("cp"),
2437
+ sp: d.fetch("sp"),
2438
+ gp: d.fetch("gp"),
2439
+ ep: d.fetch("ep"),
2440
+ pp: d.fetch("pp"),
2441
+ )
2442
+ end
2443
+
2444
+ def self.from_json!(json)
2445
+ from_dynamic!(JSON.parse(json))
2446
+ end
2447
+
2448
+ def to_dynamic
2449
+ {
2450
+ "cp" => cp,
2451
+ "sp" => sp,
2452
+ "gp" => gp,
2453
+ "ep" => ep,
2454
+ "pp" => pp,
2455
+ }
2456
+ end
2457
+
2458
+ def to_json(options = nil)
2459
+ JSON.generate(to_dynamic, options)
2460
+ end
2461
+ end
2462
+
2463
+ class CustomItem < Dry::Struct
2464
+ attribute :id, Types::Integer
2465
+ attribute :custom_item_name, Types::String
2466
+ attribute :description, Types::String.optional
2467
+ attribute :weight, Types::Integer.optional
2468
+ attribute :cost, Types::Nil
2469
+ attribute :quantity, Types::Integer
2470
+ attribute :notes, Types::Nil
2471
+
2472
+ def self.from_dynamic!(d)
2473
+ d = Types::Hash[d]
2474
+ new(
2475
+ id: d.fetch("id"),
2476
+ custom_item_name: d.fetch("name"),
2477
+ description: d.fetch("description"),
2478
+ weight: d.fetch("weight"),
2479
+ cost: d.fetch("cost"),
2480
+ quantity: d.fetch("quantity"),
2481
+ notes: d.fetch("notes"),
2482
+ )
2483
+ end
2484
+
2485
+ def self.from_json!(json)
2486
+ from_dynamic!(JSON.parse(json))
2487
+ end
2488
+
2489
+ def to_dynamic
2490
+ {
2491
+ "id" => id,
2492
+ "name" => custom_item_name,
2493
+ "description" => description,
2494
+ "weight" => weight,
2495
+ "cost" => cost,
2496
+ "quantity" => quantity,
2497
+ "notes" => notes,
2498
+ }
2499
+ end
2500
+
2501
+ def to_json(options = nil)
2502
+ JSON.generate(to_dynamic, options)
2503
+ end
2504
+ end
2505
+
2506
+ class DeathSaves < Dry::Struct
2507
+ attribute :fail_count, Types::Integer.optional
2508
+ attribute :success_count, Types::Integer.optional
2509
+ attribute :is_stabilized, Types::Bool
2510
+
2511
+ def self.from_dynamic!(d)
2512
+ d = Types::Hash[d]
2513
+ new(
2514
+ fail_count: d.fetch("failCount"),
2515
+ success_count: d.fetch("successCount"),
2516
+ is_stabilized: d.fetch("isStabilized"),
2517
+ )
2518
+ end
2519
+
2520
+ def self.from_json!(json)
2521
+ from_dynamic!(JSON.parse(json))
2522
+ end
2523
+
2524
+ def to_dynamic
2525
+ {
2526
+ "failCount" => fail_count,
2527
+ "successCount" => success_count,
2528
+ "isStabilized" => is_stabilized,
2529
+ }
2530
+ end
2531
+
2532
+ def to_json(options = nil)
2533
+ JSON.generate(to_dynamic, options)
2534
+ end
2535
+ end
2536
+
2537
+ class DefaultBackdrop < Dry::Struct
2538
+ attribute :backdrop_avatar_url, Types::String.optional
2539
+ attribute :small_backdrop_avatar_url, Types::String.optional
2540
+ attribute :large_backdrop_avatar_url, Types::String.optional
2541
+ attribute :thumbnail_backdrop_avatar_url, Types::String.optional
2542
+
2543
+ def self.from_dynamic!(d)
2544
+ d = Types::Hash[d]
2545
+ new(
2546
+ backdrop_avatar_url: d["backdropAvatarUrl"],
2547
+ small_backdrop_avatar_url: d["smallBackdropAvatarUrl"],
2548
+ large_backdrop_avatar_url: d["largeBackdropAvatarUrl"],
2549
+ thumbnail_backdrop_avatar_url: d["thumbnailBackdropAvatarUrl"],
2550
+ )
2551
+ end
2552
+
2553
+ def self.from_json!(json)
2554
+ from_dynamic!(JSON.parse(json))
2555
+ end
2556
+
2557
+ def to_dynamic
2558
+ {
2559
+ "backdropAvatarUrl" => backdrop_avatar_url,
2560
+ "smallBackdropAvatarUrl" => small_backdrop_avatar_url,
2561
+ "largeBackdropAvatarUrl" => large_backdrop_avatar_url,
2562
+ "thumbnailBackdropAvatarUrl" => thumbnail_backdrop_avatar_url,
2563
+ }
2564
+ end
2565
+
2566
+ def to_json(options = nil)
2567
+ JSON.generate(to_dynamic, options)
2568
+ end
2569
+ end
2570
+
2571
+ class ThemeColor < Dry::Struct
2572
+ attribute :theme_color_id, Types::Integer
2573
+ attribute :theme_color, Types::String
2574
+ attribute :background_color, Types::String
2575
+ attribute :theme_color_name, Types::String
2576
+ attribute :race_id, Types::Nil
2577
+ attribute :sub_race_id, Types::Nil
2578
+ attribute :class_id, Types::Integer
2579
+ attribute :tags, Types.Array(Types::String)
2580
+ attribute :decoration_key, Types::String
2581
+
2582
+ def self.from_dynamic!(d)
2583
+ d = Types::Hash[d]
2584
+ new(
2585
+ theme_color_id: d.fetch("themeColorId"),
2586
+ theme_color: d.fetch("themeColor"),
2587
+ background_color: d.fetch("backgroundColor"),
2588
+ theme_color_name: d.fetch("name"),
2589
+ race_id: d.fetch("raceId"),
2590
+ sub_race_id: d.fetch("subRaceId"),
2591
+ class_id: d.fetch("classId"),
2592
+ tags: d.fetch("tags"),
2593
+ decoration_key: d.fetch("decorationKey"),
2594
+ )
2595
+ end
2596
+
2597
+ def self.from_json!(json)
2598
+ from_dynamic!(JSON.parse(json))
2599
+ end
2600
+
2601
+ def to_dynamic
2602
+ {
2603
+ "themeColorId" => theme_color_id,
2604
+ "themeColor" => theme_color,
2605
+ "backgroundColor" => background_color,
2606
+ "name" => theme_color_name,
2607
+ "raceId" => race_id,
2608
+ "subRaceId" => sub_race_id,
2609
+ "classId" => class_id,
2610
+ "tags" => tags,
2611
+ "decorationKey" => decoration_key,
2612
+ }
2613
+ end
2614
+
2615
+ def to_json(options = nil)
2616
+ JSON.generate(to_dynamic, options)
2617
+ end
2618
+ end
2619
+
2620
+ class Decorations < Dry::Struct
2621
+ attribute :avatar_url, Types::String.optional
2622
+ attribute :frame_avatar_url, Types::String.optional
2623
+ attribute :backdrop_avatar_url, Types::String.optional
2624
+ attribute :small_backdrop_avatar_url, Types::String.optional
2625
+ attribute :large_backdrop_avatar_url, Types::String.optional
2626
+ attribute :thumbnail_backdrop_avatar_url, Types::String.optional
2627
+ attribute :default_backdrop, DefaultBackdrop
2628
+ attribute :avatar_id, Types::Integer.optional
2629
+ attribute :portrait_decoration_key, Types::Nil
2630
+ attribute :frame_avatar_decoration_key, Types::String.optional
2631
+ attribute :frame_avatar_id, Types::Integer.optional
2632
+ attribute :backdrop_avatar_decoration_key, Types::String.optional
2633
+ attribute :backdrop_avatar_id, Types::Integer.optional
2634
+ attribute :small_backdrop_avatar_decoration_key, Types::String
2635
+ attribute :small_backdrop_avatar_id, Types::Integer.optional
2636
+ attribute :large_backdrop_avatar_decoration_key, Types::String
2637
+ attribute :large_backdrop_avatar_id, Types::Integer.optional
2638
+ attribute :thumbnail_backdrop_avatar_decoration_key, Types::String
2639
+ attribute :thumbnail_backdrop_avatar_id, Types::Integer.optional
2640
+ attribute :theme_color, ThemeColor.optional
2641
+
2642
+ def self.from_dynamic!(d)
2643
+ d = Types::Hash[d]
2644
+ new(
2645
+ avatar_url: d.fetch("avatarUrl"),
2646
+ frame_avatar_url: d.fetch("frameAvatarUrl"),
2647
+ backdrop_avatar_url: d.fetch("backdropAvatarUrl"),
2648
+ small_backdrop_avatar_url: d.fetch("smallBackdropAvatarUrl"),
2649
+ large_backdrop_avatar_url: d.fetch("largeBackdropAvatarUrl"),
2650
+ thumbnail_backdrop_avatar_url: d.fetch("thumbnailBackdropAvatarUrl"),
2651
+ default_backdrop: DefaultBackdrop.from_dynamic!(d.fetch("defaultBackdrop")),
2652
+ avatar_id: d.fetch("avatarId"),
2653
+ portrait_decoration_key: d.fetch("portraitDecorationKey"),
2654
+ frame_avatar_decoration_key: d.fetch("frameAvatarDecorationKey"),
2655
+ frame_avatar_id: d.fetch("frameAvatarId"),
2656
+ backdrop_avatar_decoration_key: d.fetch("backdropAvatarDecorationKey"),
2657
+ backdrop_avatar_id: d.fetch("backdropAvatarId"),
2658
+ small_backdrop_avatar_decoration_key: d.fetch("smallBackdropAvatarDecorationKey"),
2659
+ small_backdrop_avatar_id: d.fetch("smallBackdropAvatarId"),
2660
+ large_backdrop_avatar_decoration_key: d.fetch("largeBackdropAvatarDecorationKey"),
2661
+ large_backdrop_avatar_id: d.fetch("largeBackdropAvatarId"),
2662
+ thumbnail_backdrop_avatar_decoration_key: d.fetch("thumbnailBackdropAvatarDecorationKey"),
2663
+ thumbnail_backdrop_avatar_id: d.fetch("thumbnailBackdropAvatarId"),
2664
+ theme_color: d.fetch("themeColor") ? ThemeColor.from_dynamic!(d.fetch("themeColor")) : nil,
2665
+ )
2666
+ end
2667
+
2668
+ def self.from_json!(json)
2669
+ from_dynamic!(JSON.parse(json))
2670
+ end
2671
+
2672
+ def to_dynamic
2673
+ {
2674
+ "avatarUrl" => avatar_url,
2675
+ "frameAvatarUrl" => frame_avatar_url,
2676
+ "backdropAvatarUrl" => backdrop_avatar_url,
2677
+ "smallBackdropAvatarUrl" => small_backdrop_avatar_url,
2678
+ "largeBackdropAvatarUrl" => large_backdrop_avatar_url,
2679
+ "thumbnailBackdropAvatarUrl" => thumbnail_backdrop_avatar_url,
2680
+ "defaultBackdrop" => default_backdrop.to_dynamic,
2681
+ "avatarId" => avatar_id,
2682
+ "portraitDecorationKey" => portrait_decoration_key,
2683
+ "frameAvatarDecorationKey" => frame_avatar_decoration_key,
2684
+ "frameAvatarId" => frame_avatar_id,
2685
+ "backdropAvatarDecorationKey" => backdrop_avatar_decoration_key,
2686
+ "backdropAvatarId" => backdrop_avatar_id,
2687
+ "smallBackdropAvatarDecorationKey" => small_backdrop_avatar_decoration_key,
2688
+ "smallBackdropAvatarId" => small_backdrop_avatar_id,
2689
+ "largeBackdropAvatarDecorationKey" => large_backdrop_avatar_decoration_key,
2690
+ "largeBackdropAvatarId" => large_backdrop_avatar_id,
2691
+ "thumbnailBackdropAvatarDecorationKey" => thumbnail_backdrop_avatar_decoration_key,
2692
+ "thumbnailBackdropAvatarId" => thumbnail_backdrop_avatar_id,
2693
+ "themeColor" => theme_color&.to_dynamic,
2694
+ }
2695
+ end
2696
+
2697
+ def to_json(options = nil)
2698
+ JSON.generate(to_dynamic, options)
2699
+ end
2700
+ end
2701
+
2702
+ class Definition1 < Dry::Struct
2703
+ attribute :id, Types::Integer
2704
+ attribute :entity_type_id, Types::Integer
2705
+ attribute :definition_key, Types::String
2706
+ attribute :definition_name, Types::String
2707
+ attribute :description, Types::String
2708
+ attribute :snippet, Types::String
2709
+ attribute :activation, Activation
2710
+ attribute :source_id, Types::Nil
2711
+ attribute :source_page_number, Types::Nil
2712
+ attribute :creature_rules, Types.Array(Types::Any)
2713
+ attribute :prerequisites, Types.Array(Prerequisite)
2714
+ attribute :is_homebrew, Types::Bool
2715
+ attribute :sources, Types.Array(Source)
2716
+ attribute :spell_list_ids, Types.Array(Types::Any)
2717
+
2718
+ def self.from_dynamic!(d)
2719
+ d = Types::Hash[d]
2720
+ new(
2721
+ id: d.fetch("id"),
2722
+ entity_type_id: d.fetch("entityTypeId"),
2723
+ definition_key: d.fetch("definitionKey"),
2724
+ definition_name: d.fetch("name"),
2725
+ description: d.fetch("description"),
2726
+ snippet: d.fetch("snippet"),
2727
+ activation: Activation.from_dynamic!(d.fetch("activation")),
2728
+ source_id: d.fetch("sourceId"),
2729
+ source_page_number: d.fetch("sourcePageNumber"),
2730
+ creature_rules: d.fetch("creatureRules"),
2731
+ prerequisites: d.fetch("prerequisites").map { |x| Prerequisite.from_dynamic!(x) },
2732
+ is_homebrew: d.fetch("isHomebrew"),
2733
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
2734
+ spell_list_ids: d.fetch("spellListIds"),
2735
+ )
2736
+ end
2737
+
2738
+ def self.from_json!(json)
2739
+ from_dynamic!(JSON.parse(json))
2740
+ end
2741
+
2742
+ def to_dynamic
2743
+ {
2744
+ "id" => id,
2745
+ "entityTypeId" => entity_type_id,
2746
+ "definitionKey" => definition_key,
2747
+ "name" => definition_name,
2748
+ "description" => description,
2749
+ "snippet" => snippet,
2750
+ "activation" => activation.to_dynamic,
2751
+ "sourceId" => source_id,
2752
+ "sourcePageNumber" => source_page_number,
2753
+ "creatureRules" => creature_rules,
2754
+ "prerequisites" => prerequisites.map { |x| x.to_dynamic },
2755
+ "isHomebrew" => is_homebrew,
2756
+ "sources" => sources.map { |x| x.to_dynamic },
2757
+ "spellListIds" => spell_list_ids,
2758
+ }
2759
+ end
2760
+
2761
+ def to_json(options = nil)
2762
+ JSON.generate(to_dynamic, options)
2763
+ end
2764
+ end
2765
+
2766
+ class Feat < Dry::Struct
2767
+ attribute :component_type_id, Types::Integer
2768
+ attribute :component_id, Types::Integer
2769
+ attribute :definition, Definition1
2770
+ attribute :definition_id, Types::Integer
2771
+
2772
+ def self.from_dynamic!(d)
2773
+ d = Types::Hash[d]
2774
+ new(
2775
+ component_type_id: d.fetch("componentTypeId"),
2776
+ component_id: d.fetch("componentId"),
2777
+ definition: Definition1.from_dynamic!(d.fetch("definition")),
2778
+ definition_id: d.fetch("definitionId"),
2779
+ )
2780
+ end
2781
+
2782
+ def self.from_json!(json)
2783
+ from_dynamic!(JSON.parse(json))
2784
+ end
2785
+
2786
+ def to_dynamic
2787
+ {
2788
+ "componentTypeId" => component_type_id,
2789
+ "componentId" => component_id,
2790
+ "definition" => definition.to_dynamic,
2791
+ "definitionId" => definition_id,
2792
+ }
2793
+ end
2794
+
2795
+ def to_json(options = nil)
2796
+ JSON.generate(to_dynamic, options)
2797
+ end
2798
+ end
2799
+
2800
+ module AttunementDescription
2801
+ DruidOrRanger = "druid or ranger"
2802
+ Empty = ""
2803
+ Spellcaster = "Spellcaster"
2804
+ Warlock = "Warlock"
2805
+ Wizard = "wizard"
2806
+ end
2807
+
2808
+ module DamageType
2809
+ Bludgeoning = "Bludgeoning"
2810
+ Piercing = "Piercing"
2811
+ Slashing = "Slashing"
2812
+ end
2813
+
2814
+ module FilterType
2815
+ Armor = "Armor"
2816
+ OtherGear = "Other Gear"
2817
+ Potion = "Potion"
2818
+ Ring = "Ring"
2819
+ Rod = "Rod"
2820
+ Wand = "Wand"
2821
+ Weapon = "Weapon"
2822
+ WondrousItem = "Wondrous item"
2823
+ end
2824
+
2825
+ module Rarity
2826
+ Common = "Common"
2827
+ Rare = "Rare"
2828
+ Uncommon = "Uncommon"
2829
+ VeryRare = "Very Rare"
2830
+ end
2831
+
2832
+ module SubType
2833
+ AdventuringGear = "Adventuring Gear"
2834
+ Ammunition = "Ammunition"
2835
+ ArcaneFocus = "Arcane Focus"
2836
+ DruidicFocus = "Druidic Focus"
2837
+ HolySymbol = "Holy Symbol"
2838
+ Potion = "Potion"
2839
+ Tool = "Tool"
2840
+ end
2841
+
2842
+ module Tag
2843
+ Buff = "Buff"
2844
+ Combat = "Combat"
2845
+ Communication = "Communication"
2846
+ Consumable = "Consumable"
2847
+ Container = "Container"
2848
+ Control = "Control"
2849
+ Creation = "Creation"
2850
+ Damage = "Damage"
2851
+ Deception = "Deception"
2852
+ Detection = "Detection"
2853
+ Exploration = "Exploration"
2854
+ Eyewear = "Eyewear"
2855
+ Focus = "Focus"
2856
+ Handwear = "Handwear"
2857
+ Headwear = "Headwear"
2858
+ Healing = "Healing"
2859
+ Instrument = "Instrument"
2860
+ Jewelry = "Jewelry"
2861
+ Movement = "Movement"
2862
+ Outerwear = "Outerwear"
2863
+ Social = "Social"
2864
+ Utility = "Utility"
2865
+ Warding = "Warding"
2866
+ end
2867
+
2868
+ class WeaponBehavior < Dry::Struct
2869
+ attribute :base_item_id, Types::Integer
2870
+ attribute :base_type_id, Types::Integer
2871
+ attribute :weapon_behavior_type, Types::String
2872
+ attribute :attack_type, Types::Integer
2873
+ attribute :category_id, Types::Integer
2874
+ attribute :properties, Types.Array(Organization)
2875
+ attribute :damage, Die
2876
+ attribute :damage_type, Types::DamageType
2877
+ attribute :range, Types::Integer
2878
+ attribute :long_range, Types::Integer
2879
+ attribute :is_monk_weapon, Types::Bool
2880
+
2881
+ def self.from_dynamic!(d)
2882
+ d = Types::Hash[d]
2883
+ new(
2884
+ base_item_id: d.fetch("baseItemId"),
2885
+ base_type_id: d.fetch("baseTypeId"),
2886
+ weapon_behavior_type: d.fetch("type"),
2887
+ attack_type: d.fetch("attackType"),
2888
+ category_id: d.fetch("categoryId"),
2889
+ properties: d.fetch("properties").map { |x| Organization.from_dynamic!(x) },
2890
+ damage: Die.from_dynamic!(d.fetch("damage")),
2891
+ damage_type: d.fetch("damageType"),
2892
+ range: d.fetch("range"),
2893
+ long_range: d.fetch("longRange"),
2894
+ is_monk_weapon: d.fetch("isMonkWeapon"),
2895
+ )
2896
+ end
2897
+
2898
+ def self.from_json!(json)
2899
+ from_dynamic!(JSON.parse(json))
2900
+ end
2901
+
2902
+ def to_dynamic
2903
+ {
2904
+ "baseItemId" => base_item_id,
2905
+ "baseTypeId" => base_type_id,
2906
+ "type" => weapon_behavior_type,
2907
+ "attackType" => attack_type,
2908
+ "categoryId" => category_id,
2909
+ "properties" => properties.map { |x| x.to_dynamic },
2910
+ "damage" => damage.to_dynamic,
2911
+ "damageType" => damage_type,
2912
+ "range" => range,
2913
+ "longRange" => long_range,
2914
+ "isMonkWeapon" => is_monk_weapon,
2915
+ }
2916
+ end
2917
+
2918
+ def to_json(options = nil)
2919
+ JSON.generate(to_dynamic, options)
2920
+ end
2921
+ end
2922
+
2923
+ class InventoryDefinition < Dry::Struct
2924
+ attribute :id, Types::Integer
2925
+ attribute :base_type_id, Types::Integer
2926
+ attribute :entity_type_id, Types::Integer
2927
+ attribute :definition_key, Types::String
2928
+ attribute :can_equip, Types::Bool
2929
+ attribute :magic, Types::Bool
2930
+ attribute :definition_name, Types::String
2931
+ attribute :snippet, Types::String.optional
2932
+ attribute :weight, Types::Double
2933
+ attribute :weight_multiplier, Types::Integer
2934
+ attribute :capacity, Types::String.optional
2935
+ attribute :capacity_weight, Types::Integer
2936
+ attribute :definition_type, Types::String.optional
2937
+ attribute :description, Types::String.optional
2938
+ attribute :can_attune, Types::Bool
2939
+ attribute :attunement_description, Types::AttunementDescription.optional
2940
+ attribute :rarity, Types::Rarity.optional
2941
+ attribute :is_homebrew, Types::Bool
2942
+ attribute :version, Types::Nil
2943
+ attribute :source_id, Types::Nil
2944
+ attribute :source_page_number, Types::Nil
2945
+ attribute :stackable, Types::Bool
2946
+ attribute :bundle_size, Types::Integer
2947
+ attribute :avatar_url, Types::String.optional
2948
+ attribute :large_avatar_url, Types::String.optional
2949
+ attribute :filter_type, Types::FilterType.optional
2950
+ attribute :cost, Types::Double.optional
2951
+ attribute :is_pack, Types::Bool
2952
+ attribute :tags, Types.Array(Types::Tag)
2953
+ attribute :granted_modifiers, Types.Array(ItemElement)
2954
+ attribute :sub_type, Types::SubType.optional
2955
+ attribute :is_consumable, Types::Bool
2956
+ attribute :weapon_behaviors, Types.Array(WeaponBehavior)
2957
+ attribute :base_item_id, Types::Integer.optional
2958
+ attribute :base_armor_name, Types::String.optional
2959
+ attribute :strength_requirement, Types::Integer.optional
2960
+ attribute :armor_class, Types::Integer.optional
2961
+ attribute :stealth_check, Types::Integer.optional
2962
+ attribute :damage, Die.optional
2963
+ attribute :damage_type, Types::DamageType.optional
2964
+ attribute :fixed_damage, Types::Nil
2965
+ attribute :properties, Types.Array(Organization).optional
2966
+ attribute :attack_type, Types::Integer.optional
2967
+ attribute :category_id, Types::Integer.optional
2968
+ attribute :range, Types::Integer.optional
2969
+ attribute :long_range, Types::Integer.optional
2970
+ attribute :is_monk_weapon, Types::Bool
2971
+ attribute :level_infusion_granted, Types::Integer.optional
2972
+ attribute :sources, Types.Array(Source)
2973
+ attribute :armor_type_id, Types::Integer.optional
2974
+ attribute :gear_type_id, Types::Integer.optional
2975
+ attribute :grouped_id, Types::Integer.optional
2976
+ attribute :can_be_added_to_inventory, Types::Bool
2977
+ attribute :is_container, Types::Bool
2978
+ attribute :is_custom_item, Types::Bool
2979
+
2980
+ def self.from_dynamic!(d)
2981
+ d = Types::Hash[d]
2982
+ new(
2983
+ id: d.fetch("id"),
2984
+ base_type_id: d.fetch("baseTypeId"),
2985
+ entity_type_id: d.fetch("entityTypeId"),
2986
+ definition_key: d.fetch("definitionKey"),
2987
+ can_equip: d.fetch("canEquip"),
2988
+ magic: d.fetch("magic"),
2989
+ definition_name: d.fetch("name"),
2990
+ snippet: d.fetch("snippet"),
2991
+ weight: d.fetch("weight"),
2992
+ weight_multiplier: d.fetch("weightMultiplier"),
2993
+ capacity: d.fetch("capacity"),
2994
+ capacity_weight: d.fetch("capacityWeight"),
2995
+ definition_type: d.fetch("type"),
2996
+ description: d.fetch("description"),
2997
+ can_attune: d.fetch("canAttune"),
2998
+ attunement_description: d.fetch("attunementDescription"),
2999
+ rarity: d.fetch("rarity"),
3000
+ is_homebrew: d.fetch("isHomebrew"),
3001
+ version: d.fetch("version"),
3002
+ source_id: d.fetch("sourceId"),
3003
+ source_page_number: d.fetch("sourcePageNumber"),
3004
+ stackable: d.fetch("stackable"),
3005
+ bundle_size: d.fetch("bundleSize"),
3006
+ avatar_url: d.fetch("avatarUrl"),
3007
+ large_avatar_url: d.fetch("largeAvatarUrl"),
3008
+ filter_type: d.fetch("filterType"),
3009
+ cost: d.fetch("cost"),
3010
+ is_pack: d.fetch("isPack"),
3011
+ tags: d.fetch("tags"),
3012
+ granted_modifiers: d.fetch("grantedModifiers").map { |x| ItemElement.from_dynamic!(x) },
3013
+ sub_type: d.fetch("subType"),
3014
+ is_consumable: d.fetch("isConsumable"),
3015
+ weapon_behaviors: d.fetch("weaponBehaviors").map { |x| WeaponBehavior.from_dynamic!(x) },
3016
+ base_item_id: d.fetch("baseItemId"),
3017
+ base_armor_name: d.fetch("baseArmorName"),
3018
+ strength_requirement: d.fetch("strengthRequirement"),
3019
+ armor_class: d.fetch("armorClass"),
3020
+ stealth_check: d.fetch("stealthCheck"),
3021
+ damage: d.fetch("damage") ? Die.from_dynamic!(d.fetch("damage")) : nil,
3022
+ damage_type: d.fetch("damageType"),
3023
+ fixed_damage: d.fetch("fixedDamage"),
3024
+ properties: d.fetch("properties")&.map { |x| Organization.from_dynamic!(x) },
3025
+ attack_type: d.fetch("attackType"),
3026
+ category_id: d.fetch("categoryId"),
3027
+ range: d.fetch("range"),
3028
+ long_range: d.fetch("longRange"),
3029
+ is_monk_weapon: d.fetch("isMonkWeapon"),
3030
+ level_infusion_granted: d.fetch("levelInfusionGranted"),
3031
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
3032
+ armor_type_id: d.fetch("armorTypeId"),
3033
+ gear_type_id: d.fetch("gearTypeId"),
3034
+ grouped_id: d.fetch("groupedId"),
3035
+ can_be_added_to_inventory: d.fetch("canBeAddedToInventory"),
3036
+ is_container: d.fetch("isContainer"),
3037
+ is_custom_item: d.fetch("isCustomItem"),
3038
+ )
3039
+ end
3040
+
3041
+ def self.from_json!(json)
3042
+ from_dynamic!(JSON.parse(json))
3043
+ end
3044
+
3045
+ def to_dynamic
3046
+ {
3047
+ "id" => id,
3048
+ "baseTypeId" => base_type_id,
3049
+ "entityTypeId" => entity_type_id,
3050
+ "definitionKey" => definition_key,
3051
+ "canEquip" => can_equip,
3052
+ "magic" => magic,
3053
+ "name" => definition_name,
3054
+ "snippet" => snippet,
3055
+ "weight" => weight,
3056
+ "weightMultiplier" => weight_multiplier,
3057
+ "capacity" => capacity,
3058
+ "capacityWeight" => capacity_weight,
3059
+ "type" => definition_type,
3060
+ "description" => description,
3061
+ "canAttune" => can_attune,
3062
+ "attunementDescription" => attunement_description,
3063
+ "rarity" => rarity,
3064
+ "isHomebrew" => is_homebrew,
3065
+ "version" => version,
3066
+ "sourceId" => source_id,
3067
+ "sourcePageNumber" => source_page_number,
3068
+ "stackable" => stackable,
3069
+ "bundleSize" => bundle_size,
3070
+ "avatarUrl" => avatar_url,
3071
+ "largeAvatarUrl" => large_avatar_url,
3072
+ "filterType" => filter_type,
3073
+ "cost" => cost,
3074
+ "isPack" => is_pack,
3075
+ "tags" => tags,
3076
+ "grantedModifiers" => granted_modifiers.map { |x| x.to_dynamic },
3077
+ "subType" => sub_type,
3078
+ "isConsumable" => is_consumable,
3079
+ "weaponBehaviors" => weapon_behaviors.map { |x| x.to_dynamic },
3080
+ "baseItemId" => base_item_id,
3081
+ "baseArmorName" => base_armor_name,
3082
+ "strengthRequirement" => strength_requirement,
3083
+ "armorClass" => armor_class,
3084
+ "stealthCheck" => stealth_check,
3085
+ "damage" => damage&.to_dynamic,
3086
+ "damageType" => damage_type,
3087
+ "fixedDamage" => fixed_damage,
3088
+ "properties" => properties&.map { |x| x.to_dynamic },
3089
+ "attackType" => attack_type,
3090
+ "categoryId" => category_id,
3091
+ "range" => range,
3092
+ "longRange" => long_range,
3093
+ "isMonkWeapon" => is_monk_weapon,
3094
+ "levelInfusionGranted" => level_infusion_granted,
3095
+ "sources" => sources.map { |x| x.to_dynamic },
3096
+ "armorTypeId" => armor_type_id,
3097
+ "gearTypeId" => gear_type_id,
3098
+ "groupedId" => grouped_id,
3099
+ "canBeAddedToInventory" => can_be_added_to_inventory,
3100
+ "isContainer" => is_container,
3101
+ "isCustomItem" => is_custom_item,
3102
+ }
3103
+ end
3104
+
3105
+ def to_json(options = nil)
3106
+ JSON.generate(to_dynamic, options)
3107
+ end
3108
+ end
3109
+
3110
+ class InventoryLimitedUse < Dry::Struct
3111
+ attribute :max_uses, Types::Integer
3112
+ attribute :number_used, Types::Integer
3113
+ attribute :reset_type, Types::String
3114
+ attribute :reset_type_description, Types::String
3115
+
3116
+ def self.from_dynamic!(d)
3117
+ d = Types::Hash[d]
3118
+ new(
3119
+ max_uses: d.fetch("maxUses"),
3120
+ number_used: d.fetch("numberUsed"),
3121
+ reset_type: d.fetch("resetType"),
3122
+ reset_type_description: d.fetch("resetTypeDescription"),
3123
+ )
3124
+ end
3125
+
3126
+ def self.from_json!(json)
3127
+ from_dynamic!(JSON.parse(json))
3128
+ end
3129
+
3130
+ def to_dynamic
3131
+ {
3132
+ "maxUses" => max_uses,
3133
+ "numberUsed" => number_used,
3134
+ "resetType" => reset_type,
3135
+ "resetTypeDescription" => reset_type_description,
3136
+ }
3137
+ end
3138
+
3139
+ def to_json(options = nil)
3140
+ JSON.generate(to_dynamic, options)
3141
+ end
3142
+ end
3143
+
3144
+ class Inventory < Dry::Struct
3145
+ attribute :id, Types::Integer
3146
+ attribute :entity_type_id, Types::Integer
3147
+ attribute :definition, InventoryDefinition
3148
+ attribute :definition_id, Types::Integer
3149
+ attribute :definition_type_id, Types::Integer
3150
+ attribute :display_as_attack, Types::Nil
3151
+ attribute :quantity, Types::Integer
3152
+ attribute :is_attuned, Types::Bool
3153
+ attribute :equipped, Types::Bool
3154
+ attribute :equipped_entity_type_id, Types::Integer.optional
3155
+ attribute :equipped_entity_id, Types::Integer.optional
3156
+ attribute :charges_used, Types::Integer
3157
+ attribute :limited_use, InventoryLimitedUse.optional
3158
+ attribute :container_entity_id, Types::Integer
3159
+ attribute :container_entity_type_id, Types::Integer
3160
+ attribute :container_definition_key, Types::String
3161
+ attribute :currency, Types::Nil
3162
+
3163
+ def self.from_dynamic!(d)
3164
+ d = Types::Hash[d]
3165
+ new(
3166
+ id: d.fetch("id"),
3167
+ entity_type_id: d.fetch("entityTypeId"),
3168
+ definition: InventoryDefinition.from_dynamic!(d.fetch("definition")),
3169
+ definition_id: d.fetch("definitionId"),
3170
+ definition_type_id: d.fetch("definitionTypeId"),
3171
+ display_as_attack: d.fetch("displayAsAttack"),
3172
+ quantity: d.fetch("quantity"),
3173
+ is_attuned: d.fetch("isAttuned"),
3174
+ equipped: d.fetch("equipped"),
3175
+ equipped_entity_type_id: d.fetch("equippedEntityTypeId"),
3176
+ equipped_entity_id: d.fetch("equippedEntityId"),
3177
+ charges_used: d.fetch("chargesUsed"),
3178
+ limited_use: d.fetch("limitedUse") ? InventoryLimitedUse.from_dynamic!(d.fetch("limitedUse")) : nil,
3179
+ container_entity_id: d.fetch("containerEntityId"),
3180
+ container_entity_type_id: d.fetch("containerEntityTypeId"),
3181
+ container_definition_key: d.fetch("containerDefinitionKey"),
3182
+ currency: d.fetch("currency"),
3183
+ )
3184
+ end
3185
+
3186
+ def self.from_json!(json)
3187
+ from_dynamic!(JSON.parse(json))
3188
+ end
3189
+
3190
+ def to_dynamic
3191
+ {
3192
+ "id" => id,
3193
+ "entityTypeId" => entity_type_id,
3194
+ "definition" => definition.to_dynamic,
3195
+ "definitionId" => definition_id,
3196
+ "definitionTypeId" => definition_type_id,
3197
+ "displayAsAttack" => display_as_attack,
3198
+ "quantity" => quantity,
3199
+ "isAttuned" => is_attuned,
3200
+ "equipped" => equipped,
3201
+ "equippedEntityTypeId" => equipped_entity_type_id,
3202
+ "equippedEntityId" => equipped_entity_id,
3203
+ "chargesUsed" => charges_used,
3204
+ "limitedUse" => limited_use&.to_dynamic,
3205
+ "containerEntityId" => container_entity_id,
3206
+ "containerEntityTypeId" => container_entity_type_id,
3207
+ "containerDefinitionKey" => container_definition_key,
3208
+ "currency" => currency,
3209
+ }
3210
+ end
3211
+
3212
+ def to_json(options = nil)
3213
+ JSON.generate(to_dynamic, options)
3214
+ end
3215
+ end
3216
+
3217
+ class Modifiers < Dry::Struct
3218
+ attribute :race, Types.Array(ItemElement)
3219
+ attribute :modifiers_class, Types.Array(ItemElement)
3220
+ attribute :background, Types.Array(ItemElement)
3221
+ attribute :item, Types.Array(ItemElement)
3222
+ attribute :feat, Types.Array(ItemElement)
3223
+ attribute :condition, Types.Array(Types::Any)
3224
+
3225
+ def self.from_dynamic!(d)
3226
+ d = Types::Hash[d]
3227
+ new(
3228
+ race: d.fetch("race").map { |x| ItemElement.from_dynamic!(x) },
3229
+ modifiers_class: d.fetch("class").map { |x| ItemElement.from_dynamic!(x) },
3230
+ background: d.fetch("background").map { |x| ItemElement.from_dynamic!(x) },
3231
+ item: d.fetch("item").map { |x| ItemElement.from_dynamic!(x) },
3232
+ feat: d.fetch("feat").map { |x| ItemElement.from_dynamic!(x) },
3233
+ condition: d.fetch("condition"),
3234
+ )
3235
+ end
3236
+
3237
+ def self.from_json!(json)
3238
+ from_dynamic!(JSON.parse(json))
3239
+ end
3240
+
3241
+ def to_dynamic
3242
+ {
3243
+ "race" => race.map { |x| x.to_dynamic },
3244
+ "class" => modifiers_class.map { |x| x.to_dynamic },
3245
+ "background" => background.map { |x| x.to_dynamic },
3246
+ "item" => item.map { |x| x.to_dynamic },
3247
+ "feat" => feat.map { |x| x.to_dynamic },
3248
+ "condition" => condition,
3249
+ }
3250
+ end
3251
+
3252
+ def to_json(options = nil)
3253
+ JSON.generate(to_dynamic, options)
3254
+ end
3255
+ end
3256
+
3257
+ class Notes < Dry::Struct
3258
+ attribute :allies, Types::Nil
3259
+ attribute :personal_possessions, Types::String.optional
3260
+ attribute :other_holdings, Types::Nil
3261
+ attribute :organizations, Types::Nil
3262
+ attribute :enemies, Types::Nil
3263
+ attribute :backstory, Types::String.optional
3264
+ attribute :other_notes, Types::Nil
3265
+
3266
+ def self.from_dynamic!(d)
3267
+ d = Types::Hash[d]
3268
+ new(
3269
+ allies: d.fetch("allies"),
3270
+ personal_possessions: d.fetch("personalPossessions"),
3271
+ other_holdings: d.fetch("otherHoldings"),
3272
+ organizations: d.fetch("organizations"),
3273
+ enemies: d.fetch("enemies"),
3274
+ backstory: d.fetch("backstory"),
3275
+ other_notes: d.fetch("otherNotes"),
3276
+ )
3277
+ end
3278
+
3279
+ def self.from_json!(json)
3280
+ from_dynamic!(JSON.parse(json))
3281
+ end
3282
+
3283
+ def to_dynamic
3284
+ {
3285
+ "allies" => allies,
3286
+ "personalPossessions" => personal_possessions,
3287
+ "otherHoldings" => other_holdings,
3288
+ "organizations" => organizations,
3289
+ "enemies" => enemies,
3290
+ "backstory" => backstory,
3291
+ "otherNotes" => other_notes,
3292
+ }
3293
+ end
3294
+
3295
+ def to_json(options = nil)
3296
+ JSON.generate(to_dynamic, options)
3297
+ end
3298
+ end
3299
+
3300
+ class PactMagic < Dry::Struct
3301
+ attribute :level, Types::Integer
3302
+ attribute :used, Types::Integer
3303
+ attribute :available, Types::Integer
3304
+
3305
+ def self.from_dynamic!(d)
3306
+ d = Types::Hash[d]
3307
+ new(
3308
+ level: d.fetch("level"),
3309
+ used: d.fetch("used"),
3310
+ available: d.fetch("available"),
3311
+ )
3312
+ end
3313
+
3314
+ def self.from_json!(json)
3315
+ from_dynamic!(JSON.parse(json))
3316
+ end
3317
+
3318
+ def to_dynamic
3319
+ {
3320
+ "level" => level,
3321
+ "used" => used,
3322
+ "available" => available,
3323
+ }
3324
+ end
3325
+
3326
+ def to_json(options = nil)
3327
+ JSON.generate(to_dynamic, options)
3328
+ end
3329
+ end
3330
+
3331
+ class Preferences < Dry::Struct
3332
+ attribute :use_homebrew_content, Types::Bool
3333
+ attribute :progression_type, Types::Integer
3334
+ attribute :encumbrance_type, Types::Integer
3335
+ attribute :ignore_coin_weight, Types::Bool
3336
+ attribute :hit_point_type, Types::Integer
3337
+ attribute :show_unarmed_strike, Types::Bool
3338
+ attribute :show_scaled_spells, Types::Bool
3339
+ attribute :primary_sense, Types::Integer
3340
+ attribute :primary_movement, Types::Integer
3341
+ attribute :privacy_type, Types::Integer
3342
+ attribute :sharing_type, Types::Integer
3343
+ attribute :ability_score_display_type, Types::Integer
3344
+ attribute :enforce_feat_rules, Types::Bool
3345
+ attribute :enforce_multiclass_rules, Types::Bool
3346
+ attribute :enable_optional_class_features, Types::Bool
3347
+ attribute :enable_optional_origins, Types::Bool
3348
+ attribute :enable_dark_mode, Types::Bool
3349
+ attribute :enable_container_currency, Types::Bool
3350
+
3351
+ def self.from_dynamic!(d)
3352
+ d = Types::Hash[d]
3353
+ new(
3354
+ use_homebrew_content: d.fetch("useHomebrewContent"),
3355
+ progression_type: d.fetch("progressionType"),
3356
+ encumbrance_type: d.fetch("encumbranceType"),
3357
+ ignore_coin_weight: d.fetch("ignoreCoinWeight"),
3358
+ hit_point_type: d.fetch("hitPointType"),
3359
+ show_unarmed_strike: d.fetch("showUnarmedStrike"),
3360
+ show_scaled_spells: d.fetch("showScaledSpells"),
3361
+ primary_sense: d.fetch("primarySense"),
3362
+ primary_movement: d.fetch("primaryMovement"),
3363
+ privacy_type: d.fetch("privacyType"),
3364
+ sharing_type: d.fetch("sharingType"),
3365
+ ability_score_display_type: d.fetch("abilityScoreDisplayType"),
3366
+ enforce_feat_rules: d.fetch("enforceFeatRules"),
3367
+ enforce_multiclass_rules: d.fetch("enforceMulticlassRules"),
3368
+ enable_optional_class_features: d.fetch("enableOptionalClassFeatures"),
3369
+ enable_optional_origins: d.fetch("enableOptionalOrigins"),
3370
+ enable_dark_mode: d.fetch("enableDarkMode"),
3371
+ enable_container_currency: d.fetch("enableContainerCurrency"),
3372
+ )
3373
+ end
3374
+
3375
+ def self.from_json!(json)
3376
+ from_dynamic!(JSON.parse(json))
3377
+ end
3378
+
3379
+ def to_dynamic
3380
+ {
3381
+ "useHomebrewContent" => use_homebrew_content,
3382
+ "progressionType" => progression_type,
3383
+ "encumbranceType" => encumbrance_type,
3384
+ "ignoreCoinWeight" => ignore_coin_weight,
3385
+ "hitPointType" => hit_point_type,
3386
+ "showUnarmedStrike" => show_unarmed_strike,
3387
+ "showScaledSpells" => show_scaled_spells,
3388
+ "primarySense" => primary_sense,
3389
+ "primaryMovement" => primary_movement,
3390
+ "privacyType" => privacy_type,
3391
+ "sharingType" => sharing_type,
3392
+ "abilityScoreDisplayType" => ability_score_display_type,
3393
+ "enforceFeatRules" => enforce_feat_rules,
3394
+ "enforceMulticlassRules" => enforce_multiclass_rules,
3395
+ "enableOptionalClassFeatures" => enable_optional_class_features,
3396
+ "enableOptionalOrigins" => enable_optional_origins,
3397
+ "enableDarkMode" => enable_dark_mode,
3398
+ "enableContainerCurrency" => enable_container_currency,
3399
+ }
3400
+ end
3401
+
3402
+ def to_json(options = nil)
3403
+ JSON.generate(to_dynamic, options)
3404
+ end
3405
+ end
3406
+
3407
+ module ProvidedFrom
3408
+ Database = "database"
3409
+ Storage = "storage"
3410
+ end
3411
+
3412
+ class RacialTrait < Dry::Struct
3413
+ attribute :definition, ClassFeatureDefinition
3414
+
3415
+ def self.from_dynamic!(d)
3416
+ d = Types::Hash[d]
3417
+ new(
3418
+ definition: ClassFeatureDefinition.from_dynamic!(d.fetch("definition")),
3419
+ )
3420
+ end
3421
+
3422
+ def self.from_json!(json)
3423
+ from_dynamic!(JSON.parse(json))
3424
+ end
3425
+
3426
+ def to_dynamic
3427
+ {
3428
+ "definition" => definition.to_dynamic,
3429
+ }
3430
+ end
3431
+
3432
+ def to_json(options = nil)
3433
+ JSON.generate(to_dynamic, options)
3434
+ end
3435
+ end
3436
+
3437
+ class Normal < Dry::Struct
3438
+ attribute :walk, Types::Integer
3439
+ attribute :fly, Types::Integer
3440
+ attribute :burrow, Types::Integer
3441
+ attribute :swim, Types::Integer
3442
+ attribute :climb, Types::Integer
3443
+
3444
+ def self.from_dynamic!(d)
3445
+ d = Types::Hash[d]
3446
+ new(
3447
+ walk: d.fetch("walk"),
3448
+ fly: d.fetch("fly"),
3449
+ burrow: d.fetch("burrow"),
3450
+ swim: d.fetch("swim"),
3451
+ climb: d.fetch("climb"),
3452
+ )
3453
+ end
3454
+
3455
+ def self.from_json!(json)
3456
+ from_dynamic!(JSON.parse(json))
3457
+ end
3458
+
3459
+ def to_dynamic
3460
+ {
3461
+ "walk" => walk,
3462
+ "fly" => fly,
3463
+ "burrow" => burrow,
3464
+ "swim" => swim,
3465
+ "climb" => climb,
3466
+ }
3467
+ end
3468
+
3469
+ def to_json(options = nil)
3470
+ JSON.generate(to_dynamic, options)
3471
+ end
3472
+ end
3473
+
3474
+ class WeightSpeeds < Dry::Struct
3475
+ attribute :normal, Normal
3476
+ attribute :encumbered, Types::Nil
3477
+ attribute :heavily_encumbered, Types::Nil
3478
+ attribute :push_drag_lift, Types::Nil
3479
+ attribute :override, Types::Nil
3480
+
3481
+ def self.from_dynamic!(d)
3482
+ d = Types::Hash[d]
3483
+ new(
3484
+ normal: Normal.from_dynamic!(d.fetch("normal")),
3485
+ encumbered: d.fetch("encumbered"),
3486
+ heavily_encumbered: d.fetch("heavilyEncumbered"),
3487
+ push_drag_lift: d.fetch("pushDragLift"),
3488
+ override: d.fetch("override"),
3489
+ )
3490
+ end
3491
+
3492
+ def self.from_json!(json)
3493
+ from_dynamic!(JSON.parse(json))
3494
+ end
3495
+
3496
+ def to_dynamic
3497
+ {
3498
+ "normal" => normal.to_dynamic,
3499
+ "encumbered" => encumbered,
3500
+ "heavilyEncumbered" => heavily_encumbered,
3501
+ "pushDragLift" => push_drag_lift,
3502
+ "override" => override,
3503
+ }
3504
+ end
3505
+
3506
+ def to_json(options = nil)
3507
+ JSON.generate(to_dynamic, options)
3508
+ end
3509
+ end
3510
+
3511
+ class Race < Dry::Struct
3512
+ attribute :is_sub_race, Types::Bool
3513
+ attribute :base_race_name, Types::String
3514
+ attribute :entity_race_id, Types::Integer
3515
+ attribute :entity_race_type_id, Types::Integer
3516
+ attribute :definition_key, Types::String
3517
+ attribute :full_name, Types::String
3518
+ attribute :base_race_id, Types::Integer
3519
+ attribute :base_race_type_id, Types::Integer
3520
+ attribute :description, Types::String
3521
+ attribute :avatar_url, Types::String.optional
3522
+ attribute :large_avatar_url, Types::String.optional
3523
+ attribute :portrait_avatar_url, Types::String.optional
3524
+ attribute :more_details_url, Types::String
3525
+ attribute :is_homebrew, Types::Bool
3526
+ attribute :is_legacy, Types::Bool
3527
+ attribute :group_ids, Types.Array(Types::Integer)
3528
+ attribute :race_type, Types::Integer
3529
+ attribute :supports_subrace, Types::Nil
3530
+ attribute :sub_race_short_name, Types::String.optional
3531
+ attribute :base_name, Types::String
3532
+ attribute :racial_traits, Types.Array(RacialTrait)
3533
+ attribute :weight_speeds, WeightSpeeds
3534
+ attribute :feat_ids, Types.Array(Types::Any)
3535
+ attribute :size, Types::Nil
3536
+ attribute :size_id, Types::Integer
3537
+ attribute :sources, Types.Array(Source)
3538
+
3539
+ def self.from_dynamic!(d)
3540
+ d = Types::Hash[d]
3541
+ new(
3542
+ is_sub_race: d.fetch("isSubRace"),
3543
+ base_race_name: d.fetch("baseRaceName"),
3544
+ entity_race_id: d.fetch("entityRaceId"),
3545
+ entity_race_type_id: d.fetch("entityRaceTypeId"),
3546
+ definition_key: d.fetch("definitionKey"),
3547
+ full_name: d.fetch("fullName"),
3548
+ base_race_id: d.fetch("baseRaceId"),
3549
+ base_race_type_id: d.fetch("baseRaceTypeId"),
3550
+ description: d.fetch("description"),
3551
+ avatar_url: d.fetch("avatarUrl"),
3552
+ large_avatar_url: d.fetch("largeAvatarUrl"),
3553
+ portrait_avatar_url: d.fetch("portraitAvatarUrl"),
3554
+ more_details_url: d.fetch("moreDetailsUrl"),
3555
+ is_homebrew: d.fetch("isHomebrew"),
3556
+ is_legacy: d.fetch("isLegacy"),
3557
+ group_ids: d.fetch("groupIds"),
3558
+ race_type: d.fetch("type"),
3559
+ supports_subrace: d.fetch("supportsSubrace"),
3560
+ sub_race_short_name: d.fetch("subRaceShortName"),
3561
+ base_name: d.fetch("baseName"),
3562
+ racial_traits: d.fetch("racialTraits").map { |x| RacialTrait.from_dynamic!(x) },
3563
+ weight_speeds: WeightSpeeds.from_dynamic!(d.fetch("weightSpeeds")),
3564
+ feat_ids: d.fetch("featIds"),
3565
+ size: d.fetch("size"),
3566
+ size_id: d.fetch("sizeId"),
3567
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
3568
+ )
3569
+ end
3570
+
3571
+ def self.from_json!(json)
3572
+ from_dynamic!(JSON.parse(json))
3573
+ end
3574
+
3575
+ def to_dynamic
3576
+ {
3577
+ "isSubRace" => is_sub_race,
3578
+ "baseRaceName" => base_race_name,
3579
+ "entityRaceId" => entity_race_id,
3580
+ "entityRaceTypeId" => entity_race_type_id,
3581
+ "definitionKey" => definition_key,
3582
+ "fullName" => full_name,
3583
+ "baseRaceId" => base_race_id,
3584
+ "baseRaceTypeId" => base_race_type_id,
3585
+ "description" => description,
3586
+ "avatarUrl" => avatar_url,
3587
+ "largeAvatarUrl" => large_avatar_url,
3588
+ "portraitAvatarUrl" => portrait_avatar_url,
3589
+ "moreDetailsUrl" => more_details_url,
3590
+ "isHomebrew" => is_homebrew,
3591
+ "isLegacy" => is_legacy,
3592
+ "groupIds" => group_ids,
3593
+ "type" => race_type,
3594
+ "supportsSubrace" => supports_subrace,
3595
+ "subRaceShortName" => sub_race_short_name,
3596
+ "baseName" => base_name,
3597
+ "racialTraits" => racial_traits.map { |x| x.to_dynamic },
3598
+ "weightSpeeds" => weight_speeds.to_dynamic,
3599
+ "featIds" => feat_ids,
3600
+ "size" => size,
3601
+ "sizeId" => size_id,
3602
+ "sources" => sources.map { |x| x.to_dynamic },
3603
+ }
3604
+ end
3605
+
3606
+ def to_json(options = nil)
3607
+ JSON.generate(to_dynamic, options)
3608
+ end
3609
+ end
3610
+
3611
+ module AdditionalDescription
3612
+ DoesNotRequireMaterialComponents = "does not require material components"
3613
+ DoesnTRequireAnyComponents = "Doesn't require any components"
3614
+ Empty = ""
3615
+ TheHandIsInvisible = "the hand is invisible"
3616
+ end
3617
+
3618
+ module Restriction
3619
+ DoesnTRequireConcentration = "Doesn't require concentration"
3620
+ Empty = ""
3621
+ end
3622
+
3623
+ class SpellsClass < Dry::Struct
3624
+ attribute :override_save_dc, Types::Nil
3625
+ attribute :limited_use, ClassLimitedUse.optional
3626
+ attribute :id, Types::Integer
3627
+ attribute :entity_type_id, Types::Integer
3628
+ attribute :definition, SpellDefinition
3629
+ attribute :definition_id, Types::Integer
3630
+ attribute :prepared, Types::Bool
3631
+ attribute :counts_as_known_spell, Types::Bool
3632
+ attribute :uses_spell_slot, Types::Bool
3633
+ attribute :cast_at_level, Types::Integer.optional
3634
+ attribute :always_prepared, Types::Bool
3635
+ attribute :restriction, Types::Restriction
3636
+ attribute :spell_casting_ability_id, Types::Integer.optional
3637
+ attribute :display_as_attack, Types::Nil
3638
+ attribute :additional_description, Types::AdditionalDescription.optional
3639
+ attribute :cast_only_as_ritual, Types::Bool
3640
+ attribute :ritual_casting_type, Types::Integer.optional
3641
+ attribute :range, DefinitionRange
3642
+ attribute :activation, Activation
3643
+ attribute :base_level_at_will, Types::Bool
3644
+ attribute :at_will_limited_use_level, Types::Nil
3645
+ attribute :is_signature_spell, Types::Nil
3646
+ attribute :component_id, Types::Integer
3647
+ attribute :component_type_id, Types::Integer
3648
+ attribute :spell_list_id, Types::Nil
3649
+
3650
+ def self.from_dynamic!(d)
3651
+ d = Types::Hash[d]
3652
+ new(
3653
+ override_save_dc: d.fetch("overrideSaveDc"),
3654
+ limited_use: d.fetch("limitedUse") ? ClassLimitedUse.from_dynamic!(d.fetch("limitedUse")) : nil,
3655
+ id: d.fetch("id"),
3656
+ entity_type_id: d.fetch("entityTypeId"),
3657
+ definition: SpellDefinition.from_dynamic!(d.fetch("definition")),
3658
+ definition_id: d.fetch("definitionId"),
3659
+ prepared: d.fetch("prepared"),
3660
+ counts_as_known_spell: d.fetch("countsAsKnownSpell"),
3661
+ uses_spell_slot: d.fetch("usesSpellSlot"),
3662
+ cast_at_level: d.fetch("castAtLevel"),
3663
+ always_prepared: d.fetch("alwaysPrepared"),
3664
+ restriction: d.fetch("restriction"),
3665
+ spell_casting_ability_id: d.fetch("spellCastingAbilityId"),
3666
+ display_as_attack: d.fetch("displayAsAttack"),
3667
+ additional_description: d.fetch("additionalDescription"),
3668
+ cast_only_as_ritual: d.fetch("castOnlyAsRitual"),
3669
+ ritual_casting_type: d.fetch("ritualCastingType"),
3670
+ range: DefinitionRange.from_dynamic!(d.fetch("range")),
3671
+ activation: Activation.from_dynamic!(d.fetch("activation")),
3672
+ base_level_at_will: d.fetch("baseLevelAtWill"),
3673
+ at_will_limited_use_level: d.fetch("atWillLimitedUseLevel"),
3674
+ is_signature_spell: d.fetch("isSignatureSpell"),
3675
+ component_id: d.fetch("componentId"),
3676
+ component_type_id: d.fetch("componentTypeId"),
3677
+ spell_list_id: d.fetch("spellListId"),
3678
+ )
3679
+ end
3680
+
3681
+ def self.from_json!(json)
3682
+ from_dynamic!(JSON.parse(json))
3683
+ end
3684
+
3685
+ def to_dynamic
3686
+ {
3687
+ "overrideSaveDc" => override_save_dc,
3688
+ "limitedUse" => limited_use&.to_dynamic,
3689
+ "id" => id,
3690
+ "entityTypeId" => entity_type_id,
3691
+ "definition" => definition.to_dynamic,
3692
+ "definitionId" => definition_id,
3693
+ "prepared" => prepared,
3694
+ "countsAsKnownSpell" => counts_as_known_spell,
3695
+ "usesSpellSlot" => uses_spell_slot,
3696
+ "castAtLevel" => cast_at_level,
3697
+ "alwaysPrepared" => always_prepared,
3698
+ "restriction" => restriction,
3699
+ "spellCastingAbilityId" => spell_casting_ability_id,
3700
+ "displayAsAttack" => display_as_attack,
3701
+ "additionalDescription" => additional_description,
3702
+ "castOnlyAsRitual" => cast_only_as_ritual,
3703
+ "ritualCastingType" => ritual_casting_type,
3704
+ "range" => range.to_dynamic,
3705
+ "activation" => activation.to_dynamic,
3706
+ "baseLevelAtWill" => base_level_at_will,
3707
+ "atWillLimitedUseLevel" => at_will_limited_use_level,
3708
+ "isSignatureSpell" => is_signature_spell,
3709
+ "componentId" => component_id,
3710
+ "componentTypeId" => component_type_id,
3711
+ "spellListId" => spell_list_id,
3712
+ }
3713
+ end
3714
+
3715
+ def to_json(options = nil)
3716
+ JSON.generate(to_dynamic, options)
3717
+ end
3718
+ end
3719
+
3720
+ class Item < Dry::Struct
3721
+ attribute :override_save_dc, Types::Integer.optional
3722
+ attribute :limited_use, ClassLimitedUse.optional
3723
+ attribute :id, Types::Integer
3724
+ attribute :entity_type_id, Types::Integer
3725
+ attribute :definition, SpellDefinition
3726
+ attribute :definition_id, Types::Integer
3727
+ attribute :prepared, Types::Bool
3728
+ attribute :counts_as_known_spell, Types::Nil
3729
+ attribute :uses_spell_slot, Types::Bool
3730
+ attribute :cast_at_level, Types::Nil
3731
+ attribute :always_prepared, Types::Bool
3732
+ attribute :restriction, Types::Nil
3733
+ attribute :spell_casting_ability_id, Types::Nil
3734
+ attribute :display_as_attack, Types::Bool
3735
+ attribute :additional_description, Types::Nil
3736
+ attribute :cast_only_as_ritual, Types::Bool
3737
+ attribute :ritual_casting_type, Types::Nil
3738
+ attribute :range, DefinitionRange
3739
+ attribute :activation, Activation
3740
+ attribute :base_level_at_will, Types::Bool
3741
+ attribute :at_will_limited_use_level, Types::Nil
3742
+ attribute :is_signature_spell, Types::Nil
3743
+ attribute :component_id, Types::Integer
3744
+ attribute :component_type_id, Types::Integer
3745
+ attribute :spell_list_id, Types::Nil
3746
+
3747
+ def self.from_dynamic!(d)
3748
+ d = Types::Hash[d]
3749
+ new(
3750
+ override_save_dc: d.fetch("overrideSaveDc"),
3751
+ limited_use: d.fetch("limitedUse") ? ClassLimitedUse.from_dynamic!(d.fetch("limitedUse")) : nil,
3752
+ id: d.fetch("id"),
3753
+ entity_type_id: d.fetch("entityTypeId"),
3754
+ definition: SpellDefinition.from_dynamic!(d.fetch("definition")),
3755
+ definition_id: d.fetch("definitionId"),
3756
+ prepared: d.fetch("prepared"),
3757
+ counts_as_known_spell: d.fetch("countsAsKnownSpell"),
3758
+ uses_spell_slot: d.fetch("usesSpellSlot"),
3759
+ cast_at_level: d.fetch("castAtLevel"),
3760
+ always_prepared: d.fetch("alwaysPrepared"),
3761
+ restriction: d.fetch("restriction"),
3762
+ spell_casting_ability_id: d.fetch("spellCastingAbilityId"),
3763
+ display_as_attack: d.fetch("displayAsAttack"),
3764
+ additional_description: d.fetch("additionalDescription"),
3765
+ cast_only_as_ritual: d.fetch("castOnlyAsRitual"),
3766
+ ritual_casting_type: d.fetch("ritualCastingType"),
3767
+ range: DefinitionRange.from_dynamic!(d.fetch("range")),
3768
+ activation: Activation.from_dynamic!(d.fetch("activation")),
3769
+ base_level_at_will: d.fetch("baseLevelAtWill"),
3770
+ at_will_limited_use_level: d.fetch("atWillLimitedUseLevel"),
3771
+ is_signature_spell: d.fetch("isSignatureSpell"),
3772
+ component_id: d.fetch("componentId"),
3773
+ component_type_id: d.fetch("componentTypeId"),
3774
+ spell_list_id: d.fetch("spellListId"),
3775
+ )
3776
+ end
3777
+
3778
+ def self.from_json!(json)
3779
+ from_dynamic!(JSON.parse(json))
3780
+ end
3781
+
3782
+ def to_dynamic
3783
+ {
3784
+ "overrideSaveDc" => override_save_dc,
3785
+ "limitedUse" => limited_use&.to_dynamic,
3786
+ "id" => id,
3787
+ "entityTypeId" => entity_type_id,
3788
+ "definition" => definition.to_dynamic,
3789
+ "definitionId" => definition_id,
3790
+ "prepared" => prepared,
3791
+ "countsAsKnownSpell" => counts_as_known_spell,
3792
+ "usesSpellSlot" => uses_spell_slot,
3793
+ "castAtLevel" => cast_at_level,
3794
+ "alwaysPrepared" => always_prepared,
3795
+ "restriction" => restriction,
3796
+ "spellCastingAbilityId" => spell_casting_ability_id,
3797
+ "displayAsAttack" => display_as_attack,
3798
+ "additionalDescription" => additional_description,
3799
+ "castOnlyAsRitual" => cast_only_as_ritual,
3800
+ "ritualCastingType" => ritual_casting_type,
3801
+ "range" => range.to_dynamic,
3802
+ "activation" => activation.to_dynamic,
3803
+ "baseLevelAtWill" => base_level_at_will,
3804
+ "atWillLimitedUseLevel" => at_will_limited_use_level,
3805
+ "isSignatureSpell" => is_signature_spell,
3806
+ "componentId" => component_id,
3807
+ "componentTypeId" => component_type_id,
3808
+ "spellListId" => spell_list_id,
3809
+ }
3810
+ end
3811
+
3812
+ def to_json(options = nil)
3813
+ JSON.generate(to_dynamic, options)
3814
+ end
3815
+ end
3816
+
3817
+ class Spells < Dry::Struct
3818
+ attribute :race, Types.Array(SpellsClass)
3819
+ attribute :spells_class, Types.Array(SpellsClass)
3820
+ attribute :background, Types::Nil
3821
+ attribute :item, Types.Array(Item)
3822
+ attribute :feat, Types.Array(SpellsClass)
3823
+
3824
+ def self.from_dynamic!(d)
3825
+ d = Types::Hash[d]
3826
+ new(
3827
+ race: d.fetch("race").map { |x| SpellsClass.from_dynamic!(x) },
3828
+ spells_class: d.fetch("class").map { |x| SpellsClass.from_dynamic!(x) },
3829
+ background: d.fetch("background"),
3830
+ item: d.fetch("item").map { |x| Item.from_dynamic!(x) },
3831
+ feat: d.fetch("feat").map { |x| SpellsClass.from_dynamic!(x) },
3832
+ )
3833
+ end
3834
+
3835
+ def self.from_json!(json)
3836
+ from_dynamic!(JSON.parse(json))
3837
+ end
3838
+
3839
+ def to_dynamic
3840
+ {
3841
+ "race" => race.map { |x| x.to_dynamic },
3842
+ "class" => spells_class.map { |x| x.to_dynamic },
3843
+ "background" => background,
3844
+ "item" => item.map { |x| x.to_dynamic },
3845
+ "feat" => feat.map { |x| x.to_dynamic },
3846
+ }
3847
+ end
3848
+
3849
+ def to_json(options = nil)
3850
+ JSON.generate(to_dynamic, options)
3851
+ end
3852
+ end
3853
+
3854
+ module StatusSlug
3855
+ Active = "active"
3856
+ end
3857
+
3858
+ class Definition2 < Dry::Struct
3859
+ attribute :id, Types::Integer
3860
+ attribute :entity_type_id, Types::Integer
3861
+ attribute :definition_name, Types::String
3862
+ attribute :description, Types::String
3863
+ attribute :snippet, Types::String
3864
+ attribute :activation, Types::Nil
3865
+ attribute :source_id, Types::Integer.optional
3866
+ attribute :source_page_number, Types::Integer.optional
3867
+ attribute :creature_rules, Types.Array(Types::Any)
3868
+ attribute :spell_list_ids, Types.Array(Types::Any)
3869
+
3870
+ def self.from_dynamic!(d)
3871
+ d = Types::Hash[d]
3872
+ new(
3873
+ id: d.fetch("id"),
3874
+ entity_type_id: d.fetch("entityTypeId"),
3875
+ definition_name: d.fetch("name"),
3876
+ description: d.fetch("description"),
3877
+ snippet: d.fetch("snippet"),
3878
+ activation: d.fetch("activation"),
3879
+ source_id: d.fetch("sourceId"),
3880
+ source_page_number: d.fetch("sourcePageNumber"),
3881
+ creature_rules: d.fetch("creatureRules"),
3882
+ spell_list_ids: d.fetch("spellListIds"),
3883
+ )
3884
+ end
3885
+
3886
+ def self.from_json!(json)
3887
+ from_dynamic!(JSON.parse(json))
3888
+ end
3889
+
3890
+ def to_dynamic
3891
+ {
3892
+ "id" => id,
3893
+ "entityTypeId" => entity_type_id,
3894
+ "name" => definition_name,
3895
+ "description" => description,
3896
+ "snippet" => snippet,
3897
+ "activation" => activation,
3898
+ "sourceId" => source_id,
3899
+ "sourcePageNumber" => source_page_number,
3900
+ "creatureRules" => creature_rules,
3901
+ "spellListIds" => spell_list_ids,
3902
+ }
3903
+ end
3904
+
3905
+ def to_json(options = nil)
3906
+ JSON.generate(to_dynamic, options)
3907
+ end
3908
+ end
3909
+
3910
+ class OptionsClass < Dry::Struct
3911
+ attribute :component_id, Types::Integer
3912
+ attribute :component_type_id, Types::Integer
3913
+ attribute :definition, Definition2
3914
+
3915
+ def self.from_dynamic!(d)
3916
+ d = Types::Hash[d]
3917
+ new(
3918
+ component_id: d.fetch("componentId"),
3919
+ component_type_id: d.fetch("componentTypeId"),
3920
+ definition: Definition2.from_dynamic!(d.fetch("definition")),
3921
+ )
3922
+ end
3923
+
3924
+ def self.from_json!(json)
3925
+ from_dynamic!(JSON.parse(json))
3926
+ end
3927
+
3928
+ def to_dynamic
3929
+ {
3930
+ "componentId" => component_id,
3931
+ "componentTypeId" => component_type_id,
3932
+ "definition" => definition.to_dynamic,
3933
+ }
3934
+ end
3935
+
3936
+ def to_json(options = nil)
3937
+ JSON.generate(to_dynamic, options)
3938
+ end
3939
+ end
3940
+
3941
+ class Options < Dry::Struct
3942
+ attribute :race, Types.Array(OptionsClass)
3943
+ attribute :options_class, Types.Array(OptionsClass)
3944
+ attribute :background, Types::Nil
3945
+ attribute :item, Types::Nil
3946
+ attribute :feat, Types.Array(OptionsClass)
3947
+
3948
+ def self.from_dynamic!(d)
3949
+ d = Types::Hash[d]
3950
+ new(
3951
+ race: d.fetch("race").map { |x| OptionsClass.from_dynamic!(x) },
3952
+ options_class: d.fetch("class").map { |x| OptionsClass.from_dynamic!(x) },
3953
+ background: d.fetch("background"),
3954
+ item: d.fetch("item"),
3955
+ feat: d.fetch("feat").map { |x| OptionsClass.from_dynamic!(x) },
3956
+ )
3957
+ end
3958
+
3959
+ def self.from_json!(json)
3960
+ from_dynamic!(JSON.parse(json))
3961
+ end
3962
+
3963
+ def to_dynamic
3964
+ {
3965
+ "race" => race.map { |x| x.to_dynamic },
3966
+ "class" => options_class.map { |x| x.to_dynamic },
3967
+ "background" => background,
3968
+ "item" => item,
3969
+ "feat" => feat.map { |x| x.to_dynamic },
3970
+ }
3971
+ end
3972
+
3973
+ def to_json(options = nil)
3974
+ JSON.generate(to_dynamic, options)
3975
+ end
3976
+ end
3977
+
3978
+ class Traits < Dry::Struct
3979
+ attribute :personality_traits, Types::String.optional
3980
+ attribute :ideals, Types::String.optional
3981
+ attribute :bonds, Types::String.optional
3982
+ attribute :flaws, Types::String.optional
3983
+ attribute :appearance, Types::Nil
3984
+
3985
+ def self.from_dynamic!(d)
3986
+ d = Types::Hash[d]
3987
+ new(
3988
+ personality_traits: d.fetch("personalityTraits"),
3989
+ ideals: d.fetch("ideals"),
3990
+ bonds: d.fetch("bonds"),
3991
+ flaws: d.fetch("flaws"),
3992
+ appearance: d.fetch("appearance"),
3993
+ )
3994
+ end
3995
+
3996
+ def self.from_json!(json)
3997
+ from_dynamic!(JSON.parse(json))
3998
+ end
3999
+
4000
+ def to_dynamic
4001
+ {
4002
+ "personalityTraits" => personality_traits,
4003
+ "ideals" => ideals,
4004
+ "bonds" => bonds,
4005
+ "flaws" => flaws,
4006
+ "appearance" => appearance,
4007
+ }
4008
+ end
4009
+
4010
+ def to_json(options = nil)
4011
+ JSON.generate(to_dynamic, options)
4012
+ end
4013
+ end
4014
+
4015
+ class TopLevel < Dry::Struct
4016
+ attribute :id, Types::Integer
4017
+ attribute :user_id, Types::Integer
4018
+ attribute :username, Types::Username
4019
+ attribute :is_assigned_to_player, Types::Bool
4020
+ attribute :readonly_url, Types::String
4021
+ attribute :decorations, Decorations
4022
+ attribute :top_level_name, Types::String
4023
+ attribute :social_name, Types::Nil
4024
+ attribute :gender, Types::String.optional
4025
+ attribute :faith, Types::String.optional
4026
+ attribute :age, Types::Integer.optional
4027
+ attribute :hair, Types::String.optional
4028
+ attribute :eyes, Types::String.optional
4029
+ attribute :skin, Types::String.optional
4030
+ attribute :height, Types::String.optional
4031
+ attribute :weight, Types::Integer.optional
4032
+ attribute :inspiration, Types::Bool
4033
+ attribute :base_hit_points, Types::Integer
4034
+ attribute :bonus_hit_points, Types::Nil
4035
+ attribute :override_hit_points, Types::Nil
4036
+ attribute :removed_hit_points, Types::Integer
4037
+ attribute :temporary_hit_points, Types::Integer
4038
+ attribute :current_xp, Types::Integer
4039
+ attribute :alignment_id, Types::Integer.optional
4040
+ attribute :lifestyle_id, Types::Integer.optional
4041
+ attribute :stats, Types.Array(Stat)
4042
+ attribute :bonus_stats, Types.Array(Stat)
4043
+ attribute :override_stats, Types.Array(Stat)
4044
+ attribute :background, TopLevelBackground
4045
+ attribute :race, Race.optional
4046
+ attribute :race_definition_id, Types::Nil
4047
+ attribute :race_definition_type_id, Types::Nil
4048
+ attribute :notes, Notes
4049
+ attribute :traits, Traits
4050
+ attribute :preferences, Preferences
4051
+ attribute :configuration, Configuration
4052
+ attribute :lifestyle, Types::Nil
4053
+ attribute :inventory, Types.Array(Inventory)
4054
+ attribute :currencies, Currencies
4055
+ attribute :classes, Types.Array(TopLevelClass)
4056
+ attribute :feats, Types.Array(Feat)
4057
+ attribute :features, Types.Array(Types::Any)
4058
+ attribute :custom_defense_adjustments, Types.Array(Types::Any)
4059
+ attribute :custom_senses, Types.Array(Types::Any)
4060
+ attribute :custom_speeds, Types.Array(Types::Any)
4061
+ attribute :custom_proficiencies, Types.Array(Types::Any)
4062
+ attribute :custom_actions, Types.Array(Types::Any)
4063
+ attribute :character_values, Types.Array(CharacterValue)
4064
+ attribute :conditions, Types.Array(TopLevelCondition)
4065
+ attribute :death_saves, DeathSaves
4066
+ attribute :adjustment_xp, Types::Integer.optional
4067
+ attribute :spell_slots, Types.Array(PactMagic)
4068
+ attribute :pact_magic, Types.Array(PactMagic)
4069
+ attribute :active_source_categories, Types.Array(Types::Integer)
4070
+ attribute :spells, Spells
4071
+ attribute :top_level_options, Options
4072
+ attribute :choices, Choices
4073
+ attribute :actions, Actions
4074
+ attribute :modifiers, Modifiers
4075
+ attribute :class_spells, Types.Array(ClassSpell)
4076
+ attribute :custom_items, Types.Array(CustomItem)
4077
+ attribute :campaign, Campaign.optional
4078
+ attribute :creatures, Types.Array(Types::Any)
4079
+ attribute :optional_origins, Types.Array(Types::Any)
4080
+ attribute :optional_class_features, Types.Array(Types::Any)
4081
+ attribute :date_modified, Types::String
4082
+ attribute :provided_from, Types::ProvidedFrom
4083
+ attribute :can_edit, Types::Bool
4084
+ attribute :status, Types::Integer
4085
+ attribute :status_slug, Types::StatusSlug
4086
+ attribute :campaign_setting, Types::Nil
4087
+
4088
+ def self.from_dynamic!(d)
4089
+ d = Types::Hash[d]
4090
+ new(
4091
+ id: d.fetch("id"),
4092
+ user_id: d.fetch("userId"),
4093
+ username: d.fetch("username"),
4094
+ is_assigned_to_player: d.fetch("isAssignedToPlayer"),
4095
+ readonly_url: d.fetch("readonlyUrl"),
4096
+ decorations: Decorations.from_dynamic!(d.fetch("decorations")),
4097
+ top_level_name: d.fetch("name"),
4098
+ social_name: d.fetch("socialName"),
4099
+ gender: d.fetch("gender"),
4100
+ faith: d.fetch("faith"),
4101
+ age: d.fetch("age"),
4102
+ hair: d.fetch("hair"),
4103
+ eyes: d.fetch("eyes"),
4104
+ skin: d.fetch("skin"),
4105
+ height: d.fetch("height"),
4106
+ weight: d.fetch("weight"),
4107
+ inspiration: d.fetch("inspiration"),
4108
+ base_hit_points: d.fetch("baseHitPoints"),
4109
+ bonus_hit_points: d.fetch("bonusHitPoints"),
4110
+ override_hit_points: d.fetch("overrideHitPoints"),
4111
+ removed_hit_points: d.fetch("removedHitPoints"),
4112
+ temporary_hit_points: d.fetch("temporaryHitPoints"),
4113
+ current_xp: d.fetch("currentXp"),
4114
+ alignment_id: d.fetch("alignmentId"),
4115
+ lifestyle_id: d.fetch("lifestyleId"),
4116
+ stats: d.fetch("stats").map { |x| Stat.from_dynamic!(x) },
4117
+ bonus_stats: d.fetch("bonusStats").map { |x| Stat.from_dynamic!(x) },
4118
+ override_stats: d.fetch("overrideStats").map { |x| Stat.from_dynamic!(x) },
4119
+ background: TopLevelBackground.from_dynamic!(d.fetch("background")),
4120
+ race: d.fetch("race") ? Race.from_dynamic!(d.fetch("race")) : nil,
4121
+ race_definition_id: d.fetch("raceDefinitionId"),
4122
+ race_definition_type_id: d.fetch("raceDefinitionTypeId"),
4123
+ notes: Notes.from_dynamic!(d.fetch("notes")),
4124
+ traits: Traits.from_dynamic!(d.fetch("traits")),
4125
+ preferences: Preferences.from_dynamic!(d.fetch("preferences")),
4126
+ configuration: Configuration.from_dynamic!(d.fetch("configuration")),
4127
+ lifestyle: d.fetch("lifestyle"),
4128
+ inventory: d.fetch("inventory").map { |x| Inventory.from_dynamic!(x) },
4129
+ currencies: Currencies.from_dynamic!(d.fetch("currencies")),
4130
+ classes: d.fetch("classes").map { |x| TopLevelClass.from_dynamic!(x) },
4131
+ feats: d.fetch("feats").map { |x| Feat.from_dynamic!(x) },
4132
+ features: d.fetch("features"),
4133
+ custom_defense_adjustments: d.fetch("customDefenseAdjustments"),
4134
+ custom_senses: d.fetch("customSenses"),
4135
+ custom_speeds: d.fetch("customSpeeds"),
4136
+ custom_proficiencies: d.fetch("customProficiencies"),
4137
+ custom_actions: d.fetch("customActions"),
4138
+ character_values: d.fetch("characterValues").map { |x| CharacterValue.from_dynamic!(x) },
4139
+ conditions: d.fetch("conditions").map { |x| TopLevelCondition.from_dynamic!(x) },
4140
+ death_saves: DeathSaves.from_dynamic!(d.fetch("deathSaves")),
4141
+ adjustment_xp: d.fetch("adjustmentXp"),
4142
+ spell_slots: d.fetch("spellSlots").map { |x| PactMagic.from_dynamic!(x) },
4143
+ pact_magic: d.fetch("pactMagic").map { |x| PactMagic.from_dynamic!(x) },
4144
+ active_source_categories: d.fetch("activeSourceCategories"),
4145
+ spells: Spells.from_dynamic!(d.fetch("spells")),
4146
+ top_level_options: Options.from_dynamic!(d.fetch("options")),
4147
+ choices: Choices.from_dynamic!(d.fetch("choices")),
4148
+ actions: Actions.from_dynamic!(d.fetch("actions")),
4149
+ modifiers: Modifiers.from_dynamic!(d.fetch("modifiers")),
4150
+ class_spells: d.fetch("classSpells").map { |x| ClassSpell.from_dynamic!(x) },
4151
+ custom_items: d.fetch("customItems").map { |x| CustomItem.from_dynamic!(x) },
4152
+ campaign: d.fetch("campaign") ? Campaign.from_dynamic!(d.fetch("campaign")) : nil,
4153
+ creatures: d.fetch("creatures"),
4154
+ optional_origins: d.fetch("optionalOrigins"),
4155
+ optional_class_features: d.fetch("optionalClassFeatures"),
4156
+ date_modified: d.fetch("dateModified"),
4157
+ provided_from: d.fetch("providedFrom"),
4158
+ can_edit: d.fetch("canEdit"),
4159
+ status: d.fetch("status"),
4160
+ status_slug: d.fetch("statusSlug"),
4161
+ campaign_setting: d.fetch("campaignSetting"),
4162
+ )
4163
+ end
4164
+
4165
+ def self.from_json!(json)
4166
+ from_dynamic!(JSON.parse(json))
4167
+ end
4168
+
4169
+ def to_dynamic
4170
+ {
4171
+ "id" => id,
4172
+ "userId" => user_id,
4173
+ "username" => username,
4174
+ "isAssignedToPlayer" => is_assigned_to_player,
4175
+ "readonlyUrl" => readonly_url,
4176
+ "decorations" => decorations.to_dynamic,
4177
+ "name" => top_level_name,
4178
+ "socialName" => social_name,
4179
+ "gender" => gender,
4180
+ "faith" => faith,
4181
+ "age" => age,
4182
+ "hair" => hair,
4183
+ "eyes" => eyes,
4184
+ "skin" => skin,
4185
+ "height" => height,
4186
+ "weight" => weight,
4187
+ "inspiration" => inspiration,
4188
+ "baseHitPoints" => base_hit_points,
4189
+ "bonusHitPoints" => bonus_hit_points,
4190
+ "overrideHitPoints" => override_hit_points,
4191
+ "removedHitPoints" => removed_hit_points,
4192
+ "temporaryHitPoints" => temporary_hit_points,
4193
+ "currentXp" => current_xp,
4194
+ "alignmentId" => alignment_id,
4195
+ "lifestyleId" => lifestyle_id,
4196
+ "stats" => stats.map { |x| x.to_dynamic },
4197
+ "bonusStats" => bonus_stats.map { |x| x.to_dynamic },
4198
+ "overrideStats" => override_stats.map { |x| x.to_dynamic },
4199
+ "background" => background.to_dynamic,
4200
+ "race" => race&.to_dynamic,
4201
+ "raceDefinitionId" => race_definition_id,
4202
+ "raceDefinitionTypeId" => race_definition_type_id,
4203
+ "notes" => notes.to_dynamic,
4204
+ "traits" => traits.to_dynamic,
4205
+ "preferences" => preferences.to_dynamic,
4206
+ "configuration" => configuration.to_dynamic,
4207
+ "lifestyle" => lifestyle,
4208
+ "inventory" => inventory.map { |x| x.to_dynamic },
4209
+ "currencies" => currencies.to_dynamic,
4210
+ "classes" => classes.map { |x| x.to_dynamic },
4211
+ "feats" => feats.map { |x| x.to_dynamic },
4212
+ "features" => features,
4213
+ "customDefenseAdjustments" => custom_defense_adjustments,
4214
+ "customSenses" => custom_senses,
4215
+ "customSpeeds" => custom_speeds,
4216
+ "customProficiencies" => custom_proficiencies,
4217
+ "customActions" => custom_actions,
4218
+ "characterValues" => character_values.map { |x| x.to_dynamic },
4219
+ "conditions" => conditions.map { |x| x.to_dynamic },
4220
+ "deathSaves" => death_saves.to_dynamic,
4221
+ "adjustmentXp" => adjustment_xp,
4222
+ "spellSlots" => spell_slots.map { |x| x.to_dynamic },
4223
+ "pactMagic" => pact_magic.map { |x| x.to_dynamic },
4224
+ "activeSourceCategories" => active_source_categories,
4225
+ "spells" => spells.to_dynamic,
4226
+ "options" => top_level_options.to_dynamic,
4227
+ "choices" => choices.to_dynamic,
4228
+ "actions" => actions.to_dynamic,
4229
+ "modifiers" => modifiers.to_dynamic,
4230
+ "classSpells" => class_spells.map { |x| x.to_dynamic },
4231
+ "customItems" => custom_items.map { |x| x.to_dynamic },
4232
+ "campaign" => campaign&.to_dynamic,
4233
+ "creatures" => creatures,
4234
+ "optionalOrigins" => optional_origins,
4235
+ "optionalClassFeatures" => optional_class_features,
4236
+ "dateModified" => date_modified,
4237
+ "providedFrom" => provided_from,
4238
+ "canEdit" => can_edit,
4239
+ "status" => status,
4240
+ "statusSlug" => status_slug,
4241
+ "campaignSetting" => campaign_setting,
4242
+ }
4243
+ end
4244
+
4245
+ def to_json(options = nil)
4246
+ JSON.generate(to_dynamic, options)
4247
+ end
4248
+ end
4249
+ end
4250
+ end