ddb_ruby 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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