From 7797ad5d40084cca66c296996dcdc38446a6d987 Mon Sep 17 00:00:00 2001 From: Elkien3 Date: Wed, 17 Jun 2020 18:42:40 -0500 Subject: [PATCH] add treatable cut wound lotta stuff, don't feel like explaining, cheers --- body.lua | 72 +++++++++--------- hitloc.lua | 42 ++++------- init.lua | 14 ++-- injuries.lua | 111 ++++++++++++++++++++++++++++ textures/applypressure.png | Bin 0 -> 11377 bytes textures/blackline.png | Bin 0 -> 546 bytes textures/bpcuff.png | Bin 0 -> 3085 bytes textures/bpcuffbladder.png | Bin 0 -> 1565 bytes textures/medical_cut.png | Bin 0 -> 855 bytes timers.lua | 51 +++++++++++-- tools.lua | 147 ++++++++++++++++++++++++++++++++----- vitals.lua | 34 ++++++--- 12 files changed, 368 insertions(+), 103 deletions(-) create mode 100644 injuries.lua create mode 100644 textures/applypressure.png create mode 100644 textures/blackline.png create mode 100644 textures/bpcuff.png create mode 100644 textures/bpcuffbladder.png create mode 100644 textures/medical_cut.png diff --git a/body.lua b/body.lua index 4803479..64eb93c 100644 --- a/body.lua +++ b/body.lua @@ -1,3 +1,4 @@ + minetest.register_entity("medical:body", { hp_max = 1, physical = false, @@ -10,62 +11,63 @@ minetest.register_entity("medical:body", { makes_footstep_sound = false, automatic_rotate = false, on_activate = function(self, staticdata, dtime_s) + if not staticdata or staticdata == "" then staticdata = "Elkien" end--return end + --self.object:set_acceleration({x=0, y=-10, z=0}) + self.owner = staticdata self.object:set_animation({x=162,y=167}, 1) self.object:set_armor_groups({immortal = 1}) - self.object:set_yaw(math.random(-math.pi, math.pi)) + self.object:set_yaw(math.random(-math.pi, math.pi)) --todo: have a set rotation value + medical.init_injuries(self) end, --[[get_staticdata = function(self) --return end,--]] on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir) if not puncher:is_player() then return end + local name = puncher:get_player_name() local wielditem = puncher:get_wielded_item() local wieldname = wielditem:get_name() local hitloc, local_hitloc = medical.gethitloc(self.object, puncher, tool_capabilities, dir) - if medical.attachedtools[wieldname] then - medical.attachedtools[wieldname](self, puncher, wielditem, hitloc, local_hitloc) + local hitlimb = medical.getlimb(self.object, puncher, tool_capabilities, dir, hitloc) + if not puncher:get_player_control(puncher).sneak and medical.attachedtools[wieldname] and medical.attachedtools[wieldname](self, puncher, wielditem, hitloc, local_hitloc) then + + elseif medical.data[name].injuries and medical.data[name].injuries[hitlimb] then + medical.injury_handle(self.owner, puncher, false, wieldname, hitlimb) end -- attach things end, on_rightclick = function(self, clicker) if not clicker:is_player() then return end + local name = clicker:get_player_name() local wielditem = clicker:get_wielded_item() local wieldname = wielditem:get_name() local hitloc, local_hitloc = medical.gethitloc(self.object, clicker, nil, nil) - if medical.usedtools[wieldname] then - medical.usedtools[wieldname](self, clicker, wielditem, hitloc, local_hitloc) + local hitlimb = medical.getlimb(self.object, clicker, tool_capabilities, dir, hitloc) + if not clicker:get_player_control(clicker).sneak and medical.usedtools[wieldname] and medical.usedtools[wieldname](self, clicker, wielditem, hitloc, local_hitloc) then + + elseif medical.data[name].injuries and medical.data[name].injuries[hitlimb] then + medical.injury_handle(self.owner, clicker, true, wieldname, hitlimb) end -- use things end }) ---open fracture test -minetest.register_entity("medical:fracturetest", { - hp_max = 1, - physical = true, - weight = 5, - collisionbox = {-0.1,-0.1,-0.1, 0.1,0.1,0.1}, - visual = "mesh", - mesh = "bone.b3d", - visual_size = {x=1, y=1},--{x=.211, y=.211}, - textures = {"default_clay.png","default_clay.png","default_clay.png","default_clay.png","default_clay.png","default_clay.png"}, -- number of required textures depends on visual - colors = {}, -- number of required colors depends on visual - spritediv = {x=1, y=1}, - initial_sprite_basepos = {x=0, y=0}, - is_visible = true, - makes_footstep_sound = false, - automatic_rotate = false, - on_activate = function(self, staticdata, dtime_s) - minetest.after(1, function() - local all_objects = minetest.get_objects_inside_radius(self.object:get_pos(), 10) - local _,obj - for _,obj in ipairs(all_objects) do - if obj:get_entity_name() == "medical:body" then - minetest.chat_send_all(obj:get_entity_name()) - self.object:set_attach(obj, "Arm_Right", {x=0,y=4,z=0}, {x=1,y=0,z=math.random(-10, 10)}) - break - end - end - end) - end -}) \ No newline at end of file +local injuryflip = {Arm_Right = 180, Arm_Left = 180, Leg_Right = 180, Leg_Left = 180} +local injurypos = {Head = -1.2} + +function medical.init_injuries(self) + local name = self.owner + local player = minetest.get_player_by_name(name) + local data = medical.data[name] + local pos = self.object:get_pos() + if medical.data[name].injuries then + for bone, injury in pairs (medical.data[name].injuries) do + local injurydef = medical.injuries[injury.name] + local ent = minetest.add_entity(pos, injurydef.entity, minetest.serialize({owner = name, bone = bone})) + local rot = injuryflip[bone] or 0 + local pos = injurypos[bone] or 0 + ent:set_attach(self.object, bone, {x=0, y=2, z=pos}, {x=rot,y=0,z=math.random(-10, 10)}) + medical.data[name].injuries[bone].ent = ent + end + end +end \ No newline at end of file diff --git a/hitloc.lua b/hitloc.lua index 7fcdf76..6fbd44d 100644 --- a/hitloc.lua +++ b/hitloc.lua @@ -1,32 +1,20 @@ -local limb_location = {} +--standing locations +local limb = {} +limb["standing"]= {Head = {x=0,y=1.6,z=0}, Body = {x=0,y=1,z=0}, Arm_Right = {x=.3,y=1,z=0}, Arm_Left = {x=-.3,y=1,z=0}, Leg_Right = {x=.1,y=.4,z=0}, Leg_Left = {x=-.1,y=.4,z=0}} + +-- sitting locations +limb["sitting"] = {Head = {x=0,y=.9,z=0}, Body = {x=0,y=.4,z=0}, Arm_Right = {x=.3,y=.4,z=0}, Arm_Left = {x=-.3,y=.4,z=0}, Leg_Right = {x=.1,y=.1,z=.35}, Leg_Left = {x=-.1,y=.1,z=.35}} ---todo: make these change depending on what state the patient is in. ---[[ standing locations -limb_location.head = {x=0,y=1.6,z=0} -limb_location.torso = {x=0,y=1,z=0} -limb_location.rightarm = {x=.3,y=1,z=0} -limb_location.leftarm = {x=-.3,y=1,z=0} -limb_location.rightleg = {x=.1,y=.4,z=0} -limb_location.leftleg = {x=-.1,y=.4,z=0} ---]] ---[[ sitting locations -limb_location.head = {x=0,y=.9,z=0} -limb_location.torso = {x=0,y=.4,z=0} -limb_location.rightarm = {x=.3,y=.4,z=0} -limb_location.leftarm = {x=-.3,y=.4,z=0} -limb_location.rightleg = {x=.1,y=.1,z=.35} -limb_location.leftleg = {x=-.1,y=.1,z=.35} ---]] -- laying locations -limb_location.head = {x=0,y=.1,z=-.65} -limb_location.torso = {x=0,y=.1,z=-.2} -limb_location.rightarm = {x=.4,y=.1,z=-.125} -limb_location.leftarm = {x=-.4,y=.1,z=-.125} -limb_location.rightleg = {x=.2,y=.1,z=.5} -limb_location.leftleg = {x=-.2,y=.1,z=.5} +limb["laying"] = {Head = {x=0,y=.1,z=-.65}, Body = {x=0,y=.1,z=-.2}, Arm_Right = {x=.4,y=.1,z=-.125}, Arm_Left = {x=-.4,y=.1,z=-.125}, Leg_Right = {x=.2,y=.1,z=.5}, Leg_Left = {x=-.2,y=.1,z=.5}} -local DEBUG_WAYPOINT = true -local DEBUG_CHAT = true +function medical.get_limb_locations(self) + --todo: make these change depending on what state the patient is in. + return limb["laying"] +end + +local DEBUG_WAYPOINT = false +local DEBUG_CHAT = false local function rotateVector(x, y, a) local c = math.cos(a) @@ -131,7 +119,7 @@ function medical.getlimb(player, hitter, tool_capabilities, dir, hitloc) else playeryaw = player:get_yaw() end - for id, pos in pairs(limb_location) do + for id, pos in pairs(medical.get_limb_locations(player)) do local x, z = rotateVector(pos.x, pos.z, playeryaw) local rot_pos = {x=x,y=pos.y,z=z} local adj_pos = vector.add(playerpos, rot_pos) diff --git a/init.lua b/init.lua index 6285c74..2e56b49 100644 --- a/init.lua +++ b/init.lua @@ -2,17 +2,17 @@ medical = {} medical.mod_storage = minetest.get_mod_storage() medical.usedtools = {} medical.attachedtools = {} -medical.data = medical.mod_storage:to_table() or {} -if not medical.data.vitals then medical.data.vitals = {} end -if not medical.data.injuries then medical.data.injuries = {} end - ---mod_storage:from_table(medical) +medical.data = minetest.deserialize(medical.mod_storage:get_string("data")) or {} local modpath = minetest.get_modpath(minetest.get_current_modname()) -dofile(modpath.."/timers.lua") dofile(modpath.."/controls.lua") +dofile(modpath.."/timers.lua") dofile(modpath.."/vitals.lua") dofile(modpath.."/hitloc.lua") dofile(modpath.."/body.lua") -dofile(modpath.."/tools.lua") \ No newline at end of file +dofile(modpath.."/tools.lua") +dofile(modpath.."/injuries.lua") + +medical.data["Elkien"] = {} +medical.data["Elkien"].injuries = {Arm_Left = {name = "cut"}} \ No newline at end of file diff --git a/injuries.lua b/injuries.lua new file mode 100644 index 0000000..3d0bfa5 --- /dev/null +++ b/injuries.lua @@ -0,0 +1,111 @@ +medical.injuries = {} + +function medical.injury_handle(owner, player, rightclick, tool, hitlimb, finish) + local name = player:get_player_name() + local injury = medical.data[owner].injuries[hitlimb] + local injurydef = medical.injuries[injury.name] + if not injury.step then injury.step = 1 end + local stepdef = injurydef.steps[injury.step] + if finish then + injury.step = injury.step + 1 + if not injurydef.steps[injury.step] then + if injury.ent then + injury.ent:remove() + medical.data[owner].injuries[hitlimb] = nil + end + return + end + if tool ~= stepdef.tool or rightclick ~= stepdef.rightclick then + return end + end + local stopfunc + local stoparg + if stepdef.hud then + medical.hud[name] = player:hud_add({ + hud_elem_type = "image", + position = {x = 0.5, y = 0.55}, + offset = {x = 0, y = 0}, + text = stepdef.hud, + scale = { x = 10, y = 10}, + alignment = { x = 0, y = 0 }, + }) + player:hud_set_flags({wielditem=false}) + stoparg = name + stopfunc = function(stoparg) + local player = minetest.get_player_by_name(stoparg) + if medical.hud[stoparg] then + player:hud_remove(medical.hud[stoparg]) + medical.hud[stoparg] = nil + player:hud_set_flags({wielditem=true}) + end + end + end + if stepdef.time then + medical.start_timer(owner, stepdef.time, false, {owner, player, rightclick, tool, hitlimb, true}, medical.injury_handle, stoparg, stopfunc, "RMB", name) + else + medical.injury_handle(owner, player, rightclick, tool, hitlimb, true) + end +end + +minetest.register_entity("medical:cut", { + hp_max = 1, + physical = false, + weight = 5, + collisionbox = {-0.1,-0.1,-0.1, 0.1,0.1,0.1}, + visual = "cube", + visual_size = {x=.211, y=.211}, + textures = {"invis.png", "invis.png", "invis.png", "invis.png", "invis.png", "medical_cut.png"}, -- number of required textures depends on visual -- number of required textures depends on visual + colors = {}, -- number of required colors depends on visual + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = false, + on_activate = function(self, staticdata, dtime_s) + if not staticdata or staticdata == "" then self.object:remove() return end + local data = minetest.deserialize(staticdata) + self.owner = data.owner + self.bone = data.bone + end +}) + +medical.injuries["cut"] = { +entity = "medical:cut", +steps = {{tool = "", rightclick = true, time = 5, hud = "applypressure.png"}},--steps = {"medical:dressing", "", "medical:dressing", "", "medical:tourniquet", ""},-- maybe make the optional steps removed if the initial severety of the wound is less severe. would need a way to make sure the player knows thta in real life tourniquets should only be applied in real situation only if neccisary and you know how, and should only be removed by professionals, lest bleeding start again. +--vitals = {depends on severity and current treatment}, +healtime = nil,-- maybe make a severity value that starts at 1 or something, and goes down as you treat, or if the wound is less severe to start with. +medical_step = nil, +} + + +--open fracture test +minetest.register_entity("medical:fracturetest", { + hp_max = 1, + physical = true, + weight = 5, + collisionbox = {-0.1,-0.1,-0.1, 0.1,0.1,0.1}, + visual = "mesh", + mesh = "bone.b3d", + visual_size = {x=1, y=1},--{x=.211, y=.211}, + textures = {"default_clay.png","default_clay.png","default_clay.png","default_clay.png","default_clay.png","default_clay.png"}, -- number of required textures depends on visual + colors = {}, -- number of required colors depends on visual + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = false, + on_activate = function(self, staticdata, dtime_s) + minetest.after(1, function() + self.object:remove() + local all_objects = minetest.get_objects_inside_radius(self.object:get_pos(), 10) + local _,obj + for _,obj in ipairs(all_objects) do + if obj:get_entity_name() == "medical:body" then + minetest.chat_send_all(obj:get_entity_name()) + self.object:set_attach(obj, "Arm_Right", {x=0,y=4,z=0}, {x=1,y=0,z=math.random(-10, 10)}) + break + end + end + end) + end +}) \ No newline at end of file diff --git a/textures/applypressure.png b/textures/applypressure.png new file mode 100644 index 0000000000000000000000000000000000000000..33594019e9c26ced5d0d767d6402d07e0f85e620 GIT binary patch literal 11377 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 literal 0 HcmV?d00001 diff --git a/textures/bpcuff.png b/textures/bpcuff.png new file mode 100644 index 0000000000000000000000000000000000000000..d638cf9a0201fb5ad7d5db7fdc68c1f4e87cbc55 GIT binary patch literal 3085 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 by8pibAp&<{14}4300000NkvXXu0mjfl+v>& literal 0 HcmV?d00001 diff --git a/textures/bpcuffbladder.png b/textures/bpcuffbladder.png new file mode 100644 index 0000000000000000000000000000000000000000..fa311e314dbac672d60133b36ef273597bf6bc2e GIT binary patch literal 1565 zcmV+&2IBdNP)EX>4Tx04R}tkv&MmKpe$i(@I4u4ptCx2w0sgh>AE$6^me@v=v%)FuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|}?mh0_0Yam~R5LIEsG4P@ z;xRFsTNQ(^2w(s}2qO|R^+b9x1JChw4J|`YG=z_$LT$f#b<6LxD;F)0~lbR*5p0lat9cE(j`N3BtK1|PypV~=$mpt|1Hq7=JwXw$LRx*p{|y1fP+I| ztVr4G9`Ek%?Csw(t^R%hJ`Qq{Z3L_I00006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru^z!5(^4K z;vrS7N?Qnv(k4v;QJbb|z;<5twSDiMxic(KHYkhQwZn#gc@{_CocYfK_+MSna6W77 z6dxTLu>KvR-2h0$oE-tK-&*y%{(9TcNyN~}fBFTsxk~^eh3uEd4j<$vrXF9}j^)!y z)=G}HJ&;SrSw5Gs88g^MrIg#7xyJ^87mq*lXe)WzD%GpUrxF)0&(BE0vO)+XVmRH#V14Kj94**RE=kjVHozy!HaOl2b zU$yB;0QmaC)ia&|HBAdr5eN|?3?-tr4Y%&$$bpd?9S4|RSXu{wSDt>1Zq~!`X48iN zK*&D;{d+P12pUZfwYrzHTWG_UOt@02JYgCJKna3CKq>+!Vxd^b;@-g`4BZ4}8V0gy zqvHV2KRnjEQS(o8&Y?3Mnyy1ZfiVqZ`-d?!kVnm}qEsp)mr6Pv2Wa}d2trI5N(2E1 z6kwVbn5Lu2eN@V22q}@v51_oh;dKcI2F1W!M z2q+?vC?Zw_>swpcs=A<*A`}9?2o8084!krqLB78{UyV7|n@+@p!3Y|z3mFO+OowSX zunhx5332-DrG=eV^j!h`Rr8W>oP3h@#-bnVI#JPx0RkXY0A(8b`wK`WVhE|+vttJZ zT-_DGchfVK&(Hiqa;f-cJZilbH4P+_2}r@gbc)gY_rtO1^z^mG^;Q>KOWSa7Hf2l> z=K1XPmB0%L3qpl-GJ!%ig>TPaq^+2*txb7mDc)S-Y<*mxD1H_yN(HK(=&x2G-wVUT}2DF$XSKCft P00000NkvXXu0mjf^^mXH literal 0 HcmV?d00001 diff --git a/textures/medical_cut.png b/textures/medical_cut.png new file mode 100644 index 0000000000000000000000000000000000000000..01f66dfb9369fd48a1afadbc4b596e5841a60779 GIT binary patch literal 855 zcmV-d1E~CoP)EX>4Tx04R}tkv&MmKpe$iKcp&^4i*$~$WWcEh>AE$6^me@v=v%)FuC*#nlvOS zE{=k0!NHHks)LKOt`4q(Aou~|}?mh0_0p3Q1DTaRnP*hV- z#bZJ?w<-i);YSDq7)OuD3@wpf%)oVg-NVDzyC~0cKlkV8lk)}xJOc3?({z(~gLr1s z)Hv@GhgnIKiO-40bh;q%BiAK|-#8a-_VUcIo=MFUhlzz^2TL8yO1eTkO&pOGmGZq= zhh@%NoRvzAweHDZ7|g3HX|B^8MjT5>APE5yYAB-u6H!`KQVgVMKjz{evi(VNN#rVn zkz)Z>C=hKw_#gc4)+kI(I!VD8(Dh-*TUnkRto8Msp0{%Ql5{Up8K z)*?qhXdAe=ZfnvWaJd5vK53#Z+LDi^w@?7y&*+sb!yXN%P+Q;bwkfE-YZ-9eC zV6;ft>n`u^?(FT~Gp+u90DQl4tEs7OFaQ7m24YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2jm0~7cV*?n-Pcr000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0003lNkl%5q$P~ zcurFeLttltr^N#ANrEq9a7K1d@M|q*#xMZ5D$DKyuimRCaaWe;tD+Nf5xvhcPMsqG z5~wMnY9~o zRHQutyF)GM05^i}Z|0&YZ3qbm-8iN`Q;+W_!V6_4{d0C4IY&a2ACbsl@K0B~KF zc5m)c2u*DLb`Au#mj2;A2o#ef(Ojh3>iQ@I5YT2-wHtGhB2F+#k|yoJ-?niad%q`e h^t;9wdw2 literal 0 HcmV?d00001 diff --git a/timers.lua b/timers.lua index 6d7c84a..beb9fef 100644 --- a/timers.lua +++ b/timers.lua @@ -1,6 +1,6 @@ medical.timers = {} -function medical.start_timer(name, length, loop, arg, func) +function medical.start_timer(name, length, loop, arg, func, stoparg, stopfunc, cancel_on_release, cancel_owner) local index if name then index = name @@ -20,13 +20,32 @@ function medical.start_timer(name, length, loop, arg, func) medical.timers[index].loop = loop medical.timers[index].arg = arg medical.timers[index].func = func + medical.timers[index].stoparg = stoparg + medical.timers[index].stopfunc = stopfunc + if cancel_owner and cancel_on_release then + medical.timers[index].cancel_on_release = cancel_on_release + medical.timers[index].cancel_owner = cancel_owner + local player = minetest.get_player_by_name(cancel_owner) + if player and not medical.lookingplayer[cancel_owner] then medical.lookingplayer[cancel_owner] = {dir = player:get_look_dir(), pos = player:get_pos()} end + end return index end function medical.stop_timer(name, runonce) local timer = medical.timers[name] if runonce then - timer.func(timer.arg) + if type(timer.arg) == "table" then + timer.func(unpack(timer.arg)) + else + timer.func(timer.arg) + end + end + if timer.stopfunc then + if type(timer.stoparg) == "table" then + timer.stopfunc(unpack(timer.stoparg)) + else + timer.stopfunc(timer.stoparg) + end end medical.timers[name] = nil end @@ -35,12 +54,32 @@ minetest.register_globalstep(function(dtime) for index, timer in pairs (medical.timers) do timer.timeleft = timer.timeleft - dtime if timer.timeleft <= 0 then - timer.func(timer.arg) - if timer.loop then - medical.start_timer(index, timer.length, timer.loop, timer.arg, timer.func) + if type(timer.arg) == "table" then + timer.func(unpack(timer.arg)) else - medical.stoptimer(name) + timer.func(timer.arg) + end + if timer.loop then + medical.start_timer(index, timer.length, timer.loop, timer.arg, timer.func, timer.stoparg, timer.stopfunc, timer.cancel_on_release, timer.cancel_owner) + else + medical.stop_timer(index) end end end +end) + +controls.register_on_release(function(player, key, time) + local name = player:get_player_name() + for index, timer in pairs (medical.timers) do + if name == timer.cancel_owner and timer.cancel_on_release == key then + medical.stop_timer(index) + end + end +end) +medical.register_on_lookaway(function(player, name) + for index, timer in pairs (medical.timers) do + if name == timer.cancel_owner and timer.cancel_on_release then + medical.stop_timer(index) + end + end end) \ No newline at end of file diff --git a/tools.lua b/tools.lua index d7f9530..68244a6 100644 --- a/tools.lua +++ b/tools.lua @@ -9,10 +9,10 @@ medical.usedtools[""] = function(self, clicker, wielditem, hitloc, local_hitloc) vitalpoints.pedalright = {x=.20,y=.1,z=.7} vitalpoints.pedalleft = {x=-.20,y=.1,z=.7} local distance, hitpart = medical.getclosest(vitalpoints, local_hitloc) - if distance > .15 then return end + if distance > .15 then return false end local cname = clicker:get_player_name() + local sname = self.owner if medical.hud[cname] then clicker:hud_remove(medical.hud[cname]) medical.hud[cname] = nil end - if not medical.lookingplayer[cname] then medical.lookingplayer[cname] = {dir = clicker:get_look_dir(), pos = clicker:get_pos()} end medical.hud[cname] = clicker:hud_add({ hud_elem_type = "image", position = {x = 0.5, y = 0.55}, @@ -21,7 +21,8 @@ medical.usedtools[""] = function(self, clicker, wielditem, hitloc, local_hitloc) scale = { x = 10, y = 10}, alignment = { x = 0, y = 0 }, }) - medical.start_timer(cname.."pulsecheck", 60/medical.data.vitals[cname].pulse, true, cname, --todo: change this to give the patient's pulse instead of yours + clicker:hud_set_flags({wielditem=false}) + medical.start_timer(sname.."pulsecheck", 60/medical.data[sname].vitals.pulse, true, sname, function(arg) minetest.sound_play("human-heartbeat-daniel_simon", { pos = hitloc, @@ -41,23 +42,133 @@ medical.usedtools[""] = function(self, clicker, wielditem, hitloc, local_hitloc) hitter:hud_remove(circle) end end) - end + end, + cname, + function(stoparg) + local player = minetest.get_player_by_name(stoparg) + if medical.hud[stoparg] then + player:hud_remove(medical.hud[stoparg]) + medical.hud[stoparg] = nil + player:hud_set_flags({wielditem=true}) + end + end, "RMB", cname ) + return true +end +medical.attachedtools[""] = function(self, clicker, wielditem, hitloc, local_hitloc) + --local limb = medical.getlimb(self.object, clicker, nil, nil, hitloc) + local all_objects = minetest.get_objects_inside_radius(hitloc, 10) + local cname = clicker:get_player_name() + for _,obj in ipairs(all_objects) do + local pos = obj:get_pos() + local marker = clicker:hud_add({ + hud_elem_type = "waypoint", + name = obj:get_entity_name(), + number = 0xFF0000, + world_pos = obj:get_pos() + }) + minetest.after(5, function() + local hitter = minetest.get_player_by_name(cname) + if hitter then + hitter:hud_remove(marker) + end + end) + end end -controls.register_on_release(function(player, key, time) - local name = player:get_player_name() - if key == "RMB" and medical.hud[name] then - player:hud_remove(medical.hud[name]) medical.hud[name] = nil - medical.lookingplayer[name] = nil - medical.stop_timer(name.."pulsecheck", false) +minetest.register_tool("medical:bpcuff", { + description = "Blood Pressure Cuff", + inventory_image = "bpcuff.png", +}) + +minetest.register_tool("medical:bpbladder", { + description = "Blood Pressure Cuff", + inventory_image = "bpcuffbladder.png", + on_use = function(itemstack, player, pointed_thing) + --inflate bp cuff end -end) -medical.register_on_lookaway(function(player, name) - if medical.hud[name] then - player:hud_remove(medical.hud[name]) - medical.hud[name] = nil - medical.lookingplayer[name] = nil - medical.stop_timer(name.."pulsecheck", false) +}) + +minetest.register_entity("medical:bpcuff", { + hp_max = 1, + physical = false, + weight = 5, + collisionbox = {-0.1,-0.1,-0.1, 0.1,0.1,0.1}, + visual = "cube", + visual_size = {x=.25, y=.25},--{x=.211, y=.211}, + textures = {"default_coal_block.png", "default_coal_block.png", "default_coal_block.png", "default_coal_block.png", "default_coal_block.png", "default_coal_block.png"}, -- number of required textures depends on visual + colors = {}, -- number of required colors depends on visual + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = false, + on_activate = function(self, staticdata, dtime_s) + if not staticdata or staticdata == "" then self.object:remove() end + self.owner = staticdata end -end) \ No newline at end of file +}) + +minetest.register_entity("medical:line", { + hp_max = 1, + physical = false, + weight = 5, + collisionbox = {-0.1,-0.1,-0.1, 0.1,0.1,0.1}, + visual = "cube", + visual_size = {x=.05, y=.1}, + textures = {"blackline.png", "blackline.png", "blackline.png", "blackline.png", "blackline.png", "blackline.png"}, -- number of required textures depends on visual + colors = {}, -- number of required colors depends on visual + spritediv = {x=1, y=1}, + initial_sprite_basepos = {x=0, y=0}, + is_visible = true, + makes_footstep_sound = false, + automatic_rotate = false, + on_step = function(self, dtime) + if not self.target or not self.owner then self.object:remove() return end + local player = minetest.get_player_by_name(self.owner) + local op = player:get_pos() + op.y = op.y + 1 + op = vector.add(op, vector.multiply(player:get_player_velocity(), .1)) + if self.lastpos and vector.equals(self.lastpos, op) then return end + local tp = self.target + + if vector.distance(op, tp) > 1.5 then + local inv = player:get_inventory() + local list = "main" + return + end + + local delta = vector.subtract(op, tp) + local yaw = math.atan2(delta.z, delta.x) - math.pi / 2 + local pitch = math.atan2(delta.y, math.sqrt(delta.z*delta.z + delta.x*delta.x)) + pitch = pitch + math.pi/2 + + self.object:move_to({x=(op.x+tp.x)/2, y=(op.y+tp.y)/2, z=(op.z+tp.z)/2, }) + self.object:set_rotation({x=pitch, y=yaw, z=0}) + self.object:set_properties({visual_size = {x=.05, y=vector.distance(tp, op)}}) + self.lastpos = op + end, + on_activate = function(self, staticdata, dtime_s) + if not staticdata or staticdata == "" then self.object:remove() end + self.owner = staticdata + self.target = self.object:get_pos() + end +}) + +medical.attachedtools["medical:bpcuff"] = function(self, clicker, wielditem, hitloc, local_hitloc) + local limb = medical.getlimb(self.object, clicker, nil, nil, hitloc) + local bone + if limb == "rightarm" then bone = "Arm_Right" elseif limb == "leftarm" then bone = "Arm_Left" else return end + local pos = self.object:get_pos() + local obj = minetest.add_entity(pos, "medical:bpcuff", clicker:get_player_name()) + minetest.after(0, function() + local marker = clicker:hud_add({ + hud_elem_type = "waypoint", + name = "hit", + number = 0xFF0000, + world_pos = obj:get_pos() + }) end) + obj:set_attach(self.object, bone, {x=0,y=.5,z=0}, {x=0,y=0,z=0}) + --local obj = minetest.add_entity(hitloc, "medical:line", clicker:get_player_name()) + minetest.after(0, function() clicker:set_wielded_item({name = ""})end) +end \ No newline at end of file diff --git a/vitals.lua b/vitals.lua index 6770fa6..34bd6b7 100644 --- a/vitals.lua +++ b/vitals.lua @@ -8,22 +8,36 @@ default_vitals.volume = 5000 --milliliters default_vitals.systolic = 110 --mmHg default_vitals.diastolic = 70 --mmHg +minetest.register_on_joinplayer(function(player) + local name = player:get_player_name() + if not medical.data[name] then + medical.data[name] = {} + end + if not medical.data[name].vitals then + medical.data[name].vitals = default_vitals + end +end) + minetest.register_globalstep(function(dtime) timer = timer + dtime; if timer >= 5 then for _,player in ipairs(minetest.get_connected_players()) do - --player:set_bone_position("Head", {x=0,y=10,z=0}, {x=0,y=180,z=0}) - --local bonepos = player:get_bone_position("Head") - --[[local text = "" - for id, data in pairs (bonepos) do - text = text.." "..tostring(id)..":"..dump(data) - end - minetest.chat_send_all(text)--]] local name = player:get_player_name() - if not medical.data.vitals[name] then medical.data.vitals[name] = default_vitals end - if medical.data.injuries[name] then + if medical.data[name].injuries then --handle loss of vital signs due to injuries + for index, injury in pairs (medical.data[name].injuries) do + local injurydef = medical.injuries[injury.name] + if injurydef.medical_step then + injurydef.medical_step() + end + if injury.vitals then + for vital, amount in pairs (injury.vitals) do + medical.data[name].vitals[vital] = medical.data[name].vitals[vital] - amount + end + end + --handle loss of vital signs due to injuries + end end if hunger then @@ -34,7 +48,7 @@ minetest.register_globalstep(function(dtime) --handle thirst things end - mv = medical.data.vitals[name] + local mv = medical.data[name].vitals local perfusion = ((mv.oxygen-60)/34) * ((mv.pulse-30)/40) * ((mv.volume-2000)/3000) * ((mv.temp-70)/28) if perfusion < .9 then --compensate by raising pulse and respiratory rate