spell.json 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708
  1. {
  2. "type" : "object",
  3. "$schema" : "http://json-schema.org/draft-04/schema",
  4. "title" : "VCMI spell format",
  5. "description" : "Format used to define new spells in VCMI",
  6. "definitions" : {
  7. "animationQueue" : {
  8. "type" : "array",
  9. "items" : {
  10. "anyOf" :[
  11. {
  12. //dummy animation, pause, Value - frame count
  13. "type" : "number"
  14. },
  15. {
  16. //assumed verticalPosition: top
  17. "type" : "string",
  18. "format" : "animationFile"
  19. },
  20. {
  21. "type" : "object",
  22. "properties" : {
  23. "verticalPosition" : {"type" : "string", "enum" :["top","bottom"]},
  24. "defName" : {"type" : "string", "format" : "animationFile"},
  25. "effectName" : { "type" : "string" },
  26. "transparency" : {"type" : "number", "minimum" : 0, "maximum" : 1}
  27. },
  28. "additionalProperties" : false
  29. }
  30. ]
  31. }
  32. },
  33. "animation" : {
  34. "type" : "object",
  35. "additionalProperties" : false,
  36. "properties" : {
  37. "affect" : {"$ref" : "#/definitions/animationQueue"},
  38. "hit" : {"$ref" : "#/definitions/animationQueue"},
  39. "cast" : {"$ref" : "#/definitions/animationQueue"},
  40. "projectile" : {
  41. "type" : "array",
  42. "items" : {
  43. "type" : "object",
  44. "properties" : {
  45. "defName" : {"type" : "string", "format" : "animationFile"},
  46. "minimumAngle" : {"type" : "number", "minimum" : 0}
  47. },
  48. "additionalProperties" : false
  49. }
  50. }
  51. }
  52. },
  53. "adventureEffect" : {
  54. "type" : "object",
  55. "required" : [ "type" ],
  56. "properties" : {
  57. "type" : {
  58. "type" : "string",
  59. "enum" : [ "generic", "dimensionDoor", "removeObject", "summonBoat", "townPortal", "viewWorld" ]
  60. },
  61. "castsPerDay" : { "type" : "number" },
  62. "castsPerDayXL" : { "type" : "number" },
  63. "bonuses" : { "additionalProperties" : { "$ref" : "bonusInstance.json" }}
  64. },
  65. "allOf" : [
  66. {
  67. "if" : { "properties" : { "type" : { "const" : "dimensionDoor" } } },
  68. "then" : {
  69. "properties" : {
  70. "castsPerDay" : {},
  71. "castsPerDayXL" : {},
  72. "bonuses" : {},
  73. "type" : {},
  74. "rangeX" : { "type" : "number" },
  75. "rangeY" : { "type" : "number" },
  76. "ignoreFow" : { "type" : "boolean" },
  77. "cursor" : { "type" : "string" },
  78. "cursorGuarded" : { "type" : "string" },
  79. "movementPointsRequired" : { "type" : "number" },
  80. "movementPointsTaken" : { "type" : "number" },
  81. "waterLandFailureTakesPoints" : { "type" : "boolean" },
  82. "exposeFow" : { "type" : "boolean" }
  83. },
  84. "additionalProperties" : false
  85. }
  86. },
  87. {
  88. "if" : { "properties" : { "type" : { "const" : "removeObject" } } },
  89. "then" : {
  90. "properties" : {
  91. "castsPerDay" : {},
  92. "castsPerDayXL" : {},
  93. "bonuses" : {},
  94. "type" : {},
  95. "rangeX" : { "type" : "number" },
  96. "rangeY" : { "type" : "number" },
  97. "ignoreFow" : { "type" : "boolean" },
  98. "cursor" : { "type" : "string" },
  99. "objects" : { "additionalProperties" : { "type" : "boolean" } }
  100. },
  101. "additionalProperties" : false
  102. }
  103. },
  104. {
  105. "if" : { "properties" : { "type" : { "const" : "summonBoat" } } },
  106. "then" : {
  107. "properties" : {
  108. "castsPerDay" : {},
  109. "castsPerDayXL" : {},
  110. "bonuses" : {},
  111. "type" : {},
  112. "useExistingBoat" : { "type" : "boolean" },
  113. "createdBoat" : { "type" : "string" }
  114. },
  115. "additionalProperties" : false
  116. }
  117. },
  118. {
  119. "if" : { "properties" : { "type" : { "const" : "townPortal" } } },
  120. "then" : {
  121. "properties" : {
  122. "castsPerDay" : {},
  123. "castsPerDayXL" : {},
  124. "bonuses" : {},
  125. "type" : {},
  126. "movementPointsRequired" : { "type" : "number" },
  127. "movementPointsTaken" : { "type" : "number" },
  128. "allowTownSelection" : { "type" : "boolean" },
  129. "skipOccupiedTowns" : { "type" : "boolean" }
  130. },
  131. "additionalProperties" : false
  132. }
  133. },
  134. {
  135. "if" : { "properties" : { "type" : { "const" : "viewWorld" } } },
  136. "then" : {
  137. "properties" : {
  138. "castsPerDay" : {},
  139. "castsPerDayXL" : {},
  140. "bonuses" : {},
  141. "type" : {},
  142. "showTerrain" : { "type" : "boolean" },
  143. "objects" : { "additionalProperties" : { "type" : "boolean" } }
  144. },
  145. "additionalProperties" : false
  146. }
  147. }
  148. ]
  149. },
  150. "battleEffect" : {
  151. "type" : "object",
  152. "required" : [ "type" ],
  153. "properties" : {
  154. "type" : {
  155. "type" : "string",
  156. "enum" : [
  157. "core:catapult",
  158. "core:clone",
  159. "core:damage",
  160. "core:demonSummon",
  161. "core:dispel",
  162. "core:heal",
  163. "core:moat",
  164. "core:obstacle",
  165. "core:removeObstacle",
  166. "core:sacrifice",
  167. "core:summon",
  168. "core:teleport",
  169. "core:timed"
  170. ]
  171. },
  172. "indirect" : { "type" : "boolean" },
  173. "optional" : { "type" : "boolean" }
  174. },
  175. "allOf" : [
  176. {
  177. "if" : { "properties" : { "type" : { "const" : "core:catapult" } } },
  178. "then" : {
  179. "properties" : {
  180. "type" : {},
  181. "indirect" : {},
  182. "optional" : {},
  183. "targetsToAttack" : { "type" : "number" },
  184. "chanceToHitKeep" : { "type" : "number" },
  185. "chanceToHitGate" : { "type" : "number" },
  186. "chanceToHitTower" : { "type" : "number" },
  187. "chanceToHitWall" : { "type" : "number" },
  188. "chanceToNormalHit" : { "type" : "number" },
  189. "chanceToCrit" : { "type" : "number" }
  190. },
  191. "additionalProperties" : false
  192. }
  193. },
  194. {
  195. "if" : { "properties" : { "type" : { "const" : "core:clone" } } },
  196. "then" : {
  197. "properties" : {
  198. "type" : {},
  199. "indirect" : {},
  200. "optional" : {},
  201. "ignoreImmunity" : { "type" : "boolean" },
  202. "chainLength" : { "type" : "number" },
  203. "chainFactor" : { "type" : "number" },
  204. "maxTier" : { "type" : "number" }
  205. },
  206. "additionalProperties" : false
  207. }
  208. },
  209. {
  210. "if" : { "properties" : { "type" : { "const" : "core:damage" } } },
  211. "then" : {
  212. "properties" : {
  213. "type" : {},
  214. "indirect" : {},
  215. "optional" : {},
  216. "ignoreImmunity" : { "type" : "boolean" },
  217. "chainLength" : { "type" : "number" },
  218. "chainFactor" : { "type" : "number" },
  219. "killByPercentage" : { "type" : "boolean" },
  220. "killByCount" : { "type" : "boolean" }
  221. },
  222. "additionalProperties" : false
  223. }
  224. },
  225. {
  226. "if" : { "properties" : { "type" : { "const" : "core:demonSummon" } } },
  227. "then" : {
  228. "properties" : {
  229. "type" : {},
  230. "indirect" : {},
  231. "optional" : {},
  232. "ignoreImmunity" : { "type" : "boolean" },
  233. "chainLength" : { "type" : "number" },
  234. "chainFactor" : { "type" : "number" },
  235. "id" : { "type" : "string" },
  236. "permanent" : { "type" : "boolean" }
  237. },
  238. "additionalProperties" : false
  239. }
  240. },
  241. {
  242. "if" : { "properties" : { "type" : { "const" : "core:dispel" } } },
  243. "then" : {
  244. "properties" : {
  245. "type" : {},
  246. "indirect" : {},
  247. "optional" : {},
  248. "ignoreImmunity" : { "type" : "boolean" },
  249. "chainLength" : { "type" : "number" },
  250. "chainFactor" : { "type" : "number" },
  251. "dispelPositive" : { "type" : "boolean" },
  252. "dispelNegative" : { "type" : "boolean" },
  253. "dispelNeutral" : { "type" : "boolean" }
  254. },
  255. "additionalProperties" : false
  256. }
  257. },
  258. {
  259. "if" : { "properties" : { "type" : { "enum" : [ "core:heal", "core:sacrifice" ] } } },
  260. "then" : {
  261. "properties" : {
  262. "type" : {},
  263. "indirect" : {},
  264. "optional" : {},
  265. "ignoreImmunity" : { "type" : "boolean" },
  266. "chainLength" : { "type" : "number" },
  267. "chainFactor" : { "type" : "number" },
  268. "healLevel" : { "type" : "string" },
  269. "healPower" : { "type" : "string" },
  270. "minFullUnits" : { "type" : "number" }
  271. },
  272. "additionalProperties" : false
  273. }
  274. },
  275. {
  276. "if" : { "properties" : { "type" : { "const" : "core:moat" } } },
  277. "then" : {
  278. "properties" : {
  279. "type" : {},
  280. "indirect" : {},
  281. "optional" : {},
  282. "hidden" : { "type" : "boolean" },
  283. "trap" : { "type" : "boolean" },
  284. "removeOnTrigger" : { "type" : "boolean" },
  285. "dispellable" : { "type" : "boolean" },
  286. "moatDamage" : { "type" : "number" },
  287. "moatHexes" : { "type" : "array", "items" : { "type" : "array", "items" : { "type" : "number" } } },
  288. "triggerAbility" : { "type" : "string" },
  289. "defender" : { },
  290. "bonus" : { "additionalProperties" : { "$ref" : "bonusInstance.json" } }
  291. },
  292. "additionalProperties" : false
  293. }
  294. },
  295. {
  296. "if" : { "properties" : { "type" : { "const" : "core:obstacle" } } },
  297. "then" : {
  298. "properties" : {
  299. "type" : {},
  300. "indirect" : {},
  301. "optional" : {},
  302. "hidden" : { "type" : "boolean" },
  303. "passable" : { "type" : "boolean" },
  304. "trap" : { "type" : "boolean" },
  305. "removeOnTrigger" : { "type" : "boolean" },
  306. "hideNative" : { "type" : "boolean" },
  307. "patchCount" : { "type" : "number" },
  308. "turnsRemaining" : { "type" : "number" },
  309. "triggerAbility" : { "type" : "string" },
  310. "attacker" : { },
  311. "defender" : { }
  312. },
  313. "additionalProperties" : false
  314. }
  315. },
  316. {
  317. "if" : { "properties" : { "type" : { "const" : "core:removeObstacle" } } },
  318. "then" : {
  319. "properties" : {
  320. "type" : {},
  321. "indirect" : {},
  322. "optional" : {},
  323. "removeAbsolute" : { "type" : "boolean" },
  324. "removeUsual" : { "type" : "boolean" },
  325. "removeAllSpells" : { "type" : "boolean" },
  326. "removeSpells" : { }
  327. },
  328. "additionalProperties" : false
  329. }
  330. },
  331. {
  332. "if" : { "properties" : { "type" : { "const" : "core:summon" } } },
  333. "then" : {
  334. "properties" : {
  335. "type" : {},
  336. "indirect" : {},
  337. "optional" : {},
  338. "id" : { "type" : "string" },
  339. "permanent" : { "type" : "boolean" },
  340. "exclusive" : { "type" : "boolean" },
  341. "summonByHealth" : { "type" : "boolean" },
  342. "summonSameUnit" : { "type" : "boolean" }
  343. },
  344. "additionalProperties" : false
  345. }
  346. },
  347. {
  348. "if" : { "properties" : { "type" : { "const" : "core:teleport" } } },
  349. "then" : {
  350. "properties" : {
  351. "type" : {},
  352. "indirect" : {},
  353. "optional" : {},
  354. "ignoreImmunity" : { "type" : "boolean" },
  355. "chainLength" : { "type" : "number" },
  356. "chainFactor" : { "type" : "number" },
  357. "triggerObstacles" : { "type" : "boolean" },
  358. "isWallPassable" : { "type" : "boolean" },
  359. "isMoatPassable" : { "type" : "boolean" }
  360. },
  361. "additionalProperties" : false
  362. }
  363. },
  364. {
  365. "if" : { "properties" : { "type" : { "const" : "core:timed" } } },
  366. "then" : {
  367. "properties" : {
  368. "type" : {},
  369. "indirect" : {},
  370. "optional" : {},
  371. "ignoreImmunity" : { "type" : "boolean" },
  372. "chainLength" : { "type" : "number" },
  373. "chainFactor" : { "type" : "number" },
  374. "cumulative" : { "type" : "boolean" },
  375. "bonus" : { "additionalProperties" : { "$ref" : "bonusInstance.json" } }
  376. },
  377. "additionalProperties" : false
  378. }
  379. }
  380. ]
  381. },
  382. "flags" : {
  383. "type" : "object",
  384. "additionalProperties" : {
  385. "type" : "boolean"
  386. }
  387. },
  388. "levelInfo" : {
  389. "type" : "object",
  390. "required" :["range", "description", "cost", "power"],
  391. "additionalProperties" : false,
  392. "properties" : {
  393. "description" : {
  394. "type" : "string",
  395. "description" : "Localizable description. Use {xxx} for formatting"
  396. },
  397. "cost" : {
  398. "type" : "number",
  399. "description" : "Cost in mana points"
  400. },
  401. "power" : {
  402. "type" : "number"
  403. },
  404. "range" : {
  405. "type" : "string",
  406. "description" : "spell range description in SRSL"
  407. },
  408. "effects" : {
  409. "type" : "object",
  410. "description" : "Timed effects (updated by prolongation)",
  411. "additionalProperties" : {
  412. "$ref" : "bonusInstance.json"
  413. }
  414. },
  415. "cumulativeEffects" : {
  416. "type" : "object",
  417. "description" : "Timed effects (updated by unique bonus)",
  418. "additionalProperties" : {
  419. "$ref" : "bonusInstance.json"
  420. }
  421. },
  422. "battleEffects" : {
  423. "type" : "object",
  424. "additionalProperties" : {
  425. "$ref" : "#/definitions/battleEffect"
  426. }
  427. },
  428. "adventureEffect" : {
  429. "$ref" : "#/definitions/adventureEffect"
  430. },
  431. "targetModifier" : {
  432. "type" : "object",
  433. "additionalProperties" : false,
  434. "properties" : {
  435. "smart" : {
  436. "type" : "boolean",
  437. "description" : "true: friendly/hostile based on positiveness; false: all targets"
  438. },
  439. "clearAffected" :
  440. {
  441. "type" : "boolean",
  442. "description" : "LOCATION target only. All affected hexes/tile must be clear"
  443. }
  444. }
  445. }
  446. }
  447. },
  448. "texts" : {
  449. "type" : "object",
  450. "additionalProperties" : false
  451. }
  452. },
  453. "required" : ["type", "name", "school", "level", "power", "flags", "levels"],
  454. "additionalProperties" : false,
  455. "allOf": [
  456. {
  457. "if": {
  458. "not" : {
  459. "properties": {
  460. "index" : {
  461. "type" : "number"
  462. }
  463. }
  464. },
  465. "properties": {
  466. "type": {
  467. "enum" : ["adventure", "combat"]
  468. }
  469. }
  470. },
  471. "then": {
  472. "required" : ["school", "gainChance" ],
  473. "properties": {
  474. "levels": {
  475. "required" : ["none", "basic", "advanced", "expert"]
  476. },
  477. "graphics" : {
  478. "required" : ["iconBook", "iconScroll", "iconEffect", "iconImmune", "iconScenarioBonus"]
  479. }
  480. }
  481. }
  482. },
  483. {
  484. "if": {
  485. "not" : {
  486. "properties": {
  487. "index" : {
  488. "type" : "number"
  489. }
  490. }
  491. },
  492. "properties": {
  493. "type": {
  494. "const" : "ability"
  495. }
  496. }
  497. },
  498. "then": {
  499. "required" : ["school", "gainChance" ],
  500. "properties": {
  501. "levels": {
  502. "required" : ["none"]
  503. },
  504. "graphics" : {
  505. "required" : ["iconEffect", "iconImmune"]
  506. }
  507. }
  508. }
  509. }
  510. ],
  511. "properties" : {
  512. "index" : {
  513. "type" : "number",
  514. "description" : "numeric id of spell required only for original spells, prohibited for new spells"
  515. },
  516. "name" : {
  517. "type" : "string",
  518. "description" : "Localizable name of this spell"
  519. },
  520. "type" : {
  521. "type" : "string",
  522. "enum" : ["adventure", "combat", "ability"],
  523. "description" : "Spell type"
  524. },
  525. "school" : {
  526. "type" : "object",
  527. "description" : "List of spell schools this spell belongs to",
  528. "additionalProperties" : {
  529. "type" : "boolean"
  530. }
  531. },
  532. "level" : {
  533. "type" : "number",
  534. "description" : "Spell level",
  535. "minimum" : 0,
  536. "maximum" : 5
  537. },
  538. "power" : {
  539. "type" : "number",
  540. "description" : "Base power of the spell"
  541. },
  542. "defaultGainChance" : {
  543. "type" : "number",
  544. "description" : "Gain chance by default for all factions"
  545. },
  546. "canCastOnSelf" : {
  547. "type" : "boolean",
  548. "description" : "If used as creature spell, unit can cast this spell on itself"
  549. },
  550. "canCastOnlyOnSelf" : {
  551. "type" : "boolean",
  552. "description" : "If used as creature spell, unit can cast this spell only on itself"
  553. },
  554. "canCastWithoutSkip" : {
  555. "type" : "boolean",
  556. "description" : "If used the creature will not skip the turn after casting a spell."
  557. },
  558. "gainChance" : {
  559. "type" : "object",
  560. "description" : "Chance for this spell to appear in Mage Guild of a specific faction",
  561. "additionalProperties" : {
  562. "type" : "number",
  563. "minimum" : 0
  564. }
  565. },
  566. "targetType" : {
  567. "type" : "string",
  568. "description" : "NO_TARGET - instant cast no aiming, default; CREATURE - target is unit; OBSTACLE - target is OBSTACLE; LOCATION - target is location",
  569. "enum" : ["NO_TARGET","CREATURE","OBSTACLE","LOCATION"]
  570. },
  571. "counters" : {
  572. "$ref" : "#/definitions/flags",
  573. "description" : "Flags structure ids of countering spells"
  574. },
  575. "flags" : {
  576. "type" : "object",
  577. "description" : "Various flags",
  578. "additionalProperties" : false,
  579. "properties" : {
  580. "indifferent" : {
  581. "type" : "boolean",
  582. "description" : "Spell is indifferent for target"
  583. },
  584. "negative" : {
  585. "type" : "boolean",
  586. "description" : "Spell is negative for target"
  587. },
  588. "positive" : {
  589. "type" : "boolean",
  590. "description" : "Spell is positive for target"
  591. },
  592. "damage" : {
  593. "type" : "boolean",
  594. "description" : "Spell does damage (direct or indirect)"
  595. },
  596. "offensive" : {
  597. "type" : "boolean",
  598. "description" : "Spell does direct damage (implicitly sets damage and negative)"
  599. },
  600. "rising" : {
  601. "type" : "boolean",
  602. "description" : "Rising spell (implicitly sets positive)"
  603. },
  604. "special" : {
  605. "type" : "boolean",
  606. "description" : "Special spell. Can be given only by BonusType::SPELL"
  607. },
  608. "nonMagical" : {
  609. "type" : "boolean",
  610. "description" : "Non-magical ability. Usually used by some creatures. Should not be affected by sorcery and generic magic resistance. School resistances apply. Examples: dendroid bind, efreet fire shield."
  611. }
  612. }
  613. },
  614. "immunity" : {
  615. "$ref" : "#/definitions/flags",
  616. "description" : "flags structure of bonus names, any one of these bonus grants immunity"
  617. },
  618. "absoluteImmunity" : {
  619. "$ref" : "#/definitions/flags",
  620. "description" : "flags structure of bonus names. Any one of these bonus grants immunity, can't be negated"
  621. },
  622. "limit" : {
  623. "$ref" : "#/definitions/flags",
  624. "description" : "flags structure of bonus names, presence of all bonuses required to be affected by."
  625. },
  626. "absoluteLimit" : {
  627. "$ref" : "#/definitions/flags",
  628. "description" : "flags structure of bonus names, presence of all bonuses required to be affected by, can't be negated."
  629. },
  630. "targetCondition" : {
  631. "type" : "object",
  632. "additionalProperties" : false,
  633. "properties" : {
  634. "noneOf" : { "type" : "object", "additionalProperties" : { "type" : "string", "enum" : [ "absolute", "normal" ] } },
  635. "anyOf" : { "type" : "object", "additionalProperties" : { "type" : "string", "enum" : [ "absolute", "normal" ] } },
  636. "allOf" : { "type" : "object", "additionalProperties" : { "type" : "string", "enum" : [ "absolute", "normal" ] } }
  637. }
  638. },
  639. "animation" : {"$ref" : "#/definitions/animation"},
  640. "graphics" : {
  641. "type" : "object",
  642. "additionalProperties" : false,
  643. "properties" : {
  644. "iconBook" : {
  645. "type" : "string",
  646. "description" : "Resourse path of icon for spellbook" ,
  647. "format" : "imageFile"
  648. },
  649. "iconScroll" : {
  650. "type" : "string",
  651. "description" : "Resourse path of icon for spell scrolls",
  652. "format" : "imageFile"
  653. },
  654. "iconEffect" : {
  655. "type" : "string",
  656. "description" : "Resourse path of icon for spell effects during battle",
  657. "format" : "imageFile"
  658. },
  659. "iconImmune" : {
  660. "type" : "string",
  661. "description" : "Resourse path of icon for SPELL_IMMUNITY bonus (relative to DATA or SPRITES)",
  662. "format" : "imageFile"
  663. },
  664. "iconScenarioBonus" : {
  665. "type" : "string",
  666. "description" : "Resourse path of 58x64 icon for scenario bonus",
  667. "format" : "imageFile"
  668. }
  669. }
  670. },
  671. "sounds" : {
  672. "type" : "object",
  673. "additionalProperties" : false,
  674. "properties" : {
  675. "cast" : {
  676. "type" : "string",
  677. "description" : "Resourse path of cast sound"
  678. }
  679. }
  680. },
  681. "levels" : {
  682. "type" : "object",
  683. "additionalProperties" : false,
  684. "properties" : {
  685. "none" : {
  686. "$ref" : "#/definitions/levelInfo"
  687. },
  688. "basic" : {
  689. "$ref" : "#/definitions/levelInfo"
  690. },
  691. "advanced" : {
  692. "$ref" : "#/definitions/levelInfo"
  693. },
  694. "expert" : {
  695. "$ref" : "#/definitions/levelInfo"
  696. }
  697. }
  698. },
  699. "onlyOnWaterMap" : {
  700. "type" : "boolean",
  701. "description" : "If true, spell won't be available on a map without water"
  702. }
  703. }
  704. }