Advertisement
Guest User

[Dwarf Fortress] PatrikLundell's biomemanipulator.lua

a guest
Jun 30th, 2017
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 84.29 KB | None | 0 0
  1. -- Allows manipulation of region biomes, mainly changing of evilness and addition/removal of plants and creatures from biome regions.
  2. --
  3. --[====[
  4.  
  5. biomemanipulator
  6. ========
  7. -- The biome determination logic is mainly copied and adapted from https://github.com/ragundo/exportmaps/blob/master/cpp/df_utils/biome_type.cpp#L105
  8. --
  9. ]====]
  10. local gui = require 'gui'
  11. local dialog = require 'gui.dialogs'
  12. local widgets =require 'gui.widgets'
  13. local guiScript = require 'gui.script'
  14. local utils = require 'utils'
  15.  
  16. local args = {...}
  17.  
  18. local Main_Page = {}
  19. local Animal_Page = {}
  20. local Plant_Page = {}
  21.  
  22. --================================================================
  23. -- The Grid widget defines an pen supporting X/Y character display grid supporting display of
  24. -- a grid larger than the frame allows through a panning viewport. The init function requires
  25. -- the specification of the width and height attributes that defines the grid dimensions.
  26. -- The grid coordinates are 0 based.
  27. --
  28. Grid = defclass (Grid, widgets.Widget)
  29. Grid.ATTRS =
  30. {width = DEFAULT_NIL,
  31. height = DEFAULT_NIL}
  32.  
  33. --================================================================
  34.  
  35. function Grid:init ()
  36. if type (self.width) ~= 'number' or
  37. type (self.height) ~= 'number' or
  38. self.width < 0 or
  39. self.height < 0 then
  40. error ("Grid widgets have to have their width and height set permanently on initiation")
  41. return
  42. end
  43.  
  44. self.grid = dfhack.penarray.new (self.width, self.height)
  45.  
  46. self.viewport = {x1 = 0,
  47. x2 = self.frame.r - self.frame.l,
  48. y1 = 0,
  49. y2 = self.frame.b - self.frame.t}
  50. end
  51.  
  52. --================================================================
  53.  
  54. function Grid:panTo (x, y)
  55. local x_size = self.viewport.x2 - self.viewport.x1 + 1
  56. local y_size = self.viewport.y2 - self.viewport.y1 + 1
  57.  
  58. self.viewport.x1 = x
  59.  
  60. if self.viewport.x1 + x_size > self.width then
  61. self.viewport.x1 = self.width - x_size
  62. end
  63.  
  64. if self.viewport.x1 < 0 then
  65. self.viewport.x1 = 0
  66. end
  67.  
  68. self.viewport.x2 = self.viewport.x1 + x_size - 1
  69.  
  70. self.viewport.y1 = y
  71.  
  72. if self.viewport.y1 + y_size > self.height then
  73. self.viewport.y1 = self.height - y_size
  74. end
  75.  
  76. if self.viewport.y1 < 0 then
  77. self.viewport.y1 = 0
  78. end
  79.  
  80. self.viewport.y2 = self.viewport.y1 + y_size - 1
  81. end
  82.  
  83. --================================================================
  84. -- Pans the viewport in the X and Y dimensions the number of steps specified by the parameters.
  85. -- It will stop the panning at 0, however, and will not pan outside of the grid (a grid smaller)
  86. -- than the frame will still have non grid parts in the frame, of course).
  87. --
  88. function Grid:pan (x, y)
  89. self:panTo (self.viewport.x1 + x, self.viewport.y1 + y)
  90. end
  91.  
  92. --================================================================
  93.  
  94. function Grid:panCenter (x, y)
  95. self:panTo (x - math.floor ((self.viewport.x2 - self.viewport.x1 + 1) / 2),
  96. y - math.floor ((self.viewport.y2 - self.viewport.y1 + 1) / 2))
  97. end
  98.  
  99. --================================================================
  100. -- Assigns a value to the specified grid (not frame) coordinates. The 'pen'
  101. -- parameter has to be a DFHack 'pen' table or object.
  102. --
  103. function Grid:set (x, y, pen)
  104. if x < 0 or x >= self.width then
  105. error ("Grid:set error: x out of bounds " .. tostring (x) .. " vs 0 - " .. tostring (self.width - 1))
  106. return
  107.  
  108. elseif y < 0 or y >= self.height then
  109. error ("Grid:set error: y out of bounds " .. tostring (y) .. " vs 0 - " .. tostring (self.height - 1))
  110. return
  111. end
  112.  
  113. self.grid:set_tile (x, y, pen)
  114. end
  115.  
  116. --================================================================
  117. -- Returns the data at position x, y in the grid.
  118. --
  119. function Grid:get (x, y)
  120. if x < 0 or x >= self.width then
  121. error ("Grid:set error: x out of bounds " .. tostring (x) .. " vs 0 - " .. tostring (self.width - 1))
  122. return
  123.  
  124. elseif y < 0 or y >= self.height then
  125. error ("Grid:set error: y out of bounds " .. tostring (y) .. " vs 0 - " .. tostring (self.height - 1))
  126. return
  127. else
  128. return self.grid:get_tile (x, y)
  129. end
  130. end
  131.  
  132. --================================================================
  133. -- Renders the contents within the viewport into the frame.
  134. --
  135. function Grid:onRenderBody (dc)
  136. self.grid:draw (self.frame.l,
  137. self.frame.t,
  138. self.viewport.x2 - self.viewport.x1 + 1,
  139. self.viewport.y2 - self.viewport.y1 + 1,
  140. self.viewport.x1,
  141. self.viewport.y1)
  142. end
  143.  
  144. --================================================================
  145. --================================================================
  146.  
  147. function biomemanipulator (region)
  148. local map_width = df.global.world.world_data.world_width
  149. local map_height = df.global.world.world_data.world_height
  150. local pole = df.global.world.world_data.flip_latitude
  151. local evilness
  152. local animals = 0
  153. local plants = 0
  154. local size
  155. local x
  156. local y
  157. local Focus = "Main"
  158. local Unrestricted = false
  159.  
  160. if region == NIL then
  161. x = df.global.world.world_data.region_details [0].pos.x
  162. y = df.global.world.world_data.region_details [0].pos.y
  163. region = df.global.world.world_data.region_map [x]:_displace (y).region_id
  164.  
  165. else
  166. x = df.global.world.world_data.regions [region].region_coords.x [0]
  167. y = df.global.world.world_data.regions [region].region_coords.x [0]
  168. end
  169.  
  170. evilness = df.global.world.world_data.region_map [x]:_displace (y).evilness
  171. size = #df.global.world.world_data.regions [region].region_coords.x
  172.  
  173. for i, population in ipairs (df.global.world.world_data.regions [region].population) do
  174. if population.type == df.world_population_type.Animal or
  175. population.type == df.world_population_type.Vermin or
  176. population.type == df.world_population_type.VerminInnumerable or
  177. population.type == df.world_population_type.ColonyInsect then
  178. animals = animals + 1
  179.  
  180. elseif population.type == df.world_population_type.Tree or
  181. population.type == df.world_population_type.Grass or
  182. population.type == df.world_population_type.Bush then
  183. plants = plants + 1
  184. end
  185. end
  186.  
  187. local keybindings = {
  188. evilness = {key = "CUSTOM_E",
  189. desc = "Change biome's Evilness"},
  190. unrestricted = {key = "CUSTOM_U",
  191. desc = "Toggles whether plant and animal selection is limited to region applicable types"},
  192. animals = {key = "CUSTOM_A",
  193. desc = "Change Animals within the biome"},
  194. plants = {key = "CUSTOM_P",
  195. desc = "Change Plants within the biome"},
  196. floradiversity = {key = "CUSTOM_F",
  197. desc = "Gives all regions all plants legal to their biomes"},
  198. faunadiversity = {key = "CUSTOM_SHIFT_F",
  199. desc = "Gives all regions all creatures legal to their biomes"},
  200. region = {key = "CUSTOM_R",
  201. desc = "Display the region map"},
  202. biome = {key = "CUSTOM_B",
  203. desc = "Display the biome map"},
  204. min_count = {key = "CUSTOM_X",
  205. desc = "Change the minimum number of a creature"},
  206. max_count = {key = "CUSTOM_SHIFT_X",
  207. desc = "Change the maximum number of a creature"},
  208. next_edit = {key = "CHANGETAB",
  209. desc = "Change focus to the next item"},
  210. prev_edit = {key = "SEC_CHANGETAB",
  211. desc = "Change focus to the previous item"},
  212. up = {key = "CURSOR_UP",
  213. desc = "Shifts focus 1 step upwards"},
  214. down = {key = "CURSOR_DOWN",
  215. desc = "Shifts focus 1 step downwards"},
  216. left = {key = "CURSOR_LEFT",
  217. desc = "Shifts focus 1 step to the left"},
  218. right = {key = "CURSOR_RIGHT",
  219. desc = "Shift focus 1 step to the right"},
  220. upleft = {key = "CURSOR_UPLEFT",
  221. desc = "Shifts focus 1 step up to the left"},
  222. upright = {key = "CURSOR_UPRIGHT",
  223. desc = "Shifts focus 1 step up to the right"},
  224. downleft = {key = "CURSOR_DOWNLEFT",
  225. desc = "Shifts focus 1 step down to the left"},
  226. downright = {key = "CURSOR_DOWNRIGHT",
  227. desc = "Shifts focus 1 step down to the right"},
  228. help = {key = "HELP",
  229. desc= " Show this help/info"}}
  230.  
  231. --============================================================
  232.  
  233. function check_tropicality_no_poles_world (temperature)
  234. local is_possible_tropical_area_by_latitude = false
  235. local is_tropical_area_by_latitude = false
  236.  
  237. -- No poles => Temperature determines tropicality
  238. --
  239. if temperature >= 75 then
  240. is_possible_tropical_area_by_latitude = true
  241. end
  242. is_tropical_area_by_latitude = temperature >= 85
  243.  
  244. return is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude
  245. end
  246.  
  247. --============================================================
  248.  
  249. function check_tropicality_north_pole_only_world (pos_y,
  250. map_height)
  251. local v6
  252. local is_possible_tropical_area_by_latitude = false
  253. local is_tropical_area_by_latitude = false
  254.  
  255. if map_height == 17 then
  256. v6 = pos_y * 16
  257.  
  258. elseif map_height == 33 then
  259. v6 = pos_y * 8
  260.  
  261. elseif map_height == 65 then
  262. v6 = pos_y * 4
  263.  
  264. elseif map_height == 129 then
  265. v6 = pos_y * 2
  266.  
  267. else
  268. v6 = pos_y
  269. end
  270.  
  271. is_possible_tropical_area_by_latitude = v6 > 170
  272. is_tropical_area_by_latitude = v6 >= 200
  273.  
  274. return is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude
  275. end
  276.  
  277. --============================================================
  278.  
  279. function check_tropicality_south_pole_only_world (pos_y,
  280. map_height)
  281. local v6 = map_height - pos_y - 1
  282. local is_possible_tropical_area_by_latitude = false
  283. local is_tropical_area_by_latitude = false
  284.  
  285. if map_height == 17 then
  286. v6 = v6 * 16
  287.  
  288. elseif map_height == 33 then
  289. v6 = v6 * 8
  290.  
  291. elseif map_height == 65 then
  292. v6 = v6 * 4
  293.  
  294. elseif map_height == 129 then
  295. v6 = v6 * 2
  296.  
  297. else
  298. v6 = v6
  299. end
  300.  
  301. is_possible_tropical_area_by_latitude = v6 > 170
  302. is_tropical_area_by_latitude = v6 >= 200
  303.  
  304. return is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude
  305. end
  306.  
  307. --============================================================
  308.  
  309. function check_tropicality_both_poles_world (pos_y,
  310. map_height)
  311. local v6
  312. local is_possible_tropical_area_by_latitude = false
  313. local is_tropical_area_by_latitude = false
  314.  
  315. if pos_y < math.floor (map_height / 2) then
  316. v6 = 2 * pos_y
  317.  
  318. else
  319. v6 = map_height + 2 * (math.floor (map_height / 2) - pos_y) - 1
  320.  
  321. if v6 < 0 then
  322. v6 = 0
  323. end
  324.  
  325. if v6 >= map_height then
  326. v6 = map_height - 1
  327. end
  328. end
  329.  
  330. if map_height == 17 then
  331. v6 = v6 * 16
  332.  
  333. elseif map_height == 33 then
  334. v6 = v6 * 8
  335.  
  336. elseif map_height == 65 then
  337. v6 = v6 * 4
  338.  
  339. elseif map_height == 129 then
  340. v6 = v6 * 2
  341.  
  342. else
  343. v6 = v6
  344. end
  345.  
  346. is_possible_tropical_area_by_latitude = v6 > 170
  347. is_tropical_area_by_latitude = v6 >= 200
  348.  
  349. return is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude
  350. end
  351.  
  352. --============================================================
  353.  
  354. function check_tropicality (pos_y,
  355. map_height,
  356. temperature)
  357. local flip_latitude = df.global.world.world_data.flip_latitude
  358.  
  359. if flip_latitude == -1 then -- No poles
  360. return check_tropicality_no_poles_world (temperature)
  361.  
  362. elseif flip_latitude == 0 then -- North pole
  363. return check_tropicality_north_pole_only_world (pos_y,
  364. map_height)
  365.  
  366. elseif flip_latitude == 1 then -- South pole
  367. return check_tropicality_south_pole_only_world (pos_y,
  368. map_height)
  369.  
  370. elseif flip_latitude == 2 then -- Both poles
  371. return check_tropicality_both_poles_world (pos_y,
  372. map_height)
  373.  
  374. else
  375. return false, false
  376. end
  377. end
  378.  
  379. --============================================================
  380.  
  381. function get_parameter_percentage (flip_latitude,
  382. pos_y,
  383. rainfall,
  384. map_height)
  385. local result
  386. local ypos = pos_y
  387.  
  388. if flip_latitude == -1 then -- No poles
  389. return 100
  390.  
  391. elseif flip_latitude == 1 then -- South pole
  392. ypos = map_height - ypos - 1
  393.  
  394. elseif flip_latitude == 2 then -- North and South pole
  395. if ypos < math.floor (map_height / 2) then
  396. ypos = ypos * 2
  397.  
  398. else
  399. ypos = map_height + 2 * (math.floor (map_height / 2) - ypos) - 1
  400. if ypos < 0 then
  401. ypos = 0
  402. end
  403.  
  404. if ypos >= map_height then
  405. ypos = map_height - 1
  406. end
  407. end
  408. end
  409.  
  410. local latitude
  411. if map_height == 17 then
  412. latitude = 16 * ypos
  413. elseif map_height == 33 then
  414. latitude = 8 * ypos
  415. elseif map_height == 65 then
  416. latitude = 4 * ypos
  417. elseif map_height == 129 then
  418. latitude = 2 * ypos
  419. else
  420. latitude = ypos
  421. end
  422.  
  423. if latitude > 220 then
  424. return 100
  425.  
  426. elseif latitude > 190 and
  427. latitude < 201 then
  428. return 0
  429.  
  430. elseif latitude >= 201 then
  431. result = rainfall + 16 * (latitude - 207)
  432.  
  433. else
  434. result = 16 * (184 - latitude) - rainfall
  435. end
  436.  
  437. if result < 0 then
  438. return 0
  439. elseif result > 100 then
  440. return 100
  441. else
  442. return result
  443. end
  444. end
  445.  
  446. --============================================================
  447.  
  448. function get_region_parameter (pos_y,
  449. rainfall,
  450. map_height)
  451.  
  452. local result = 100
  453.  
  454. if map_height > 65 then -- Medium & Large worlds
  455. return get_parameter_percentage (df.global.world.world_data.flip_latitude,
  456. pos_y,
  457. rainfall,
  458. map_height)
  459. end
  460.  
  461. return result
  462. end
  463.  
  464. --============================================================
  465.  
  466. function get_lake_biome (is_possible_tropical_area_by_latitude,
  467. salinity)
  468. if salinity < 33 then
  469. if is_possible_tropical_area_by_latitude then
  470. return df.biome_type.LAKE_TROPICAL_FRESHWATER
  471. else
  472. return df.biome_type.LAKE_TEMPERATE_FRESHWATER
  473. end
  474.  
  475. elseif salinity < 66 then
  476. if is_possible_tropical_area_by_latitude then
  477. return df.biome_type.LAKE_TROPICAL_BRACKISHWATER
  478. else
  479. return df.biome_type.LAKE_TEMPERATE_BRACKISHWATER
  480. end
  481.  
  482. else
  483. if is_possible_tropical_area_by_latitude then
  484. return df.biome_type.LAKE_TROPICAL_SALTWATER
  485. else
  486. return df.biome_type.LAKE_TEMPERATE_SALTWATER
  487. end
  488. end
  489. end
  490.  
  491. --============================================================
  492.  
  493. function get_ocean_biome (is_tropical_area_by_latitude,
  494. temperature)
  495. if is_tropical_area_by_latitude then
  496. return df.biome_type.OCEAN_TROPICAL
  497. elseif temperature <= -5 then
  498. return df.biome_type.OCEAN_ARCTIC
  499. else
  500. return df.biome_type.OCEAN_TEMPERATE
  501. end
  502. end
  503.  
  504. --============================================================
  505.  
  506. function get_desert_biome (drainage)
  507. if drainage < 33 then
  508. return df.biome_type.DESERT_SAND
  509. elseif drainage < 66 then
  510. return df.biome_type.DESERT_ROCK
  511. else
  512. return df.biome_type.DESERT_BADLAND
  513. end
  514. end
  515.  
  516. --============================================================
  517.  
  518. function get_biome_grassland (is_possible_tropical_area_by_latitude,
  519. is_tropical_area_by_latitude,
  520. rainfall,
  521. pos_y,
  522. map_height)
  523.  
  524. if (is_possible_tropical_area_by_latitude and
  525. get_region_parameter(pos_y, rainfall, map_height) < 66) or
  526. is_tropical_area_by_latitude then
  527. return df.biome_type.GRASSLAND_TROPICAL
  528. else
  529. return df.biome_type.GRASSLAND_TEMPERATE
  530. end
  531. end
  532.  
  533. --============================================================
  534.  
  535. function get_biome_savanna (is_possible_tropical_area_by_latitude,
  536. is_tropical_area_by_latitude,
  537. rainfall,
  538. pos_y,
  539. map_height)
  540. if is_tropical_area_by_latitude or
  541. (is_possible_tropical_area_by_latitude and
  542. get_region_parameter (pos_y, rainfall, map_height) <= 6) then
  543. return df.biome_type.SAVANNA_TROPICAL
  544. else
  545. return df.biome_type.SAVANNA_TEMPERATE
  546. end
  547. end
  548.  
  549. --============================================================
  550.  
  551. function get_biome_desert_or_grassland_or_savanna (is_possible_tropical_area_by_latitude,
  552. is_tropical_area_by_latitude,
  553. vegetation,
  554. drainage,
  555. rainfall,
  556. pos_y,
  557. map_height)
  558. if vegetation < 10 then
  559. return get_desert_biome (drainage)
  560.  
  561. elseif vegetation < 20 then
  562. return get_biome_grassland (is_possible_tropical_area_by_latitude,
  563. is_tropical_area_by_latitude,
  564. rainfall,
  565. pos_y,
  566. map_height)
  567.  
  568. else
  569. return get_biome_savanna (is_possible_tropical_area_by_latitude,
  570. is_tropical_area_by_latitude,
  571. rainfall,
  572. pos_y,
  573. map_height)
  574. end
  575. end
  576.  
  577. --============================================================
  578.  
  579. function get_biome_shrubland (is_possible_tropical_area_by_latitude,
  580. is_tropical_area_by_latitude,
  581. rainfall,
  582. pos_y,
  583. map_height)
  584. if is_tropical_area_by_latitude or
  585. (is_possible_tropical_area_by_latitude and
  586. get_region_parameter (pos_y, rainfall, map_height) < 66) then
  587. return df.biome_type.SHRUBLAND_TROPICAL
  588. else
  589. return df.biome_type.SHRUBLAND_TEMPERATE
  590. end
  591. end
  592.  
  593. --============================================================
  594.  
  595. function get_biome_marsh (is_possible_tropical_area_by_latitude,
  596. is_tropical_area_by_latitude,
  597. salinity,
  598. rainfall,
  599. pos_y,
  600. map_height)
  601. if salinity < 66 then
  602. if is_tropical_area_by_latitude or
  603. (is_possible_tropical_area_by_latitude and
  604. get_region_parameter (pos_y, rainfall, map_height) < 66) then
  605. return df.biome_type.MARSH_TROPICAL_FRESHWATER
  606. else
  607. return df.biome_type.MARSH_TEMPERATE_FRESHWATER
  608. end
  609.  
  610. else
  611. if is_tropical_area_by_latitude or
  612. (is_possible_tropical_area_by_latitude and
  613. get_region_parameter (pos_y, rainfall, map_height) < 66) then
  614. return df.biome_type.MARSH_TROPICAL_SALTWATER
  615. else
  616. return df.biome_type.MARSH_TEMPERATE_SALTWATER
  617. end
  618. end
  619. end
  620.  
  621. --============================================================
  622.  
  623. function get_biome_shrubland_or_marsh (is_possible_tropical_area_by_latitude,
  624. is_tropical_area_by_latitude,
  625. drainage,
  626. salinity,
  627. rainfall,
  628. pos_y,
  629. map_height)
  630. if drainage < 33 then
  631. return get_biome_marsh (is_possible_tropical_area_by_latitude,
  632. is_tropical_area_by_latitude,
  633. salinity,
  634. rainfall,
  635. pos_y,
  636. map_height)
  637. else
  638. return get_biome_shrubland (is_possible_tropical_area_by_latitude,
  639. is_tropical_area_by_latitude,
  640. rainfall,
  641. pos_y,
  642. map_height)
  643. end
  644. end
  645.  
  646. --============================================================
  647.  
  648. function get_biome_forest (is_possible_tropical_area_by_latitude,
  649. is_tropical_area_by_latitude,
  650. rainfall,
  651. temperature,
  652. pos_y,
  653. map_height)
  654. local parameter = get_region_parameter (pos_y, rainfall, map_height)
  655.  
  656. if is_possible_tropical_area_by_latitude then
  657. if (parameter < 66 or
  658. is_tropical_area_by_latitude) and
  659. rainfall < 75 then
  660. return df.biome_type.FOREST_TROPICAL_CONIFER
  661.  
  662. elseif parameter < 66 then
  663. return df.biome_type.FOREST_TROPICAL_DRY_BROADLEAF
  664.  
  665. elseif is_tropical_area_by_latitude then
  666. return df.biome_type.FOREST_TROPICAL_MOIST_BROADLEAF
  667.  
  668. elseif rainfall < 75 or
  669. temperature < 65 then
  670. if temperature < 10 then
  671. return df.biome_type.FOREST_TAIGA
  672.  
  673. else
  674. return df.biome_type.FOREST_TEMPERATE_CONIFER
  675. end
  676.  
  677. else
  678. return df.biome_type.FOREST_TEMPERATE_BROADLEAF
  679. end
  680.  
  681. else
  682. if rainfall < 75 or
  683. temperature < 65 then
  684. if temperature < 10 then
  685. return df.biome_type.FOREST_TAIGA
  686. else
  687. return df.biome_type.FOREST_TEMPERATE_CONIFER
  688. end
  689.  
  690. else
  691. return df.biome_type.FOREST_TEMPERATE_BROADLEAF
  692. end
  693. end
  694. end
  695.  
  696. --============================================================
  697.  
  698. function get_biome_swamp (is_possible_tropical_area_by_latitude,
  699. is_tropical_area_by_latitude,
  700. salinity,
  701. drainage,
  702. rainfall,
  703. pos_y,
  704. map_height)
  705. local parameter = get_region_parameter (pos_y, rainfall, map_height)
  706.  
  707. if is_possible_tropical_area_by_latitude then
  708. if salinity < 66 then
  709. if parameter < 66 or
  710. is_tropical_area_by_latitude then
  711. return df.biome_type.SWAMP_TROPICAL_FRESHWATER
  712. else
  713. return df.biome_type.SWAMP_TEMPERATE_FRESHWATER
  714. end
  715.  
  716. elseif parameter < 66 or
  717. is_tropical_area_by_latitude then
  718. if drainage < 10 then
  719. return df.biome_type.SWAMP_MANGROVE
  720. else
  721. return df.biome_type.SWAMP_TROPICAL_SALTWATER
  722. end
  723.  
  724. else
  725. return df.biome_type.SWAMP_TEMPERATE_SALTWATER
  726. end
  727.  
  728. else
  729. if salinity < 66 then
  730. return df.biome_type.SWAMP_TEMPERATE_FRESHWATER
  731. else
  732. return df.biome_type.SWAMP_TEMPERATE_SALTWATER
  733. end
  734. end
  735. end
  736.  
  737. --============================================================
  738.  
  739. function get_biome_type (biome_pos_y,
  740. map_height,
  741. temperature,
  742. elevation,
  743. drainage,
  744. rainfall,
  745. salinity,
  746. vegetation,
  747. region_id)
  748.  
  749. local is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude =
  750. check_tropicality (biome_pos_y,
  751. map_height,
  752. temperature)
  753.  
  754. if df.global.world.world_data.regions[region_id].type == df.world_region_type.Lake then
  755. return get_lake_biome (is_possible_tropical_area_by_latitude,
  756. salinity)
  757.  
  758. elseif elevation >= 150 then
  759. return df.biome_type.MOUNTAIN
  760.  
  761. elseif elevation < 100 then
  762. return get_ocean_biome (is_tropical_area_by_latitude,
  763. temperature)
  764.  
  765. elseif temperature <= -5 then
  766. if drainage < 75 then
  767. return df.biome_type.TUNDRA
  768. else
  769. return df.biome_type.GLACIER
  770. end
  771.  
  772. elseif vegetation < 33 then
  773. return get_biome_desert_or_grassland_or_savanna (is_possible_tropical_area_by_latitude,
  774. is_tropical_area_by_latitude,
  775. vegetation,
  776. drainage,
  777. rainfall,
  778. biome_pos_y,
  779. map_height)
  780.  
  781. elseif vegetation < 66 then
  782. return get_biome_shrubland_or_marsh (is_possible_tropical_area_by_latitude,
  783. is_tropical_area_by_latitude,
  784. drainage,
  785. salinity,
  786. rainfall,
  787. biome_pos_y,
  788. map_height)
  789.  
  790. elseif drainage < 33 then
  791. return get_biome_swamp (is_possible_tropical_area_by_latitude,
  792. is_tropical_area_by_latitude,
  793. salinity,
  794. drainage,
  795. rainfall,
  796. biome_pos_y,
  797. map_height)
  798. else
  799. return get_biome_forest (is_possible_tropical_area_by_latitude,
  800. is_tropical_area_by_latitude,
  801. rainfall,
  802. temperature,
  803. biome_pos_y,
  804. map_height)
  805. end
  806. end
  807.  
  808. --============================================================
  809.  
  810. function get_biome_character (local_pos_y,
  811. biome_reference_y,
  812. biome_home_y,
  813. map_height,
  814. temperature,
  815. elevation,
  816. drainage,
  817. rainfall,
  818. salinity,
  819. vegetation,
  820. region_id)
  821.  
  822. local biome_type
  823.  
  824. biome_type = get_biome_type (biome_reference_y,
  825. map_height,
  826. temperature,
  827. elevation,
  828. drainage,
  829. rainfall,
  830. salinity,
  831. vegetation,
  832. region_id)
  833.  
  834. if biome_type == df.biome_type.MOUNTAIN then
  835. return '+'
  836. elseif biome_type == df.biome_type.GLACIER then
  837. return '*'
  838. elseif biome_type == df.biome_type.TUNDRA then
  839. return 't'
  840. elseif biome_type == df.biome_type.SWAMP_TEMPERATE_FRESHWATER then
  841. return 'p'
  842. elseif biome_type == df.biome_type.SWAMP_TEMPERATE_SALTWATER then
  843. return 'r'
  844. elseif biome_type == df.biome_type.MARSH_TEMPERATE_FRESHWATER then
  845. return 'n'
  846. elseif biome_type == df.biome_type.MARSH_TEMPERATE_SALTWATER then
  847. return 'y'
  848. elseif biome_type == df.biome_type.SWAMP_TROPICAL_FRESHWATER then
  849. return 'P'
  850. elseif biome_type == df.biome_type.SWAMP_TROPICAL_SALTWATER then
  851. return 'R'
  852. elseif biome_type == df.biome_type.SWAMP_MANGROVE then
  853. return 'M'
  854. elseif biome_type == df.biome_type.MARSH_TROPICAL_FRESHWATER then
  855. return 'N'
  856. elseif biome_type == df.biome_type.MARSH_TROPICAL_SALTWATER then
  857. return 'Y'
  858. elseif biome_type == df.biome_type.FOREST_TAIGA then
  859. return 'T'
  860. elseif biome_type == df.biome_type.FOREST_TEMPERATE_CONIFER then
  861. return 'c'
  862. elseif biome_type == df.biome_type.FOREST_TEMPERATE_BROADLEAF then
  863. return 'l'
  864. elseif biome_type == df.biome_type.FOREST_TROPICAL_CONIFER then
  865. return 'C'
  866. elseif biome_type == df.biome_type.FOREST_TROPICAL_DRY_BROADLEAF then
  867. return 'd'
  868. elseif biome_type == df.biome_type.FOREST_TROPICAL_MOIST_BROADLEAF then
  869. return 'L'
  870. elseif biome_type == df.biome_type.GRASSLAND_TEMPERATE then
  871. return 'g'
  872. elseif biome_type == df.biome_type.SAVANNA_TEMPERATE then
  873. return 's'
  874. elseif biome_type == df.biome_type.SHRUBLAND_TEMPERATE then
  875. return 'u'
  876. elseif biome_type == df.biome_type.GRASSLAND_TROPICAL then
  877. return 'G'
  878. elseif biome_type == df.biome_type.SAVANNA_TROPICAL then
  879. return 'S'
  880. elseif biome_type == df.biome_type.SHRUBLAND_TROPICAL then
  881. return 'U'
  882. elseif biome_type == df.biome_type.DESERT_BADLAND then
  883. return 'B'
  884. elseif biome_type == df.biome_type.DESERT_ROCK then
  885. return 'e'
  886. elseif biome_type == df.biome_type.DESERT_SAND then
  887. return 'D'
  888. elseif biome_type == df.biome_type.OCEAN_TROPICAL then
  889. return 'O'
  890. elseif biome_type == df.biome_type.OCEAN_TEMPERATE then
  891. return 'o'
  892. elseif biome_type == df.biome_type.OCEAN_ARCTIC then
  893. return 'a'
  894. elseif biome_type == df.biome_type.POOL_TEMPERATE_FRESHWATER then
  895. return '.'
  896. elseif biome_type == df.biome_type.POOL_TEMPERATE_BRACKISHWATER then
  897. return ':'
  898. elseif biome_type == df.biome_type.POOL_TEMPERATE_SALTWATER then
  899. return '!'
  900. elseif biome_type == df.biome_type.POOL_TROPICAL_FRESHWATER then
  901. return ','
  902. elseif biome_type == df.biome_type.POOL_TROPICAL_BRACKISHWATER then
  903. return ';'
  904. elseif biome_type == df.biome_type.POOL_TROPICAL_SALTWATER then
  905. return '|'
  906. elseif biome_type == df.biome_type.LAKE_TEMPERATE_FRESHWATER then
  907. return '<'
  908. elseif biome_type == df.biome_type.LAKE_TEMPERATE_BRACKISHWATER then
  909. return '-'
  910. elseif biome_type == df.biome_type.LAKE_TEMPERATE_SALTWATER then
  911. return '['
  912. elseif biome_type == df.biome_type.LAKE_TROPICAL_FRESHWATER then
  913. return '>'
  914. elseif biome_type == df.biome_type.LAKE_TROPICAL_BRACKISHWATER then
  915. return '='
  916. elseif biome_type == df.biome_type.LAKE_TROPICAL_SALTWATER then
  917. return ']'
  918. elseif biome_type == df.biome_type.RIVER_TEMPERATE_FRESHWATER then
  919. return '\\'
  920. elseif biome_type == df.biome_type.RIVER_TEMPERATE_BRACKISHWATER then
  921. return '%'
  922. elseif biome_type == df.biome_type.RIVER_TEMPERATE_SALTWATER then
  923. return '('
  924. elseif biome_type == df.biome_type.RIVER_TROPICAL_FRESHWATER then
  925. return '/'
  926. elseif biome_type == df.biome_type.RIVER_TROPICAL_BRACKISHWATER then
  927. return '&'
  928. elseif biome_type == df.biome_type.RIVER_TROPICAL_SALTWATER then
  929. return ')'
  930. elseif biome_type == df.biome_type.SUBTERRANEAN_WATER then -- Never generated
  931. return '_'
  932. elseif biome_type == df.biome_type.SUBTERRANEAN_CHASM then -- Never generated
  933. return '^'
  934. elseif biome_type == df.biome_type.SUBTERRANEAN_LAVA then
  935. return '~'
  936. end
  937. end
  938.  
  939. --============================================================
  940.  
  941. function Sort (list)
  942. local temp
  943.  
  944. for i, dummy in ipairs (list) do
  945. for k = i + 1, #list do
  946. if list [k].name < list [i].name then
  947. temp = list [i]
  948. list [i] = list [k]
  949. list [k] = temp
  950. end
  951. end
  952. end
  953. end
  954.  
  955. --============================================================
  956.  
  957. function Is_Animal (value)
  958. return value == df.world_population_type.Animal or
  959. value == df.world_population_type.Vermin or
  960. value == df.world_population_type.VerminInnumerable or
  961. value == df.world_population_type.ColonyInsect
  962.  
  963. end
  964.  
  965. --============================================================
  966.  
  967. function Is_Plant (value)
  968. return value == df.world_population_type.Tree or
  969. value == df.world_population_type.Grass or
  970. value == df.world_population_type.Bush
  971. end
  972.  
  973. --============================================================
  974.  
  975. function Locate_Animal (index)
  976. for i, population in ipairs (df.global.world.world_data.regions [region].population) do
  977. if Is_Animal (population.type) and
  978. population.race == index then
  979. return i
  980. end
  981. end
  982.  
  983. return NIL
  984. end
  985.  
  986. --============================================================
  987.  
  988. function Locate_Plant (index)
  989. for i, population in ipairs (df.global.world.world_data.regions [region].population) do
  990. if Is_Plant (population.type) and
  991. population.plant == index then
  992. return i
  993. end
  994. end
  995.  
  996. return NIL
  997. end
  998.  
  999. --============================================================
  1000.  
  1001. function Fit_Right (Item, Size)
  1002. if string.len (Item) > Size then
  1003. return string.rep ('#', Size)
  1004. else
  1005. return string.rep (' ', Size - string.len (Item)) .. Item
  1006. end
  1007. end
  1008.  
  1009. --============================================================
  1010.  
  1011. function Savagery_Pen (evilness)
  1012. if evilness < 33 then
  1013. return COLOR_LIGHTCYAN
  1014. elseif evilness < 66 then
  1015. return COLOR_YELLOW
  1016. else
  1017. return COLOR_LIGHTMAGENTA
  1018. end
  1019. end
  1020.  
  1021. --============================================================
  1022.  
  1023. local Region_Pen =
  1024. {[0] = COLOR_WHITE,
  1025. [1] = COLOR_LIGHTCYAN,
  1026. [2] = COLOR_CYAN,
  1027. [3] = COLOR_LIGHTBLUE,
  1028. [4] = COLOR_BLUE,
  1029. [5] = COLOR_LIGHTGREEN,
  1030. [6] = COLOR_GREEN,
  1031. [7] = COLOR_YELLOW,
  1032. [8] = COLOR_LIGHTMAGENTA,
  1033. [9] = COLOR_MAGENTA,
  1034. [10] = COLOR_LIGHTRED,
  1035. [11] = COLOR_RED,
  1036. [12] = COLOR_GREY,
  1037. [13] = COLOR_DARKGREY,
  1038. [14] = COLOR_BROWN}
  1039.  
  1040. --============================================================
  1041.  
  1042. local Region_Character =
  1043. {[0] = 'A',
  1044. [1] = 'B',
  1045. [2] = 'C',
  1046. [3] = 'D',
  1047. [4] = 'E',
  1048. [5] = 'F',
  1049. [6] = 'G',
  1050. [7] = 'H',
  1051. [8] = 'K',
  1052. [9] = 'L',
  1053. [10] = 'M',
  1054. [11] = 'O',
  1055. [12] = 'P',
  1056. [13] = 'R',
  1057. [14] = 'S'}
  1058.  
  1059. --============================================================
  1060.  
  1061. function Make_Region (x, y)
  1062. local ch
  1063. local fg
  1064. local bg
  1065. local tile_color
  1066. local region_id
  1067.  
  1068. for i = 0, map_height - 1 do
  1069. for k = 0, map_width - 1 do
  1070. region_id = df.global.world.world_data.region_map [k]:_displace (i).region_id
  1071. ch = Region_Character [math.floor (region_id / 15) % 15]
  1072.  
  1073. if x == k and y == i then
  1074. fg = COLOR_BLACK
  1075. bg = Region_Pen [region_id % 15]
  1076. tile_color = false
  1077.  
  1078. else
  1079. fg = Region_Pen [region_id % 15]
  1080. bg = COLOR_BLACK
  1081. tile_color = true
  1082. end
  1083.  
  1084. Main_Page.Region_Grid:set (k, i,{ch = ch,
  1085. fg = fg,
  1086. bg = bg,
  1087. bold = false,
  1088. tile = nil,
  1089. tile_color = tile_color,
  1090. tile_fg = nil,
  1091. tile_bg = nil})
  1092. end
  1093. end
  1094. end
  1095.  
  1096. --============================================================
  1097.  
  1098. function Biome_Color (savagery, evilness)
  1099. if evilness < 33 then
  1100. if savagery < 33 then
  1101. return COLOR_BLUE
  1102. elseif savagery < 66 then
  1103. return COLOR_GREEN
  1104. else
  1105. return COLOR_LIGHTCYAN
  1106. end
  1107.  
  1108. elseif evilness < 66 then
  1109. if savagery < 33 then
  1110. return COLOR_GREY
  1111. elseif savagery < 66 then
  1112. return COLOR_LIGHTGREEN
  1113. else
  1114. return COLOR_YELLOW
  1115. end
  1116.  
  1117. else
  1118. if savagery < 33 then
  1119. return COLOR_MAGENTA
  1120. elseif savagery < 66 then
  1121. return COLOR_LIGHTRED
  1122. else
  1123. return COLOR_RED
  1124. end
  1125. end
  1126. end
  1127.  
  1128. --============================================================
  1129.  
  1130. function Make_Biome (x, y)
  1131. local ch
  1132. local fg
  1133. local bg
  1134. local tile_color
  1135. local region
  1136.  
  1137. for i = 0, map_height - 1 do
  1138. for k = 0, map_width - 1 do
  1139. region = df.global.world.world_data.region_map [k]:_displace (i)
  1140.  
  1141. ch = get_biome_character (i,
  1142. i,
  1143. i,
  1144. map_height,
  1145. region.temperature,
  1146. region.elevation,
  1147. region.drainage,
  1148. region.rainfall,
  1149. region.salinity,
  1150. region.vegetation,
  1151. region.region_id)
  1152.  
  1153. if x == k and y == i then
  1154. fg = COLOR_BLACK
  1155. bg = Biome_Color (region.savagery, region.evilness)
  1156. tile_color = false
  1157.  
  1158. else
  1159. fg = Biome_Color (region.savagery, region.evilness)
  1160. bg = COLOR_BLACK
  1161. tile_color = true
  1162. end
  1163.  
  1164. Main_Page.Biome_Grid:set (k, i,{ch = ch,
  1165. fg = fg,
  1166. bg = bg,
  1167. bold = false,
  1168. tile = nil,
  1169. tile_color = tile_color,
  1170. tile_fg = nil,
  1171. tile_bg = nil})
  1172. end
  1173. end
  1174. end
  1175.  
  1176. --============================================================
  1177.  
  1178. function Add_One (List, Index)
  1179. List [Index] = List [Index] + 1
  1180. end
  1181.  
  1182. --============================================================
  1183.  
  1184. function Make_Profile (region)
  1185. local Profile =
  1186. {BIOME_MOUNTAIN = 0,
  1187. BIOME_GLACIER = 0,
  1188. BIOME_TUNDRA = 0,
  1189. BIOME_SWAMP_TEMPERATE_SALTWATER = 0,
  1190. BIOME_SWAMP_TEMPERATE_FRESHWATER = 0,
  1191. BIOME_MARSH_TEMPERATE_FRESHWATER = 0,
  1192. BIOME_MARSH_TEMPERATE_SALTWATER = 0,
  1193. BIOME_SWAMP_TROPICAL_FRESHWATER = 0,
  1194. BIOME_SWAMP_TROPICAL_SALTWATER = 0,
  1195. BIOME_SWAMP_MANGROVE = 0,
  1196. BIOME_MARSH_TROPICAL_FRESHWATER = 0,
  1197. BIOME_MARSH_TROPICAL_SALTWATER = 0,
  1198. BIOME_FOREST_TAIGA = 0,
  1199. BIOME_FOREST_TEMPERATE_CONIFER = 0,
  1200. BIOME_FOREST_TEMPERATE_BROADLEAF = 0,
  1201. BIOME_FOREST_TROPICAL_CONIFER = 0,
  1202. BIOME_FOREST_TROPICAL_DRY_BROADLEAF = 0,
  1203. BIOME_FOREST_TROPICAL_MOIST_BROADLEAF = 0,
  1204. BIOME_GRASSLAND_TEMPERATE = 0,
  1205. BIOME_SAVANNA_TEMPERATE = 0,
  1206. BIOME_SHRUBLAND_TEMPERATE = 0,
  1207. BIOME_GRASSLAND_TROPICAL = 0,
  1208. BIOME_SAVANNA_TROPICAL = 0,
  1209. BIOME_SHRUBLAND_TROPICAL = 0,
  1210. BIOME_DESERT_BADLAND = 0,
  1211. BIOME_DESERT_ROCK = 0,
  1212. BIOME_DESERT_SAND = 0,
  1213. BIOME_OCEAN_TROPICAL = 0,
  1214. BIOME_OCEAN_TEMPERATE = 0,
  1215. BIOME_OCEAN_ARCTIC = 0,
  1216. --BIOME_SUBTERRANEAN_WATER = 0,
  1217. --BIOME_SUBTERRANEAN_CHASM = 0,
  1218. --BIOME_SUBTERRANEAN_LAVA = 0,
  1219. GOOD = false,
  1220. EVIL = false,
  1221. SAVAGE = 0}
  1222.  
  1223. for i, x_coord in ipairs (df.global.world.world_data.regions [region].region_coords.x) do
  1224. local y_coord = df.global.world.world_data.regions [region].region_coords.y [i]
  1225. local biome = df.global.world.world_data.region_map [x_coord]:_displace (y_coord)
  1226. local is_possible_tropical_area_by_latitude, is_tropical_area_by_latitude =
  1227. check_tropicality (y_coord,
  1228. map_height,
  1229. biome.temperature,
  1230. pole)
  1231.  
  1232. local biome_type = get_biome_type
  1233. (y_coord,
  1234. map_height,
  1235. biome.temperature,
  1236. biome.elevation,
  1237. biome.drainage,
  1238. biome.rainfall,
  1239. biome.salinity,
  1240. biome.rainfall, -- biome.vegetation, -- Should be vegetation, but doesn't seem to be set before finalization.
  1241. pole,
  1242. is_possible_tropical_area_by_latitude,
  1243. is_tropical_area_by_latitude)
  1244.  
  1245. Add_One (Profile, "BIOME_" .. df.biome_type [biome_type])
  1246.  
  1247. if biome.evilness < 33 then
  1248. Profile.GOOD = true
  1249. elseif biome.evilness >= 66 then
  1250. Profile.EVIL = true
  1251. end
  1252.  
  1253. if biome.savagery >= 66 then
  1254. Add_One (Profile, "SAVAGE")
  1255. end
  1256. end
  1257.  
  1258. Animal_Page.Present_List = {}
  1259. Animal_Page.Absent_List = {}
  1260. Animal_Page.Forbidden_List = {}
  1261. Plant_Page.Present_List = {}
  1262. Plant_Page.Absent_List = {}
  1263. Plant_Page.Forbidden_List = {}
  1264.  
  1265. for i, creature in ipairs (df.global.world.raws.creatures.all) do
  1266. local found = false
  1267. local matching
  1268.  
  1269. for k, v in ipairs (df.global.world.world_data.regions [region].population) do
  1270. if Is_Animal (v.type) and
  1271. v.race == i then
  1272. table.insert (Animal_Page.Present_List, {name = creature.creature_id, index = i})
  1273. found = true
  1274. break
  1275. end
  1276. end
  1277.  
  1278. if not found then
  1279. if creature.flags.EQUIPMENT_WAGON or
  1280. creature.flags.CASTE_MEGABEAST or
  1281. creature.flags.CASTE_SEMIMEGABEAST or
  1282. -- creature.flags.GENERATED or -- When is this flag set?
  1283. creature.flags.CASTE_TITAN or
  1284. creature.flags.CASTE_UNIQUE_DEMON or
  1285. creature.flags.CASTE_DEMON or
  1286. creature.flags.CASTE_NIGHT_CREATURE_ANY or
  1287. (creature.flags.GOOD and not Profile.GOOD) or
  1288. (creature.flags.EVIL and not Profile.EVIL) or
  1289. (creature.flags.SAVAGE and Profile.SAVAGE == 0) then
  1290. matching = false
  1291.  
  1292. elseif (creature.flags.BIOME_MOUNTAIN and Profile.BIOME_MOUNTAIN > 0) or
  1293. (creature.flags.BIOME_GLACIER and Profile.BIOME_GLACIER > 0) or
  1294. (creature.flags.BIOME_TUNDRA and Profile.BIOME_TUNDRA > 0) or
  1295. (creature.flags.BIOME_SWAMP_TEMPERATE_FRESHWATER and Profile.BIOME_SWAMP_TEMPERATE_FRESHWATER > 0) or
  1296. (creature.flags.BIOME_SWAMP_TEMPERATE_SALTWATER and Profile.BIOME_SWAMP_TEMPERATE_SALTWATER > 0) or
  1297. (creature.flags.BIOME_MARSH_TEMPERATE_FRESHWATER and Profile.BIOME_MARSH_TEMPERATE_FRESHWATER > 0) or
  1298. (creature.flags.BIOME_MARSH_TEMPERATE_SALTWATER and Profile.BIOME_MARSH_TEMPERATE_SALTWATER > 0) or
  1299. (creature.flags.BIOME_SWAMP_TROPICAL_FRESHWATER and Profile.BIOME_SWAMP_TROPICAL_FRESHWATER > 0) or
  1300. (creature.flags.BIOME_SWAMP_TROPICAL_SALTWATER and Profile.BIOME_SWAMP_TROPICAL_SALTWATER > 0) or
  1301. (creature.flags.BIOME_SWAMP_MANGROVE and Profile.BIOME_SWAMP_MANGROVE > 0) or
  1302. (creature.flags.BIOME_MARSH_TROPICAL_FRESHWATER and Profile.BIOME_MARSH_TROPICAL_FRESHWATER > 0) or
  1303. (creature.flags.BIOME_MARSH_TROPICAL_SALTWATER and Profile.BIOME_MARSH_TROPICAL_SALTWATER > 0) or
  1304. (creature.flags.BIOME_FOREST_TAIGA and Profile.BIOME_FOREST_TAIGA > 0) or
  1305. (creature.flags.BIOME_FOREST_TEMPERATE_CONIFER and Profile.BIOME_FOREST_TEMPERATE_CONIFER > 0) or
  1306. (creature.flags.BIOME_FOREST_TEMPERATE_BROADLEAF and Profile.BIOME_FOREST_TEMPERATE_BROADLEAF > 0) or
  1307. (creature.flags.BIOME_FOREST_TROPICAL_CONIFER and Profile.BIOME_FOREST_TROPICAL_CONIFER > 0) or
  1308. (creature.flags.BIOME_FOREST_TROPICAL_DRY_BROADLEAF and Profile.BIOME_FOREST_TROPICAL_DRY_BROADLEAF > 0) or
  1309. (creature.flags.BIOME_FOREST_TROPICAL_MOIST_BROADLEAF and Profile.BIOME_FOREST_TROPICAL_MOIST_BROADLEAF > 0) or
  1310. (creature.flags.BIOME_GRASSLAND_TEMPERATE and Profile.BIOME_GRASSLAND_TEMPERATE > 0) or
  1311. (creature.flags.BIOME_SAVANNA_TEMPERATE and Profile.BIOME_SAVANNA_TEMPERATE > 0) or
  1312. (creature.flags.BIOME_SHRUBLAND_TEMPERATE and Profile.BIOME_SHRUBLAND_TEMPERATE > 0) or
  1313. (creature.flags.BIOME_GRASSLAND_TROPICAL and Profile.BIOME_GRASSLAND_TROPICAL > 0) or
  1314. (creature.flags.BIOME_SAVANNA_TROPICAL and Profile.BIOME_SAVANNA_TROPICAL > 0) or
  1315. (creature.flags.BIOME_SHRUBLAND_TROPICAL and Profile.BIOME_SHRUBLAND_TROPICAL > 0) or
  1316. (creature.flags.BIOME_DESERT_BADLAND and Profile.BIOME_DESERT_BADLAND > 0) or
  1317. (creature.flags.BIOME_DESERT_ROCK and Profile.BIOME_DESERT_ROCK > 0) or
  1318. (creature.flags.BIOME_DESERT_SAND and Profile.BIOME_DESERT_SAND > 0) or
  1319. (creature.flags.BIOME_OCEAN_TROPICAL and Profile.BIOME_OCEAN_TROPICAL > 0) or
  1320. (creature.flags.BIOME_OCEAN_TEMPERATE and Profile.BIOME_OCEAN_TEMPERATE > 0) or
  1321. (creature.flags.BIOME_OCEAN_ARCTIC and Profile.BIOME_OCEAN_ARCTIC > 0) then
  1322. matching = true
  1323. end
  1324.  
  1325. if matching then
  1326. table.insert (Animal_Page.Absent_List, {name = creature.creature_id, index = i})
  1327. elseif Unrestricted then
  1328. table.insert (Animal_Page.Absent_List, {name = creature.creature_id, index = i})
  1329. end
  1330. end
  1331. end
  1332.  
  1333. for i, plant in ipairs (df.global.world.raws.plants.all) do
  1334. local found = false
  1335. local matching
  1336.  
  1337. for k, v in ipairs (df.global.world.world_data.regions [region].population) do
  1338. if Is_Plant (v.type) and
  1339. v.plant == i then
  1340. table.insert (Plant_Page.Present_List, {name = plant.id, index = i})
  1341. found = true
  1342. break
  1343. end
  1344. end
  1345.  
  1346. if not found then
  1347. if (plant.flags.GOOD and not Profile.GOOD) or
  1348. (plant.flags.EVIL and not Profile.EVIL) or
  1349. (plant.flags.SAVAGE and Profile.SAVAGE == 0) then
  1350. matching = false
  1351.  
  1352. elseif (plant.flags.BIOME_MOUNTAIN and Profile.BIOME_MOUNTAIN > 0) or
  1353. (plant.flags.BIOME_GLACIER and Profile.BIOME_GLACIER > 0) or
  1354. (plant.flags.BIOME_TUNDRA and Profile.BIOME_TUNDRA > 0) or
  1355. (plant.flags.BIOME_SWAMP_TEMPERATE_FRESHWATER and Profile.BIOME_SWAMP_TEMPERATE_FRESHWATER > 0) or
  1356. (plant.flags.BIOME_SWAMP_TEMPERATE_SALTWATER and Profile.BIOME_SWAMP_TEMPERATE_SALTWATER > 0) or
  1357. (plant.flags.BIOME_MARSH_TEMPERATE_FRESHWATER and Profile.BIOME_MARSH_TEMPERATE_FRESHWATER > 0) or
  1358. (plant.flags.BIOME_MARSH_TEMPERATE_SALTWATER and Profile.BIOME_MARSH_TEMPERATE_SALTWATER > 0) or
  1359. (plant.flags.BIOME_SWAMP_TROPICAL_FRESHWATER and Profile.BIOME_SWAMP_TROPICAL_FRESHWATER > 0) or
  1360. (plant.flags.BIOME_SWAMP_TROPICAL_SALTWATER and Profile.BIOME_SWAMP_TROPICAL_SALTWATER > 0) or
  1361. (plant.flags.BIOME_SWAMP_MANGROVE and Profile.BIOME_SWAMP_MANGROVE > 0) or
  1362. (plant.flags.BIOME_MARSH_TROPICAL_FRESHWATER and Profile.BIOME_MARSH_TROPICAL_FRESHWATER > 0) or
  1363. (plant.flags.BIOME_MARSH_TROPICAL_SALTWATER and Profile.BIOME_MARSH_TROPICAL_SALTWATER > 0) or
  1364. (plant.flags.BIOME_FOREST_TAIGA and Profile.BIOME_FOREST_TAIGA > 0) or
  1365. (plant.flags.BIOME_FOREST_TEMPERATE_CONIFER and Profile.BIOME_FOREST_TEMPERATE_CONIFER > 0) or
  1366. (plant.flags.BIOME_FOREST_TEMPERATE_BROADLEAF and Profile.BIOME_FOREST_TEMPERATE_BROADLEAF > 0) or
  1367. (plant.flags.BIOME_FOREST_TROPICAL_CONIFER and Profile.BIOME_FOREST_TROPICAL_CONIFER > 0) or
  1368. (plant.flags.BIOME_FOREST_TROPICAL_DRY_BROADLEAF and Profile.BIOME_FOREST_TROPICAL_DRY_BROADLEAF > 0) or
  1369. (plant.flags.BIOME_FOREST_TROPICAL_MOIST_BROADLEAF and Profile.BIOME_FOREST_TROPICAL_MOIST_BROADLEAF > 0) or
  1370. (plant.flags.BIOME_GRASSLAND_TEMPERATE and Profile.BIOME_GRASSLAND_TEMPERATE > 0) or
  1371. (plant.flags.BIOME_SAVANNA_TEMPERATE and Profile.BIOME_SAVANNA_TEMPERATE > 0) or
  1372. (plant.flags.BIOME_SHRUBLAND_TEMPERATE and Profile.BIOME_SHRUBLAND_TEMPERATE > 0) or
  1373. (plant.flags.BIOME_GRASSLAND_TROPICAL and Profile.BIOME_GRASSLAND_TROPICAL > 0) or
  1374. (plant.flags.BIOME_SAVANNA_TROPICAL and Profile.BIOME_SAVANNA_TROPICAL > 0) or
  1375. (plant.flags.BIOME_SHRUBLAND_TROPICAL and Profile.BIOME_SHRUBLAND_TROPICAL > 0) or
  1376. (plant.flags.BIOME_DESERT_BADLAND and Profile.BIOME_DESERT_BADLAND > 0) or
  1377. (plant.flags.BIOME_DESERT_ROCK and Profile.BIOME_DESERT_ROCK > 0) or
  1378. (plant.flags.BIOME_DESERT_SAND and Profile.BIOME_DESERT_SAND > 0) or
  1379. (plant.flags.BIOME_OCEAN_TROPICAL and Profile.BIOME_OCEAN_TROPICAL > 0) or
  1380. (plant.flags.BIOME_OCEAN_TEMPERATE and Profile.BIOME_OCEAN_TEMPERATE > 0) or
  1381. (plant.flags.BIOME_OCEAN_ARCTIC and Profile.BIOME_OCEAN_ARCTIC > 0) then
  1382. matching = true
  1383. end
  1384.  
  1385. if matching then
  1386. table.insert (Plant_Page.Absent_List, {name = plant.id, index = i})
  1387.  
  1388. elseif Unrestricted then
  1389. table.insert (Plant_Page.Absent_List, {name = plant.id, index = i})
  1390. end
  1391. end
  1392. end
  1393.  
  1394. Sort (Animal_Page.Present_List)
  1395. Sort (Animal_Page.Absent_List)
  1396. Sort (Plant_Page.Present_List)
  1397. Sort (Plant_Page.Absent_List)
  1398.  
  1399. return Profile
  1400. end
  1401.  
  1402. --============================================================
  1403.  
  1404. function Apply_Animal_Selection (index, choice)
  1405. if not Animal_Page.Present then
  1406. return -- Startup, so it doesn't exist properly yet
  1407. end
  1408.  
  1409. local animal_visible = true
  1410.  
  1411. if not Animal_Page.Present.active or
  1412. choice == NIL or
  1413. #Animal_Page.Present_List == 0 then
  1414. animal_visible = false
  1415.  
  1416. else
  1417. local region_index = Locate_Animal (Animal_Page.Present_List [index].index)
  1418. local element = df.global.world.world_data.regions [region].population [region_index]
  1419.  
  1420. Animal_Page.Type:setText (df.world_population_type [element.type])
  1421. Animal_Page.Race:setText (choice.text)
  1422. Animal_Page.Min_Count:setText (Fit_Right (tostring (element.count_min), 8))
  1423. Animal_Page.Max_Count:setText (Fit_Right (tostring (element.count_max), 8))
  1424. end
  1425.  
  1426. for i, element in ipairs (Animal_Page.Animal_Visible_List) do
  1427. element.visible = animal_visible
  1428. end
  1429. end
  1430.  
  1431. --============================================================
  1432.  
  1433. function Apply_Plant_Selection (index, choice)
  1434. if not Plant_Page.Present then
  1435. return -- Startup, so it doesn't exist properly yet
  1436. end
  1437.  
  1438. local plant_visible = true
  1439.  
  1440. if not Plant_Page.Present.active or
  1441. choice == NIL or
  1442. #Plant_Page.Present_List == 0 then
  1443. plant_visible = false
  1444.  
  1445. else
  1446. local region_index = Locate_Plant (Plant_Page.Present_List [index].index)
  1447. local element = df.global.world.world_data.regions [region].population [region_index]
  1448.  
  1449. Plant_Page.Type:setText (df.world_population_type [element.type])
  1450. Plant_Page.Plant:setText (choice.text)
  1451. end
  1452.  
  1453. for i, element in ipairs (Plant_Page.Plant_Visible_List) do
  1454. element.visible = plant_visible
  1455. end
  1456. end
  1457.  
  1458. --============================================================
  1459.  
  1460. function Make_List (List)
  1461. local Result = {}
  1462. for i, element in ipairs (List) do
  1463. table.insert (Result, element.name)
  1464. end
  1465.  
  1466. return Result
  1467. end
  1468.  
  1469. --============================================================
  1470.  
  1471. function Update (delta_x, delta_y)
  1472. x = x + delta_x
  1473. if x < 0 then
  1474. x = 0
  1475. elseif x >= map_width then
  1476. x = map_width - 1
  1477. end
  1478.  
  1479. y = y + delta_y
  1480. if y < 0 then
  1481. y = 0
  1482. elseif y >= map_height then
  1483. y = map_height - 1
  1484. end
  1485.  
  1486. region = df.global.world.world_data.region_map [x]:_displace (y).region_id
  1487. evilness = df.global.world.world_data.region_map [x]:_displace (y).evilness
  1488. size = #df.global.world.world_data.regions [region].region_coords.x
  1489.  
  1490. animals = 0
  1491. plants = 0
  1492. for i, population in ipairs (df.global.world.world_data.regions [region].population) do
  1493. if Is_Animal (population.type) then
  1494. animals = animals + 1
  1495.  
  1496. elseif Is_Plant (population.type) then
  1497. plants = plants + 1
  1498. end
  1499. end
  1500.  
  1501. Main_Page.Profile = Make_Profile (region)
  1502. Make_Region (x, y)
  1503. Make_Biome (x, y)
  1504.  
  1505. Main_Page.X:setText (Fit_Right (tostring (x), 3))
  1506. Main_Page.Y:setText (Fit_Right (tostring (y), 3))
  1507. Main_Page.Biome:setText (Fit_Right (tostring (region), 4))
  1508. Main_Page.Size:setText (Fit_Right (tostring (size), 6))
  1509. Main_Page.Type:setText (df.world_region_type [df.global.world.world_data.regions [region].type])
  1510.  
  1511. Main_Page.Evilness:setText (Fit_Right (tostring (evilness), 3))
  1512. Main_Page.Evilness.text_pen = Savagery_Pen (evilness)
  1513.  
  1514. Main_Page.Animals:setText (Fit_Right (tostring (animals), 3))
  1515. Main_Page.Plants:setText (Fit_Right (tostring (plants), 3))
  1516.  
  1517. Main_Page.Region_Grid:panCenter (x, y)
  1518. Main_Page.Biome_Grid:panCenter (x, y)
  1519.  
  1520. Animal_Page.Present:setChoices (Make_List (Animal_Page.Present_List), 1)
  1521. Animal_Page.Absent:setChoices (Make_List (Animal_Page.Absent_List), 1)
  1522. Apply_Animal_Selection ()
  1523.  
  1524. Plant_Page.Present:setChoices (Make_List (Plant_Page.Present_List), 1)
  1525. Plant_Page.Absent:setChoices (Make_List (Plant_Page.Absent_List), 1)
  1526. Apply_Plant_Selection ()
  1527. end
  1528.  
  1529. --============================================================
  1530.  
  1531. BiomeManipulatorUi = defclass (BiomeManipulatorUi, gui.FramedScreen)
  1532. BiomeManipulatorUi.ATTRS = {
  1533. frame_style = gui.GREY_LINE_FRAME,
  1534. frame_title = "Biome Manipulator",
  1535. }
  1536.  
  1537. --============================================================
  1538.  
  1539. function BiomeManipulatorUi:onHelp ()
  1540. self.subviews.pages:setSelected (4)
  1541. Focus = "Help"
  1542. end
  1543.  
  1544. --============================================================
  1545.  
  1546. function Disclaimer ()
  1547. local helptext = {{text = "Help/Info"}, NEWLINE, NEWLINE}
  1548.  
  1549. for i, v in pairs (keybindings) do
  1550. table.insert (helptext, {text = v.desc, key = v.key, key_sep = ': '})
  1551. table.insert (helptext, NEWLINE)
  1552. end
  1553.  
  1554. table.insert (helptext, NEWLINE)
  1555. local dsc =
  1556. {"The Biome Manipulator is used pre embark to manipulate biome regions in the world, in", NEWLINE,
  1557. "particular pre embark.", NEWLINE,
  1558. "The main screen displays the world map using characters indicating the biome of the", NEWLINE,
  1559. "various world tiles. This display can be alternated with a region display, where", NEWLINE,
  1560. "regions are given a color and a letter, with no meaning other than to tell them apart.", NEWLINE,
  1561. "The purpose of this second display is to see whether biomes belong to the same region or", NEWLINE,
  1562. "not.", NEWLINE,
  1563. "Above the map the main display shows the X/Y coordinates of the current world tile, the", NEWLINE,
  1564. "biome region number it refers to (useless in itself unless using DFHack), and the", NEWLINE,
  1565. "general type of biomes the region contains.", NEWLINE,
  1566. "Below that information you have a number of fields where command keys are displayed", NEWLINE,
  1567. "together with a summary of the information they control. The Evilness field shows the", NEWLINE,
  1568. "Evilness value of the current world tile (color coded for good/neutral/evil), and", NEWLINE,
  1569. "pressing the command key allows you to change the Evilness value for all tiles belonging", NEWLINE,
  1570. "to the same region to the specified value. That also causes animals and plants dependent", NEWLINE,
  1571. "on the old Evilness value but not supported by the new one to be removed from the region", NEWLINE,
  1572. "population list. Any evil interaction associated with the region is also removed of the", NEWLINE,
  1573. "ceases to be evil.", NEWLINE,
  1574. "The Animals field shows the number of creature species tied to the region, and the 'a'", NEWLINE,
  1575. "key changes the focus to the Animal page where you can add and remove creatures to/from", NEWLINE,
  1576. "the region, as well as change the counts for creatures.", NEWLINE,
  1577. "The Plants field shows the number of plant species tied to the region, and the 'p' key", NEWLINE,
  1578. "changes the focus to the Plant page, which works the same as for the creature ones, but", NEWLINE,
  1579. "on plants.", NEWLINE,
  1580. "The Unrestricted key 'u' allows you to change the Animal and Plant selections to span", NEWLINE,
  1581. "the complete range defined by DF (the default is restricted to what DF defines as legal)", NEWLINE,
  1582. "for the region). Usage of this mode is mostly untested, and thus the user takes a risk", NEWLINE,
  1583. "using it.", NEWLINE,
  1584. "The floradiversity key 'f' sets all biome regions to contain all plants legal to their", NEWLINE,
  1585. "respecive biomes, while the Faunadiversity one, 'F', does the same for creatures", NEWLINE,
  1586. " throughout the world. Note that neither of these are affected by the Unrestricted value.", NEWLINE,
  1587. "All changes performed by this tool are applied directly to DF, so the only ways to cancel", NEWLINE,
  1588. "changes are to manually reverse them or to abort the save without embarking.", NEWLINE,
  1589. NEWLINE,
  1590. "The biome map uses a color coding to indicate savagery + evilness and a large number of", NEWLINE,
  1591. "characters to indicate various biome versions.", NEWLINE,
  1592. "The biomes listed are the ones present in the corresponding DF enumeration, (except for", NEWLINE,
  1593. "Subterranean Chasm and Subterranean Water which aren't detected, and pools and rivers", NEWLINE,
  1594. "which are embedded in biomes, rather than forming biomes themselves).", NEWLINE,
  1595. NEWLINE,
  1596. "Color coding key:", NEWLINE,
  1597. {text = "Serene ", pen = COLOR_BLUE}, {text = "Mirthful ", pen = COLOR_GREEN}, {text = "Joyous Wilds ", pen = COLOR_LIGHTCYAN}, NEWLINE,
  1598. {text = "Calm ", pen = COLOR_GREY}, {text = "Wilderness ", pen = COLOR_LIGHTGREEN}, {text = "Untamed Wilds", pen = COLOR_YELLOW}, NEWLINE,
  1599. {text = "Sinister ", pen = COLOR_MAGENTA}, {text = "Haunted ", pen = COLOR_LIGHTRED}, {text = "Terrifying ", pen = COLOR_RED}, NEWLINE,
  1600. NEWLINE,
  1601. "The environment character symbols use lower case for the temperate version and upper case", NEWLINE,
  1602. "for the tropical one. The one exception is d/D.", NEWLINE,
  1603. "Biome", NEWLINE,
  1604. "a = Arctic Ocean", NEWLINE,
  1605. " B = Badlands", NEWLINE,
  1606. "c = Temperate Conifer C = Tropical Conifer", NEWLINE,
  1607. "d = Dry Tropical Broadleaf D = Sand Desert", NEWLINE,
  1608. "e = Rocky Desert", NEWLINE,
  1609. "g = Temperate Grassland G = Tropical Grassland", NEWLINE,
  1610. "l = Temperate Broadleaf L = Tropical Moist Broadleaf", NEWLINE,
  1611. " M = Mangrove Swamp", NEWLINE,
  1612. "n = Temperate Freshwater Marsh N = Tropical Freshwater Marsh", NEWLINE,
  1613. "o = Temperate Ocean O = Tropical Ocean", NEWLINE,
  1614. "p = Temperate Freshwater Swamp P = Tropical Freshwater Swamp", NEWLINE,
  1615. "r = Temperate Saltwater Swamp R = Tropical Saltwater Swamp", NEWLINE,
  1616. "s = Temperate Savanna S = Tropical Savanna", NEWLINE,
  1617. "t = Tundra T = Taiga", NEWLINE,
  1618. "u = Temperate Shrubland U = Tropical Shrubland", NEWLINE,
  1619. "Y = Temperate Saltwater Marsh Y = Tropical Saltwater Marsh", NEWLINE,
  1620. "+ = Mountain * = Glacier", NEWLINE,
  1621. -- " ~ = Subterranean Lava", NEWLINE, -- Commented out won't appear.
  1622. -- ". = Temperate Freshwater Pool , = Tropical Freshwater Pool", NEWLINE,
  1623. -- ": = Temperate Brackish Pool ; = Tropical Brackish Pool", NEWLINE,
  1624. -- "! = Temperate Saltwater Pool | = Tropical Saltwater Pool", NEWLINE,
  1625. "< = Temperate Freshwater Lake > = Tropical Freshwater Lake", NEWLINE,
  1626. "- = Temperate Brackish Lake = = Tropical Brackish Lake", NEWLINE,
  1627. "[ = Temperate Saltwater Lake ] = Tropical Saltwater Lake", NEWLINE,
  1628. -- "\\ = Temperate Freshwater River / = Tropical Freshwater River", NEWLINE,
  1629. -- "% = Temperate Brackish River & = Tropical Brackish River", NEWLINE,
  1630. -- "( = Temperate Saltwater River ) = Tropical Saltwater River", NEWLINE,
  1631. NEWLINE,
  1632. "Version 0.1, 2017-06-26", NEWLINE,
  1633. "Caveats: Only tested to a limited degree.", NEWLINE
  1634. }
  1635.  
  1636. for i, v in pairs (dsc) do
  1637. table.insert (helptext, v)
  1638. end
  1639.  
  1640. return helptext
  1641. end
  1642.  
  1643. --============================================================
  1644.  
  1645. function BiomeManipulatorUi:init ()
  1646. self.stack = {}
  1647. self.item_count = 0
  1648. self.keys = {}
  1649.  
  1650. local screen_width, screen_height = dfhack.screen.getWindowSize ()
  1651.  
  1652. Main_Page.Background =
  1653. widgets.Label {text = {{text = "Help/Info",
  1654. key = keybindings.help.key,
  1655. key_sep = '()'},
  1656. " X: Y: Biome: Size: Type:", NEWLINE,
  1657. {text = "",
  1658. key = keybindings.evilness.key,
  1659. key_sep = '()'},
  1660. {text = " Evilness: ",
  1661. pen = COLOR_LIGHTBLUE},
  1662. {text = "",
  1663. key = keybindings.animals.key,
  1664. key_sep = '()'},
  1665. {text = " Animals: ",
  1666. pen = COLOR_LIGHTBLUE},
  1667. {text = "",
  1668. key = keybindings.plants.key,
  1669. key_sep = '()'},
  1670. {text = " Plants:",
  1671. pen = COLOR_LIGHTBLUE}, NEWLINE,
  1672. {text = "",
  1673. key = keybindings.unrestricted.key,
  1674. key_sep = '()'},
  1675. {text = " Unrestricted: ",
  1676. pen = COLOR_LIGHTBLUE},
  1677. {text = "",
  1678. key = keybindings.floradiversity.key,
  1679. key_sep = '()'},
  1680. {text = " floradiversity",
  1681. pen = COLOR_LIGHTBLUE},
  1682. {text = "",
  1683. key = keybindings.faunadiversity.key,
  1684. key_sep = '()'},
  1685. {text = " Faunadiversity",
  1686. pen = COLOR_LIGHTBLUE}},
  1687. frame = {l = 1, t = 1, y_align = 0}}
  1688.  
  1689. Main_Page.X =
  1690. widgets.Label {text = Fit_Right (tostring (x), 3),
  1691. frame = {l = 17, t = 1, yalign = 0}}
  1692.  
  1693. Main_Page.Y =
  1694. widgets.Label {text = Fit_Right (tostring (y), 3),
  1695. frame = {l = 23, t = 1, yalign = 0}}
  1696.  
  1697. Main_Page.Biome =
  1698. widgets.Label {text = Fit_Right (tostring (region), 4),
  1699. frame = {l = 33, t = 1, yalign = 0}}
  1700.  
  1701. Main_Page.Size =
  1702. widgets.Label {text = Fit_Right (tostring (size), 6),
  1703. frame = {l = 43, t = 1, yalign = 0}}
  1704.  
  1705. Main_Page.Type =
  1706. widgets.Label {text = df.world_region_type [df.global.world.world_data.regions [region].type],
  1707. frame = {l = 56, t = 1, yalign = 0}}
  1708.  
  1709. Main_Page.Evilness =
  1710. widgets.Label {text = Fit_Right (tostring (evilness), 3),
  1711. frame = {l = 15, t = 2, yalign = 0},
  1712. text_pen = Savagery_Pen (evilness)}
  1713.  
  1714. Main_Page.Animals =
  1715. widgets.Label {text = Fit_Right (tostring (animals), 3),
  1716. frame = {l = 34, t = 2, yalign = 0},
  1717. text_pen = COLOR_LIGHTBLUE}
  1718.  
  1719. Main_Page.Plants =
  1720. widgets.Label {text = Fit_Right (tostring (plants), 3),
  1721. frame = {l = 50, t = 2, yalign = 0},
  1722. text_pen = COLOR_LIGHTBLUE}
  1723.  
  1724. Main_Page.Unrestricted =
  1725. widgets.Label {text = tostring (Unrestricted),
  1726. frame = {l = 20, t = 3, yalign = 0},
  1727. text_pen = COLOR_LIGHTBLUE}
  1728.  
  1729. Main_Page.Region_Grid = Grid {frame = {l = 1,
  1730. t = 6,
  1731. r = math.min (map_width, screen_width - 1),
  1732. b = math.min (map_height + 4, screen_height - 2)},
  1733. width = map_width,
  1734. height = map_height,
  1735. visible = false}
  1736.  
  1737. Main_Page.Biome_Grid = Grid {frame = {l = 1,
  1738. t = 6,
  1739. r = math.min (map_width, screen_width - 1),
  1740. b = math.min (map_height + 4, screen_height - 2)},
  1741. width = map_width,
  1742. height = map_height,
  1743. visible = true}
  1744.  
  1745. Make_Region (x, y)
  1746. Make_Biome (x, y)
  1747. Main_Page.Profile = Make_Profile (region)
  1748.  
  1749. local mainPage = widgets.Panel {
  1750. subviews = {Main_Page.Background,
  1751. Main_Page.X,
  1752. Main_Page.Y,
  1753. Main_Page.Biome,
  1754. Main_Page.Size,
  1755. Main_Page.Type,
  1756. Main_Page.Evilness,
  1757. Main_Page.Animals,
  1758. Main_Page.Plants,
  1759. Main_Page.Unrestricted,
  1760. Main_Page.Region_Grid,
  1761. Main_Page.Biome_Grid}}
  1762.  
  1763. Animal_Page.Background =
  1764. widgets.Label {text = "Creatures Present Creatures Absent",
  1765. frame = {l = 1, t = 4, yalign = 0}}
  1766.  
  1767. Animal_Page.Animal_Background =
  1768. widgets.Label {text = {" Type: Race:\n",
  1769. {text = "",
  1770. key = keybindings.min_count.key,
  1771. key_sep = '()'},
  1772. {text = " Count min: ",
  1773. pen = COLOR_LIGHTBLUE},
  1774. {text = "",
  1775. key = keybindings.max_count.key,
  1776. key_sep = '()'},
  1777. {text = " Count Max:",
  1778. pen = COLOR_LIGHTBLUE}},
  1779. frame = {l = 1, t = 1, yalign = 0}}
  1780.  
  1781. Animal_Page.Animal_Visible_List = {}
  1782. table.insert (Animal_Page.Animal_Visible_List, Animal_Page.Animal_Background)
  1783.  
  1784. Animal_Page.Type =
  1785. widgets.Label {text = "",
  1786. frame = {l = 12, t = 1, yalign = 0}}
  1787. table.insert (Animal_Page.Animal_Visible_List, Animal_Page.Type)
  1788.  
  1789. Animal_Page.Race =
  1790. widgets.Label {text = "",
  1791. frame = {l = 37, t = 1, yalign = 0}}
  1792. table.insert (Animal_Page.Animal_Visible_List, Animal_Page.Race)
  1793.  
  1794. Animal_Page.Min_Count =
  1795. widgets.Label {text = "",
  1796. frame = {l = 17, t = 2, yalign = 0}}
  1797. table.insert (Animal_Page.Animal_Visible_List, Animal_Page.Min_Count)
  1798.  
  1799. Animal_Page.Max_Count =
  1800. widgets.Label {text = "",
  1801. frame = {l = 42, t = 2, yalign = 0}}
  1802. table.insert (Animal_Page.Animal_Visible_List, Animal_Page.Max_Count)
  1803.  
  1804. Animal_Page.Present =
  1805. widgets.List {view_id = "Present Animals",
  1806. choices = Make_List (Animal_Page.Present_List),
  1807. frame = {l = 1, r = 25, t = 6, yalign = 0},
  1808. on_submit = self:callback ("removeAnimal"),
  1809. text_pen = COLOR_DARKGRAY,
  1810. cursor_pen = COLOR_YELLOW,
  1811. inactive_pen = COLOR_GREY,
  1812. on_select = (function (index, choice) Apply_Animal_Selection (index, choice) end)}
  1813.  
  1814. Apply_Animal_Selection (Animal_Page.Present:getSelected ())
  1815.  
  1816. Animal_Page.Absent =
  1817. widgets.List {view_id = "Absent Animals",
  1818. choices = Make_List (Animal_Page.Absent_List),
  1819. frame = {l = 27, r = 51, t = 6, yalign = 0},
  1820. on_submit = self:callback ("addAnimal"),
  1821. text_pen = COLOR_DARKGRAY,
  1822. cursor_pen = COLOR_YELLOW,
  1823. inactive_pen = COLOR_GREY}
  1824.  
  1825. local animalPage = widgets.Panel {
  1826. subviews = {Animal_Page.Background,
  1827. Animal_Page.Animal_Background,
  1828. Animal_Page.Type,
  1829. Animal_Page.Race,
  1830. Animal_Page.Min_Count,
  1831. Animal_Page.Max_Count,
  1832. Animal_Page.Present,
  1833. Animal_Page.Absent}}
  1834.  
  1835. Plant_Page.Background =
  1836. widgets.Label {text = "Plants Present Plants Absent",
  1837. frame = {l = 1, t = 4, yalign = 0}}
  1838.  
  1839. Plant_Page.Plant_Background =
  1840. widgets.Label {text = {" Type: Plant:"},
  1841. frame = {l = 1, t = 1, yalign = 0}}
  1842.  
  1843. Plant_Page.Plant_Visible_List = {}
  1844. table.insert (Plant_Page.Plant_Visible_List, Plant_Page.Plant_Background)
  1845.  
  1846. Plant_Page.Type =
  1847. widgets.Label {text = "",
  1848. frame = {l = 12, t = 1, yalign = 0}}
  1849. table.insert (Plant_Page.Plant_Visible_List, Plant_Page.Type)
  1850.  
  1851. Plant_Page.Plant =
  1852. widgets.Label {text = "",
  1853. frame = {l = 37, t = 1, yalign = 0}}
  1854. table.insert (Plant_Page.Plant_Visible_List, Plant_Page.Plant)
  1855.  
  1856. Plant_Page.Present =
  1857. widgets.List {view_id = "Present Plants",
  1858. choices = Make_List (Plant_Page.Present_List),
  1859. frame = {l = 1, r = 25, t = 6, yalign = 0},
  1860. on_submit = self:callback ("removePlant"),
  1861. text_pen = COLOR_DARKGRAY,
  1862. cursor_pen = COLOR_YELLOW,
  1863. inactive_pen = COLOR_GREY,
  1864. on_select = (function (index, choice) Apply_Plant_Selection (index, choice) end)}
  1865.  
  1866. Apply_Plant_Selection (Plant_Page.Present:getSelected ())
  1867.  
  1868. Plant_Page.Absent =
  1869. widgets.List {view_id = "Absent Plants",
  1870. choices = Make_List (Plant_Page.Absent_List),
  1871. frame = {l = 27, r= 51, t = 6, yalign = 0},
  1872. on_submit = self:callback ("addPlant"),
  1873. text_pen = COLOR_DARKGRAY,
  1874. cursor_pen = COLOR_YELLOW,
  1875. inactive_pen = COLOR_GREY}
  1876.  
  1877. local plantPage = widgets.Panel {
  1878. subviews = {Plant_Page.Background,
  1879. Plant_Page.Plant_Background,
  1880. Plant_Page.Type,
  1881. Plant_Page.Plant,
  1882. Plant_Page.Present,
  1883. Plant_Page.Absent}}
  1884.  
  1885. helpPage = widgets.Panel {
  1886. subviews = {widgets.Label {text = Disclaimer (),
  1887. frame = {l = 1, t = 1, yalign = 0}}}}
  1888.  
  1889. local pages = widgets.Pages
  1890. {subviews = {mainPage,
  1891. animalPage,
  1892. plantPage,
  1893. helpPage},view_id = "pages",
  1894. }
  1895.  
  1896. pages:setSelected (1)
  1897. Focus = "Main"
  1898.  
  1899. self:addviews {pages}
  1900. end
  1901.  
  1902. --==============================================================
  1903.  
  1904. function BiomeManipulatorUi:updateEvilness (value)
  1905. if not tonumber (value) or
  1906. tonumber (value) < 0 or
  1907. tonumber (value) > 100 then
  1908. dialog.showMessage ("Error!", "The Evilness legal range is 0 - 100", COLOR_LIGHTRED)
  1909. else
  1910. local val = tonumber (value)
  1911. local purge_good = false
  1912. local purge_evil = false
  1913. local typ
  1914. local x_coord
  1915.  
  1916. if evilness < 33 and
  1917. val >= 33 then
  1918. purge_good = true
  1919.  
  1920. elseif evilness >= 66 and val < 66 then
  1921. purge_evil = true
  1922. end
  1923.  
  1924. if purge_good or purge_evil then
  1925. for i = #df.global.world.world_data.regions [region].population - 1, 0, -1 do
  1926. typ = df.global.world.world_data.regions [region].population [i].type
  1927. if Is_Animal (typ) then
  1928. if (purge_good and
  1929. df.global.world.raws.creatures.all [df.global.world.world_data.regions [region].population [i].race].flags.GOOD) or
  1930. (purge_evil and
  1931. df.global.world.raws.creatures.all [df.global.world.world_data.regions [region].population [i].race].flags.EVIL) then
  1932. df.global.world.world_data.regions [region].population:erase (i)
  1933. end
  1934.  
  1935. elseif Is_Plant (typ) then
  1936. if (purge_good and
  1937. df.global.world.raws.plants.all [df.global.world.world_data.regions [region].population [i].plant].flags.GOOD) or
  1938. (purge_evil and
  1939. df.global.world.raws.plants.all [df.global.world.world_data.regions [region].population [i].plant].flags.EVIL) then
  1940. df.global.world.world_data.regions [region].population:erase (i)
  1941. end
  1942. end
  1943. end
  1944. end
  1945.  
  1946. if purge_evil then
  1947. for i = #df.global.world.interaction_instances.all - 1, 0, -1 do
  1948. if df.global.world.interaction_instances.all [i].region_index == region then
  1949. df.global.world.interaction_instances.all:erase (i)
  1950. end
  1951. end
  1952. end
  1953.  
  1954. for i, x_coord in ipairs (df.global.world.world_data.regions [region].region_coords.x) do
  1955. df.global.world.world_data.region_map [x_coord]:_displace (df.global.world.world_data.regions [region].region_coords.y [i]).evilness = val
  1956. end
  1957. end
  1958.  
  1959. Update (0, 0)
  1960. end
  1961.  
  1962. --==============================================================
  1963.  
  1964. function BiomeManipulatorUi:Floradiversity ()
  1965. local Profile
  1966. local unrestricted_cache = Unrestricted
  1967. local plant
  1968. Unrestricted = false
  1969.  
  1970. for i, biome_region in ipairs (df.global.world.world_data.regions) do
  1971. dfhack.println ("Updating flora for region " .. tostring (i))
  1972. Profile = Make_Profile (i)
  1973.  
  1974. for k, plant_entry in ipairs (Plant_Page.Absent_List) do
  1975. plant = df.global.world.raws.plants.all [plant_entry.index]
  1976. local new_plant = df.world_population:new ()
  1977. new_plant.plant = plant_entry.index
  1978.  
  1979. if plant.flags.TREE then
  1980. new_plant.type = df.world_population_type.Tree
  1981.  
  1982. elseif plant.flags.GRASS then
  1983. new_plant.type = df.world_population_type.Grass
  1984.  
  1985. else
  1986. new_plant.type = df.world_population_type.Bush
  1987. end
  1988.  
  1989. new_plant.count_min = 10000001
  1990. new_plant.count_max = 10000001
  1991.  
  1992. df.global.world.world_data.regions [i].population:insert ("#", new_plant)
  1993. end
  1994. end
  1995.  
  1996. Unrestricted = unrestricted_cache
  1997. Update (0, 0)
  1998. end
  1999.  
  2000. --==============================================================
  2001.  
  2002. function BiomeManipulatorUi:Faunadiversity ()
  2003. local Profile
  2004. local unrestricted_cache = Unrestricted
  2005. local creature
  2006. Unrestricted = false
  2007.  
  2008. for i, biome_region in ipairs (df.global.world.world_data.regions) do
  2009. dfhack.println ("Updating fauna for region " .. tostring (i))
  2010. Profile = Make_Profile (i)
  2011.  
  2012. for k, animal_entry in ipairs (Animal_Page.Absent_List) do
  2013. creature = df.global.world.raws.creatures.all [animal_entry.index]
  2014. local new_creature = df.world_population:new ()
  2015. new_creature.race = animal_entry.index
  2016.  
  2017. if creature.flags.VERMIN_SOIL_COLONY then
  2018. new_creature.type = df.world_population_type.ColonyInsect
  2019.  
  2020. elseif creature.flags.any_vermin then
  2021. if creature.flags.UBIQUITOUS then
  2022. new_creature.type = df.world_population_type.VerminInnumerable
  2023.  
  2024. else
  2025. new_creature.type = df.world_population_type.Vermin
  2026. end
  2027.  
  2028. else
  2029. new_creature.type = df.world_population_type.Animal
  2030. end
  2031.  
  2032. if creature.flags.UBIQUITOUS then
  2033. new_creature.count_min = 10000001
  2034. new_creature.count_max = 10000001
  2035.  
  2036. else
  2037. local creature_biome_count = 0
  2038. for t, q in pairs (Profile) do
  2039. if type (q) == 'number' and
  2040. q ~= "SAVAGE" and
  2041. creature.flags [t] then
  2042. creature_biome_count = creature_biome_count + q
  2043. end
  2044. end
  2045.  
  2046. if creature.flags.SAVAGE then
  2047. creature_biome_count = math.min (creature_biome_count, Profile.SAVAGE)
  2048. end
  2049.  
  2050. new_creature.count_min = creature_biome_count * (7 + math.random (9))
  2051. new_creature.count_max = new_creature.count_min
  2052. end
  2053.  
  2054. df.global.world.world_data.regions [i].population:insert ("#", new_creature)
  2055. end
  2056. end
  2057.  
  2058. Unrestricted = unrestricted_cache
  2059. Update (0, 0)
  2060. end
  2061.  
  2062. --==============================================================
  2063.  
  2064. function BiomeManipulatorUi:removeAnimal (index, choice)
  2065. if choice ~= NIL then
  2066. table.insert (Animal_Page.Absent_List, {name = choice.text, index = Animal_Page.Present_List [index].index})
  2067. Sort (Animal_Page.Absent_List)
  2068. Animal_Page.Absent:setChoices (Make_List (Animal_Page.Absent_List))
  2069. df.global.world.world_data.regions [region].population:erase (Locate_Animal (Animal_Page.Present_List [index].index))
  2070.  
  2071. table.remove (Animal_Page.Present_List, index)
  2072. Animal_Page.Present:setChoices (Make_List (Animal_Page.Present_List))
  2073. end
  2074. end
  2075.  
  2076. --==============================================================
  2077.  
  2078. function BiomeManipulatorUi:addAnimal (index, choice)
  2079. if choice ~= NIL then
  2080. table.insert (Animal_Page.Present_List, {name = choice.text, index = Animal_Page.Absent_List [index].index})
  2081. Sort (Animal_Page.Present_List)
  2082. Animal_Page.Present:setChoices (Make_List (Animal_Page.Present_List))
  2083.  
  2084. local creature = df.global.world.raws.creatures.all [Animal_Page.Absent_List [index].index]
  2085. local new_creature = df.world_population:new ()
  2086. new_creature.race = Animal_Page.Absent_List [index].index
  2087.  
  2088. if creature.flags.VERMIN_SOIL_COLONY then
  2089. new_creature.type = df.world_population_type.ColonyInsect
  2090.  
  2091. elseif creature.flags.any_vermin then
  2092. if creature.flags.UBIQUITOUS then
  2093. new_creature.type = df.world_population_type.VerminInnumerable
  2094.  
  2095. else
  2096. new_creature.type = df.world_population_type.Vermin
  2097. end
  2098.  
  2099. else
  2100. new_creature.type = df.world_population_type.Animal
  2101. end
  2102.  
  2103. if creature.flags.UBIQUITOUS then
  2104. new_creature.count_min = 10000001
  2105. new_creature.count_max = 10000001
  2106.  
  2107. else
  2108. local creature_biome_count = 0
  2109. for t, q in pairs (Main_Page.Profile) do
  2110. if type (q) == 'number' and
  2111. q ~= "SAVAGE" and
  2112. creature.flags [t] then
  2113. creature_biome_count = creature_biome_count + q
  2114. end
  2115. end
  2116.  
  2117. if creature.flags.SAVAGE then
  2118. creature_biome_count = math.min (creature_biome_count, Main_Page.Profile.SAVAGE)
  2119. end
  2120.  
  2121. new_creature.count_min = creature_biome_count * (7 + math.random (9))
  2122. new_creature.count_max = new_creature.count_min
  2123. end
  2124.  
  2125. df.global.world.world_data.regions [region].population:insert ("#", new_creature)
  2126.  
  2127. table.remove (Animal_Page.Absent_List, index)
  2128. Animal_Page.Absent:setChoices (Make_List (Animal_Page.Absent_List))
  2129. end
  2130. end
  2131.  
  2132. --==============================================================
  2133.  
  2134. function BiomeManipulatorUi:updateAnimalMinCount (value)
  2135. if not tonumber (value) or
  2136. tonumber (value) < 0 or
  2137. tonumber (value) > tonumber (Animal_Page.Max_Count.text) then
  2138. dialog.showMessage ("Error!", "The min count cannot be negative or exceed Max count", COLOR_LIGHTRED)
  2139. else
  2140. local index, choice = Animal_Page.Present:getSelected ()
  2141. local pop_index = Locate_Animal (Animal_Page.Present_List [index].index)
  2142. df.global.world.world_data.regions [region].population [pop_index].count_min = tonumber (value)
  2143. Animal_Page.Min_Count:setText (Fit_Right (value, 8))
  2144. end
  2145. end
  2146.  
  2147. --==============================================================
  2148.  
  2149. function BiomeManipulatorUi:updateAnimalMaxCount (value)
  2150. if not tonumber (value) or
  2151. tonumber (value) < 0 or
  2152. tonumber (value) < tonumber (Animal_Page.Min_Count.text) then
  2153. dialog.showMessage ("Error!", "The Max count cannot be negative or less than the min count", COLOR_LIGHTRED)
  2154. else
  2155. local index, choice = Animal_Page.Present:getSelected ()
  2156. local pop_index = Locate_Animal (Animal_Page.Present_List [index].index)
  2157. df.global.world.world_data.regions [region].population [pop_index].count_max = tonumber (value)
  2158. Animal_Page.Max_Count:setText (Fit_Right (value, 8))
  2159. end
  2160. end
  2161.  
  2162. --==============================================================
  2163.  
  2164. function BiomeManipulatorUi:removePlant (index, choice)
  2165. if choice ~= NIL then
  2166. table.insert (Plant_Page.Absent_List, {name = choice.text, index = Plant_Page.Present_List [index].index})
  2167. Sort (Plant_Page.Absent_List)
  2168. Plant_Page.Absent:setChoices (Make_List (Plant_Page.Absent_List))
  2169. df.global.world.world_data.regions [region].population:erase (Locate_Plant (Plant_Page.Present_List [index].index))
  2170.  
  2171. table.remove (Plant_Page.Present_List, index)
  2172. Plant_Page.Present:setChoices (Make_List (Plant_Page.Present_List))
  2173. end
  2174. end
  2175.  
  2176. --==============================================================
  2177.  
  2178. function BiomeManipulatorUi:addPlant (index, choice)
  2179. if choice ~= NIL then
  2180. table.insert (Plant_Page.Present_List, {name = choice.text, index = Plant_Page.Absent_List [index].index})
  2181. Sort (Plant_Page.Present_List)
  2182. Plant_Page.Present:setChoices (Make_List (Plant_Page.Present_List))
  2183. local plant = df.global.world.raws.plants.all [Plant_Page.Absent_List [index].index]
  2184. local new_plant = df.world_population:new ()
  2185. new_plant.plant = Plant_Page.Absent_List [index].index
  2186.  
  2187. if plant.flags.TREE then
  2188. new_plant.type = df.world_population_type.Tree
  2189.  
  2190. elseif plant.flags.GRASS then
  2191. new_plant.type = df.world_population_type.Grass
  2192.  
  2193. else
  2194. new_plant.type = df.world_population_type.Bush
  2195. end
  2196.  
  2197. new_plant.count_min = 10000001
  2198. new_plant.count_max = 10000001
  2199.  
  2200. df.global.world.world_data.regions [region].population:insert ("#", new_plant)
  2201.  
  2202. table.remove (Plant_Page.Absent_List, index)
  2203. Plant_Page.Absent:setChoices (Make_List (Plant_Page.Absent_List))
  2204. end
  2205. end
  2206.  
  2207. --==============================================================
  2208.  
  2209. function BiomeManipulatorUi:onInput (keys)
  2210. if keys.LEAVESCREEN_ALL then
  2211. self:dismiss ()
  2212. end
  2213.  
  2214. if keys.LEAVESCREEN then
  2215. if Focus == "Help" or
  2216. Focus == "Animal" or
  2217. Focus == "Plant" then
  2218. Focus = "Main"
  2219. self.subviews.pages:setSelected (1)
  2220.  
  2221. else
  2222. self:dismiss ()
  2223. end
  2224. end
  2225.  
  2226. if keys [keybindings.evilness.key] then
  2227. if Focus == "Main" then
  2228. dialog.showInputPrompt("Evilness",
  2229. "Changing evilness to a different range will result\n" ..
  2230. "in all plants and animals dependent on the former\n" ..
  2231. "Evilness to be removed from the biome.\n" ..
  2232. "Any change to the Evilness value will cause that\n" ..
  2233. "value to be applied to all world tiles belonging\n" ..
  2234. "to the edited region, destroying any variation\n\n" ..
  2235. "Also removes any interactions associated with the\n" ..
  2236. "region.\n" ..
  2237. "Evilness (" .. tostring (evilness) .."):",
  2238. COLOR_WHITE,
  2239. "",
  2240. self:callback ("updateEvilness"))
  2241. end
  2242.  
  2243. elseif keys [keybindings.animals.key] then
  2244. Animal_Page.Present.active = true
  2245. Animal_Page.Absent.active = false
  2246. Apply_Animal_Selection (Animal_Page.Present:getSelected ())
  2247. Focus = "Animal"
  2248. self.subviews.pages:setSelected (2)
  2249.  
  2250. elseif keys [keybindings.plants.key] then
  2251. Plant_Page.Present.active = true
  2252. Plant_Page.Absent.active = false
  2253. Apply_Plant_Selection (Plant_Page.Present:getSelected ())
  2254. Focus = "Plant"
  2255. self.subviews.pages:setSelected (3)
  2256.  
  2257. elseif keys [keybindings.unrestricted.key] then
  2258. if Focus == "Main" then
  2259. if not Unrestricted then
  2260. dialog.showYesNoPrompt("Enabling unrestricted plant and creature selection",
  2261. "Defaults to disabled for a reason...\n" ..
  2262. "When Unrestricted is True the plant and creature\n" ..
  2263. "selection choices list all those existing in DF\n" ..
  2264. "regardless of whether they make sense or not.\n" ..
  2265. "Using this mode is completely on the user's own\n" ..
  2266. "responsibility, as potential results are crashes\n" ..
  2267. "(probably not), plain failure to have any effect\n" ..
  2268. "(not unreasonable), or just stupid.\n" ..
  2269. "Are you sure you want to enable Unrestricted mode?",
  2270. COLOR_MAGENTA,
  2271. (function () Unrestricted = true
  2272. Main_Page.Unrestricted:setText (tostring (Unrestricted))
  2273. Update (0, 0)
  2274. end),
  2275. (function () end))
  2276.  
  2277. else
  2278. dialog.showMessage ("Leaving Terra Incognita", "You have returned to plant/creature selections within the normal DF habitat bounds.")
  2279. Unrestricted = false
  2280. Main_Page.Unrestricted:setText (tostring (Unrestricted))
  2281. Update (0, 0)
  2282. end
  2283. end
  2284.  
  2285. elseif keys [keybindings.floradiversity.key] then
  2286. if Focus == "Main" then
  2287. dialog.showYesNoPrompt("Floradiversity",
  2288. "This command assigns all plants legal to each region\n" ..
  2289. "in the world to be present in those regions\n" ..
  2290. "Are you sure you want to do that?",
  2291. COLOR_WHITE,
  2292. self:callback ("Floradiversity"),
  2293. (function () end))
  2294. end
  2295.  
  2296. elseif keys [keybindings.faunadiversity.key] then
  2297. if Focus == "Main" then
  2298. dialog.showYesNoPrompt("Faunadiversity",
  2299. "This command assigns all creatures legal to each region\n" ..
  2300. "in the world to be present in those regions\n" ..
  2301. "Are you sure you want to do that?",
  2302. COLOR_WHITE,
  2303. self:callback ("Faunadiversity"),
  2304. (function () end))
  2305. end
  2306.  
  2307. elseif keys [keybindings.region.key] then
  2308. Main_Page.Region_Grid.visible = true
  2309. Main_Page.Biome_Grid.visible = false
  2310.  
  2311. elseif keys [keybindings.biome.key] then
  2312. Main_Page.Region_Grid.visible = false
  2313. Main_Page.Biome_Grid.visible = true
  2314.  
  2315. elseif keys [keybindings.next_edit.key] or
  2316. keys [keybindings.prev_edit.key] then -- As long as there's only two objects...
  2317. if Focus == "Animal" then
  2318. if Animal_Page.Present.active then
  2319. Animal_Page.Present.active = false
  2320. Animal_Page.Absent.active = true
  2321.  
  2322. for i, element in ipairs (Animal_Page.Animal_Visible_List) do
  2323. element.visible = false
  2324. end
  2325.  
  2326. else
  2327. Animal_Page.Present.active = true
  2328. Animal_Page.Absent.active = false
  2329.  
  2330. Apply_Animal_Selection (Animal_Page.Present:getSelected ())
  2331. end
  2332.  
  2333. elseif Focus == "Plant" then
  2334. if Plant_Page.Present.active then
  2335. Plant_Page.Present.active = false
  2336. Plant_Page.Absent.active = true
  2337.  
  2338. for i, element in ipairs (Plant_Page.Plant_Visible_List) do
  2339. element.visible = false
  2340. end
  2341.  
  2342. else
  2343. Plant_Page.Present.active = true
  2344. Plant_Page.Absent.active = false
  2345.  
  2346. Apply_Plant_Selection (Plant_Page.Present:getSelected ())
  2347. end
  2348. end
  2349.  
  2350. elseif keys [keybindings.min_count.key] then
  2351. if Focus == "Animal" and
  2352. Animal_Page.Min_Count.visible then
  2353. dialog.showInputPrompt("min count",
  2354. "Has to be non negative and less than or equal to\n" ..
  2355. "Max Count\n" ..
  2356. "min count (" .. tostring (Animal_Page.Min_Count.text) .."):",
  2357. COLOR_WHITE,
  2358. "",
  2359. self:callback ("updateAnimalMinCount"))
  2360. end
  2361.  
  2362. elseif keys [keybindings.max_count.key] then
  2363. if Focus == "Animal" and
  2364. Animal_Page.Max_Count.visible then
  2365. dialog.showInputPrompt("Max count",
  2366. "Has to be non negative and equal to or greater than\n" ..
  2367. "min Count\n" ..
  2368. "Max count (" .. tostring (Animal_Page.Max_Count.text) .."):",
  2369. COLOR_WHITE,
  2370. "",
  2371. self:callback ("updateAnimalMaxCount"))
  2372. end
  2373.  
  2374. elseif keys [keybindings.up.key] then
  2375. if Focus == "Main" then
  2376. Update (0, -1)
  2377. end
  2378.  
  2379. elseif keys [keybindings.down.key] then
  2380. if Focus == "Main" then
  2381. Update (0, 1)
  2382. end
  2383.  
  2384. elseif keys [keybindings.left.key] then
  2385. if Focus == "Main" then
  2386. Update (-1, 0)
  2387. end
  2388.  
  2389. elseif keys [keybindings.right.key] then
  2390. if Focus == "Main" then
  2391. Update (1, 0)
  2392. end
  2393.  
  2394. elseif keys [keybindings.upleft.key] then
  2395. if Focus == "Main" then
  2396. Update (-1, -1)
  2397. end
  2398.  
  2399. elseif keys [keybindings.upright.key] then
  2400. if Focus == "Main" then
  2401. Update (1, -1)
  2402. end
  2403.  
  2404. elseif keys [keybindings.downleft.key] then
  2405. if Focus == "Main" then
  2406. Update (-1, 1)
  2407. end
  2408.  
  2409. elseif keys [keybindings.downright.key] then
  2410. if Focus == "Main" then
  2411. Update (1, 1)
  2412. end
  2413. end
  2414.  
  2415. self.super.onInput (self, keys)
  2416. end
  2417.  
  2418. --============================================================
  2419.  
  2420. function Show_Viewer ()
  2421. local screen = BiomeManipulatorUi {}
  2422. persist_screen = screen
  2423. screen:show ()
  2424. end
  2425.  
  2426. --============================================================
  2427.  
  2428. Show_Viewer ()
  2429. end
  2430.  
  2431. if not dfhack.isWorldLoaded () then
  2432. dfhack.color (COLOR_LIGHTRED)
  2433. dfhack.print ("Error: This script requires a world to be loaded.")
  2434. dfhack.color(COLOR_RESET)
  2435. dfhack.println ()
  2436. return
  2437. end
  2438.  
  2439. if #args > 1 or
  2440. #args == 1 and
  2441. (tonumber (args [1]) == NIL or
  2442. tonumber (args [1]) < 0 or
  2443. tonumber (args [1]) >= #df.global.world.world_data.regions) then
  2444. dfhack.color (COLOR_LIGHTRED)
  2445. dfhack.print ("biomemanipulator takes either no arguments, or a single numerical argument specifying the number of the biome region")
  2446. dfhack.color (COLOR_RESET)
  2447. dfhack.println ()
  2448. return
  2449. end
  2450.  
  2451. biomemanipulator (args [1])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement