ddb_ruby 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3519 @@
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
+ # character = Character.from_json! "{…}"
7
+ # puts character.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 Types
17
+ include Dry.Types(default: :nominal)
18
+
19
+ Integer = Coercible::Integer
20
+ Bool = Types::Params::Bool
21
+ Hash = Coercible::Hash
22
+ String = Coercible::String
23
+ Double = Coercible::Float | Coercible::Integer
24
+ Restriction = Coercible::String.enum("Concentration", "")
25
+ EntityType = Coercible::String.enum("class-feature")
26
+ ContainerDefinitionKey = Coercible::String.enum("1581111423:53552888")
27
+ FilterType = Coercible::String.enum("Armor", "Other Gear", "Potion", "Weapon")
28
+ Rarity = Coercible::String.enum("Common", "Rare", "Uncommon")
29
+ end
30
+
31
+ class Activation < Dry::Struct
32
+ attribute :activation_time, Types::Integer.optional
33
+ attribute :activation_type, Types::Integer.optional
34
+
35
+ def self.from_dynamic!(d)
36
+ d = Types::Hash[d]
37
+ new(
38
+ activation_time: d.fetch("activationTime"),
39
+ activation_type: d.fetch("activationType"),
40
+ )
41
+ end
42
+
43
+ def self.from_json!(json)
44
+ from_dynamic!(JSON.parse(json))
45
+ end
46
+
47
+ def to_dynamic
48
+ {
49
+ "activationTime" => activation_time,
50
+ "activationType" => activation_type,
51
+ }
52
+ end
53
+
54
+ def to_json(options = nil)
55
+ JSON.generate(to_dynamic, options)
56
+ end
57
+ end
58
+
59
+ class ClassLimitedUse < Dry::Struct
60
+ attribute :limited_use_name, Types::Nil
61
+ attribute :stat_modifier_uses_id, Types::Nil
62
+ attribute :reset_type, Types::Integer
63
+ attribute :number_used, Types::Integer
64
+ attribute :min_number_consumed, Types::Integer
65
+ attribute :max_number_consumed, Types::Integer
66
+ attribute :max_uses, Types::Integer
67
+ attribute :operator, Types::Integer
68
+ attribute :use_proficiency_bonus, Types::Bool
69
+ attribute :proficiency_bonus_operator, Types::Integer
70
+ attribute :reset_dice, Types::Nil
71
+
72
+ def self.from_dynamic!(d)
73
+ d = Types::Hash[d]
74
+ new(
75
+ limited_use_name: d.fetch("name"),
76
+ stat_modifier_uses_id: d.fetch("statModifierUsesId"),
77
+ reset_type: d.fetch("resetType"),
78
+ number_used: d.fetch("numberUsed"),
79
+ min_number_consumed: d.fetch("minNumberConsumed"),
80
+ max_number_consumed: d.fetch("maxNumberConsumed"),
81
+ max_uses: d.fetch("maxUses"),
82
+ operator: d.fetch("operator"),
83
+ use_proficiency_bonus: d.fetch("useProficiencyBonus"),
84
+ proficiency_bonus_operator: d.fetch("proficiencyBonusOperator"),
85
+ reset_dice: d.fetch("resetDice"),
86
+ )
87
+ end
88
+
89
+ def self.from_json!(json)
90
+ from_dynamic!(JSON.parse(json))
91
+ end
92
+
93
+ def to_dynamic
94
+ {
95
+ "name" => limited_use_name,
96
+ "statModifierUsesId" => stat_modifier_uses_id,
97
+ "resetType" => reset_type,
98
+ "numberUsed" => number_used,
99
+ "minNumberConsumed" => min_number_consumed,
100
+ "maxNumberConsumed" => max_number_consumed,
101
+ "maxUses" => max_uses,
102
+ "operator" => operator,
103
+ "useProficiencyBonus" => use_proficiency_bonus,
104
+ "proficiencyBonusOperator" => proficiency_bonus_operator,
105
+ "resetDice" => reset_dice,
106
+ }
107
+ end
108
+
109
+ def to_json(options = nil)
110
+ JSON.generate(to_dynamic, options)
111
+ end
112
+ end
113
+
114
+ class ClassRange < Dry::Struct
115
+ attribute :range, Types::Nil
116
+ attribute :long_range, Types::Nil
117
+ attribute :aoe_type, Types::Nil
118
+ attribute :aoe_size, Types::Nil
119
+ attribute :has_aoe_special_description, Types::Bool
120
+ attribute :minimum_range, Types::Nil
121
+
122
+ def self.from_dynamic!(d)
123
+ d = Types::Hash[d]
124
+ new(
125
+ range: d.fetch("range"),
126
+ long_range: d.fetch("longRange"),
127
+ aoe_type: d.fetch("aoeType"),
128
+ aoe_size: d.fetch("aoeSize"),
129
+ has_aoe_special_description: d.fetch("hasAoeSpecialDescription"),
130
+ minimum_range: d.fetch("minimumRange"),
131
+ )
132
+ end
133
+
134
+ def self.from_json!(json)
135
+ from_dynamic!(JSON.parse(json))
136
+ end
137
+
138
+ def to_dynamic
139
+ {
140
+ "range" => range,
141
+ "longRange" => long_range,
142
+ "aoeType" => aoe_type,
143
+ "aoeSize" => aoe_size,
144
+ "hasAoeSpecialDescription" => has_aoe_special_description,
145
+ "minimumRange" => minimum_range,
146
+ }
147
+ end
148
+
149
+ def to_json(options = nil)
150
+ JSON.generate(to_dynamic, options)
151
+ end
152
+ end
153
+
154
+ class ActionsClass < Dry::Struct
155
+ attribute :component_id, Types::Integer
156
+ attribute :component_type_id, Types::Integer
157
+ attribute :id, Types::String
158
+ attribute :entity_type_id, Types::String
159
+ attribute :limited_use, ClassLimitedUse.optional
160
+ attribute :class_name, Types::String
161
+ attribute :description, Types::String.optional
162
+ attribute :snippet, Types::String
163
+ attribute :ability_modifier_stat_id, Types::Nil
164
+ attribute :on_miss_description, Types::String.optional
165
+ attribute :save_fail_description, Types::String.optional
166
+ attribute :save_success_description, Types::String.optional
167
+ attribute :save_stat_id, Types::Nil
168
+ attribute :fixed_save_dc, Types::Nil
169
+ attribute :attack_type_range, Types::Nil
170
+ attribute :action_type, Types::Integer
171
+ attribute :attack_subtype, Types::Nil
172
+ attribute :dice, Types::Nil
173
+ attribute :value, Types::Nil
174
+ attribute :damage_type_id, Types::Nil
175
+ attribute :is_martial_arts, Types::Bool
176
+ attribute :is_proficient, Types::Bool
177
+ attribute :spell_range_type, Types::Nil
178
+ attribute :display_as_attack, Types::Nil
179
+ attribute :range, ClassRange
180
+ attribute :activation, Activation
181
+ attribute :number_of_targets, Types::Nil
182
+ attribute :fixed_to_hit, Types::Nil
183
+ attribute :ammunition, Types::Nil
184
+
185
+ def self.from_dynamic!(d)
186
+ d = Types::Hash[d]
187
+ new(
188
+ component_id: d.fetch("componentId"),
189
+ component_type_id: d.fetch("componentTypeId"),
190
+ id: d.fetch("id"),
191
+ entity_type_id: d.fetch("entityTypeId"),
192
+ limited_use: d.fetch("limitedUse") ? ClassLimitedUse.from_dynamic!(d.fetch("limitedUse")) : nil,
193
+ class_name: d.fetch("name"),
194
+ description: d.fetch("description"),
195
+ snippet: d.fetch("snippet"),
196
+ ability_modifier_stat_id: d.fetch("abilityModifierStatId"),
197
+ on_miss_description: d.fetch("onMissDescription"),
198
+ save_fail_description: d.fetch("saveFailDescription"),
199
+ save_success_description: d.fetch("saveSuccessDescription"),
200
+ save_stat_id: d.fetch("saveStatId"),
201
+ fixed_save_dc: d.fetch("fixedSaveDc"),
202
+ attack_type_range: d.fetch("attackTypeRange"),
203
+ action_type: d.fetch("actionType"),
204
+ attack_subtype: d.fetch("attackSubtype"),
205
+ dice: d.fetch("dice"),
206
+ value: d.fetch("value"),
207
+ damage_type_id: d.fetch("damageTypeId"),
208
+ is_martial_arts: d.fetch("isMartialArts"),
209
+ is_proficient: d.fetch("isProficient"),
210
+ spell_range_type: d.fetch("spellRangeType"),
211
+ display_as_attack: d.fetch("displayAsAttack"),
212
+ range: ClassRange.from_dynamic!(d.fetch("range")),
213
+ activation: Activation.from_dynamic!(d.fetch("activation")),
214
+ number_of_targets: d.fetch("numberOfTargets"),
215
+ fixed_to_hit: d.fetch("fixedToHit"),
216
+ ammunition: d.fetch("ammunition"),
217
+ )
218
+ end
219
+
220
+ def self.from_json!(json)
221
+ from_dynamic!(JSON.parse(json))
222
+ end
223
+
224
+ def to_dynamic
225
+ {
226
+ "componentId" => component_id,
227
+ "componentTypeId" => component_type_id,
228
+ "id" => id,
229
+ "entityTypeId" => entity_type_id,
230
+ "limitedUse" => limited_use&.to_dynamic,
231
+ "name" => class_name,
232
+ "description" => description,
233
+ "snippet" => snippet,
234
+ "abilityModifierStatId" => ability_modifier_stat_id,
235
+ "onMissDescription" => on_miss_description,
236
+ "saveFailDescription" => save_fail_description,
237
+ "saveSuccessDescription" => save_success_description,
238
+ "saveStatId" => save_stat_id,
239
+ "fixedSaveDc" => fixed_save_dc,
240
+ "attackTypeRange" => attack_type_range,
241
+ "actionType" => action_type,
242
+ "attackSubtype" => attack_subtype,
243
+ "dice" => dice,
244
+ "value" => value,
245
+ "damageTypeId" => damage_type_id,
246
+ "isMartialArts" => is_martial_arts,
247
+ "isProficient" => is_proficient,
248
+ "spellRangeType" => spell_range_type,
249
+ "displayAsAttack" => display_as_attack,
250
+ "range" => range.to_dynamic,
251
+ "activation" => activation.to_dynamic,
252
+ "numberOfTargets" => number_of_targets,
253
+ "fixedToHit" => fixed_to_hit,
254
+ "ammunition" => ammunition,
255
+ }
256
+ end
257
+
258
+ def to_json(options = nil)
259
+ JSON.generate(to_dynamic, options)
260
+ end
261
+ end
262
+
263
+ class HigherLevelDefinition < Dry::Struct
264
+ attribute :level, Types::Integer
265
+ attribute :type_id, Types::Integer
266
+ attribute :dice, Types::Nil
267
+ attribute :value, Types::Integer
268
+ attribute :details, Types::String
269
+
270
+ def self.from_dynamic!(d)
271
+ d = Types::Hash[d]
272
+ new(
273
+ level: d.fetch("level"),
274
+ type_id: d.fetch("typeId"),
275
+ dice: d.fetch("dice"),
276
+ value: d.fetch("value"),
277
+ details: d.fetch("details"),
278
+ )
279
+ end
280
+
281
+ def self.from_json!(json)
282
+ from_dynamic!(JSON.parse(json))
283
+ end
284
+
285
+ def to_dynamic
286
+ {
287
+ "level" => level,
288
+ "typeId" => type_id,
289
+ "dice" => dice,
290
+ "value" => value,
291
+ "details" => details,
292
+ }
293
+ end
294
+
295
+ def to_json(options = nil)
296
+ JSON.generate(to_dynamic, options)
297
+ end
298
+ end
299
+
300
+ class AtHigherLevels < Dry::Struct
301
+ attribute :higher_level_definitions, Types.Array(HigherLevelDefinition)
302
+ attribute :additional_attacks, Types.Array(Types::Any)
303
+ attribute :additional_targets, Types.Array(Types::Any)
304
+ attribute :area_of_effect, Types.Array(Types::Any)
305
+ attribute :duration, Types.Array(Types::Any)
306
+ attribute :creatures, Types.Array(Types::Any)
307
+ attribute :special, Types.Array(Types::Any)
308
+ attribute :points, Types.Array(Types::Any)
309
+ attribute :range, Types.Array(Types::Any)
310
+
311
+ def self.from_dynamic!(d)
312
+ d = Types::Hash[d]
313
+ new(
314
+ higher_level_definitions: d.fetch("higherLevelDefinitions").map { |x| HigherLevelDefinition.from_dynamic!(x) },
315
+ additional_attacks: d.fetch("additionalAttacks"),
316
+ additional_targets: d.fetch("additionalTargets"),
317
+ area_of_effect: d.fetch("areaOfEffect"),
318
+ duration: d.fetch("duration"),
319
+ creatures: d.fetch("creatures"),
320
+ special: d.fetch("special"),
321
+ points: d.fetch("points"),
322
+ range: d.fetch("range"),
323
+ )
324
+ end
325
+
326
+ def self.from_json!(json)
327
+ from_dynamic!(JSON.parse(json))
328
+ end
329
+
330
+ def to_dynamic
331
+ {
332
+ "higherLevelDefinitions" => higher_level_definitions.map { |x| x.to_dynamic },
333
+ "additionalAttacks" => additional_attacks,
334
+ "additionalTargets" => additional_targets,
335
+ "areaOfEffect" => area_of_effect,
336
+ "duration" => duration,
337
+ "creatures" => creatures,
338
+ "special" => special,
339
+ "points" => points,
340
+ "range" => range,
341
+ }
342
+ end
343
+
344
+ def to_json(options = nil)
345
+ JSON.generate(to_dynamic, options)
346
+ end
347
+ end
348
+
349
+ module Restriction
350
+ Concentration = "Concentration"
351
+ Empty = ""
352
+ end
353
+
354
+ class DefinitionDuration < Dry::Struct
355
+ attribute :duration_interval, Types::Integer
356
+ attribute :duration_unit, Types::String
357
+ attribute :duration_type, Types::Restriction
358
+
359
+ def self.from_dynamic!(d)
360
+ d = Types::Hash[d]
361
+ new(
362
+ duration_interval: d.fetch("durationInterval"),
363
+ duration_unit: d.fetch("durationUnit"),
364
+ duration_type: d.fetch("durationType"),
365
+ )
366
+ end
367
+
368
+ def self.from_json!(json)
369
+ from_dynamic!(JSON.parse(json))
370
+ end
371
+
372
+ def to_dynamic
373
+ {
374
+ "durationInterval" => duration_interval,
375
+ "durationUnit" => duration_unit,
376
+ "durationType" => duration_type,
377
+ }
378
+ end
379
+
380
+ def to_json(options = nil)
381
+ JSON.generate(to_dynamic, options)
382
+ end
383
+ end
384
+
385
+ class Die < Dry::Struct
386
+ attribute :dice_count, Types::Integer.optional
387
+ attribute :dice_value, Types::Integer.optional
388
+ attribute :dice_multiplier, Types::Integer.optional
389
+ attribute :fixed_value, Types::Integer.optional
390
+ attribute :dice_string, Types::String.optional
391
+
392
+ def self.from_dynamic!(d)
393
+ d = Types::Hash[d]
394
+ new(
395
+ dice_count: d.fetch("diceCount"),
396
+ dice_value: d.fetch("diceValue"),
397
+ dice_multiplier: d.fetch("diceMultiplier"),
398
+ fixed_value: d.fetch("fixedValue"),
399
+ dice_string: d.fetch("diceString"),
400
+ )
401
+ end
402
+
403
+ def self.from_json!(json)
404
+ from_dynamic!(JSON.parse(json))
405
+ end
406
+
407
+ def to_dynamic
408
+ {
409
+ "diceCount" => dice_count,
410
+ "diceValue" => dice_value,
411
+ "diceMultiplier" => dice_multiplier,
412
+ "fixedValue" => fixed_value,
413
+ "diceString" => dice_string,
414
+ }
415
+ end
416
+
417
+ def to_json(options = nil)
418
+ JSON.generate(to_dynamic, options)
419
+ end
420
+ end
421
+
422
+ class BackgroundDuration < Dry::Struct
423
+ attribute :duration_interval, Types::Integer
424
+ attribute :duration_unit, Types::String
425
+
426
+ def self.from_dynamic!(d)
427
+ d = Types::Hash[d]
428
+ new(
429
+ duration_interval: d.fetch("durationInterval"),
430
+ duration_unit: d.fetch("durationUnit"),
431
+ )
432
+ end
433
+
434
+ def self.from_json!(json)
435
+ from_dynamic!(JSON.parse(json))
436
+ end
437
+
438
+ def to_dynamic
439
+ {
440
+ "durationInterval" => duration_interval,
441
+ "durationUnit" => duration_unit,
442
+ }
443
+ end
444
+
445
+ def to_json(options = nil)
446
+ JSON.generate(to_dynamic, options)
447
+ end
448
+ end
449
+
450
+ class ItemElement < Dry::Struct
451
+ attribute :fixed_value, Types::Integer.optional
452
+ attribute :id, Types::String
453
+ attribute :entity_id, Types::Integer.optional
454
+ attribute :entity_type_id, Types::Integer.optional
455
+ attribute :background_type, Types::String
456
+ attribute :sub_type, Types::String
457
+ attribute :dice, Die.optional
458
+ attribute :restriction, Types::Restriction.optional
459
+ attribute :stat_id, Types::Nil
460
+ attribute :requires_attunement, Types::Bool
461
+ attribute :duration, BackgroundDuration.optional
462
+ attribute :friendly_type_name, Types::String
463
+ attribute :friendly_subtype_name, Types::String
464
+ attribute :is_granted, Types::Bool
465
+ attribute :bonus_types, Types.Array(Types::Any)
466
+ attribute :value, Types::Integer.optional
467
+ attribute :available_to_multiclass, Types::Bool.optional
468
+ attribute :modifier_type_id, Types::Integer
469
+ attribute :modifier_sub_type_id, Types::Integer
470
+ attribute :component_id, Types::Integer
471
+ attribute :component_type_id, Types::Integer
472
+ attribute :die, Die.optional
473
+ attribute :count, Types::Integer.optional
474
+ attribute :duration_unit, Types::Nil.optional
475
+ attribute :use_primary_stat, Types::Bool.optional
476
+ attribute :at_higher_levels, AtHigherLevels.optional
477
+
478
+ def self.from_dynamic!(d)
479
+ d = Types::Hash[d]
480
+ new(
481
+ fixed_value: d.fetch("fixedValue"),
482
+ id: d.fetch("id"),
483
+ entity_id: d.fetch("entityId"),
484
+ entity_type_id: d.fetch("entityTypeId"),
485
+ background_type: d.fetch("type"),
486
+ sub_type: d.fetch("subType"),
487
+ dice: d.fetch("dice") ? Die.from_dynamic!(d.fetch("dice")) : nil,
488
+ restriction: d.fetch("restriction"),
489
+ stat_id: d.fetch("statId"),
490
+ requires_attunement: d.fetch("requiresAttunement"),
491
+ duration: d.fetch("duration") ? BackgroundDuration.from_dynamic!(d.fetch("duration")) : nil,
492
+ friendly_type_name: d.fetch("friendlyTypeName"),
493
+ friendly_subtype_name: d.fetch("friendlySubtypeName"),
494
+ is_granted: d.fetch("isGranted"),
495
+ bonus_types: d.fetch("bonusTypes"),
496
+ value: d.fetch("value"),
497
+ available_to_multiclass: d.fetch("availableToMulticlass"),
498
+ modifier_type_id: d.fetch("modifierTypeId"),
499
+ modifier_sub_type_id: d.fetch("modifierSubTypeId"),
500
+ component_id: d.fetch("componentId"),
501
+ component_type_id: d.fetch("componentTypeId"),
502
+ die: d["die"] ? Die.from_dynamic!(d["die"]) : nil,
503
+ count: d["count"],
504
+ duration_unit: d["durationUnit"],
505
+ use_primary_stat: d["usePrimaryStat"],
506
+ at_higher_levels: d["atHigherLevels"] ? AtHigherLevels.from_dynamic!(d["atHigherLevels"]) : nil,
507
+ )
508
+ end
509
+
510
+ def self.from_json!(json)
511
+ from_dynamic!(JSON.parse(json))
512
+ end
513
+
514
+ def to_dynamic
515
+ {
516
+ "fixedValue" => fixed_value,
517
+ "id" => id,
518
+ "entityId" => entity_id,
519
+ "entityTypeId" => entity_type_id,
520
+ "type" => background_type,
521
+ "subType" => sub_type,
522
+ "dice" => dice&.to_dynamic,
523
+ "restriction" => restriction,
524
+ "statId" => stat_id,
525
+ "requiresAttunement" => requires_attunement,
526
+ "duration" => duration&.to_dynamic,
527
+ "friendlyTypeName" => friendly_type_name,
528
+ "friendlySubtypeName" => friendly_subtype_name,
529
+ "isGranted" => is_granted,
530
+ "bonusTypes" => bonus_types,
531
+ "value" => value,
532
+ "availableToMulticlass" => available_to_multiclass,
533
+ "modifierTypeId" => modifier_type_id,
534
+ "modifierSubTypeId" => modifier_sub_type_id,
535
+ "componentId" => component_id,
536
+ "componentTypeId" => component_type_id,
537
+ "die" => die&.to_dynamic,
538
+ "count" => count,
539
+ "durationUnit" => duration_unit,
540
+ "usePrimaryStat" => use_primary_stat,
541
+ "atHigherLevels" => at_higher_levels&.to_dynamic,
542
+ }
543
+ end
544
+
545
+ def to_json(options = nil)
546
+ JSON.generate(to_dynamic, options)
547
+ end
548
+ end
549
+
550
+ class DefinitionRange < Dry::Struct
551
+ attribute :origin, Types::String
552
+ attribute :range_value, Types::Integer
553
+ attribute :aoe_type, Types::Nil
554
+ attribute :aoe_value, Types::Nil
555
+
556
+ def self.from_dynamic!(d)
557
+ d = Types::Hash[d]
558
+ new(
559
+ origin: d.fetch("origin"),
560
+ range_value: d.fetch("rangeValue"),
561
+ aoe_type: d.fetch("aoeType"),
562
+ aoe_value: d.fetch("aoeValue"),
563
+ )
564
+ end
565
+
566
+ def self.from_json!(json)
567
+ from_dynamic!(JSON.parse(json))
568
+ end
569
+
570
+ def to_dynamic
571
+ {
572
+ "origin" => origin,
573
+ "rangeValue" => range_value,
574
+ "aoeType" => aoe_type,
575
+ "aoeValue" => aoe_value,
576
+ }
577
+ end
578
+
579
+ def to_json(options = nil)
580
+ JSON.generate(to_dynamic, options)
581
+ end
582
+ end
583
+
584
+ class Source < Dry::Struct
585
+ attribute :source_id, Types::Integer
586
+ attribute :page_number, Types::Integer.optional
587
+ attribute :source_type, Types::Integer
588
+
589
+ def self.from_dynamic!(d)
590
+ d = Types::Hash[d]
591
+ new(
592
+ source_id: d.fetch("sourceId"),
593
+ page_number: d.fetch("pageNumber"),
594
+ source_type: d.fetch("sourceType"),
595
+ )
596
+ end
597
+
598
+ def self.from_json!(json)
599
+ from_dynamic!(JSON.parse(json))
600
+ end
601
+
602
+ def to_dynamic
603
+ {
604
+ "sourceId" => source_id,
605
+ "pageNumber" => page_number,
606
+ "sourceType" => source_type,
607
+ }
608
+ end
609
+
610
+ def to_json(options = nil)
611
+ JSON.generate(to_dynamic, options)
612
+ end
613
+ end
614
+
615
+ class ItemDefinition < Dry::Struct
616
+ attribute :id, Types::Integer
617
+ attribute :definition_key, Types::String
618
+ attribute :definition_name, Types::String
619
+ attribute :level, Types::Integer
620
+ attribute :school, Types::String
621
+ attribute :duration, DefinitionDuration
622
+ attribute :activation, Activation
623
+ attribute :range, DefinitionRange
624
+ attribute :as_part_of_weapon_attack, Types::Bool
625
+ attribute :description, Types::String
626
+ attribute :snippet, Types::String
627
+ attribute :concentration, Types::Bool
628
+ attribute :ritual, Types::Bool
629
+ attribute :range_area, Types::Nil
630
+ attribute :damage_effect, Types::Nil
631
+ attribute :components, Types.Array(Types::Integer)
632
+ attribute :components_description, Types::String
633
+ attribute :save_dc_ability_id, Types::Nil
634
+ attribute :healing, Types::Nil
635
+ attribute :healing_dice, Types.Array(Types::Any)
636
+ attribute :temp_hp_dice, Types.Array(Types::Any)
637
+ attribute :attack_type, Types::Nil
638
+ attribute :can_cast_at_higher_level, Types::Bool
639
+ attribute :is_homebrew, Types::Bool
640
+ attribute :version, Types::Nil
641
+ attribute :source_id, Types::Nil
642
+ attribute :source_page_number, Types::Integer
643
+ attribute :requires_saving_throw, Types::Bool
644
+ attribute :requires_attack_roll, Types::Bool
645
+ attribute :at_higher_levels, AtHigherLevels
646
+ attribute :modifiers, Types.Array(ItemElement)
647
+ attribute :conditions, Types.Array(Types::Any)
648
+ attribute :tags, Types.Array(Types::String)
649
+ attribute :casting_time_description, Types::String
650
+ attribute :scale_type, Types::String
651
+ attribute :sources, Types.Array(Source)
652
+ attribute :spell_groups, Types.Array(Types::Any)
653
+
654
+ def self.from_dynamic!(d)
655
+ d = Types::Hash[d]
656
+ new(
657
+ id: d.fetch("id"),
658
+ definition_key: d.fetch("definitionKey"),
659
+ definition_name: d.fetch("name"),
660
+ level: d.fetch("level"),
661
+ school: d.fetch("school"),
662
+ duration: DefinitionDuration.from_dynamic!(d.fetch("duration")),
663
+ activation: Activation.from_dynamic!(d.fetch("activation")),
664
+ range: DefinitionRange.from_dynamic!(d.fetch("range")),
665
+ as_part_of_weapon_attack: d.fetch("asPartOfWeaponAttack"),
666
+ description: d.fetch("description"),
667
+ snippet: d.fetch("snippet"),
668
+ concentration: d.fetch("concentration"),
669
+ ritual: d.fetch("ritual"),
670
+ range_area: d.fetch("rangeArea"),
671
+ damage_effect: d.fetch("damageEffect"),
672
+ components: d.fetch("components"),
673
+ components_description: d.fetch("componentsDescription"),
674
+ save_dc_ability_id: d.fetch("saveDcAbilityId"),
675
+ healing: d.fetch("healing"),
676
+ healing_dice: d.fetch("healingDice"),
677
+ temp_hp_dice: d.fetch("tempHpDice"),
678
+ attack_type: d.fetch("attackType"),
679
+ can_cast_at_higher_level: d.fetch("canCastAtHigherLevel"),
680
+ is_homebrew: d.fetch("isHomebrew"),
681
+ version: d.fetch("version"),
682
+ source_id: d.fetch("sourceId"),
683
+ source_page_number: d.fetch("sourcePageNumber"),
684
+ requires_saving_throw: d.fetch("requiresSavingThrow"),
685
+ requires_attack_roll: d.fetch("requiresAttackRoll"),
686
+ at_higher_levels: AtHigherLevels.from_dynamic!(d.fetch("atHigherLevels")),
687
+ modifiers: d.fetch("modifiers").map { |x| ItemElement.from_dynamic!(x) },
688
+ conditions: d.fetch("conditions"),
689
+ tags: d.fetch("tags"),
690
+ casting_time_description: d.fetch("castingTimeDescription"),
691
+ scale_type: d.fetch("scaleType"),
692
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
693
+ spell_groups: d.fetch("spellGroups"),
694
+ )
695
+ end
696
+
697
+ def self.from_json!(json)
698
+ from_dynamic!(JSON.parse(json))
699
+ end
700
+
701
+ def to_dynamic
702
+ {
703
+ "id" => id,
704
+ "definitionKey" => definition_key,
705
+ "name" => definition_name,
706
+ "level" => level,
707
+ "school" => school,
708
+ "duration" => duration.to_dynamic,
709
+ "activation" => activation.to_dynamic,
710
+ "range" => range.to_dynamic,
711
+ "asPartOfWeaponAttack" => as_part_of_weapon_attack,
712
+ "description" => description,
713
+ "snippet" => snippet,
714
+ "concentration" => concentration,
715
+ "ritual" => ritual,
716
+ "rangeArea" => range_area,
717
+ "damageEffect" => damage_effect,
718
+ "components" => components,
719
+ "componentsDescription" => components_description,
720
+ "saveDcAbilityId" => save_dc_ability_id,
721
+ "healing" => healing,
722
+ "healingDice" => healing_dice,
723
+ "tempHpDice" => temp_hp_dice,
724
+ "attackType" => attack_type,
725
+ "canCastAtHigherLevel" => can_cast_at_higher_level,
726
+ "isHomebrew" => is_homebrew,
727
+ "version" => version,
728
+ "sourceId" => source_id,
729
+ "sourcePageNumber" => source_page_number,
730
+ "requiresSavingThrow" => requires_saving_throw,
731
+ "requiresAttackRoll" => requires_attack_roll,
732
+ "atHigherLevels" => at_higher_levels.to_dynamic,
733
+ "modifiers" => modifiers.map { |x| x.to_dynamic },
734
+ "conditions" => conditions,
735
+ "tags" => tags,
736
+ "castingTimeDescription" => casting_time_description,
737
+ "scaleType" => scale_type,
738
+ "sources" => sources.map { |x| x.to_dynamic },
739
+ "spellGroups" => spell_groups,
740
+ }
741
+ end
742
+
743
+ def to_json(options = nil)
744
+ JSON.generate(to_dynamic, options)
745
+ end
746
+ end
747
+
748
+ class Item < Dry::Struct
749
+ attribute :override_save_dc, Types::Nil
750
+ attribute :limited_use, Types::Nil
751
+ attribute :id, Types::Integer
752
+ attribute :entity_type_id, Types::Integer
753
+ attribute :definition, ItemDefinition
754
+ attribute :definition_id, Types::Integer
755
+ attribute :prepared, Types::Bool
756
+ attribute :counts_as_known_spell, Types::Nil
757
+ attribute :uses_spell_slot, Types::Bool
758
+ attribute :cast_at_level, Types::Nil
759
+ attribute :always_prepared, Types::Bool
760
+ attribute :restriction, Types::Nil
761
+ attribute :spell_casting_ability_id, Types::Nil
762
+ attribute :display_as_attack, Types::Bool
763
+ attribute :additional_description, Types::Nil
764
+ attribute :cast_only_as_ritual, Types::Bool
765
+ attribute :ritual_casting_type, Types::Nil
766
+ attribute :range, DefinitionRange
767
+ attribute :activation, Activation
768
+ attribute :base_level_at_will, Types::Bool
769
+ attribute :at_will_limited_use_level, Types::Nil
770
+ attribute :is_signature_spell, Types::Nil
771
+ attribute :component_id, Types::Integer
772
+ attribute :component_type_id, Types::Integer
773
+ attribute :spell_list_id, Types::Nil
774
+
775
+ def self.from_dynamic!(d)
776
+ d = Types::Hash[d]
777
+ new(
778
+ override_save_dc: d.fetch("overrideSaveDc"),
779
+ limited_use: d.fetch("limitedUse"),
780
+ id: d.fetch("id"),
781
+ entity_type_id: d.fetch("entityTypeId"),
782
+ definition: ItemDefinition.from_dynamic!(d.fetch("definition")),
783
+ definition_id: d.fetch("definitionId"),
784
+ prepared: d.fetch("prepared"),
785
+ counts_as_known_spell: d.fetch("countsAsKnownSpell"),
786
+ uses_spell_slot: d.fetch("usesSpellSlot"),
787
+ cast_at_level: d.fetch("castAtLevel"),
788
+ always_prepared: d.fetch("alwaysPrepared"),
789
+ restriction: d.fetch("restriction"),
790
+ spell_casting_ability_id: d.fetch("spellCastingAbilityId"),
791
+ display_as_attack: d.fetch("displayAsAttack"),
792
+ additional_description: d.fetch("additionalDescription"),
793
+ cast_only_as_ritual: d.fetch("castOnlyAsRitual"),
794
+ ritual_casting_type: d.fetch("ritualCastingType"),
795
+ range: DefinitionRange.from_dynamic!(d.fetch("range")),
796
+ activation: Activation.from_dynamic!(d.fetch("activation")),
797
+ base_level_at_will: d.fetch("baseLevelAtWill"),
798
+ at_will_limited_use_level: d.fetch("atWillLimitedUseLevel"),
799
+ is_signature_spell: d.fetch("isSignatureSpell"),
800
+ component_id: d.fetch("componentId"),
801
+ component_type_id: d.fetch("componentTypeId"),
802
+ spell_list_id: d.fetch("spellListId"),
803
+ )
804
+ end
805
+
806
+ def self.from_json!(json)
807
+ from_dynamic!(JSON.parse(json))
808
+ end
809
+
810
+ def to_dynamic
811
+ {
812
+ "overrideSaveDc" => override_save_dc,
813
+ "limitedUse" => limited_use,
814
+ "id" => id,
815
+ "entityTypeId" => entity_type_id,
816
+ "definition" => definition.to_dynamic,
817
+ "definitionId" => definition_id,
818
+ "prepared" => prepared,
819
+ "countsAsKnownSpell" => counts_as_known_spell,
820
+ "usesSpellSlot" => uses_spell_slot,
821
+ "castAtLevel" => cast_at_level,
822
+ "alwaysPrepared" => always_prepared,
823
+ "restriction" => restriction,
824
+ "spellCastingAbilityId" => spell_casting_ability_id,
825
+ "displayAsAttack" => display_as_attack,
826
+ "additionalDescription" => additional_description,
827
+ "castOnlyAsRitual" => cast_only_as_ritual,
828
+ "ritualCastingType" => ritual_casting_type,
829
+ "range" => range.to_dynamic,
830
+ "activation" => activation.to_dynamic,
831
+ "baseLevelAtWill" => base_level_at_will,
832
+ "atWillLimitedUseLevel" => at_will_limited_use_level,
833
+ "isSignatureSpell" => is_signature_spell,
834
+ "componentId" => component_id,
835
+ "componentTypeId" => component_type_id,
836
+ "spellListId" => spell_list_id,
837
+ }
838
+ end
839
+
840
+ def to_json(options = nil)
841
+ JSON.generate(to_dynamic, options)
842
+ end
843
+ end
844
+
845
+ class Actions < Dry::Struct
846
+ attribute :race, Types.Array(Types::Any)
847
+ attribute :actions_class, Types.Array(ActionsClass)
848
+ attribute :background, Types::Nil
849
+ attribute :item, Types.Array(Item).optional
850
+ attribute :feat, Types.Array(Types::Any)
851
+
852
+ def self.from_dynamic!(d)
853
+ d = Types::Hash[d]
854
+ new(
855
+ race: d.fetch("race"),
856
+ actions_class: d.fetch("class").map { |x| ActionsClass.from_dynamic!(x) },
857
+ background: d.fetch("background"),
858
+ item: d.fetch("item")&.map { |x| Item.from_dynamic!(x) },
859
+ feat: d.fetch("feat"),
860
+ )
861
+ end
862
+
863
+ def self.from_json!(json)
864
+ from_dynamic!(JSON.parse(json))
865
+ end
866
+
867
+ def to_dynamic
868
+ {
869
+ "race" => race,
870
+ "class" => actions_class.map { |x| x.to_dynamic },
871
+ "background" => background,
872
+ "item" => item&.map { |x| x.to_dynamic },
873
+ "feat" => feat,
874
+ }
875
+ end
876
+
877
+ def to_json(options = nil)
878
+ JSON.generate(to_dynamic, options)
879
+ end
880
+ end
881
+
882
+ class CustomBackground < Dry::Struct
883
+ attribute :id, Types::Integer
884
+ attribute :entity_type_id, Types::Integer
885
+ attribute :custom_background_name, Types::Nil
886
+ attribute :description, Types::Nil
887
+ attribute :features_background, Types::Nil
888
+ attribute :characteristics_background, Types::Nil
889
+ attribute :features_background_definition_id, Types::Nil
890
+ attribute :characteristics_background_definition_id, Types::Nil
891
+ attribute :background_type, Types::Nil
892
+
893
+ def self.from_dynamic!(d)
894
+ d = Types::Hash[d]
895
+ new(
896
+ id: d.fetch("id"),
897
+ entity_type_id: d.fetch("entityTypeId"),
898
+ custom_background_name: d.fetch("name"),
899
+ description: d.fetch("description"),
900
+ features_background: d.fetch("featuresBackground"),
901
+ characteristics_background: d.fetch("characteristicsBackground"),
902
+ features_background_definition_id: d.fetch("featuresBackgroundDefinitionId"),
903
+ characteristics_background_definition_id: d.fetch("characteristicsBackgroundDefinitionId"),
904
+ background_type: d.fetch("backgroundType"),
905
+ )
906
+ end
907
+
908
+ def self.from_json!(json)
909
+ from_dynamic!(JSON.parse(json))
910
+ end
911
+
912
+ def to_dynamic
913
+ {
914
+ "id" => id,
915
+ "entityTypeId" => entity_type_id,
916
+ "name" => custom_background_name,
917
+ "description" => description,
918
+ "featuresBackground" => features_background,
919
+ "characteristicsBackground" => characteristics_background,
920
+ "featuresBackgroundDefinitionId" => features_background_definition_id,
921
+ "characteristicsBackgroundDefinitionId" => characteristics_background_definition_id,
922
+ "backgroundType" => background_type,
923
+ }
924
+ end
925
+
926
+ def to_json(options = nil)
927
+ JSON.generate(to_dynamic, options)
928
+ end
929
+ end
930
+
931
+ class Bond < Dry::Struct
932
+ attribute :id, Types::Integer
933
+ attribute :description, Types::String
934
+ attribute :dice_roll, Types::Integer
935
+
936
+ def self.from_dynamic!(d)
937
+ d = Types::Hash[d]
938
+ new(
939
+ id: d.fetch("id"),
940
+ description: d.fetch("description"),
941
+ dice_roll: d.fetch("diceRoll"),
942
+ )
943
+ end
944
+
945
+ def self.from_json!(json)
946
+ from_dynamic!(JSON.parse(json))
947
+ end
948
+
949
+ def to_dynamic
950
+ {
951
+ "id" => id,
952
+ "description" => description,
953
+ "diceRoll" => dice_roll,
954
+ }
955
+ end
956
+
957
+ def to_json(options = nil)
958
+ JSON.generate(to_dynamic, options)
959
+ end
960
+ end
961
+
962
+ class BackgroundDefinition < Dry::Struct
963
+ attribute :id, Types::Integer
964
+ attribute :entity_type_id, Types::Integer
965
+ attribute :definition_key, Types::String
966
+ attribute :definition_name, Types::String
967
+ attribute :description, Types::String
968
+ attribute :snippet, Types::String
969
+ attribute :short_description, Types::String
970
+ attribute :skill_proficiencies_description, Types::String
971
+ attribute :tool_proficiencies_description, Types::String
972
+ attribute :languages_description, Types::String
973
+ attribute :equipment_description, Types::String
974
+ attribute :feature_name, Types::String
975
+ attribute :feature_description, Types::String
976
+ attribute :avatar_url, Types::Nil
977
+ attribute :large_avatar_url, Types::Nil
978
+ attribute :suggested_characteristics_description, Types::String
979
+ attribute :suggested_proficiencies, Types::Nil
980
+ attribute :suggested_languages, Types::Nil
981
+ attribute :organization, Types::Nil
982
+ attribute :contracts_description, Types::String
983
+ attribute :spells_pre_description, Types::String
984
+ attribute :spells_post_description, Types::String
985
+ attribute :personality_traits, Types.Array(Bond)
986
+ attribute :ideals, Types.Array(Bond)
987
+ attribute :bonds, Types.Array(Bond)
988
+ attribute :flaws, Types.Array(Bond)
989
+ attribute :is_homebrew, Types::Bool
990
+ attribute :sources, Types.Array(Source)
991
+ attribute :spell_list_ids, Types.Array(Types::Any)
992
+ attribute :feat_list, Types::Nil
993
+
994
+ def self.from_dynamic!(d)
995
+ d = Types::Hash[d]
996
+ new(
997
+ id: d.fetch("id"),
998
+ entity_type_id: d.fetch("entityTypeId"),
999
+ definition_key: d.fetch("definitionKey"),
1000
+ definition_name: d.fetch("name"),
1001
+ description: d.fetch("description"),
1002
+ snippet: d.fetch("snippet"),
1003
+ short_description: d.fetch("shortDescription"),
1004
+ skill_proficiencies_description: d.fetch("skillProficienciesDescription"),
1005
+ tool_proficiencies_description: d.fetch("toolProficienciesDescription"),
1006
+ languages_description: d.fetch("languagesDescription"),
1007
+ equipment_description: d.fetch("equipmentDescription"),
1008
+ feature_name: d.fetch("featureName"),
1009
+ feature_description: d.fetch("featureDescription"),
1010
+ avatar_url: d.fetch("avatarUrl"),
1011
+ large_avatar_url: d.fetch("largeAvatarUrl"),
1012
+ suggested_characteristics_description: d.fetch("suggestedCharacteristicsDescription"),
1013
+ suggested_proficiencies: d.fetch("suggestedProficiencies"),
1014
+ suggested_languages: d.fetch("suggestedLanguages"),
1015
+ organization: d.fetch("organization"),
1016
+ contracts_description: d.fetch("contractsDescription"),
1017
+ spells_pre_description: d.fetch("spellsPreDescription"),
1018
+ spells_post_description: d.fetch("spellsPostDescription"),
1019
+ personality_traits: d.fetch("personalityTraits").map { |x| Bond.from_dynamic!(x) },
1020
+ ideals: d.fetch("ideals").map { |x| Bond.from_dynamic!(x) },
1021
+ bonds: d.fetch("bonds").map { |x| Bond.from_dynamic!(x) },
1022
+ flaws: d.fetch("flaws").map { |x| Bond.from_dynamic!(x) },
1023
+ is_homebrew: d.fetch("isHomebrew"),
1024
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
1025
+ spell_list_ids: d.fetch("spellListIds"),
1026
+ feat_list: d.fetch("featList"),
1027
+ )
1028
+ end
1029
+
1030
+ def self.from_json!(json)
1031
+ from_dynamic!(JSON.parse(json))
1032
+ end
1033
+
1034
+ def to_dynamic
1035
+ {
1036
+ "id" => id,
1037
+ "entityTypeId" => entity_type_id,
1038
+ "definitionKey" => definition_key,
1039
+ "name" => definition_name,
1040
+ "description" => description,
1041
+ "snippet" => snippet,
1042
+ "shortDescription" => short_description,
1043
+ "skillProficienciesDescription" => skill_proficiencies_description,
1044
+ "toolProficienciesDescription" => tool_proficiencies_description,
1045
+ "languagesDescription" => languages_description,
1046
+ "equipmentDescription" => equipment_description,
1047
+ "featureName" => feature_name,
1048
+ "featureDescription" => feature_description,
1049
+ "avatarUrl" => avatar_url,
1050
+ "largeAvatarUrl" => large_avatar_url,
1051
+ "suggestedCharacteristicsDescription" => suggested_characteristics_description,
1052
+ "suggestedProficiencies" => suggested_proficiencies,
1053
+ "suggestedLanguages" => suggested_languages,
1054
+ "organization" => organization,
1055
+ "contractsDescription" => contracts_description,
1056
+ "spellsPreDescription" => spells_pre_description,
1057
+ "spellsPostDescription" => spells_post_description,
1058
+ "personalityTraits" => personality_traits.map { |x| x.to_dynamic },
1059
+ "ideals" => ideals.map { |x| x.to_dynamic },
1060
+ "bonds" => bonds.map { |x| x.to_dynamic },
1061
+ "flaws" => flaws.map { |x| x.to_dynamic },
1062
+ "isHomebrew" => is_homebrew,
1063
+ "sources" => sources.map { |x| x.to_dynamic },
1064
+ "spellListIds" => spell_list_ids,
1065
+ "featList" => feat_list,
1066
+ }
1067
+ end
1068
+
1069
+ def to_json(options = nil)
1070
+ JSON.generate(to_dynamic, options)
1071
+ end
1072
+ end
1073
+
1074
+ class CharacterBackground < Dry::Struct
1075
+ attribute :has_custom_background, Types::Bool
1076
+ attribute :definition, BackgroundDefinition
1077
+ attribute :definition_id, Types::Nil
1078
+ attribute :custom_background, CustomBackground
1079
+
1080
+ def self.from_dynamic!(d)
1081
+ d = Types::Hash[d]
1082
+ new(
1083
+ has_custom_background: d.fetch("hasCustomBackground"),
1084
+ definition: BackgroundDefinition.from_dynamic!(d.fetch("definition")),
1085
+ definition_id: d.fetch("definitionId"),
1086
+ custom_background: CustomBackground.from_dynamic!(d.fetch("customBackground")),
1087
+ )
1088
+ end
1089
+
1090
+ def self.from_json!(json)
1091
+ from_dynamic!(JSON.parse(json))
1092
+ end
1093
+
1094
+ def to_dynamic
1095
+ {
1096
+ "hasCustomBackground" => has_custom_background,
1097
+ "definition" => definition.to_dynamic,
1098
+ "definitionId" => definition_id,
1099
+ "customBackground" => custom_background.to_dynamic,
1100
+ }
1101
+ end
1102
+
1103
+ def to_json(options = nil)
1104
+ JSON.generate(to_dynamic, options)
1105
+ end
1106
+ end
1107
+
1108
+ class Stat < Dry::Struct
1109
+ attribute :id, Types::Integer
1110
+ attribute :stat_name, Types::Nil
1111
+ attribute :value, Types::Integer.optional
1112
+
1113
+ def self.from_dynamic!(d)
1114
+ d = Types::Hash[d]
1115
+ new(
1116
+ id: d.fetch("id"),
1117
+ stat_name: d.fetch("name"),
1118
+ value: d.fetch("value"),
1119
+ )
1120
+ end
1121
+
1122
+ def self.from_json!(json)
1123
+ from_dynamic!(JSON.parse(json))
1124
+ end
1125
+
1126
+ def to_dynamic
1127
+ {
1128
+ "id" => id,
1129
+ "name" => stat_name,
1130
+ "value" => value,
1131
+ }
1132
+ end
1133
+
1134
+ def to_json(options = nil)
1135
+ JSON.generate(to_dynamic, options)
1136
+ end
1137
+ end
1138
+
1139
+ class CharacterElement < Dry::Struct
1140
+ attribute :user_id, Types::Integer
1141
+ attribute :username, Types::String
1142
+ attribute :character_id, Types::Integer
1143
+ attribute :character_name, Types::String
1144
+ attribute :character_url, Types::String
1145
+ attribute :avatar_url, Types::String.optional
1146
+ attribute :privacy_type, Types::Integer
1147
+ attribute :campaign_id, Types::Nil
1148
+ attribute :is_assigned, Types::Bool
1149
+
1150
+ def self.from_dynamic!(d)
1151
+ d = Types::Hash[d]
1152
+ new(
1153
+ user_id: d.fetch("userId"),
1154
+ username: d.fetch("username"),
1155
+ character_id: d.fetch("characterId"),
1156
+ character_name: d.fetch("characterName"),
1157
+ character_url: d.fetch("characterUrl"),
1158
+ avatar_url: d.fetch("avatarUrl"),
1159
+ privacy_type: d.fetch("privacyType"),
1160
+ campaign_id: d.fetch("campaignId"),
1161
+ is_assigned: d.fetch("isAssigned"),
1162
+ )
1163
+ end
1164
+
1165
+ def self.from_json!(json)
1166
+ from_dynamic!(JSON.parse(json))
1167
+ end
1168
+
1169
+ def to_dynamic
1170
+ {
1171
+ "userId" => user_id,
1172
+ "username" => username,
1173
+ "characterId" => character_id,
1174
+ "characterName" => character_name,
1175
+ "characterUrl" => character_url,
1176
+ "avatarUrl" => avatar_url,
1177
+ "privacyType" => privacy_type,
1178
+ "campaignId" => campaign_id,
1179
+ "isAssigned" => is_assigned,
1180
+ }
1181
+ end
1182
+
1183
+ def to_json(options = nil)
1184
+ JSON.generate(to_dynamic, options)
1185
+ end
1186
+ end
1187
+
1188
+ class Campaign < Dry::Struct
1189
+ attribute :id, Types::Integer
1190
+ attribute :campaign_name, Types::String
1191
+ attribute :description, Types::String
1192
+ attribute :link, Types::String
1193
+ attribute :public_notes, Types::String
1194
+ attribute :dm_user_id, Types::Integer
1195
+ attribute :dm_username, Types::String
1196
+ attribute :characters, Types.Array(CharacterElement)
1197
+
1198
+ def self.from_dynamic!(d)
1199
+ d = Types::Hash[d]
1200
+ new(
1201
+ id: d.fetch("id"),
1202
+ campaign_name: d.fetch("name"),
1203
+ description: d.fetch("description"),
1204
+ link: d.fetch("link"),
1205
+ public_notes: d.fetch("publicNotes"),
1206
+ dm_user_id: d.fetch("dmUserId"),
1207
+ dm_username: d.fetch("dmUsername"),
1208
+ characters: d.fetch("characters").map { |x| CharacterElement.from_dynamic!(x) },
1209
+ )
1210
+ end
1211
+
1212
+ def self.from_json!(json)
1213
+ from_dynamic!(JSON.parse(json))
1214
+ end
1215
+
1216
+ def to_dynamic
1217
+ {
1218
+ "id" => id,
1219
+ "name" => campaign_name,
1220
+ "description" => description,
1221
+ "link" => link,
1222
+ "publicNotes" => public_notes,
1223
+ "dmUserId" => dm_user_id,
1224
+ "dmUsername" => dm_username,
1225
+ "characters" => characters.map { |x| x.to_dynamic },
1226
+ }
1227
+ end
1228
+
1229
+ def to_json(options = nil)
1230
+ JSON.generate(to_dynamic, options)
1231
+ end
1232
+ end
1233
+
1234
+ class Definition1 < Dry::Struct
1235
+ attribute :id, Types::Integer
1236
+ attribute :entity_type_id, Types::Integer
1237
+ attribute :definition_name, Types::String
1238
+ attribute :description, Types::String
1239
+ attribute :snippet, Types::String
1240
+ attribute :activation, Types::Nil
1241
+ attribute :source_id, Types::Integer
1242
+ attribute :source_page_number, Types::Nil
1243
+ attribute :creature_rules, Types.Array(Types::Any)
1244
+ attribute :spell_list_ids, Types.Array(Types::Any)
1245
+
1246
+ def self.from_dynamic!(d)
1247
+ d = Types::Hash[d]
1248
+ new(
1249
+ id: d.fetch("id"),
1250
+ entity_type_id: d.fetch("entityTypeId"),
1251
+ definition_name: d.fetch("name"),
1252
+ description: d.fetch("description"),
1253
+ snippet: d.fetch("snippet"),
1254
+ activation: d.fetch("activation"),
1255
+ source_id: d.fetch("sourceId"),
1256
+ source_page_number: d.fetch("sourcePageNumber"),
1257
+ creature_rules: d.fetch("creatureRules"),
1258
+ spell_list_ids: d.fetch("spellListIds"),
1259
+ )
1260
+ end
1261
+
1262
+ def self.from_json!(json)
1263
+ from_dynamic!(JSON.parse(json))
1264
+ end
1265
+
1266
+ def to_dynamic
1267
+ {
1268
+ "id" => id,
1269
+ "entityTypeId" => entity_type_id,
1270
+ "name" => definition_name,
1271
+ "description" => description,
1272
+ "snippet" => snippet,
1273
+ "activation" => activation,
1274
+ "sourceId" => source_id,
1275
+ "sourcePageNumber" => source_page_number,
1276
+ "creatureRules" => creature_rules,
1277
+ "spellListIds" => spell_list_ids,
1278
+ }
1279
+ end
1280
+
1281
+ def to_json(options = nil)
1282
+ JSON.generate(to_dynamic, options)
1283
+ end
1284
+ end
1285
+
1286
+ class OptionsClass < Dry::Struct
1287
+ attribute :component_id, Types::Integer
1288
+ attribute :component_type_id, Types::Integer
1289
+ attribute :definition, Definition1
1290
+
1291
+ def self.from_dynamic!(d)
1292
+ d = Types::Hash[d]
1293
+ new(
1294
+ component_id: d.fetch("componentId"),
1295
+ component_type_id: d.fetch("componentTypeId"),
1296
+ definition: Definition1.from_dynamic!(d.fetch("definition")),
1297
+ )
1298
+ end
1299
+
1300
+ def self.from_json!(json)
1301
+ from_dynamic!(JSON.parse(json))
1302
+ end
1303
+
1304
+ def to_dynamic
1305
+ {
1306
+ "componentId" => component_id,
1307
+ "componentTypeId" => component_type_id,
1308
+ "definition" => definition.to_dynamic,
1309
+ }
1310
+ end
1311
+
1312
+ def to_json(options = nil)
1313
+ JSON.generate(to_dynamic, options)
1314
+ end
1315
+ end
1316
+
1317
+ class Options < Dry::Struct
1318
+ attribute :race, Types.Array(Types::Any)
1319
+ attribute :options_class, Types.Array(OptionsClass)
1320
+ attribute :background, Types::Nil
1321
+ attribute :item, Types::Nil
1322
+ attribute :feat, Types.Array(Types::Any)
1323
+
1324
+ def self.from_dynamic!(d)
1325
+ d = Types::Hash[d]
1326
+ new(
1327
+ race: d.fetch("race"),
1328
+ options_class: d.fetch("class").map { |x| OptionsClass.from_dynamic!(x) },
1329
+ background: d.fetch("background"),
1330
+ item: d.fetch("item"),
1331
+ feat: d.fetch("feat"),
1332
+ )
1333
+ end
1334
+
1335
+ def self.from_json!(json)
1336
+ from_dynamic!(JSON.parse(json))
1337
+ end
1338
+
1339
+ def to_dynamic
1340
+ {
1341
+ "race" => race,
1342
+ "class" => options_class.map { |x| x.to_dynamic },
1343
+ "background" => background,
1344
+ "item" => item,
1345
+ "feat" => feat,
1346
+ }
1347
+ end
1348
+
1349
+ def to_json(options = nil)
1350
+ JSON.generate(to_dynamic, options)
1351
+ end
1352
+ end
1353
+
1354
+ class ChoicesBackground < Dry::Struct
1355
+ attribute :component_id, Types::Integer
1356
+ attribute :component_type_id, Types::Integer
1357
+ attribute :id, Types::String
1358
+ attribute :parent_choice_id, Types::String.optional
1359
+ attribute :background_type, Types::Integer
1360
+ attribute :sub_type, Types::Integer.optional
1361
+ attribute :option_value, Types::Integer
1362
+ attribute :label, Types::String.optional
1363
+ attribute :is_optional, Types::Bool
1364
+ attribute :is_infinite, Types::Bool
1365
+ attribute :default_subtypes, Types.Array(Types::String)
1366
+ attribute :display_order, Types::Nil
1367
+ attribute :background_options, Types.Array(Types::Any)
1368
+ attribute :option_ids, Types.Array(Types::Integer)
1369
+
1370
+ def self.from_dynamic!(d)
1371
+ d = Types::Hash[d]
1372
+ new(
1373
+ component_id: d.fetch("componentId"),
1374
+ component_type_id: d.fetch("componentTypeId"),
1375
+ id: d.fetch("id"),
1376
+ parent_choice_id: d.fetch("parentChoiceId"),
1377
+ background_type: d.fetch("type"),
1378
+ sub_type: d.fetch("subType"),
1379
+ option_value: d.fetch("optionValue"),
1380
+ label: d.fetch("label"),
1381
+ is_optional: d.fetch("isOptional"),
1382
+ is_infinite: d.fetch("isInfinite"),
1383
+ default_subtypes: d.fetch("defaultSubtypes"),
1384
+ display_order: d.fetch("displayOrder"),
1385
+ background_options: d.fetch("options"),
1386
+ option_ids: d.fetch("optionIds"),
1387
+ )
1388
+ end
1389
+
1390
+ def self.from_json!(json)
1391
+ from_dynamic!(JSON.parse(json))
1392
+ end
1393
+
1394
+ def to_dynamic
1395
+ {
1396
+ "componentId" => component_id,
1397
+ "componentTypeId" => component_type_id,
1398
+ "id" => id,
1399
+ "parentChoiceId" => parent_choice_id,
1400
+ "type" => background_type,
1401
+ "subType" => sub_type,
1402
+ "optionValue" => option_value,
1403
+ "label" => label,
1404
+ "isOptional" => is_optional,
1405
+ "isInfinite" => is_infinite,
1406
+ "defaultSubtypes" => default_subtypes,
1407
+ "displayOrder" => display_order,
1408
+ "options" => background_options,
1409
+ "optionIds" => option_ids,
1410
+ }
1411
+ end
1412
+
1413
+ def to_json(options = nil)
1414
+ JSON.generate(to_dynamic, options)
1415
+ end
1416
+ end
1417
+
1418
+ class Option < Dry::Struct
1419
+ attribute :id, Types::Integer
1420
+ attribute :label, Types::String
1421
+ attribute :description, Types::String.optional
1422
+
1423
+ def self.from_dynamic!(d)
1424
+ d = Types::Hash[d]
1425
+ new(
1426
+ id: d.fetch("id"),
1427
+ label: d.fetch("label"),
1428
+ description: d.fetch("description"),
1429
+ )
1430
+ end
1431
+
1432
+ def self.from_json!(json)
1433
+ from_dynamic!(JSON.parse(json))
1434
+ end
1435
+
1436
+ def to_dynamic
1437
+ {
1438
+ "id" => id,
1439
+ "label" => label,
1440
+ "description" => description,
1441
+ }
1442
+ end
1443
+
1444
+ def to_json(options = nil)
1445
+ JSON.generate(to_dynamic, options)
1446
+ end
1447
+ end
1448
+
1449
+ class ChoiceDefinition < Dry::Struct
1450
+ attribute :id, Types::String
1451
+ attribute :choice_definition_options, Types.Array(Option)
1452
+
1453
+ def self.from_dynamic!(d)
1454
+ d = Types::Hash[d]
1455
+ new(
1456
+ id: d.fetch("id"),
1457
+ choice_definition_options: d.fetch("options").map { |x| Option.from_dynamic!(x) },
1458
+ )
1459
+ end
1460
+
1461
+ def self.from_json!(json)
1462
+ from_dynamic!(JSON.parse(json))
1463
+ end
1464
+
1465
+ def to_dynamic
1466
+ {
1467
+ "id" => id,
1468
+ "options" => choice_definition_options.map { |x| x.to_dynamic },
1469
+ }
1470
+ end
1471
+
1472
+ def to_json(options = nil)
1473
+ JSON.generate(to_dynamic, options)
1474
+ end
1475
+ end
1476
+
1477
+ class DefinitionKeyNameMap < Dry::Struct
1478
+
1479
+ def self.from_dynamic!(d)
1480
+ d = Types::Hash[d]
1481
+ new(
1482
+ )
1483
+ end
1484
+
1485
+ def self.from_json!(json)
1486
+ from_dynamic!(JSON.parse(json))
1487
+ end
1488
+
1489
+ def to_dynamic
1490
+ {
1491
+ }
1492
+ end
1493
+
1494
+ def to_json(options = nil)
1495
+ JSON.generate(to_dynamic, options)
1496
+ end
1497
+ end
1498
+
1499
+ class Choices < Dry::Struct
1500
+ attribute :race, Types.Array(ChoicesBackground)
1501
+ attribute :choices_class, Types.Array(ChoicesBackground)
1502
+ attribute :background, Types.Array(ChoicesBackground)
1503
+ attribute :item, Types::Nil
1504
+ attribute :feat, Types.Array(ChoicesBackground)
1505
+ attribute :choice_definitions, Types.Array(ChoiceDefinition)
1506
+ attribute :definition_key_name_map, DefinitionKeyNameMap
1507
+
1508
+ def self.from_dynamic!(d)
1509
+ d = Types::Hash[d]
1510
+ new(
1511
+ race: d.fetch("race").map { |x| ChoicesBackground.from_dynamic!(x) },
1512
+ choices_class: d.fetch("class").map { |x| ChoicesBackground.from_dynamic!(x) },
1513
+ background: d.fetch("background").map { |x| ChoicesBackground.from_dynamic!(x) },
1514
+ item: d.fetch("item"),
1515
+ feat: d.fetch("feat").map { |x| ChoicesBackground.from_dynamic!(x) },
1516
+ choice_definitions: d.fetch("choiceDefinitions").map { |x| ChoiceDefinition.from_dynamic!(x) },
1517
+ definition_key_name_map: DefinitionKeyNameMap.from_dynamic!(d.fetch("definitionKeyNameMap")),
1518
+ )
1519
+ end
1520
+
1521
+ def self.from_json!(json)
1522
+ from_dynamic!(JSON.parse(json))
1523
+ end
1524
+
1525
+ def to_dynamic
1526
+ {
1527
+ "race" => race.map { |x| x.to_dynamic },
1528
+ "class" => choices_class.map { |x| x.to_dynamic },
1529
+ "background" => background.map { |x| x.to_dynamic },
1530
+ "item" => item,
1531
+ "feat" => feat.map { |x| x.to_dynamic },
1532
+ "choiceDefinitions" => choice_definitions.map { |x| x.to_dynamic },
1533
+ "definitionKeyNameMap" => definition_key_name_map.to_dynamic,
1534
+ }
1535
+ end
1536
+
1537
+ def to_json(options = nil)
1538
+ JSON.generate(to_dynamic, options)
1539
+ end
1540
+ end
1541
+
1542
+ class ClassSpell < Dry::Struct
1543
+ attribute :entity_type_id, Types::Integer
1544
+ attribute :character_class_id, Types::Integer
1545
+ attribute :spells, Types.Array(Types::Any)
1546
+
1547
+ def self.from_dynamic!(d)
1548
+ d = Types::Hash[d]
1549
+ new(
1550
+ entity_type_id: d.fetch("entityTypeId"),
1551
+ character_class_id: d.fetch("characterClassId"),
1552
+ spells: d.fetch("spells"),
1553
+ )
1554
+ end
1555
+
1556
+ def self.from_json!(json)
1557
+ from_dynamic!(JSON.parse(json))
1558
+ end
1559
+
1560
+ def to_dynamic
1561
+ {
1562
+ "entityTypeId" => entity_type_id,
1563
+ "characterClassId" => character_class_id,
1564
+ "spells" => spells,
1565
+ }
1566
+ end
1567
+
1568
+ def to_json(options = nil)
1569
+ JSON.generate(to_dynamic, options)
1570
+ end
1571
+ end
1572
+
1573
+ module EntityType
1574
+ ClassFeature = "class-feature"
1575
+ end
1576
+
1577
+ class LevelScale < Dry::Struct
1578
+ attribute :id, Types::Integer
1579
+ attribute :level, Types::Integer
1580
+ attribute :description, Types::String
1581
+ attribute :dice, Die.optional
1582
+ attribute :fixed_value, Types::Integer
1583
+
1584
+ def self.from_dynamic!(d)
1585
+ d = Types::Hash[d]
1586
+ new(
1587
+ id: d.fetch("id"),
1588
+ level: d.fetch("level"),
1589
+ description: d.fetch("description"),
1590
+ dice: d.fetch("dice") ? Die.from_dynamic!(d.fetch("dice")) : nil,
1591
+ fixed_value: d.fetch("fixedValue"),
1592
+ )
1593
+ end
1594
+
1595
+ def self.from_json!(json)
1596
+ from_dynamic!(JSON.parse(json))
1597
+ end
1598
+
1599
+ def to_dynamic
1600
+ {
1601
+ "id" => id,
1602
+ "level" => level,
1603
+ "description" => description,
1604
+ "dice" => dice&.to_dynamic,
1605
+ "fixedValue" => fixed_value,
1606
+ }
1607
+ end
1608
+
1609
+ def to_json(options = nil)
1610
+ JSON.generate(to_dynamic, options)
1611
+ end
1612
+ end
1613
+
1614
+ class LimitedUseElement < Dry::Struct
1615
+ attribute :level, Types::Nil
1616
+ attribute :uses, Types::Integer
1617
+
1618
+ def self.from_dynamic!(d)
1619
+ d = Types::Hash[d]
1620
+ new(
1621
+ level: d.fetch("level"),
1622
+ uses: d.fetch("uses"),
1623
+ )
1624
+ end
1625
+
1626
+ def self.from_json!(json)
1627
+ from_dynamic!(JSON.parse(json))
1628
+ end
1629
+
1630
+ def to_dynamic
1631
+ {
1632
+ "level" => level,
1633
+ "uses" => uses,
1634
+ }
1635
+ end
1636
+
1637
+ def to_json(options = nil)
1638
+ JSON.generate(to_dynamic, options)
1639
+ end
1640
+ end
1641
+
1642
+ class ClassFeatureDefinition < Dry::Struct
1643
+ attribute :id, Types::Integer
1644
+ attribute :definition_key, Types::String
1645
+ attribute :entity_type_id, Types::Integer
1646
+ attribute :display_order, Types::Integer
1647
+ attribute :definition_name, Types::String
1648
+ attribute :description, Types::String
1649
+ attribute :snippet, Types::String.optional
1650
+ attribute :activation, Types::Nil
1651
+ attribute :multi_class_description, Types::String
1652
+ attribute :required_level, Types::Integer
1653
+ attribute :is_sub_class_feature, Types::Bool
1654
+ attribute :limited_use, Types.Array(LimitedUseElement)
1655
+ attribute :hide_in_builder, Types::Bool
1656
+ attribute :hide_in_sheet, Types::Bool
1657
+ attribute :source_id, Types::Integer
1658
+ attribute :source_page_number, Types::Integer.optional
1659
+ attribute :creature_rules, Types.Array(Types::Any)
1660
+ attribute :level_scales, Types.Array(LevelScale)
1661
+ attribute :infusion_rules, Types.Array(Types::Any)
1662
+ attribute :spell_list_ids, Types.Array(Types::Any)
1663
+ attribute :class_id, Types::Integer
1664
+ attribute :feature_type, Types::Integer
1665
+ attribute :sources, Types.Array(Source)
1666
+ attribute :affected_feature_definition_keys, Types.Array(Types::Any)
1667
+ attribute :entity_type, Types::EntityType
1668
+ attribute :entity_id, Types::String
1669
+
1670
+ def self.from_dynamic!(d)
1671
+ d = Types::Hash[d]
1672
+ new(
1673
+ id: d.fetch("id"),
1674
+ definition_key: d.fetch("definitionKey"),
1675
+ entity_type_id: d.fetch("entityTypeId"),
1676
+ display_order: d.fetch("displayOrder"),
1677
+ definition_name: d.fetch("name"),
1678
+ description: d.fetch("description"),
1679
+ snippet: d.fetch("snippet"),
1680
+ activation: d.fetch("activation"),
1681
+ multi_class_description: d.fetch("multiClassDescription"),
1682
+ required_level: d.fetch("requiredLevel"),
1683
+ is_sub_class_feature: d.fetch("isSubClassFeature"),
1684
+ limited_use: d.fetch("limitedUse").map { |x| LimitedUseElement.from_dynamic!(x) },
1685
+ hide_in_builder: d.fetch("hideInBuilder"),
1686
+ hide_in_sheet: d.fetch("hideInSheet"),
1687
+ source_id: d.fetch("sourceId"),
1688
+ source_page_number: d.fetch("sourcePageNumber"),
1689
+ creature_rules: d.fetch("creatureRules"),
1690
+ level_scales: d.fetch("levelScales").map { |x| LevelScale.from_dynamic!(x) },
1691
+ infusion_rules: d.fetch("infusionRules"),
1692
+ spell_list_ids: d.fetch("spellListIds"),
1693
+ class_id: d.fetch("classId"),
1694
+ feature_type: d.fetch("featureType"),
1695
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
1696
+ affected_feature_definition_keys: d.fetch("affectedFeatureDefinitionKeys"),
1697
+ entity_type: d.fetch("entityType"),
1698
+ entity_id: d.fetch("entityID"),
1699
+ )
1700
+ end
1701
+
1702
+ def self.from_json!(json)
1703
+ from_dynamic!(JSON.parse(json))
1704
+ end
1705
+
1706
+ def to_dynamic
1707
+ {
1708
+ "id" => id,
1709
+ "definitionKey" => definition_key,
1710
+ "entityTypeId" => entity_type_id,
1711
+ "displayOrder" => display_order,
1712
+ "name" => definition_name,
1713
+ "description" => description,
1714
+ "snippet" => snippet,
1715
+ "activation" => activation,
1716
+ "multiClassDescription" => multi_class_description,
1717
+ "requiredLevel" => required_level,
1718
+ "isSubClassFeature" => is_sub_class_feature,
1719
+ "limitedUse" => limited_use.map { |x| x.to_dynamic },
1720
+ "hideInBuilder" => hide_in_builder,
1721
+ "hideInSheet" => hide_in_sheet,
1722
+ "sourceId" => source_id,
1723
+ "sourcePageNumber" => source_page_number,
1724
+ "creatureRules" => creature_rules,
1725
+ "levelScales" => level_scales.map { |x| x.to_dynamic },
1726
+ "infusionRules" => infusion_rules,
1727
+ "spellListIds" => spell_list_ids,
1728
+ "classId" => class_id,
1729
+ "featureType" => feature_type,
1730
+ "sources" => sources.map { |x| x.to_dynamic },
1731
+ "affectedFeatureDefinitionKeys" => affected_feature_definition_keys,
1732
+ "entityType" => entity_type,
1733
+ "entityID" => entity_id,
1734
+ }
1735
+ end
1736
+
1737
+ def to_json(options = nil)
1738
+ JSON.generate(to_dynamic, options)
1739
+ end
1740
+ end
1741
+
1742
+ class ClassClassFeature < Dry::Struct
1743
+ attribute :definition, ClassFeatureDefinition
1744
+ attribute :level_scale, LevelScale.optional
1745
+
1746
+ def self.from_dynamic!(d)
1747
+ d = Types::Hash[d]
1748
+ new(
1749
+ definition: ClassFeatureDefinition.from_dynamic!(d.fetch("definition")),
1750
+ level_scale: d.fetch("levelScale") ? LevelScale.from_dynamic!(d.fetch("levelScale")) : nil,
1751
+ )
1752
+ end
1753
+
1754
+ def self.from_json!(json)
1755
+ from_dynamic!(JSON.parse(json))
1756
+ end
1757
+
1758
+ def to_dynamic
1759
+ {
1760
+ "definition" => definition.to_dynamic,
1761
+ "levelScale" => level_scale&.to_dynamic,
1762
+ }
1763
+ end
1764
+
1765
+ def to_json(options = nil)
1766
+ JSON.generate(to_dynamic, options)
1767
+ end
1768
+ end
1769
+
1770
+ class DefinitionClassFeature < Dry::Struct
1771
+ attribute :id, Types::Integer
1772
+ attribute :class_feature_name, Types::String
1773
+ attribute :prerequisite, Types::Nil
1774
+ attribute :description, Types::String
1775
+ attribute :required_level, Types::Integer
1776
+ attribute :display_order, Types::Integer
1777
+
1778
+ def self.from_dynamic!(d)
1779
+ d = Types::Hash[d]
1780
+ new(
1781
+ id: d.fetch("id"),
1782
+ class_feature_name: d.fetch("name"),
1783
+ prerequisite: d.fetch("prerequisite"),
1784
+ description: d.fetch("description"),
1785
+ required_level: d.fetch("requiredLevel"),
1786
+ display_order: d.fetch("displayOrder"),
1787
+ )
1788
+ end
1789
+
1790
+ def self.from_json!(json)
1791
+ from_dynamic!(JSON.parse(json))
1792
+ end
1793
+
1794
+ def to_dynamic
1795
+ {
1796
+ "id" => id,
1797
+ "name" => class_feature_name,
1798
+ "prerequisite" => prerequisite,
1799
+ "description" => description,
1800
+ "requiredLevel" => required_level,
1801
+ "displayOrder" => display_order,
1802
+ }
1803
+ end
1804
+
1805
+ def to_json(options = nil)
1806
+ JSON.generate(to_dynamic, options)
1807
+ end
1808
+ end
1809
+
1810
+ class PrerequisiteMapping < Dry::Struct
1811
+ attribute :id, Types::Integer
1812
+ attribute :entity_id, Types::Integer
1813
+ attribute :entity_type_id, Types::Integer
1814
+ attribute :prerequisite_mapping_type, Types::String
1815
+ attribute :sub_type, Types::String
1816
+ attribute :value, Types::Integer.optional
1817
+ attribute :friendly_type_name, Types::String
1818
+ attribute :friendly_sub_type_name, Types::String
1819
+
1820
+ def self.from_dynamic!(d)
1821
+ d = Types::Hash[d]
1822
+ new(
1823
+ id: d.fetch("id"),
1824
+ entity_id: d.fetch("entityId"),
1825
+ entity_type_id: d.fetch("entityTypeId"),
1826
+ prerequisite_mapping_type: d.fetch("type"),
1827
+ sub_type: d.fetch("subType"),
1828
+ value: d.fetch("value"),
1829
+ friendly_type_name: d.fetch("friendlyTypeName"),
1830
+ friendly_sub_type_name: d.fetch("friendlySubTypeName"),
1831
+ )
1832
+ end
1833
+
1834
+ def self.from_json!(json)
1835
+ from_dynamic!(JSON.parse(json))
1836
+ end
1837
+
1838
+ def to_dynamic
1839
+ {
1840
+ "id" => id,
1841
+ "entityId" => entity_id,
1842
+ "entityTypeId" => entity_type_id,
1843
+ "type" => prerequisite_mapping_type,
1844
+ "subType" => sub_type,
1845
+ "value" => value,
1846
+ "friendlyTypeName" => friendly_type_name,
1847
+ "friendlySubTypeName" => friendly_sub_type_name,
1848
+ }
1849
+ end
1850
+
1851
+ def to_json(options = nil)
1852
+ JSON.generate(to_dynamic, options)
1853
+ end
1854
+ end
1855
+
1856
+ class Prerequisite < Dry::Struct
1857
+ attribute :description, Types::String
1858
+ attribute :prerequisite_mappings, Types.Array(PrerequisiteMapping)
1859
+
1860
+ def self.from_dynamic!(d)
1861
+ d = Types::Hash[d]
1862
+ new(
1863
+ description: d.fetch("description"),
1864
+ prerequisite_mappings: d.fetch("prerequisiteMappings").map { |x| PrerequisiteMapping.from_dynamic!(x) },
1865
+ )
1866
+ end
1867
+
1868
+ def self.from_json!(json)
1869
+ from_dynamic!(JSON.parse(json))
1870
+ end
1871
+
1872
+ def to_dynamic
1873
+ {
1874
+ "description" => description,
1875
+ "prerequisiteMappings" => prerequisite_mappings.map { |x| x.to_dynamic },
1876
+ }
1877
+ end
1878
+
1879
+ def to_json(options = nil)
1880
+ JSON.generate(to_dynamic, options)
1881
+ end
1882
+ end
1883
+
1884
+ class SpellRules < Dry::Struct
1885
+ attribute :multi_class_spell_slot_divisor, Types::Integer
1886
+ attribute :is_ritual_spell_caster, Types::Bool
1887
+ attribute :level_cantrips_known_maxes, Types.Array(Types::Integer)
1888
+ attribute :level_spell_known_maxes, Types.Array(Types::Integer)
1889
+ attribute :level_spell_slots, Types.Array(Types.Array(Types::Integer))
1890
+ attribute :multi_class_spell_slot_rounding, Types::Integer
1891
+
1892
+ def self.from_dynamic!(d)
1893
+ d = Types::Hash[d]
1894
+ new(
1895
+ multi_class_spell_slot_divisor: d.fetch("multiClassSpellSlotDivisor"),
1896
+ is_ritual_spell_caster: d.fetch("isRitualSpellCaster"),
1897
+ level_cantrips_known_maxes: d.fetch("levelCantripsKnownMaxes"),
1898
+ level_spell_known_maxes: d.fetch("levelSpellKnownMaxes"),
1899
+ level_spell_slots: d.fetch("levelSpellSlots"),
1900
+ multi_class_spell_slot_rounding: d.fetch("multiClassSpellSlotRounding"),
1901
+ )
1902
+ end
1903
+
1904
+ def self.from_json!(json)
1905
+ from_dynamic!(JSON.parse(json))
1906
+ end
1907
+
1908
+ def to_dynamic
1909
+ {
1910
+ "multiClassSpellSlotDivisor" => multi_class_spell_slot_divisor,
1911
+ "isRitualSpellCaster" => is_ritual_spell_caster,
1912
+ "levelCantripsKnownMaxes" => level_cantrips_known_maxes,
1913
+ "levelSpellKnownMaxes" => level_spell_known_maxes,
1914
+ "levelSpellSlots" => level_spell_slots,
1915
+ "multiClassSpellSlotRounding" => multi_class_spell_slot_rounding,
1916
+ }
1917
+ end
1918
+
1919
+ def to_json(options = nil)
1920
+ JSON.generate(to_dynamic, options)
1921
+ end
1922
+ end
1923
+
1924
+ class SubclassDefinitionClass < Dry::Struct
1925
+ attribute :id, Types::Integer
1926
+ attribute :definition_key, Types::String
1927
+ attribute :definition_name, Types::String
1928
+ attribute :description, Types::String
1929
+ attribute :equipment_description, Types::String.optional
1930
+ attribute :parent_class_id, Types::Integer.optional
1931
+ attribute :avatar_url, Types::String.optional
1932
+ attribute :large_avatar_url, Types::String.optional
1933
+ attribute :portrait_avatar_url, Types::String.optional
1934
+ attribute :more_details_url, Types::String
1935
+ attribute :spell_casting_ability_id, Types::Nil
1936
+ attribute :sources, Types.Array(Source)
1937
+ attribute :class_features, Types.Array(DefinitionClassFeature)
1938
+ attribute :hit_dice, Types::Integer
1939
+ attribute :wealth_dice, Die.optional
1940
+ attribute :can_cast_spells, Types::Bool
1941
+ attribute :knows_all_spells, Types::Nil
1942
+ attribute :spell_prepare_type, Types::Nil
1943
+ attribute :spell_container_name, Types::Nil
1944
+ attribute :source_page_number, Types::Integer.optional
1945
+ attribute :subclass_definition, Types::Nil
1946
+ attribute :is_homebrew, Types::Bool
1947
+ attribute :primary_abilities, Types.Array(Types::Integer).optional
1948
+ attribute :spell_rules, SpellRules.optional
1949
+ attribute :prerequisites, Types.Array(Prerequisite).optional
1950
+
1951
+ def self.from_dynamic!(d)
1952
+ d = Types::Hash[d]
1953
+ new(
1954
+ id: d.fetch("id"),
1955
+ definition_key: d.fetch("definitionKey"),
1956
+ definition_name: d.fetch("name"),
1957
+ description: d.fetch("description"),
1958
+ equipment_description: d.fetch("equipmentDescription"),
1959
+ parent_class_id: d.fetch("parentClassId"),
1960
+ avatar_url: d.fetch("avatarUrl"),
1961
+ large_avatar_url: d.fetch("largeAvatarUrl"),
1962
+ portrait_avatar_url: d.fetch("portraitAvatarUrl"),
1963
+ more_details_url: d.fetch("moreDetailsUrl"),
1964
+ spell_casting_ability_id: d.fetch("spellCastingAbilityId"),
1965
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
1966
+ class_features: d.fetch("classFeatures").map { |x| DefinitionClassFeature.from_dynamic!(x) },
1967
+ hit_dice: d.fetch("hitDice"),
1968
+ wealth_dice: d.fetch("wealthDice") ? Die.from_dynamic!(d.fetch("wealthDice")) : nil,
1969
+ can_cast_spells: d.fetch("canCastSpells"),
1970
+ knows_all_spells: d.fetch("knowsAllSpells"),
1971
+ spell_prepare_type: d.fetch("spellPrepareType"),
1972
+ spell_container_name: d.fetch("spellContainerName"),
1973
+ source_page_number: d.fetch("sourcePageNumber"),
1974
+ subclass_definition: d.fetch("subclassDefinition"),
1975
+ is_homebrew: d.fetch("isHomebrew"),
1976
+ primary_abilities: d.fetch("primaryAbilities"),
1977
+ spell_rules: d.fetch("spellRules") ? SpellRules.from_dynamic!(d.fetch("spellRules")) : nil,
1978
+ prerequisites: d.fetch("prerequisites")&.map { |x| Prerequisite.from_dynamic!(x) },
1979
+ )
1980
+ end
1981
+
1982
+ def self.from_json!(json)
1983
+ from_dynamic!(JSON.parse(json))
1984
+ end
1985
+
1986
+ def to_dynamic
1987
+ {
1988
+ "id" => id,
1989
+ "definitionKey" => definition_key,
1990
+ "name" => definition_name,
1991
+ "description" => description,
1992
+ "equipmentDescription" => equipment_description,
1993
+ "parentClassId" => parent_class_id,
1994
+ "avatarUrl" => avatar_url,
1995
+ "largeAvatarUrl" => large_avatar_url,
1996
+ "portraitAvatarUrl" => portrait_avatar_url,
1997
+ "moreDetailsUrl" => more_details_url,
1998
+ "spellCastingAbilityId" => spell_casting_ability_id,
1999
+ "sources" => sources.map { |x| x.to_dynamic },
2000
+ "classFeatures" => class_features.map { |x| x.to_dynamic },
2001
+ "hitDice" => hit_dice,
2002
+ "wealthDice" => wealth_dice&.to_dynamic,
2003
+ "canCastSpells" => can_cast_spells,
2004
+ "knowsAllSpells" => knows_all_spells,
2005
+ "spellPrepareType" => spell_prepare_type,
2006
+ "spellContainerName" => spell_container_name,
2007
+ "sourcePageNumber" => source_page_number,
2008
+ "subclassDefinition" => subclass_definition,
2009
+ "isHomebrew" => is_homebrew,
2010
+ "primaryAbilities" => primary_abilities,
2011
+ "spellRules" => spell_rules&.to_dynamic,
2012
+ "prerequisites" => prerequisites&.map { |x| x.to_dynamic },
2013
+ }
2014
+ end
2015
+
2016
+ def to_json(options = nil)
2017
+ JSON.generate(to_dynamic, options)
2018
+ end
2019
+ end
2020
+
2021
+ class CharacterClass < Dry::Struct
2022
+ attribute :id, Types::Integer
2023
+ attribute :entity_type_id, Types::Integer
2024
+ attribute :level, Types::Integer
2025
+ attribute :is_starting_class, Types::Bool
2026
+ attribute :hit_dice_used, Types::Integer
2027
+ attribute :definition_id, Types::Integer
2028
+ attribute :subclass_definition_id, Types::Nil
2029
+ attribute :definition, SubclassDefinitionClass
2030
+ attribute :subclass_definition, SubclassDefinitionClass
2031
+ attribute :class_features, Types.Array(ClassClassFeature)
2032
+
2033
+ def self.from_dynamic!(d)
2034
+ d = Types::Hash[d]
2035
+ new(
2036
+ id: d.fetch("id"),
2037
+ entity_type_id: d.fetch("entityTypeId"),
2038
+ level: d.fetch("level"),
2039
+ is_starting_class: d.fetch("isStartingClass"),
2040
+ hit_dice_used: d.fetch("hitDiceUsed"),
2041
+ definition_id: d.fetch("definitionId"),
2042
+ subclass_definition_id: d.fetch("subclassDefinitionId"),
2043
+ definition: SubclassDefinitionClass.from_dynamic!(d.fetch("definition")),
2044
+ subclass_definition: SubclassDefinitionClass.from_dynamic!(d.fetch("subclassDefinition")),
2045
+ class_features: d.fetch("classFeatures").map { |x| ClassClassFeature.from_dynamic!(x) },
2046
+ )
2047
+ end
2048
+
2049
+ def self.from_json!(json)
2050
+ from_dynamic!(JSON.parse(json))
2051
+ end
2052
+
2053
+ def to_dynamic
2054
+ {
2055
+ "id" => id,
2056
+ "entityTypeId" => entity_type_id,
2057
+ "level" => level,
2058
+ "isStartingClass" => is_starting_class,
2059
+ "hitDiceUsed" => hit_dice_used,
2060
+ "definitionId" => definition_id,
2061
+ "subclassDefinitionId" => subclass_definition_id,
2062
+ "definition" => definition.to_dynamic,
2063
+ "subclassDefinition" => subclass_definition.to_dynamic,
2064
+ "classFeatures" => class_features.map { |x| x.to_dynamic },
2065
+ }
2066
+ end
2067
+
2068
+ def to_json(options = nil)
2069
+ JSON.generate(to_dynamic, options)
2070
+ end
2071
+ end
2072
+
2073
+ class Configuration < Dry::Struct
2074
+ attribute :starting_equipment_type, Types::Integer
2075
+ attribute :ability_score_type, Types::Integer
2076
+ attribute :show_help_text, Types::Bool
2077
+
2078
+ def self.from_dynamic!(d)
2079
+ d = Types::Hash[d]
2080
+ new(
2081
+ starting_equipment_type: d.fetch("startingEquipmentType"),
2082
+ ability_score_type: d.fetch("abilityScoreType"),
2083
+ show_help_text: d.fetch("showHelpText"),
2084
+ )
2085
+ end
2086
+
2087
+ def self.from_json!(json)
2088
+ from_dynamic!(JSON.parse(json))
2089
+ end
2090
+
2091
+ def to_dynamic
2092
+ {
2093
+ "startingEquipmentType" => starting_equipment_type,
2094
+ "abilityScoreType" => ability_score_type,
2095
+ "showHelpText" => show_help_text,
2096
+ }
2097
+ end
2098
+
2099
+ def to_json(options = nil)
2100
+ JSON.generate(to_dynamic, options)
2101
+ end
2102
+ end
2103
+
2104
+ class Currencies < Dry::Struct
2105
+ attribute :cp, Types::Integer
2106
+ attribute :sp, Types::Integer
2107
+ attribute :gp, Types::Integer
2108
+ attribute :ep, Types::Integer
2109
+ attribute :pp, Types::Integer
2110
+
2111
+ def self.from_dynamic!(d)
2112
+ d = Types::Hash[d]
2113
+ new(
2114
+ cp: d.fetch("cp"),
2115
+ sp: d.fetch("sp"),
2116
+ gp: d.fetch("gp"),
2117
+ ep: d.fetch("ep"),
2118
+ pp: d.fetch("pp"),
2119
+ )
2120
+ end
2121
+
2122
+ def self.from_json!(json)
2123
+ from_dynamic!(JSON.parse(json))
2124
+ end
2125
+
2126
+ def to_dynamic
2127
+ {
2128
+ "cp" => cp,
2129
+ "sp" => sp,
2130
+ "gp" => gp,
2131
+ "ep" => ep,
2132
+ "pp" => pp,
2133
+ }
2134
+ end
2135
+
2136
+ def to_json(options = nil)
2137
+ JSON.generate(to_dynamic, options)
2138
+ end
2139
+ end
2140
+
2141
+ class DeathSaves < Dry::Struct
2142
+ attribute :fail_count, Types::Nil
2143
+ attribute :success_count, Types::Nil
2144
+ attribute :is_stabilized, Types::Bool
2145
+
2146
+ def self.from_dynamic!(d)
2147
+ d = Types::Hash[d]
2148
+ new(
2149
+ fail_count: d.fetch("failCount"),
2150
+ success_count: d.fetch("successCount"),
2151
+ is_stabilized: d.fetch("isStabilized"),
2152
+ )
2153
+ end
2154
+
2155
+ def self.from_json!(json)
2156
+ from_dynamic!(JSON.parse(json))
2157
+ end
2158
+
2159
+ def to_dynamic
2160
+ {
2161
+ "failCount" => fail_count,
2162
+ "successCount" => success_count,
2163
+ "isStabilized" => is_stabilized,
2164
+ }
2165
+ end
2166
+
2167
+ def to_json(options = nil)
2168
+ JSON.generate(to_dynamic, options)
2169
+ end
2170
+ end
2171
+
2172
+ class DefaultBackdrop < Dry::Struct
2173
+ attribute :backdrop_avatar_url, Types::String
2174
+ attribute :small_backdrop_avatar_url, Types::String
2175
+ attribute :large_backdrop_avatar_url, Types::String
2176
+ attribute :thumbnail_backdrop_avatar_url, Types::String
2177
+
2178
+ def self.from_dynamic!(d)
2179
+ d = Types::Hash[d]
2180
+ new(
2181
+ backdrop_avatar_url: d.fetch("backdropAvatarUrl"),
2182
+ small_backdrop_avatar_url: d.fetch("smallBackdropAvatarUrl"),
2183
+ large_backdrop_avatar_url: d.fetch("largeBackdropAvatarUrl"),
2184
+ thumbnail_backdrop_avatar_url: d.fetch("thumbnailBackdropAvatarUrl"),
2185
+ )
2186
+ end
2187
+
2188
+ def self.from_json!(json)
2189
+ from_dynamic!(JSON.parse(json))
2190
+ end
2191
+
2192
+ def to_dynamic
2193
+ {
2194
+ "backdropAvatarUrl" => backdrop_avatar_url,
2195
+ "smallBackdropAvatarUrl" => small_backdrop_avatar_url,
2196
+ "largeBackdropAvatarUrl" => large_backdrop_avatar_url,
2197
+ "thumbnailBackdropAvatarUrl" => thumbnail_backdrop_avatar_url,
2198
+ }
2199
+ end
2200
+
2201
+ def to_json(options = nil)
2202
+ JSON.generate(to_dynamic, options)
2203
+ end
2204
+ end
2205
+
2206
+ class Decorations < Dry::Struct
2207
+ attribute :avatar_url, Types::Nil
2208
+ attribute :frame_avatar_url, Types::Nil
2209
+ attribute :backdrop_avatar_url, Types::Nil
2210
+ attribute :small_backdrop_avatar_url, Types::Nil
2211
+ attribute :large_backdrop_avatar_url, Types::Nil
2212
+ attribute :thumbnail_backdrop_avatar_url, Types::Nil
2213
+ attribute :default_backdrop, DefaultBackdrop
2214
+ attribute :avatar_id, Types::Nil
2215
+ attribute :portrait_decoration_key, Types::Nil
2216
+ attribute :frame_avatar_decoration_key, Types::Nil
2217
+ attribute :frame_avatar_id, Types::Nil
2218
+ attribute :backdrop_avatar_decoration_key, Types::Nil
2219
+ attribute :backdrop_avatar_id, Types::Nil
2220
+ attribute :small_backdrop_avatar_decoration_key, Types::String
2221
+ attribute :small_backdrop_avatar_id, Types::Nil
2222
+ attribute :large_backdrop_avatar_decoration_key, Types::String
2223
+ attribute :large_backdrop_avatar_id, Types::Nil
2224
+ attribute :thumbnail_backdrop_avatar_decoration_key, Types::String
2225
+ attribute :thumbnail_backdrop_avatar_id, Types::Nil
2226
+ attribute :theme_color, Types::Nil
2227
+
2228
+ def self.from_dynamic!(d)
2229
+ d = Types::Hash[d]
2230
+ new(
2231
+ avatar_url: d.fetch("avatarUrl"),
2232
+ frame_avatar_url: d.fetch("frameAvatarUrl"),
2233
+ backdrop_avatar_url: d.fetch("backdropAvatarUrl"),
2234
+ small_backdrop_avatar_url: d.fetch("smallBackdropAvatarUrl"),
2235
+ large_backdrop_avatar_url: d.fetch("largeBackdropAvatarUrl"),
2236
+ thumbnail_backdrop_avatar_url: d.fetch("thumbnailBackdropAvatarUrl"),
2237
+ default_backdrop: DefaultBackdrop.from_dynamic!(d.fetch("defaultBackdrop")),
2238
+ avatar_id: d.fetch("avatarId"),
2239
+ portrait_decoration_key: d.fetch("portraitDecorationKey"),
2240
+ frame_avatar_decoration_key: d.fetch("frameAvatarDecorationKey"),
2241
+ frame_avatar_id: d.fetch("frameAvatarId"),
2242
+ backdrop_avatar_decoration_key: d.fetch("backdropAvatarDecorationKey"),
2243
+ backdrop_avatar_id: d.fetch("backdropAvatarId"),
2244
+ small_backdrop_avatar_decoration_key: d.fetch("smallBackdropAvatarDecorationKey"),
2245
+ small_backdrop_avatar_id: d.fetch("smallBackdropAvatarId"),
2246
+ large_backdrop_avatar_decoration_key: d.fetch("largeBackdropAvatarDecorationKey"),
2247
+ large_backdrop_avatar_id: d.fetch("largeBackdropAvatarId"),
2248
+ thumbnail_backdrop_avatar_decoration_key: d.fetch("thumbnailBackdropAvatarDecorationKey"),
2249
+ thumbnail_backdrop_avatar_id: d.fetch("thumbnailBackdropAvatarId"),
2250
+ theme_color: d.fetch("themeColor"),
2251
+ )
2252
+ end
2253
+
2254
+ def self.from_json!(json)
2255
+ from_dynamic!(JSON.parse(json))
2256
+ end
2257
+
2258
+ def to_dynamic
2259
+ {
2260
+ "avatarUrl" => avatar_url,
2261
+ "frameAvatarUrl" => frame_avatar_url,
2262
+ "backdropAvatarUrl" => backdrop_avatar_url,
2263
+ "smallBackdropAvatarUrl" => small_backdrop_avatar_url,
2264
+ "largeBackdropAvatarUrl" => large_backdrop_avatar_url,
2265
+ "thumbnailBackdropAvatarUrl" => thumbnail_backdrop_avatar_url,
2266
+ "defaultBackdrop" => default_backdrop.to_dynamic,
2267
+ "avatarId" => avatar_id,
2268
+ "portraitDecorationKey" => portrait_decoration_key,
2269
+ "frameAvatarDecorationKey" => frame_avatar_decoration_key,
2270
+ "frameAvatarId" => frame_avatar_id,
2271
+ "backdropAvatarDecorationKey" => backdrop_avatar_decoration_key,
2272
+ "backdropAvatarId" => backdrop_avatar_id,
2273
+ "smallBackdropAvatarDecorationKey" => small_backdrop_avatar_decoration_key,
2274
+ "smallBackdropAvatarId" => small_backdrop_avatar_id,
2275
+ "largeBackdropAvatarDecorationKey" => large_backdrop_avatar_decoration_key,
2276
+ "largeBackdropAvatarId" => large_backdrop_avatar_id,
2277
+ "thumbnailBackdropAvatarDecorationKey" => thumbnail_backdrop_avatar_decoration_key,
2278
+ "thumbnailBackdropAvatarId" => thumbnail_backdrop_avatar_id,
2279
+ "themeColor" => theme_color,
2280
+ }
2281
+ end
2282
+
2283
+ def to_json(options = nil)
2284
+ JSON.generate(to_dynamic, options)
2285
+ end
2286
+ end
2287
+
2288
+ class FeatDefinition < Dry::Struct
2289
+ attribute :id, Types::Integer
2290
+ attribute :entity_type_id, Types::Integer
2291
+ attribute :definition_key, Types::String
2292
+ attribute :definition_name, Types::String
2293
+ attribute :description, Types::String
2294
+ attribute :snippet, Types::String
2295
+ attribute :activation, Activation
2296
+ attribute :source_id, Types::Nil
2297
+ attribute :source_page_number, Types::Nil
2298
+ attribute :creature_rules, Types.Array(Types::Any)
2299
+ attribute :prerequisites, Types.Array(Prerequisite)
2300
+ attribute :is_homebrew, Types::Bool
2301
+ attribute :sources, Types.Array(Source)
2302
+ attribute :spell_list_ids, Types.Array(Types::Any)
2303
+
2304
+ def self.from_dynamic!(d)
2305
+ d = Types::Hash[d]
2306
+ new(
2307
+ id: d.fetch("id"),
2308
+ entity_type_id: d.fetch("entityTypeId"),
2309
+ definition_key: d.fetch("definitionKey"),
2310
+ definition_name: d.fetch("name"),
2311
+ description: d.fetch("description"),
2312
+ snippet: d.fetch("snippet"),
2313
+ activation: Activation.from_dynamic!(d.fetch("activation")),
2314
+ source_id: d.fetch("sourceId"),
2315
+ source_page_number: d.fetch("sourcePageNumber"),
2316
+ creature_rules: d.fetch("creatureRules"),
2317
+ prerequisites: d.fetch("prerequisites").map { |x| Prerequisite.from_dynamic!(x) },
2318
+ is_homebrew: d.fetch("isHomebrew"),
2319
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
2320
+ spell_list_ids: d.fetch("spellListIds"),
2321
+ )
2322
+ end
2323
+
2324
+ def self.from_json!(json)
2325
+ from_dynamic!(JSON.parse(json))
2326
+ end
2327
+
2328
+ def to_dynamic
2329
+ {
2330
+ "id" => id,
2331
+ "entityTypeId" => entity_type_id,
2332
+ "definitionKey" => definition_key,
2333
+ "name" => definition_name,
2334
+ "description" => description,
2335
+ "snippet" => snippet,
2336
+ "activation" => activation.to_dynamic,
2337
+ "sourceId" => source_id,
2338
+ "sourcePageNumber" => source_page_number,
2339
+ "creatureRules" => creature_rules,
2340
+ "prerequisites" => prerequisites.map { |x| x.to_dynamic },
2341
+ "isHomebrew" => is_homebrew,
2342
+ "sources" => sources.map { |x| x.to_dynamic },
2343
+ "spellListIds" => spell_list_ids,
2344
+ }
2345
+ end
2346
+
2347
+ def to_json(options = nil)
2348
+ JSON.generate(to_dynamic, options)
2349
+ end
2350
+ end
2351
+
2352
+ class Feat < Dry::Struct
2353
+ attribute :component_type_id, Types::Integer
2354
+ attribute :component_id, Types::Integer
2355
+ attribute :definition, FeatDefinition
2356
+ attribute :definition_id, Types::Integer
2357
+
2358
+ def self.from_dynamic!(d)
2359
+ d = Types::Hash[d]
2360
+ new(
2361
+ component_type_id: d.fetch("componentTypeId"),
2362
+ component_id: d.fetch("componentId"),
2363
+ definition: FeatDefinition.from_dynamic!(d.fetch("definition")),
2364
+ definition_id: d.fetch("definitionId"),
2365
+ )
2366
+ end
2367
+
2368
+ def self.from_json!(json)
2369
+ from_dynamic!(JSON.parse(json))
2370
+ end
2371
+
2372
+ def to_dynamic
2373
+ {
2374
+ "componentTypeId" => component_type_id,
2375
+ "componentId" => component_id,
2376
+ "definition" => definition.to_dynamic,
2377
+ "definitionId" => definition_id,
2378
+ }
2379
+ end
2380
+
2381
+ def to_json(options = nil)
2382
+ JSON.generate(to_dynamic, options)
2383
+ end
2384
+ end
2385
+
2386
+ module ContainerDefinitionKey
2387
+ The158111142353552888 = "1581111423:53552888"
2388
+ end
2389
+
2390
+ module FilterType
2391
+ Armor = "Armor"
2392
+ OtherGear = "Other Gear"
2393
+ Potion = "Potion"
2394
+ Weapon = "Weapon"
2395
+ end
2396
+
2397
+ class Property < Dry::Struct
2398
+ attribute :id, Types::Integer
2399
+ attribute :property_name, Types::String
2400
+ attribute :description, Types::String
2401
+ attribute :notes, Types::String.optional
2402
+
2403
+ def self.from_dynamic!(d)
2404
+ d = Types::Hash[d]
2405
+ new(
2406
+ id: d.fetch("id"),
2407
+ property_name: d.fetch("name"),
2408
+ description: d.fetch("description"),
2409
+ notes: d.fetch("notes"),
2410
+ )
2411
+ end
2412
+
2413
+ def self.from_json!(json)
2414
+ from_dynamic!(JSON.parse(json))
2415
+ end
2416
+
2417
+ def to_dynamic
2418
+ {
2419
+ "id" => id,
2420
+ "name" => property_name,
2421
+ "description" => description,
2422
+ "notes" => notes,
2423
+ }
2424
+ end
2425
+
2426
+ def to_json(options = nil)
2427
+ JSON.generate(to_dynamic, options)
2428
+ end
2429
+ end
2430
+
2431
+ module Rarity
2432
+ Common = "Common"
2433
+ Rare = "Rare"
2434
+ Uncommon = "Uncommon"
2435
+ end
2436
+
2437
+ class InventoryDefinition < Dry::Struct
2438
+ attribute :id, Types::Integer
2439
+ attribute :base_type_id, Types::Integer
2440
+ attribute :entity_type_id, Types::Integer
2441
+ attribute :definition_key, Types::String
2442
+ attribute :can_equip, Types::Bool
2443
+ attribute :magic, Types::Bool
2444
+ attribute :definition_name, Types::String
2445
+ attribute :snippet, Types::String.optional
2446
+ attribute :weight, Types::Double
2447
+ attribute :weight_multiplier, Types::Integer
2448
+ attribute :capacity, Types::String.optional
2449
+ attribute :capacity_weight, Types::Integer
2450
+ attribute :definition_type, Types::String
2451
+ attribute :description, Types::String
2452
+ attribute :can_attune, Types::Bool
2453
+ attribute :attunement_description, Types::String.optional
2454
+ attribute :rarity, Types::Rarity
2455
+ attribute :is_homebrew, Types::Bool
2456
+ attribute :version, Types::Nil
2457
+ attribute :source_id, Types::Nil
2458
+ attribute :source_page_number, Types::Nil
2459
+ attribute :stackable, Types::Bool
2460
+ attribute :bundle_size, Types::Integer
2461
+ attribute :avatar_url, Types::Nil
2462
+ attribute :large_avatar_url, Types::Nil
2463
+ attribute :filter_type, Types::FilterType
2464
+ attribute :cost, Types::Double.optional
2465
+ attribute :is_pack, Types::Bool
2466
+ attribute :tags, Types.Array(Types::String)
2467
+ attribute :granted_modifiers, Types.Array(ItemElement)
2468
+ attribute :sub_type, Types::String.optional
2469
+ attribute :is_consumable, Types::Bool
2470
+ attribute :weapon_behaviors, Types.Array(Types::Any)
2471
+ attribute :base_item_id, Types::Integer.optional
2472
+ attribute :base_armor_name, Types::String.optional
2473
+ attribute :strength_requirement, Types::Integer.optional
2474
+ attribute :armor_class, Types::Integer.optional
2475
+ attribute :stealth_check, Types::Integer.optional
2476
+ attribute :damage, Die.optional
2477
+ attribute :damage_type, Types::String.optional
2478
+ attribute :fixed_damage, Types::Nil
2479
+ attribute :properties, Types.Array(Property).optional
2480
+ attribute :attack_type, Types::Integer.optional
2481
+ attribute :category_id, Types::Integer.optional
2482
+ attribute :range, Types::Integer.optional
2483
+ attribute :long_range, Types::Integer.optional
2484
+ attribute :is_monk_weapon, Types::Bool
2485
+ attribute :level_infusion_granted, Types::Nil
2486
+ attribute :sources, Types.Array(Source)
2487
+ attribute :armor_type_id, Types::Integer.optional
2488
+ attribute :gear_type_id, Types::Integer.optional
2489
+ attribute :grouped_id, Types::Integer.optional
2490
+ attribute :can_be_added_to_inventory, Types::Bool
2491
+ attribute :is_container, Types::Bool
2492
+ attribute :is_custom_item, Types::Bool
2493
+
2494
+ def self.from_dynamic!(d)
2495
+ d = Types::Hash[d]
2496
+ new(
2497
+ id: d.fetch("id"),
2498
+ base_type_id: d.fetch("baseTypeId"),
2499
+ entity_type_id: d.fetch("entityTypeId"),
2500
+ definition_key: d.fetch("definitionKey"),
2501
+ can_equip: d.fetch("canEquip"),
2502
+ magic: d.fetch("magic"),
2503
+ definition_name: d.fetch("name"),
2504
+ snippet: d.fetch("snippet"),
2505
+ weight: d.fetch("weight"),
2506
+ weight_multiplier: d.fetch("weightMultiplier"),
2507
+ capacity: d.fetch("capacity"),
2508
+ capacity_weight: d.fetch("capacityWeight"),
2509
+ definition_type: d.fetch("type"),
2510
+ description: d.fetch("description"),
2511
+ can_attune: d.fetch("canAttune"),
2512
+ attunement_description: d.fetch("attunementDescription"),
2513
+ rarity: d.fetch("rarity"),
2514
+ is_homebrew: d.fetch("isHomebrew"),
2515
+ version: d.fetch("version"),
2516
+ source_id: d.fetch("sourceId"),
2517
+ source_page_number: d.fetch("sourcePageNumber"),
2518
+ stackable: d.fetch("stackable"),
2519
+ bundle_size: d.fetch("bundleSize"),
2520
+ avatar_url: d.fetch("avatarUrl"),
2521
+ large_avatar_url: d.fetch("largeAvatarUrl"),
2522
+ filter_type: d.fetch("filterType"),
2523
+ cost: d.fetch("cost"),
2524
+ is_pack: d.fetch("isPack"),
2525
+ tags: d.fetch("tags"),
2526
+ granted_modifiers: d.fetch("grantedModifiers").map { |x| ItemElement.from_dynamic!(x) },
2527
+ sub_type: d.fetch("subType"),
2528
+ is_consumable: d.fetch("isConsumable"),
2529
+ weapon_behaviors: d.fetch("weaponBehaviors"),
2530
+ base_item_id: d.fetch("baseItemId"),
2531
+ base_armor_name: d.fetch("baseArmorName"),
2532
+ strength_requirement: d.fetch("strengthRequirement"),
2533
+ armor_class: d.fetch("armorClass"),
2534
+ stealth_check: d.fetch("stealthCheck"),
2535
+ damage: d.fetch("damage") ? Die.from_dynamic!(d.fetch("damage")) : nil,
2536
+ damage_type: d.fetch("damageType"),
2537
+ fixed_damage: d.fetch("fixedDamage"),
2538
+ properties: d.fetch("properties")&.map { |x| Property.from_dynamic!(x) },
2539
+ attack_type: d.fetch("attackType"),
2540
+ category_id: d.fetch("categoryId"),
2541
+ range: d.fetch("range"),
2542
+ long_range: d.fetch("longRange"),
2543
+ is_monk_weapon: d.fetch("isMonkWeapon"),
2544
+ level_infusion_granted: d.fetch("levelInfusionGranted"),
2545
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
2546
+ armor_type_id: d.fetch("armorTypeId"),
2547
+ gear_type_id: d.fetch("gearTypeId"),
2548
+ grouped_id: d.fetch("groupedId"),
2549
+ can_be_added_to_inventory: d.fetch("canBeAddedToInventory"),
2550
+ is_container: d.fetch("isContainer"),
2551
+ is_custom_item: d.fetch("isCustomItem"),
2552
+ )
2553
+ end
2554
+
2555
+ def self.from_json!(json)
2556
+ from_dynamic!(JSON.parse(json))
2557
+ end
2558
+
2559
+ def to_dynamic
2560
+ {
2561
+ "id" => id,
2562
+ "baseTypeId" => base_type_id,
2563
+ "entityTypeId" => entity_type_id,
2564
+ "definitionKey" => definition_key,
2565
+ "canEquip" => can_equip,
2566
+ "magic" => magic,
2567
+ "name" => definition_name,
2568
+ "snippet" => snippet,
2569
+ "weight" => weight,
2570
+ "weightMultiplier" => weight_multiplier,
2571
+ "capacity" => capacity,
2572
+ "capacityWeight" => capacity_weight,
2573
+ "type" => definition_type,
2574
+ "description" => description,
2575
+ "canAttune" => can_attune,
2576
+ "attunementDescription" => attunement_description,
2577
+ "rarity" => rarity,
2578
+ "isHomebrew" => is_homebrew,
2579
+ "version" => version,
2580
+ "sourceId" => source_id,
2581
+ "sourcePageNumber" => source_page_number,
2582
+ "stackable" => stackable,
2583
+ "bundleSize" => bundle_size,
2584
+ "avatarUrl" => avatar_url,
2585
+ "largeAvatarUrl" => large_avatar_url,
2586
+ "filterType" => filter_type,
2587
+ "cost" => cost,
2588
+ "isPack" => is_pack,
2589
+ "tags" => tags,
2590
+ "grantedModifiers" => granted_modifiers.map { |x| x.to_dynamic },
2591
+ "subType" => sub_type,
2592
+ "isConsumable" => is_consumable,
2593
+ "weaponBehaviors" => weapon_behaviors,
2594
+ "baseItemId" => base_item_id,
2595
+ "baseArmorName" => base_armor_name,
2596
+ "strengthRequirement" => strength_requirement,
2597
+ "armorClass" => armor_class,
2598
+ "stealthCheck" => stealth_check,
2599
+ "damage" => damage&.to_dynamic,
2600
+ "damageType" => damage_type,
2601
+ "fixedDamage" => fixed_damage,
2602
+ "properties" => properties&.map { |x| x.to_dynamic },
2603
+ "attackType" => attack_type,
2604
+ "categoryId" => category_id,
2605
+ "range" => range,
2606
+ "longRange" => long_range,
2607
+ "isMonkWeapon" => is_monk_weapon,
2608
+ "levelInfusionGranted" => level_infusion_granted,
2609
+ "sources" => sources.map { |x| x.to_dynamic },
2610
+ "armorTypeId" => armor_type_id,
2611
+ "gearTypeId" => gear_type_id,
2612
+ "groupedId" => grouped_id,
2613
+ "canBeAddedToInventory" => can_be_added_to_inventory,
2614
+ "isContainer" => is_container,
2615
+ "isCustomItem" => is_custom_item,
2616
+ }
2617
+ end
2618
+
2619
+ def to_json(options = nil)
2620
+ JSON.generate(to_dynamic, options)
2621
+ end
2622
+ end
2623
+
2624
+ class InventoryLimitedUse < Dry::Struct
2625
+ attribute :max_uses, Types::Integer
2626
+ attribute :number_used, Types::Integer
2627
+ attribute :reset_type, Types::String
2628
+ attribute :reset_type_description, Types::String
2629
+
2630
+ def self.from_dynamic!(d)
2631
+ d = Types::Hash[d]
2632
+ new(
2633
+ max_uses: d.fetch("maxUses"),
2634
+ number_used: d.fetch("numberUsed"),
2635
+ reset_type: d.fetch("resetType"),
2636
+ reset_type_description: d.fetch("resetTypeDescription"),
2637
+ )
2638
+ end
2639
+
2640
+ def self.from_json!(json)
2641
+ from_dynamic!(JSON.parse(json))
2642
+ end
2643
+
2644
+ def to_dynamic
2645
+ {
2646
+ "maxUses" => max_uses,
2647
+ "numberUsed" => number_used,
2648
+ "resetType" => reset_type,
2649
+ "resetTypeDescription" => reset_type_description,
2650
+ }
2651
+ end
2652
+
2653
+ def to_json(options = nil)
2654
+ JSON.generate(to_dynamic, options)
2655
+ end
2656
+ end
2657
+
2658
+ class Inventory < Dry::Struct
2659
+ attribute :id, Types::Integer
2660
+ attribute :entity_type_id, Types::Integer
2661
+ attribute :definition, InventoryDefinition
2662
+ attribute :definition_id, Types::Integer
2663
+ attribute :definition_type_id, Types::Integer
2664
+ attribute :display_as_attack, Types::Nil
2665
+ attribute :quantity, Types::Integer
2666
+ attribute :is_attuned, Types::Bool
2667
+ attribute :equipped, Types::Bool
2668
+ attribute :equipped_entity_type_id, Types::Integer.optional
2669
+ attribute :equipped_entity_id, Types::Integer.optional
2670
+ attribute :charges_used, Types::Integer
2671
+ attribute :limited_use, InventoryLimitedUse.optional
2672
+ attribute :container_entity_id, Types::Integer
2673
+ attribute :container_entity_type_id, Types::Integer
2674
+ attribute :container_definition_key, Types::ContainerDefinitionKey
2675
+ attribute :currency, Types::Nil
2676
+
2677
+ def self.from_dynamic!(d)
2678
+ d = Types::Hash[d]
2679
+ new(
2680
+ id: d.fetch("id"),
2681
+ entity_type_id: d.fetch("entityTypeId"),
2682
+ definition: InventoryDefinition.from_dynamic!(d.fetch("definition")),
2683
+ definition_id: d.fetch("definitionId"),
2684
+ definition_type_id: d.fetch("definitionTypeId"),
2685
+ display_as_attack: d.fetch("displayAsAttack"),
2686
+ quantity: d.fetch("quantity"),
2687
+ is_attuned: d.fetch("isAttuned"),
2688
+ equipped: d.fetch("equipped"),
2689
+ equipped_entity_type_id: d.fetch("equippedEntityTypeId"),
2690
+ equipped_entity_id: d.fetch("equippedEntityId"),
2691
+ charges_used: d.fetch("chargesUsed"),
2692
+ limited_use: d.fetch("limitedUse") ? InventoryLimitedUse.from_dynamic!(d.fetch("limitedUse")) : nil,
2693
+ container_entity_id: d.fetch("containerEntityId"),
2694
+ container_entity_type_id: d.fetch("containerEntityTypeId"),
2695
+ container_definition_key: d.fetch("containerDefinitionKey"),
2696
+ currency: d.fetch("currency"),
2697
+ )
2698
+ end
2699
+
2700
+ def self.from_json!(json)
2701
+ from_dynamic!(JSON.parse(json))
2702
+ end
2703
+
2704
+ def to_dynamic
2705
+ {
2706
+ "id" => id,
2707
+ "entityTypeId" => entity_type_id,
2708
+ "definition" => definition.to_dynamic,
2709
+ "definitionId" => definition_id,
2710
+ "definitionTypeId" => definition_type_id,
2711
+ "displayAsAttack" => display_as_attack,
2712
+ "quantity" => quantity,
2713
+ "isAttuned" => is_attuned,
2714
+ "equipped" => equipped,
2715
+ "equippedEntityTypeId" => equipped_entity_type_id,
2716
+ "equippedEntityId" => equipped_entity_id,
2717
+ "chargesUsed" => charges_used,
2718
+ "limitedUse" => limited_use&.to_dynamic,
2719
+ "containerEntityId" => container_entity_id,
2720
+ "containerEntityTypeId" => container_entity_type_id,
2721
+ "containerDefinitionKey" => container_definition_key,
2722
+ "currency" => currency,
2723
+ }
2724
+ end
2725
+
2726
+ def to_json(options = nil)
2727
+ JSON.generate(to_dynamic, options)
2728
+ end
2729
+ end
2730
+
2731
+ class Modifiers < Dry::Struct
2732
+ attribute :race, Types.Array(ItemElement)
2733
+ attribute :modifiers_class, Types.Array(ItemElement)
2734
+ attribute :background, Types.Array(ItemElement)
2735
+ attribute :item, Types.Array(ItemElement)
2736
+ attribute :feat, Types.Array(ItemElement)
2737
+ attribute :condition, Types.Array(Types::Any)
2738
+
2739
+ def self.from_dynamic!(d)
2740
+ d = Types::Hash[d]
2741
+ new(
2742
+ race: d.fetch("race").map { |x| ItemElement.from_dynamic!(x) },
2743
+ modifiers_class: d.fetch("class").map { |x| ItemElement.from_dynamic!(x) },
2744
+ background: d.fetch("background").map { |x| ItemElement.from_dynamic!(x) },
2745
+ item: d.fetch("item").map { |x| ItemElement.from_dynamic!(x) },
2746
+ feat: d.fetch("feat").map { |x| ItemElement.from_dynamic!(x) },
2747
+ condition: d.fetch("condition"),
2748
+ )
2749
+ end
2750
+
2751
+ def self.from_json!(json)
2752
+ from_dynamic!(JSON.parse(json))
2753
+ end
2754
+
2755
+ def to_dynamic
2756
+ {
2757
+ "race" => race.map { |x| x.to_dynamic },
2758
+ "class" => modifiers_class.map { |x| x.to_dynamic },
2759
+ "background" => background.map { |x| x.to_dynamic },
2760
+ "item" => item.map { |x| x.to_dynamic },
2761
+ "feat" => feat.map { |x| x.to_dynamic },
2762
+ "condition" => condition,
2763
+ }
2764
+ end
2765
+
2766
+ def to_json(options = nil)
2767
+ JSON.generate(to_dynamic, options)
2768
+ end
2769
+ end
2770
+
2771
+ class Notes < Dry::Struct
2772
+ attribute :allies, Types::Nil
2773
+ attribute :personal_possessions, Types::String
2774
+ attribute :other_holdings, Types::Nil
2775
+ attribute :organizations, Types::Nil
2776
+ attribute :enemies, Types::Nil
2777
+ attribute :backstory, Types::Nil
2778
+ attribute :other_notes, Types::Nil
2779
+
2780
+ def self.from_dynamic!(d)
2781
+ d = Types::Hash[d]
2782
+ new(
2783
+ allies: d.fetch("allies"),
2784
+ personal_possessions: d.fetch("personalPossessions"),
2785
+ other_holdings: d.fetch("otherHoldings"),
2786
+ organizations: d.fetch("organizations"),
2787
+ enemies: d.fetch("enemies"),
2788
+ backstory: d.fetch("backstory"),
2789
+ other_notes: d.fetch("otherNotes"),
2790
+ )
2791
+ end
2792
+
2793
+ def self.from_json!(json)
2794
+ from_dynamic!(JSON.parse(json))
2795
+ end
2796
+
2797
+ def to_dynamic
2798
+ {
2799
+ "allies" => allies,
2800
+ "personalPossessions" => personal_possessions,
2801
+ "otherHoldings" => other_holdings,
2802
+ "organizations" => organizations,
2803
+ "enemies" => enemies,
2804
+ "backstory" => backstory,
2805
+ "otherNotes" => other_notes,
2806
+ }
2807
+ end
2808
+
2809
+ def to_json(options = nil)
2810
+ JSON.generate(to_dynamic, options)
2811
+ end
2812
+ end
2813
+
2814
+ class PactMagic < Dry::Struct
2815
+ attribute :level, Types::Integer
2816
+ attribute :used, Types::Integer
2817
+ attribute :available, Types::Integer
2818
+
2819
+ def self.from_dynamic!(d)
2820
+ d = Types::Hash[d]
2821
+ new(
2822
+ level: d.fetch("level"),
2823
+ used: d.fetch("used"),
2824
+ available: d.fetch("available"),
2825
+ )
2826
+ end
2827
+
2828
+ def self.from_json!(json)
2829
+ from_dynamic!(JSON.parse(json))
2830
+ end
2831
+
2832
+ def to_dynamic
2833
+ {
2834
+ "level" => level,
2835
+ "used" => used,
2836
+ "available" => available,
2837
+ }
2838
+ end
2839
+
2840
+ def to_json(options = nil)
2841
+ JSON.generate(to_dynamic, options)
2842
+ end
2843
+ end
2844
+
2845
+ class Preferences < Dry::Struct
2846
+ attribute :use_homebrew_content, Types::Bool
2847
+ attribute :progression_type, Types::Integer
2848
+ attribute :encumbrance_type, Types::Integer
2849
+ attribute :ignore_coin_weight, Types::Bool
2850
+ attribute :hit_point_type, Types::Integer
2851
+ attribute :show_unarmed_strike, Types::Bool
2852
+ attribute :show_scaled_spells, Types::Bool
2853
+ attribute :primary_sense, Types::Integer
2854
+ attribute :primary_movement, Types::Integer
2855
+ attribute :privacy_type, Types::Integer
2856
+ attribute :sharing_type, Types::Integer
2857
+ attribute :ability_score_display_type, Types::Integer
2858
+ attribute :enforce_feat_rules, Types::Bool
2859
+ attribute :enforce_multiclass_rules, Types::Bool
2860
+ attribute :enable_optional_class_features, Types::Bool
2861
+ attribute :enable_optional_origins, Types::Bool
2862
+ attribute :enable_dark_mode, Types::Bool
2863
+ attribute :enable_container_currency, Types::Bool
2864
+
2865
+ def self.from_dynamic!(d)
2866
+ d = Types::Hash[d]
2867
+ new(
2868
+ use_homebrew_content: d.fetch("useHomebrewContent"),
2869
+ progression_type: d.fetch("progressionType"),
2870
+ encumbrance_type: d.fetch("encumbranceType"),
2871
+ ignore_coin_weight: d.fetch("ignoreCoinWeight"),
2872
+ hit_point_type: d.fetch("hitPointType"),
2873
+ show_unarmed_strike: d.fetch("showUnarmedStrike"),
2874
+ show_scaled_spells: d.fetch("showScaledSpells"),
2875
+ primary_sense: d.fetch("primarySense"),
2876
+ primary_movement: d.fetch("primaryMovement"),
2877
+ privacy_type: d.fetch("privacyType"),
2878
+ sharing_type: d.fetch("sharingType"),
2879
+ ability_score_display_type: d.fetch("abilityScoreDisplayType"),
2880
+ enforce_feat_rules: d.fetch("enforceFeatRules"),
2881
+ enforce_multiclass_rules: d.fetch("enforceMulticlassRules"),
2882
+ enable_optional_class_features: d.fetch("enableOptionalClassFeatures"),
2883
+ enable_optional_origins: d.fetch("enableOptionalOrigins"),
2884
+ enable_dark_mode: d.fetch("enableDarkMode"),
2885
+ enable_container_currency: d.fetch("enableContainerCurrency"),
2886
+ )
2887
+ end
2888
+
2889
+ def self.from_json!(json)
2890
+ from_dynamic!(JSON.parse(json))
2891
+ end
2892
+
2893
+ def to_dynamic
2894
+ {
2895
+ "useHomebrewContent" => use_homebrew_content,
2896
+ "progressionType" => progression_type,
2897
+ "encumbranceType" => encumbrance_type,
2898
+ "ignoreCoinWeight" => ignore_coin_weight,
2899
+ "hitPointType" => hit_point_type,
2900
+ "showUnarmedStrike" => show_unarmed_strike,
2901
+ "showScaledSpells" => show_scaled_spells,
2902
+ "primarySense" => primary_sense,
2903
+ "primaryMovement" => primary_movement,
2904
+ "privacyType" => privacy_type,
2905
+ "sharingType" => sharing_type,
2906
+ "abilityScoreDisplayType" => ability_score_display_type,
2907
+ "enforceFeatRules" => enforce_feat_rules,
2908
+ "enforceMulticlassRules" => enforce_multiclass_rules,
2909
+ "enableOptionalClassFeatures" => enable_optional_class_features,
2910
+ "enableOptionalOrigins" => enable_optional_origins,
2911
+ "enableDarkMode" => enable_dark_mode,
2912
+ "enableContainerCurrency" => enable_container_currency,
2913
+ }
2914
+ end
2915
+
2916
+ def to_json(options = nil)
2917
+ JSON.generate(to_dynamic, options)
2918
+ end
2919
+ end
2920
+
2921
+ class DisplayConfiguration < Dry::Struct
2922
+ attribute :racialtrait, Types::Integer
2923
+ attribute :language, Types::Integer
2924
+ attribute :abilityscore, Types::Integer
2925
+ attribute :classfeature, Types::Integer
2926
+
2927
+ def self.from_dynamic!(d)
2928
+ d = Types::Hash[d]
2929
+ new(
2930
+ racialtrait: d.fetch("RACIALTRAIT"),
2931
+ language: d.fetch("LANGUAGE"),
2932
+ abilityscore: d.fetch("ABILITYSCORE"),
2933
+ classfeature: d.fetch("CLASSFEATURE"),
2934
+ )
2935
+ end
2936
+
2937
+ def self.from_json!(json)
2938
+ from_dynamic!(JSON.parse(json))
2939
+ end
2940
+
2941
+ def to_dynamic
2942
+ {
2943
+ "RACIALTRAIT" => racialtrait,
2944
+ "LANGUAGE" => language,
2945
+ "ABILITYSCORE" => abilityscore,
2946
+ "CLASSFEATURE" => classfeature,
2947
+ }
2948
+ end
2949
+
2950
+ def to_json(options = nil)
2951
+ JSON.generate(to_dynamic, options)
2952
+ end
2953
+ end
2954
+
2955
+ class RacialTraitDefinition < Dry::Struct
2956
+ attribute :id, Types::Integer
2957
+ attribute :definition_key, Types::String
2958
+ attribute :entity_type_id, Types::Integer
2959
+ attribute :display_order, Types::Integer
2960
+ attribute :definition_name, Types::String
2961
+ attribute :description, Types::String
2962
+ attribute :snippet, Types::String.optional
2963
+ attribute :hide_in_builder, Types::Bool
2964
+ attribute :hide_in_sheet, Types::Bool
2965
+ attribute :activation, Types::Nil
2966
+ attribute :source_id, Types::Integer
2967
+ attribute :source_page_number, Types::Integer
2968
+ attribute :creature_rules, Types.Array(Types::Any)
2969
+ attribute :spell_list_ids, Types.Array(Types::Any)
2970
+ attribute :feature_type, Types::Integer
2971
+ attribute :sources, Types.Array(Source)
2972
+ attribute :affected_feature_definition_keys, Types.Array(Types::Any)
2973
+ attribute :is_called_out, Types::Bool
2974
+ attribute :entity_type, Types::String
2975
+ attribute :entity_id, Types::String
2976
+ attribute :entity_race_id, Types::Integer
2977
+ attribute :entity_race_type_id, Types::Integer
2978
+ attribute :display_configuration, DisplayConfiguration
2979
+ attribute :required_level, Types::Nil
2980
+
2981
+ def self.from_dynamic!(d)
2982
+ d = Types::Hash[d]
2983
+ new(
2984
+ id: d.fetch("id"),
2985
+ definition_key: d.fetch("definitionKey"),
2986
+ entity_type_id: d.fetch("entityTypeId"),
2987
+ display_order: d.fetch("displayOrder"),
2988
+ definition_name: d.fetch("name"),
2989
+ description: d.fetch("description"),
2990
+ snippet: d.fetch("snippet"),
2991
+ hide_in_builder: d.fetch("hideInBuilder"),
2992
+ hide_in_sheet: d.fetch("hideInSheet"),
2993
+ activation: d.fetch("activation"),
2994
+ source_id: d.fetch("sourceId"),
2995
+ source_page_number: d.fetch("sourcePageNumber"),
2996
+ creature_rules: d.fetch("creatureRules"),
2997
+ spell_list_ids: d.fetch("spellListIds"),
2998
+ feature_type: d.fetch("featureType"),
2999
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
3000
+ affected_feature_definition_keys: d.fetch("affectedFeatureDefinitionKeys"),
3001
+ is_called_out: d.fetch("isCalledOut"),
3002
+ entity_type: d.fetch("entityType"),
3003
+ entity_id: d.fetch("entityID"),
3004
+ entity_race_id: d.fetch("entityRaceId"),
3005
+ entity_race_type_id: d.fetch("entityRaceTypeId"),
3006
+ display_configuration: DisplayConfiguration.from_dynamic!(d.fetch("displayConfiguration")),
3007
+ required_level: d.fetch("requiredLevel"),
3008
+ )
3009
+ end
3010
+
3011
+ def self.from_json!(json)
3012
+ from_dynamic!(JSON.parse(json))
3013
+ end
3014
+
3015
+ def to_dynamic
3016
+ {
3017
+ "id" => id,
3018
+ "definitionKey" => definition_key,
3019
+ "entityTypeId" => entity_type_id,
3020
+ "displayOrder" => display_order,
3021
+ "name" => definition_name,
3022
+ "description" => description,
3023
+ "snippet" => snippet,
3024
+ "hideInBuilder" => hide_in_builder,
3025
+ "hideInSheet" => hide_in_sheet,
3026
+ "activation" => activation,
3027
+ "sourceId" => source_id,
3028
+ "sourcePageNumber" => source_page_number,
3029
+ "creatureRules" => creature_rules,
3030
+ "spellListIds" => spell_list_ids,
3031
+ "featureType" => feature_type,
3032
+ "sources" => sources.map { |x| x.to_dynamic },
3033
+ "affectedFeatureDefinitionKeys" => affected_feature_definition_keys,
3034
+ "isCalledOut" => is_called_out,
3035
+ "entityType" => entity_type,
3036
+ "entityID" => entity_id,
3037
+ "entityRaceId" => entity_race_id,
3038
+ "entityRaceTypeId" => entity_race_type_id,
3039
+ "displayConfiguration" => display_configuration.to_dynamic,
3040
+ "requiredLevel" => required_level,
3041
+ }
3042
+ end
3043
+
3044
+ def to_json(options = nil)
3045
+ JSON.generate(to_dynamic, options)
3046
+ end
3047
+ end
3048
+
3049
+ class RacialTrait < Dry::Struct
3050
+ attribute :definition, RacialTraitDefinition
3051
+
3052
+ def self.from_dynamic!(d)
3053
+ d = Types::Hash[d]
3054
+ new(
3055
+ definition: RacialTraitDefinition.from_dynamic!(d.fetch("definition")),
3056
+ )
3057
+ end
3058
+
3059
+ def self.from_json!(json)
3060
+ from_dynamic!(JSON.parse(json))
3061
+ end
3062
+
3063
+ def to_dynamic
3064
+ {
3065
+ "definition" => definition.to_dynamic,
3066
+ }
3067
+ end
3068
+
3069
+ def to_json(options = nil)
3070
+ JSON.generate(to_dynamic, options)
3071
+ end
3072
+ end
3073
+
3074
+ class Normal < Dry::Struct
3075
+ attribute :walk, Types::Integer
3076
+ attribute :fly, Types::Integer
3077
+ attribute :burrow, Types::Integer
3078
+ attribute :swim, Types::Integer
3079
+ attribute :climb, Types::Integer
3080
+
3081
+ def self.from_dynamic!(d)
3082
+ d = Types::Hash[d]
3083
+ new(
3084
+ walk: d.fetch("walk"),
3085
+ fly: d.fetch("fly"),
3086
+ burrow: d.fetch("burrow"),
3087
+ swim: d.fetch("swim"),
3088
+ climb: d.fetch("climb"),
3089
+ )
3090
+ end
3091
+
3092
+ def self.from_json!(json)
3093
+ from_dynamic!(JSON.parse(json))
3094
+ end
3095
+
3096
+ def to_dynamic
3097
+ {
3098
+ "walk" => walk,
3099
+ "fly" => fly,
3100
+ "burrow" => burrow,
3101
+ "swim" => swim,
3102
+ "climb" => climb,
3103
+ }
3104
+ end
3105
+
3106
+ def to_json(options = nil)
3107
+ JSON.generate(to_dynamic, options)
3108
+ end
3109
+ end
3110
+
3111
+ class WeightSpeeds < Dry::Struct
3112
+ attribute :normal, Normal
3113
+ attribute :encumbered, Types::Nil
3114
+ attribute :heavily_encumbered, Types::Nil
3115
+ attribute :push_drag_lift, Types::Nil
3116
+ attribute :override, Types::Nil
3117
+
3118
+ def self.from_dynamic!(d)
3119
+ d = Types::Hash[d]
3120
+ new(
3121
+ normal: Normal.from_dynamic!(d.fetch("normal")),
3122
+ encumbered: d.fetch("encumbered"),
3123
+ heavily_encumbered: d.fetch("heavilyEncumbered"),
3124
+ push_drag_lift: d.fetch("pushDragLift"),
3125
+ override: d.fetch("override"),
3126
+ )
3127
+ end
3128
+
3129
+ def self.from_json!(json)
3130
+ from_dynamic!(JSON.parse(json))
3131
+ end
3132
+
3133
+ def to_dynamic
3134
+ {
3135
+ "normal" => normal.to_dynamic,
3136
+ "encumbered" => encumbered,
3137
+ "heavilyEncumbered" => heavily_encumbered,
3138
+ "pushDragLift" => push_drag_lift,
3139
+ "override" => override,
3140
+ }
3141
+ end
3142
+
3143
+ def to_json(options = nil)
3144
+ JSON.generate(to_dynamic, options)
3145
+ end
3146
+ end
3147
+
3148
+ class Race < Dry::Struct
3149
+ attribute :is_sub_race, Types::Bool
3150
+ attribute :base_race_name, Types::String
3151
+ attribute :entity_race_id, Types::Integer
3152
+ attribute :entity_race_type_id, Types::Integer
3153
+ attribute :definition_key, Types::String
3154
+ attribute :full_name, Types::String
3155
+ attribute :base_race_id, Types::Integer
3156
+ attribute :base_race_type_id, Types::Integer
3157
+ attribute :description, Types::String
3158
+ attribute :avatar_url, Types::String
3159
+ attribute :large_avatar_url, Types::String
3160
+ attribute :portrait_avatar_url, Types::String
3161
+ attribute :more_details_url, Types::String
3162
+ attribute :is_homebrew, Types::Bool
3163
+ attribute :is_legacy, Types::Bool
3164
+ attribute :group_ids, Types.Array(Types::Integer)
3165
+ attribute :race_type, Types::Integer
3166
+ attribute :supports_subrace, Types::Nil
3167
+ attribute :sub_race_short_name, Types::Nil
3168
+ attribute :base_name, Types::String
3169
+ attribute :racial_traits, Types.Array(RacialTrait)
3170
+ attribute :weight_speeds, WeightSpeeds
3171
+ attribute :feat_ids, Types.Array(Types::Any)
3172
+ attribute :size, Types::Nil
3173
+ attribute :size_id, Types::Integer
3174
+ attribute :sources, Types.Array(Source)
3175
+
3176
+ def self.from_dynamic!(d)
3177
+ d = Types::Hash[d]
3178
+ new(
3179
+ is_sub_race: d.fetch("isSubRace"),
3180
+ base_race_name: d.fetch("baseRaceName"),
3181
+ entity_race_id: d.fetch("entityRaceId"),
3182
+ entity_race_type_id: d.fetch("entityRaceTypeId"),
3183
+ definition_key: d.fetch("definitionKey"),
3184
+ full_name: d.fetch("fullName"),
3185
+ base_race_id: d.fetch("baseRaceId"),
3186
+ base_race_type_id: d.fetch("baseRaceTypeId"),
3187
+ description: d.fetch("description"),
3188
+ avatar_url: d.fetch("avatarUrl"),
3189
+ large_avatar_url: d.fetch("largeAvatarUrl"),
3190
+ portrait_avatar_url: d.fetch("portraitAvatarUrl"),
3191
+ more_details_url: d.fetch("moreDetailsUrl"),
3192
+ is_homebrew: d.fetch("isHomebrew"),
3193
+ is_legacy: d.fetch("isLegacy"),
3194
+ group_ids: d.fetch("groupIds"),
3195
+ race_type: d.fetch("type"),
3196
+ supports_subrace: d.fetch("supportsSubrace"),
3197
+ sub_race_short_name: d.fetch("subRaceShortName"),
3198
+ base_name: d.fetch("baseName"),
3199
+ racial_traits: d.fetch("racialTraits").map { |x| RacialTrait.from_dynamic!(x) },
3200
+ weight_speeds: WeightSpeeds.from_dynamic!(d.fetch("weightSpeeds")),
3201
+ feat_ids: d.fetch("featIds"),
3202
+ size: d.fetch("size"),
3203
+ size_id: d.fetch("sizeId"),
3204
+ sources: d.fetch("sources").map { |x| Source.from_dynamic!(x) },
3205
+ )
3206
+ end
3207
+
3208
+ def self.from_json!(json)
3209
+ from_dynamic!(JSON.parse(json))
3210
+ end
3211
+
3212
+ def to_dynamic
3213
+ {
3214
+ "isSubRace" => is_sub_race,
3215
+ "baseRaceName" => base_race_name,
3216
+ "entityRaceId" => entity_race_id,
3217
+ "entityRaceTypeId" => entity_race_type_id,
3218
+ "definitionKey" => definition_key,
3219
+ "fullName" => full_name,
3220
+ "baseRaceId" => base_race_id,
3221
+ "baseRaceTypeId" => base_race_type_id,
3222
+ "description" => description,
3223
+ "avatarUrl" => avatar_url,
3224
+ "largeAvatarUrl" => large_avatar_url,
3225
+ "portraitAvatarUrl" => portrait_avatar_url,
3226
+ "moreDetailsUrl" => more_details_url,
3227
+ "isHomebrew" => is_homebrew,
3228
+ "isLegacy" => is_legacy,
3229
+ "groupIds" => group_ids,
3230
+ "type" => race_type,
3231
+ "supportsSubrace" => supports_subrace,
3232
+ "subRaceShortName" => sub_race_short_name,
3233
+ "baseName" => base_name,
3234
+ "racialTraits" => racial_traits.map { |x| x.to_dynamic },
3235
+ "weightSpeeds" => weight_speeds.to_dynamic,
3236
+ "featIds" => feat_ids,
3237
+ "size" => size,
3238
+ "sizeId" => size_id,
3239
+ "sources" => sources.map { |x| x.to_dynamic },
3240
+ }
3241
+ end
3242
+
3243
+ def to_json(options = nil)
3244
+ JSON.generate(to_dynamic, options)
3245
+ end
3246
+ end
3247
+
3248
+ class Traits < Dry::Struct
3249
+ attribute :personality_traits, Types::String
3250
+ attribute :ideals, Types::String
3251
+ attribute :bonds, Types::String
3252
+ attribute :flaws, Types::String
3253
+ attribute :appearance, Types::Nil
3254
+
3255
+ def self.from_dynamic!(d)
3256
+ d = Types::Hash[d]
3257
+ new(
3258
+ personality_traits: d.fetch("personalityTraits"),
3259
+ ideals: d.fetch("ideals"),
3260
+ bonds: d.fetch("bonds"),
3261
+ flaws: d.fetch("flaws"),
3262
+ appearance: d.fetch("appearance"),
3263
+ )
3264
+ end
3265
+
3266
+ def self.from_json!(json)
3267
+ from_dynamic!(JSON.parse(json))
3268
+ end
3269
+
3270
+ def to_dynamic
3271
+ {
3272
+ "personalityTraits" => personality_traits,
3273
+ "ideals" => ideals,
3274
+ "bonds" => bonds,
3275
+ "flaws" => flaws,
3276
+ "appearance" => appearance,
3277
+ }
3278
+ end
3279
+
3280
+ def to_json(options = nil)
3281
+ JSON.generate(to_dynamic, options)
3282
+ end
3283
+ end
3284
+
3285
+ class Character < Dry::Struct
3286
+ attribute :id, Types::Integer
3287
+ attribute :user_id, Types::Integer
3288
+ attribute :username, Types::String
3289
+ attribute :is_assigned_to_player, Types::Bool
3290
+ attribute :readonly_url, Types::String
3291
+ attribute :decorations, Decorations
3292
+ attribute :character_name, Types::String
3293
+ attribute :social_name, Types::Nil
3294
+ attribute :gender, Types::String
3295
+ attribute :faith, Types::String
3296
+ attribute :age, Types::Integer
3297
+ attribute :hair, Types::String
3298
+ attribute :eyes, Types::String
3299
+ attribute :skin, Types::String
3300
+ attribute :height, Types::String
3301
+ attribute :weight, Types::Integer
3302
+ attribute :inspiration, Types::Bool
3303
+ attribute :base_hit_points, Types::Integer
3304
+ attribute :bonus_hit_points, Types::Nil
3305
+ attribute :override_hit_points, Types::Nil
3306
+ attribute :removed_hit_points, Types::Integer
3307
+ attribute :temporary_hit_points, Types::Integer
3308
+ attribute :current_xp, Types::Integer
3309
+ attribute :alignment_id, Types::Integer
3310
+ attribute :lifestyle_id, Types::Integer
3311
+ attribute :stats, Types.Array(Stat)
3312
+ attribute :bonus_stats, Types.Array(Stat)
3313
+ attribute :override_stats, Types.Array(Stat)
3314
+ attribute :background, CharacterBackground
3315
+ attribute :race, Race
3316
+ attribute :race_definition_id, Types::Nil
3317
+ attribute :race_definition_type_id, Types::Nil
3318
+ attribute :notes, Notes
3319
+ attribute :traits, Traits
3320
+ attribute :preferences, Preferences
3321
+ attribute :configuration, Configuration
3322
+ attribute :lifestyle, Types::Nil
3323
+ attribute :inventory, Types.Array(Inventory)
3324
+ attribute :currencies, Currencies
3325
+ attribute :classes, Types.Array(CharacterClass)
3326
+ attribute :feats, Types.Array(Feat)
3327
+ attribute :features, Types.Array(Types::Any)
3328
+ attribute :custom_defense_adjustments, Types.Array(Types::Any)
3329
+ attribute :custom_senses, Types.Array(Types::Any)
3330
+ attribute :custom_speeds, Types.Array(Types::Any)
3331
+ attribute :custom_proficiencies, Types.Array(Types::Any)
3332
+ attribute :custom_actions, Types.Array(Types::Any)
3333
+ attribute :character_values, Types.Array(Types::Any)
3334
+ attribute :conditions, Types.Array(Types::Any)
3335
+ attribute :death_saves, DeathSaves
3336
+ attribute :adjustment_xp, Types::Nil
3337
+ attribute :spell_slots, Types.Array(PactMagic)
3338
+ attribute :pact_magic, Types.Array(PactMagic)
3339
+ attribute :active_source_categories, Types.Array(Types::Integer)
3340
+ attribute :spells, Actions
3341
+ attribute :character_options, Options
3342
+ attribute :choices, Choices
3343
+ attribute :actions, Actions
3344
+ attribute :modifiers, Modifiers
3345
+ attribute :class_spells, Types.Array(ClassSpell)
3346
+ attribute :custom_items, Types.Array(Types::Any)
3347
+ attribute :campaign, Campaign
3348
+ attribute :creatures, Types.Array(Types::Any)
3349
+ attribute :optional_origins, Types.Array(Types::Any)
3350
+ attribute :optional_class_features, Types.Array(Types::Any)
3351
+ attribute :date_modified, Types::String
3352
+ attribute :provided_from, Types::String
3353
+ attribute :can_edit, Types::Bool
3354
+ attribute :status, Types::Integer
3355
+ attribute :status_slug, Types::String
3356
+ attribute :campaign_setting, Types::Nil
3357
+
3358
+ def self.from_dynamic!(d)
3359
+ d = Types::Hash[d]
3360
+ new(
3361
+ id: d.fetch("id"),
3362
+ user_id: d.fetch("userId"),
3363
+ username: d.fetch("username"),
3364
+ is_assigned_to_player: d.fetch("isAssignedToPlayer"),
3365
+ readonly_url: d.fetch("readonlyUrl"),
3366
+ decorations: Decorations.from_dynamic!(d.fetch("decorations")),
3367
+ character_name: d.fetch("name"),
3368
+ social_name: d.fetch("socialName"),
3369
+ gender: d.fetch("gender"),
3370
+ faith: d.fetch("faith"),
3371
+ age: d.fetch("age"),
3372
+ hair: d.fetch("hair"),
3373
+ eyes: d.fetch("eyes"),
3374
+ skin: d.fetch("skin"),
3375
+ height: d.fetch("height"),
3376
+ weight: d.fetch("weight"),
3377
+ inspiration: d.fetch("inspiration"),
3378
+ base_hit_points: d.fetch("baseHitPoints"),
3379
+ bonus_hit_points: d.fetch("bonusHitPoints"),
3380
+ override_hit_points: d.fetch("overrideHitPoints"),
3381
+ removed_hit_points: d.fetch("removedHitPoints"),
3382
+ temporary_hit_points: d.fetch("temporaryHitPoints"),
3383
+ current_xp: d.fetch("currentXp"),
3384
+ alignment_id: d.fetch("alignmentId"),
3385
+ lifestyle_id: d.fetch("lifestyleId"),
3386
+ stats: d.fetch("stats").map { |x| Stat.from_dynamic!(x) },
3387
+ bonus_stats: d.fetch("bonusStats").map { |x| Stat.from_dynamic!(x) },
3388
+ override_stats: d.fetch("overrideStats").map { |x| Stat.from_dynamic!(x) },
3389
+ background: CharacterBackground.from_dynamic!(d.fetch("background")),
3390
+ race: Race.from_dynamic!(d.fetch("race")),
3391
+ race_definition_id: d.fetch("raceDefinitionId"),
3392
+ race_definition_type_id: d.fetch("raceDefinitionTypeId"),
3393
+ notes: Notes.from_dynamic!(d.fetch("notes")),
3394
+ traits: Traits.from_dynamic!(d.fetch("traits")),
3395
+ preferences: Preferences.from_dynamic!(d.fetch("preferences")),
3396
+ configuration: Configuration.from_dynamic!(d.fetch("configuration")),
3397
+ lifestyle: d.fetch("lifestyle"),
3398
+ inventory: d.fetch("inventory").map { |x| Inventory.from_dynamic!(x) },
3399
+ currencies: Currencies.from_dynamic!(d.fetch("currencies")),
3400
+ classes: d.fetch("classes").map { |x| CharacterClass.from_dynamic!(x) },
3401
+ feats: d.fetch("feats").map { |x| Feat.from_dynamic!(x) },
3402
+ features: d.fetch("features"),
3403
+ custom_defense_adjustments: d.fetch("customDefenseAdjustments"),
3404
+ custom_senses: d.fetch("customSenses"),
3405
+ custom_speeds: d.fetch("customSpeeds"),
3406
+ custom_proficiencies: d.fetch("customProficiencies"),
3407
+ custom_actions: d.fetch("customActions"),
3408
+ character_values: d.fetch("characterValues"),
3409
+ conditions: d.fetch("conditions"),
3410
+ death_saves: DeathSaves.from_dynamic!(d.fetch("deathSaves")),
3411
+ adjustment_xp: d.fetch("adjustmentXp"),
3412
+ spell_slots: d.fetch("spellSlots").map { |x| PactMagic.from_dynamic!(x) },
3413
+ pact_magic: d.fetch("pactMagic").map { |x| PactMagic.from_dynamic!(x) },
3414
+ active_source_categories: d.fetch("activeSourceCategories"),
3415
+ spells: Actions.from_dynamic!(d.fetch("spells")),
3416
+ character_options: Options.from_dynamic!(d.fetch("options")),
3417
+ choices: Choices.from_dynamic!(d.fetch("choices")),
3418
+ actions: Actions.from_dynamic!(d.fetch("actions")),
3419
+ modifiers: Modifiers.from_dynamic!(d.fetch("modifiers")),
3420
+ class_spells: d.fetch("classSpells").map { |x| ClassSpell.from_dynamic!(x) },
3421
+ custom_items: d.fetch("customItems"),
3422
+ campaign: Campaign.from_dynamic!(d.fetch("campaign")),
3423
+ creatures: d.fetch("creatures"),
3424
+ optional_origins: d.fetch("optionalOrigins"),
3425
+ optional_class_features: d.fetch("optionalClassFeatures"),
3426
+ date_modified: d.fetch("dateModified"),
3427
+ provided_from: d.fetch("providedFrom"),
3428
+ can_edit: d.fetch("canEdit"),
3429
+ status: d.fetch("status"),
3430
+ status_slug: d.fetch("statusSlug"),
3431
+ campaign_setting: d.fetch("campaignSetting"),
3432
+ )
3433
+ end
3434
+
3435
+ def self.from_json!(json)
3436
+ from_dynamic!(JSON.parse(json))
3437
+ end
3438
+
3439
+ def to_dynamic
3440
+ {
3441
+ "id" => id,
3442
+ "userId" => user_id,
3443
+ "username" => username,
3444
+ "isAssignedToPlayer" => is_assigned_to_player,
3445
+ "readonlyUrl" => readonly_url,
3446
+ "decorations" => decorations.to_dynamic,
3447
+ "name" => character_name,
3448
+ "socialName" => social_name,
3449
+ "gender" => gender,
3450
+ "faith" => faith,
3451
+ "age" => age,
3452
+ "hair" => hair,
3453
+ "eyes" => eyes,
3454
+ "skin" => skin,
3455
+ "height" => height,
3456
+ "weight" => weight,
3457
+ "inspiration" => inspiration,
3458
+ "baseHitPoints" => base_hit_points,
3459
+ "bonusHitPoints" => bonus_hit_points,
3460
+ "overrideHitPoints" => override_hit_points,
3461
+ "removedHitPoints" => removed_hit_points,
3462
+ "temporaryHitPoints" => temporary_hit_points,
3463
+ "currentXp" => current_xp,
3464
+ "alignmentId" => alignment_id,
3465
+ "lifestyleId" => lifestyle_id,
3466
+ "stats" => stats.map { |x| x.to_dynamic },
3467
+ "bonusStats" => bonus_stats.map { |x| x.to_dynamic },
3468
+ "overrideStats" => override_stats.map { |x| x.to_dynamic },
3469
+ "background" => background.to_dynamic,
3470
+ "race" => race.to_dynamic,
3471
+ "raceDefinitionId" => race_definition_id,
3472
+ "raceDefinitionTypeId" => race_definition_type_id,
3473
+ "notes" => notes.to_dynamic,
3474
+ "traits" => traits.to_dynamic,
3475
+ "preferences" => preferences.to_dynamic,
3476
+ "configuration" => configuration.to_dynamic,
3477
+ "lifestyle" => lifestyle,
3478
+ "inventory" => inventory.map { |x| x.to_dynamic },
3479
+ "currencies" => currencies.to_dynamic,
3480
+ "classes" => classes.map { |x| x.to_dynamic },
3481
+ "feats" => feats.map { |x| x.to_dynamic },
3482
+ "features" => features,
3483
+ "customDefenseAdjustments" => custom_defense_adjustments,
3484
+ "customSenses" => custom_senses,
3485
+ "customSpeeds" => custom_speeds,
3486
+ "customProficiencies" => custom_proficiencies,
3487
+ "customActions" => custom_actions,
3488
+ "characterValues" => character_values,
3489
+ "conditions" => conditions,
3490
+ "deathSaves" => death_saves.to_dynamic,
3491
+ "adjustmentXp" => adjustment_xp,
3492
+ "spellSlots" => spell_slots.map { |x| x.to_dynamic },
3493
+ "pactMagic" => pact_magic.map { |x| x.to_dynamic },
3494
+ "activeSourceCategories" => active_source_categories,
3495
+ "spells" => spells.to_dynamic,
3496
+ "options" => character_options.to_dynamic,
3497
+ "choices" => choices.to_dynamic,
3498
+ "actions" => actions.to_dynamic,
3499
+ "modifiers" => modifiers.to_dynamic,
3500
+ "classSpells" => class_spells.map { |x| x.to_dynamic },
3501
+ "customItems" => custom_items,
3502
+ "campaign" => campaign.to_dynamic,
3503
+ "creatures" => creatures,
3504
+ "optionalOrigins" => optional_origins,
3505
+ "optionalClassFeatures" => optional_class_features,
3506
+ "dateModified" => date_modified,
3507
+ "providedFrom" => provided_from,
3508
+ "canEdit" => can_edit,
3509
+ "status" => status,
3510
+ "statusSlug" => status_slug,
3511
+ "campaignSetting" => campaign_setting,
3512
+ }
3513
+ end
3514
+
3515
+ def to_json(options = nil)
3516
+ JSON.generate(to_dynamic, options)
3517
+ end
3518
+ end
3519
+ end