init.lua 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. -------------------------------------
  2. --HEALTH
  3. --[[
  4. Two global step functions
  5. Fast, and slow.
  6. Fast applies environmental and action based effects (in on_actions)
  7. Slow applies internal metabolism effects (here)
  8. ------------------------------------
  9. Some notes:
  10. Calculating sensible values for food:
  11. (intervals/day) * hunger_rate = daily basal food needs
  12. i.e. 20min/1min * 2 = 40 units per day
  13. Therefore 40 units = 2000 calories.
  14. calories -> units = 2000/40 = 50 cal/unit
  15. Sugar 3900 cal/kg = 78 units/kg
  16. Bread 2600 cal/kg = 52 units/kg
  17. Potato. 1500 cal/kg = 30 u/kg
  18. Meat 1000 cal/kg = 20 u/kg
  19. cabbage 240 cal/kg = 4.8 u/kg
  20. ]]
  21. ------------------------------------
  22. HEALTH = {}
  23. dofile(minetest.get_modpath('health')..'/health_effects.lua')
  24. dofile(minetest.get_modpath('health')..'/on_actions.lua')
  25. dofile(minetest.get_modpath('health')..'/hud.lua')
  26. --frequency of updating and applying effects
  27. local interval = 60
  28. -----------------------------
  29. --Player Attibutes
  30. --
  31. --use standard values base, so it doesn't compound each time called
  32. --Only adjusted values saved in player meta so they can be accessed without recalculating
  33. --cf hunger etc which do get change and have no base value
  34. local heal_rate = 1 -- 4
  35. local thirst_rate = -1
  36. local hunger_rate = -3 -- -2
  37. local recovery_rate = 4 -- 5
  38. local move = 0
  39. local jump = 0
  40. --no clothing temperature comfort zone
  41. local temp_min = 18--20
  42. local temp_max = 32--30
  43. --e.g. for new players
  44. local function set_default_attibutes(player)
  45. local meta = player:get_meta()
  46. meta:set_int("thirst", 100)
  47. meta:set_int("hunger", 1000)
  48. meta:set_int("energy", 1000)
  49. meta:set_int("temperature", 37)
  50. meta:set_int("heal_rate", heal_rate)
  51. meta:set_int("thirst_rate", thirst_rate)
  52. meta:set_int("hunger_rate", hunger_rate)
  53. meta:set_int("recovery_rate", recovery_rate)
  54. meta:set_int("move", move)
  55. meta:set_int("jump", jump)
  56. meta:set_int("clothing_temp_min", temp_min)
  57. meta:set_int("clothing_temp_max", temp_max )
  58. end
  59. --[[
  60. -----------------------------
  61. --Forms for sfinv
  62. --only for bug testing
  63. --get data and create form
  64. local function sfinv_get(self, player, context)
  65. local meta = player:get_meta()
  66. local player_pos = player:get_pos()
  67. player_pos.y = player_pos.y + 0.6 --adjust to body height
  68. local enviro_temp = tostring(math.floor(climate.get_point_temp(player_pos)))
  69. local health = tostring(player:get_hp())
  70. local thirst = tostring(meta:get_int("thirst"))
  71. local hunger = tostring(meta:get_int("hunger"))
  72. local energy = tostring(meta:get_int("energy"))
  73. local temperature = tostring(meta:get_int("temperature"))
  74. local heal_rate = tostring(meta:get_int("heal_rate"))
  75. local thirst_rate = tostring(meta:get_int("thirst_rate"))
  76. local hunger_rate = tostring(meta:get_int("hunger_rate"))
  77. local recovery_rate = tostring(meta:get_int("recovery_rate"))
  78. local move = tostring(meta:get_int("move"))
  79. local jump = tostring(meta:get_int("jump"))
  80. local formspec = "label[0.1,0.1; Health: " .. health .. " / 20]"..
  81. "label[0.1,0.6; Thirst: " .. thirst .. " / 100]"..
  82. "label[0.1,1.1; Hunger: " .. hunger .. " / 1000]"..
  83. "label[0.1,1.6; Energy: " .. energy .. " / 1000]"..
  84. "label[0.1,2.1; Body Temperature: " .. temperature .. " C]"..
  85. "label[0.1,3.1; Move Speed: " .. move .. " % change]"..
  86. "label[0.1,3.6; Jumping: " .. jump .. " % change]"..
  87. "label[4,0.1; Heal Rate: " .. heal_rate .. " ]"..
  88. "label[4,0.6; Thirst Rate: " .. thirst_rate .. " ]"..
  89. "label[4,1.1; Hunger Rate: " .. hunger_rate .. " ]"..
  90. "label[4,1.6; Recovery Rate: " .. recovery_rate .. " ]"..
  91. "label[4,2.1; External Temperature: " .. enviro_temp .. " C]"..
  92. "button[4,3.1;1,1;toggle_health_hud;HUD]"
  93. --..
  94. --"textarea[0.5,5.1;6,6;;Active Effects:;"..active_list.." ]"
  95. return formspec
  96. end
  97. local function register_tab()
  98. sfinv.register_page("health:health_tab", {
  99. title = "Health",
  100. on_enter = function(self, player, context)
  101. sfinv.set_player_inventory_formspec(player)
  102. end,
  103. get = function(self, player, context)
  104. local formspec = sfinv_get(self, player, context)
  105. return sfinv.make_formspec(player, context, formspec, true)
  106. end
  107. })
  108. end
  109. register_tab()
  110. ]]
  111. -----------------------------
  112. --Applies Health Effects
  113. --called by malus_bonus
  114. --runs through player's current effects, runs the function for that effect
  115. --takes all the same variables, and outputs as any effect may use them.
  116. --adjusted outputs feed back into malus_bonus
  117. local function do_effects_list(meta, player, health, energy, thirst, hunger, temperature, h_rate, r_rate, t_rate, hun_rate, mov, jum)
  118. local effects_list = meta:get_string("effects_list")
  119. effects_list = minetest.deserialize(effects_list) or {}
  120. if not effects_list then
  121. return h_rate, r_rate, t_rate, hun_rate, mov, jum, health, energy, thirst, hunger, temperature
  122. end
  123. for _, effect in ipairs(effects_list) do
  124. local name = effect[1]
  125. local order = effect[2]
  126. ----------
  127. if name == "Food Poisoning" then
  128. r_rate, mov, jum, temperature = HEALTH.food_poisoning(order, player, meta, effects_list, r_rate, mov, jum, temperature)
  129. end
  130. ----------
  131. if name == "Fungal Infection" then
  132. r_rate, mov, jum, temperature = HEALTH.fungal_infection(order, player, meta, effects_list, r_rate, mov, jum, temperature)
  133. end
  134. ----------
  135. if name == "Dust Fever" then
  136. r_rate, mov, jum, temperature = HEALTH.dust_fever(order, player, meta, effects_list, r_rate, mov, jum, temperature)
  137. end
  138. ----------
  139. if name == "Drunk" then
  140. r_rate, mov, jum, h_rate, temperature = HEALTH.drunk(order, player, meta, effects_list, r_rate, mov, jum, h_rate, temperature)
  141. end
  142. ----------
  143. if name == "Hangover" then
  144. mov, jum = HEALTH.hangover(order, player, meta, effects_list, mov, jum)
  145. end
  146. ----------
  147. if name == "Intestinal Parasites" then
  148. r_rate, hun_rate = HEALTH.intestinal_parasites(order, player, meta, effects_list, r_rate, hun_rate)
  149. end
  150. ----------
  151. if name == "Tiku High" then
  152. r_rate, hun_rate, mov, jum, temperature = HEALTH.tiku_high(order, player, meta, effects_list, r_rate, hun_rate, mov, jum, temperature)
  153. end
  154. ----------
  155. if name == "Neurotoxicity" then
  156. mov, jum = HEALTH.neurotoxicity(order, player, meta, effects_list, mov, jum)
  157. end
  158. ----------
  159. if name == "Hepatotoxicity" then
  160. mov, jum, r_rate, h_rate = HEALTH.hepatotoxicity(order, player, meta, effects_list, mov, jum, r_rate, h_rate)
  161. end
  162. ----------
  163. if name == "Photosensitivity" then
  164. h_rate, r_rate = HEALTH.photosensitivity(order, player, meta, effects_list, h_rate, r_rate)
  165. end
  166. ---------
  167. if name == "Meta-Stim" then
  168. h_rate, r_rate, hun_rate, t_rate = HEALTH.meta_stim(order, player, meta, effects_list, h_rate, r_rate, hun_rate, t_rate)
  169. end
  170. end
  171. return h_rate, r_rate, t_rate, hun_rate, mov, jum, health, energy, thirst, hunger, temperature
  172. end
  173. -----------------------------
  174. --Bonus Malus... so can be called whenever player status is changed
  175. --takes standard rates and adjusts them based on player status.
  176. --saves adjusted rates and applies physics.
  177. --send it attributes to adjust by,
  178. --also give name and meta, bc anything calling it should already have that
  179. -- returns the adjusted rates so they can be used if desired
  180. --
  181. function HEALTH.malus_bonus(player, name, meta, health, energy, thirst, hunger, temperature)
  182. --use standard values, so it doesn't compound each time adjusted.
  183. --Only saved to player meta so they can be accessed without recalculating
  184. local h_rate = heal_rate
  185. local t_rate = thirst_rate
  186. local hun_rate = hunger_rate
  187. local r_rate = recovery_rate
  188. local mov = move
  189. local jum = jump
  190. --(hunger/Energy has 10x stock)
  191. --0-20 starving/severe dehydrated: malus, no heal
  192. --20-40 malnourished/dehydrated: malus
  193. --40-60 hungry/thirsty: small malus
  194. --60-80 good:
  195. --80-100 overfull: small malus
  196. --80-100 well rested. bonus
  197. --60-80 rested.
  198. --40-60 tired. small malus
  199. --20-40 fatigued. malus
  200. --0-20 exhausted. malus no heal
  201. --<27 death
  202. --27-32: severe hypo. malus no heal
  203. --32-37: hypothermia. malus
  204. --36-38: normal
  205. --38-43: hyperthermia. malus.
  206. --43-47: severe heat stroke. malus no heal
  207. -->47 death
  208. --
  209. --update rates
  210. --
  211. --bonus/malus from health
  212. if health <= 1 then
  213. mov = mov - 50
  214. jum = jum - 50
  215. h_rate = h_rate - 3
  216. r_rate = r_rate - 4
  217. elseif health < 4 then
  218. mov = mov - 25
  219. jum = jum - 25
  220. h_rate = h_rate - 2
  221. r_rate = r_rate - 2
  222. elseif health < 8 then
  223. mov = mov - 20
  224. jum = jum - 20
  225. h_rate = h_rate - 1
  226. r_rate = r_rate - 1
  227. elseif health < 12 then
  228. mov = mov - 15
  229. jum = jum - 15
  230. elseif health < 16 then
  231. mov = mov - 10
  232. jum = jum - 10
  233. end
  234. --bonus/malus from energy
  235. if energy > 800 then
  236. h_rate = h_rate + 2
  237. mov = mov + 15
  238. jum = jum + 15
  239. elseif energy < 1 then
  240. h_rate = h_rate - 1
  241. mov = mov - 40
  242. jum = jum - 40
  243. t_rate = t_rate - 12
  244. hun_rate = hun_rate - 24
  245. elseif energy < 200 then
  246. h_rate = h_rate - 1
  247. mov = mov - 20
  248. jum = jum - 20
  249. t_rate = t_rate - 4
  250. hun_rate = hun_rate - 8
  251. elseif energy < 400 then
  252. mov = mov - 10
  253. jum = jum - 10
  254. t_rate = t_rate - 3
  255. hun_rate = hun_rate - 4
  256. elseif energy < 600 then
  257. mov = mov - 5
  258. jum = jum - 5
  259. t_rate = t_rate - 2
  260. hun_rate = hun_rate - 2
  261. elseif energy < 700 then
  262. hun_rate = hun_rate - 1
  263. end
  264. --bonus/malus from thirst
  265. if thirst > 80 then
  266. h_rate = h_rate + 1
  267. r_rate = r_rate + 2
  268. mov = mov + 1
  269. jum = jum + 1
  270. elseif thirst < 1 then
  271. h_rate = h_rate - 12
  272. r_rate = r_rate - 10
  273. mov = mov - 30
  274. jum = jum - 30
  275. elseif thirst < 20 then
  276. h_rate = h_rate - 2
  277. r_rate = r_rate - 2
  278. mov = mov - 20
  279. jum = jum - 20
  280. elseif thirst < 40 then
  281. h_rate = h_rate - 1
  282. r_rate = r_rate - 1
  283. mov = mov - 10
  284. jum = jum - 10
  285. elseif thirst < 60 then
  286. mov = mov - 1
  287. jum = jum - 1
  288. end
  289. --bonus/malus from hunger
  290. if hunger > 800 then
  291. h_rate = h_rate + 1
  292. r_rate = r_rate + 2
  293. mov = mov + 1
  294. jum = jum + 1
  295. elseif hunger < 1 then
  296. h_rate = h_rate - 12
  297. r_rate = r_rate - 10
  298. mov = mov - 30
  299. jum = jum - 30
  300. elseif hunger < 200 then
  301. h_rate = h_rate - 2
  302. r_rate = r_rate - 2
  303. mov = mov - 20
  304. jum = jum - 20
  305. elseif hunger < 400 then
  306. h_rate = h_rate - 1
  307. r_rate = r_rate - 1
  308. mov = mov - 10
  309. jum = jum - 10
  310. elseif hunger < 600 then
  311. mov = mov - 1
  312. jum = jum - 1
  313. end
  314. --temp malus..severe..having this happen would make you very ill
  315. if temperature > 100 or temperature < 0 then
  316. --you dead
  317. h_rate = h_rate - 10000
  318. r_rate = r_rate - 10000
  319. mov = mov - 10000
  320. jum = jum - 10000
  321. elseif temperature > 47 or temperature < 27 then
  322. h_rate = h_rate - 16
  323. r_rate = r_rate - 64
  324. mov = mov - 80
  325. jum = jum - 80
  326. elseif temperature > 43 or temperature < 32 then
  327. h_rate = h_rate - 8
  328. r_rate = r_rate - 32
  329. mov = mov - 40
  330. jum = jum - 40
  331. elseif temperature > 38 or temperature < 37 then
  332. h_rate = h_rate - 4
  333. r_rate = r_rate - 8
  334. mov = mov - 20
  335. jum = jum - 20
  336. end
  337. --health effects
  338. local HE_mov
  339. local HE_jum
  340. h_rate, r_rate, t_rate, hun_rate, HE_mov, HE_jum, health, energy, thirst, hunger, temperature = do_effects_list(meta, player, health, energy, thirst, hunger, temperature, h_rate, r_rate, t_rate, hun_rate, mov, jum)
  341. --save adjusted rates for access (e.g. by a medical tab/equipment etc)
  342. meta:set_int("heal_rate", h_rate)
  343. meta:set_int("thirst_rate", t_rate)
  344. meta:set_int("hunger_rate", hun_rate)
  345. meta:set_int("recovery_rate", r_rate)
  346. meta:set_int("move", HE_mov)
  347. meta:set_int("jump", HE_jum)
  348. --apply player physics
  349. --don't do in bed or it buggers the physics
  350. if not bed_rest.player[name] then
  351. player_monoids.speed:add_change(player, 1 + (mov/100), "health:physics")
  352. player_monoids.jump:add_change(player, 1 + (jum/100), "health:physics")
  353. --split physics from hunger etc from that from health effects
  354. --this means quick_physics can fiddle with one half, without overriding the half from effects
  355. HE_mov = HE_mov - mov
  356. HE_jum = HE_jum - jum
  357. player_monoids.speed:add_change(player, 1 + (HE_mov/100), "health:physics_HE")
  358. player_monoids.jump:add_change(player, 1 + (HE_jum/100), "health:physics_HE")
  359. end
  360. --return adjusted rates so can be applied if necessary
  361. return h_rate, r_rate, t_rate, hun_rate, mov, jum, health, energy, thirst, hunger, temperature
  362. end
  363. -----------------------------
  364. --Main
  365. --
  366. minetest.register_on_newplayer(function(player)
  367. set_default_attibutes(player)
  368. end)
  369. minetest.register_on_joinplayer(function(player)
  370. sfinv.set_player_inventory_formspec(player)
  371. --set physics etc
  372. local name = player:get_player_name()
  373. local meta = player:get_meta()
  374. local health = player:get_hp()
  375. local thirst = meta:get_int("thirst")
  376. local hunger = meta:get_int("hunger")
  377. local energy = meta:get_int("energy")
  378. local temperature = meta:get_int("temperature")
  379. HEALTH.malus_bonus(player, name, meta, health, energy, thirst, hunger, temperature)
  380. end)
  381. minetest.register_on_dieplayer(function(player)
  382. --redo physics (to clear what killed them)
  383. player_monoids.speed:del_change(player, "health:physics")
  384. player_monoids.jump:del_change(player, "health:physics")
  385. player_monoids.speed:del_change(player, "health:physics_HE")
  386. player_monoids.jump:del_change(player, "health:physics_HE")
  387. --clear Health effects list
  388. local meta = player:get_meta()
  389. meta:set_string("effects_list", "")
  390. meta:set_int("effects_num", 0)
  391. end)
  392. minetest.register_on_respawnplayer(function(player)
  393. set_default_attibutes(player)
  394. sfinv.set_player_inventory_formspec(player)
  395. end)
  396. if minetest.settings:get_bool("enable_damage") then
  397. --Main update values
  398. local timer = 0
  399. minetest.register_globalstep(function(dtime)
  400. timer = timer + dtime
  401. --run
  402. if timer > interval then
  403. for _,player in ipairs(minetest.get_connected_players()) do
  404. local name = player:get_player_name()
  405. local meta = player:get_meta()
  406. local health = player:get_hp()
  407. local thirst = meta:get_int("thirst")
  408. local hunger = meta:get_int("hunger")
  409. local energy = meta:get_int("energy")
  410. local temperature = meta:get_int("temperature")
  411. --apply rate adjustments so they are correct for current player status
  412. local h_rate, r_rate, t_rate, hun_rate, mov, jum, health, energy, thirst, hunger, temperature = HEALTH.malus_bonus(player, name, meta, health, energy, thirst, hunger, temperature)
  413. --
  414. --update attributes based on adjusted rates
  415. --XXX1 is the new (healt/thirst etc) value
  416. --so can be compared with old value, (which was useful...at one point)
  417. --
  418. --update and min max
  419. local health1, thirst1, hunger1, energy1, temperature1
  420. thirst1 = thirst + t_rate
  421. if thirst1 < 0 then
  422. thirst1 = 0
  423. elseif thirst1 > 100 then
  424. thirst1 = 100
  425. end
  426. hunger1 = hunger + hun_rate
  427. if hunger1 < 0 then
  428. hunger1 = 0
  429. elseif hunger1 > 1000 then
  430. hunger1 = 1000
  431. end
  432. energy1 = energy + r_rate
  433. if energy1 < 0 then
  434. energy1 = 0
  435. elseif energy1 > 1000 then
  436. energy1 = 1000
  437. end
  438. health1 = health + h_rate
  439. if temperature > 37 then
  440. temperature1 = temperature - 1
  441. if temperature > 47 then
  442. health1 = health1 - 1
  443. end
  444. elseif temperature < 37 then
  445. temperature1 = temperature + 1
  446. if temperature < 27 then
  447. health1 = health1 - 1
  448. end
  449. else
  450. temperature1 = temperature
  451. end
  452. if health1 < 0 then
  453. health1 = 0
  454. elseif health1 > 20 then
  455. health1 = 20
  456. end
  457. --update
  458. --
  459. player:set_hp(health1)
  460. meta:set_int("thirst", thirst1)
  461. meta:set_int("hunger", hunger1)
  462. meta:set_int("energy", energy1)
  463. meta:set_int("temperature", temperature1)
  464. --update form so can see change while looking
  465. sfinv.set_player_inventory_formspec(player)
  466. end
  467. end
  468. --reset
  469. if timer > interval then
  470. timer = 0
  471. end
  472. end)
  473. end