The lifeless husk of [C] bursts open, revealing a new, intact copy in the pool of viscera.
" //Bloody hell... - var/T = get_turf(src) - new /obj/effect/gibspawner/human/scree(T) - var/braindamage = C.brainloss/2 //If you have 100 brainloss, it gives you 50. - C.does_not_breathe = 0 //start breathing again - C.revive() // I did have special snowflake code, but this is easier. - C.weakened = 2 //Not going to let you get up immediately. 2 ticks before you get up. Overrides the above 10000 weaken. - C.mutations.Remove(HUSK) - C.nutrition = old_nutrition - C.brainloss = (braindamage+10) //Gives them half their prior brain damage plus ten more. - C.update_canmove() - for(var/obj/item/W in C) - C.drop_from_inventory(W) - spawn(3600 SECONDS) //1 hour wait until you can revive. - C.reviving = 0 - C.verbs -= /mob/living/carbon/human/proc/hatch + if(stat == DEAD) //Uh oh, you died! + if(hasnutriment()) //Let's hope you have nutriment in you.... If not + if(src) //Runtime prevention. + chimera_hatch() + visible_message("The lifeless husk of [src] bursts open, revealing a new, intact copy in the pool of viscera.
") //Bloody hell... + brainloss += 10 //Reviving from dead means you take a lil' brainloss on top of whatever was healed in the revive. return else - return //Ruuntime prevention - else - return //Something went wrong. + return //Runtime prevention + else //don't have nutriment to hatch! Or you somehow died in between completing your revive and hitting hatch. + to_chat(src, "Your body was unable to regenerate, what few living cells remain require additional nutrients to complete the process.") + reviving = FALSE // so they can try again when they're given a kickstart + return - else if(C.stat != DEAD) //If they're alive at the time of reviving. - C.nutrition -= C.nutrition/2 //Cut their nutrition in half. - var/old_nutrition = C.nutrition //Since the game is being annoying. - C << "Your new body awakens, bursting free from your old skin." - viewers(C) << "The dormant husk of [C] bursts open, revealing a new, intact copy in the pool of viscera.
" //Bloody hell... - var/T = get_turf(src) - new /obj/effect/gibspawner/human/scree(T) - var/braindamage = C.brainloss/2 //If you have 100 brainloss, it gives you 50. - C.revive() // I did have special snowflake code, but this is easier. - C.weakened = 2 //Not going to let you get up immediately. 2 ticks before you get up. Overrides the above 10000 weaken. - C.mutations.Remove(HUSK) - C.nutrition = old_nutrition - C.brainloss = (braindamage) //Gives them half their prior brain damage plus ten more. - C.update_canmove() - for(var/obj/item/W in C) - C.drop_from_inventory(W) - spawn(3600 SECONDS) //1 hour wait until you can revive again. - C.reviving = 0 - C.does_not_breathe = 0 //start breathing again - C.verbs -= /mob/living/carbon/human/proc/hatch + else if(stat != DEAD) //If they're alive at the time of regenerating. + chimera_hatch() + visible_message("The dormant husk of [src] bursts open, revealing a new, intact copy in the pool of viscera.
") //Bloody hell... return else return //Runtime prevention. +/mob/living/carbon/human/proc/chimera_hatch() + nutrition -= nutrition/2 //Cut their nutrition in half. + var/old_nutrition = nutrition //Since the game is being annoying. + to_chat(src, "Your new body awakens, bursting free from your old skin.") + var/T = get_turf(src) + new /obj/effect/gibspawner/human/scree(T) + var/braindamage = brainloss/2 //If you have 100 brainloss, it gives you 50. + does_not_breathe = 0 //start breathing again + revive() // I did have special snowflake code, but this is easier. + weakened = 2 //Not going to let you get up immediately. 2 ticks before you get up. Overrides the above 10000 weaken. + mutations.Remove(HUSK) + nutrition = old_nutrition + brainloss = braindamage //Gives them half their prior brain damage. + update_canmove() + for(var/obj/item/W in src) + drop_from_inventory(W) + spawn(3600 SECONDS) //1 hour wait until you can revive. + reviving = FALSE + to_chat(src, "Your body has recovered from the strenuous effort of rebuilding itself.") + verbs -= /mob/living/carbon/human/proc/hatch + return + /obj/effect/gibspawner/human/scree fleshcolor = "#14AD8B" //Scree blood. bloodcolor = "#14AD8B" @@ -209,188 +144,190 @@ if(handling_hal) return //avoid conflict with actual hallucinations handling_hal = 1 - if(client && feral) // largely a copy of handle_hallucinations() without the fake attackers. Unlike hallucinations, only fires once - if they're still feral they'll get hit again anyway. - sleep(rand(200,500)/(feral/10)) - var/halpick = rand(1,100) - switch(halpick) - if(0 to 15) //15% chance - //Screwy HUD - //src << "Screwy HUD" - hal_screwyhud = pick(1,2,3,3,4,4) - spawn(rand(100,250)) - hal_screwyhud = 0 - if(16 to 25) //10% chance - //Strange items - //src << "Traitor Items" - if(!halitem) - halitem = new - var/list/slots_free = list(ui_lhand,ui_rhand) - if(l_hand) slots_free -= ui_lhand - if(r_hand) slots_free -= ui_rhand - if(istype(src,/mob/living/carbon/human)) - var/mob/living/carbon/human/H = src - if(!H.belt) slots_free += ui_belt - if(!H.l_store) slots_free += ui_storage1 - if(!H.r_store) slots_free += ui_storage2 - if(slots_free.len) - halitem.screen_loc = pick(slots_free) - halitem.layer = 50 - switch(rand(1,6)) - if(1) //revolver - halitem.icon = 'icons/obj/gun.dmi' - halitem.icon_state = "revolver" - halitem.name = "Revolver" - if(2) //c4 - halitem.icon = 'icons/obj/assemblies.dmi' - halitem.icon_state = "plastic-explosive0" - halitem.name = "Mysterious Package" - if(prob(25)) - halitem.icon_state = "c4small_1" - if(3) //sword - halitem.icon = 'icons/obj/weapons.dmi' - halitem.icon_state = "sword1" - halitem.name = "Sword" - if(4) //stun baton - halitem.icon = 'icons/obj/weapons.dmi' - halitem.icon_state = "stunbaton" - halitem.name = "Stun Baton" - if(5) //emag - halitem.icon = 'icons/obj/card.dmi' - halitem.icon_state = "emag" - halitem.name = "Cryptographic Sequencer" - if(6) //flashbang - halitem.icon = 'icons/obj/grenade.dmi' - halitem.icon_state = "flashbang1" - halitem.name = "Flashbang" - if(client) client.screen += halitem - spawn(rand(100,250)) - if(client) - client.screen -= halitem - halitem = null - if(26 to 35) //10% chance - //Flashes of danger - //src << "Danger Flash" - if(!halimage) - var/list/possible_points = list() - for(var/turf/simulated/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/simulated/floor/target = pick(possible_points) + if(client && feral >= 10) // largely a copy of handle_hallucinations() without the fake attackers. Unlike hallucinations, only fires once - if they're still feral they'll get hit again anyway. + spawn(rand(200,500)/(feral/10)) + if(!feral) return //just to avoid fuckery in the event that they un-feral in the time it takes for the spawn to proc + var/halpick = rand(1,100) + switch(halpick) + if(0 to 15) //15% chance + //Screwy HUD + //src << "Screwy HUD" + hal_screwyhud = pick(1,2,3,3,4,4) + spawn(rand(100,250)) + hal_screwyhud = 0 + if(16 to 25) //10% chance + //Strange items + //src << "Traitor Items" + if(!halitem) + halitem = new + var/list/slots_free = list(ui_lhand,ui_rhand) + if(l_hand) slots_free -= ui_lhand + if(r_hand) slots_free -= ui_rhand + if(istype(src,/mob/living/carbon/human)) + var/mob/living/carbon/human/H = src + if(!H.belt) slots_free += ui_belt + if(!H.l_store) slots_free += ui_storage1 + if(!H.r_store) slots_free += ui_storage2 + if(slots_free.len) + halitem.screen_loc = pick(slots_free) + halitem.layer = 50 + switch(rand(1,6)) + if(1) //revolver + halitem.icon = 'icons/obj/gun.dmi' + halitem.icon_state = "revolver" + halitem.name = "Revolver" + if(2) //c4 + halitem.icon = 'icons/obj/assemblies.dmi' + halitem.icon_state = "plastic-explosive0" + halitem.name = "Mysterious Package" + if(prob(25)) + halitem.icon_state = "c4small_1" + if(3) //sword + halitem.icon = 'icons/obj/weapons.dmi' + halitem.icon_state = "sword1" + halitem.name = "Sword" + if(4) //stun baton + halitem.icon = 'icons/obj/weapons.dmi' + halitem.icon_state = "stunbaton" + halitem.name = "Stun Baton" + if(5) //emag + halitem.icon = 'icons/obj/card.dmi' + halitem.icon_state = "emag" + halitem.name = "Cryptographic Sequencer" + if(6) //flashbang + halitem.icon = 'icons/obj/grenade.dmi' + halitem.icon_state = "flashbang1" + halitem.name = "Flashbang" + if(client) client.screen += halitem + spawn(rand(100,250)) + if(client) + client.screen -= halitem + halitem = null + if(26 to 35) //10% chance + //Flashes of danger + //src << "Danger Flash" + if(!halimage) + var/list/possible_points = list() + for(var/turf/simulated/floor/F in view(src,world.view)) + possible_points += F + if(possible_points.len) + var/turf/simulated/floor/target = pick(possible_points) - switch(rand(1,3)) - if(1) - //src << "Space" - halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER) - if(2) - //src << "Fire" - halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER) - if(3) - //src << "C4" - halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01) + switch(rand(1,3)) + if(1) + //src << "Space" + halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER) + if(2) + //src << "Fire" + halimage = image('icons/effects/fire.dmi',target,"1",TURF_LAYER) + if(3) + //src << "C4" + halimage = image('icons/obj/assemblies.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01) - if(client) client.images += halimage - spawn(rand(10,50)) //Only seen for a brief moment. - if(client) client.images -= halimage - halimage = null + if(client) client.images += halimage + spawn(rand(10,50)) //Only seen for a brief moment. + if(client) client.images -= halimage + halimage = null - if(36 to 55) //20% chance - //Strange audio - //src << "Strange Audio" - switch(rand(1,12)) - if(1) src << 'sound/machines/airlock.ogg' - if(2) - if(prob(50))src << 'sound/effects/Explosion1.ogg' - else src << 'sound/effects/Explosion2.ogg' - if(3) src << 'sound/effects/explosionfar.ogg' - if(4) src << 'sound/effects/Glassbr1.ogg' - if(5) src << 'sound/effects/Glassbr2.ogg' - if(6) src << 'sound/effects/Glassbr3.ogg' - if(7) src << 'sound/machines/twobeep.ogg' - if(8) src << 'sound/machines/windowdoor.ogg' - if(9) - //To make it more realistic, I added two gunshots (enough to kill) - src << 'sound/weapons/Gunshot.ogg' - spawn(rand(10,30)) + if(36 to 55) //20% chance + //Strange audio + //src << "Strange Audio" + switch(rand(1,12)) + if(1) src << 'sound/machines/airlock.ogg' + if(2) + if(prob(50))src << 'sound/effects/Explosion1.ogg' + else src << 'sound/effects/Explosion2.ogg' + if(3) src << 'sound/effects/explosionfar.ogg' + if(4) src << 'sound/effects/Glassbr1.ogg' + if(5) src << 'sound/effects/Glassbr2.ogg' + if(6) src << 'sound/effects/Glassbr3.ogg' + if(7) src << 'sound/machines/twobeep.ogg' + if(8) src << 'sound/machines/windowdoor.ogg' + if(9) + //To make it more realistic, I added two gunshots (enough to kill) src << 'sound/weapons/Gunshot.ogg' - if(10) src << 'sound/weapons/smash.ogg' - if(11) - //Same as above, but with tasers. - src << 'sound/weapons/Taser.ogg' - spawn(rand(10,30)) + spawn(rand(10,30)) + src << 'sound/weapons/Gunshot.ogg' + if(10) src << 'sound/weapons/smash.ogg' + if(11) + //Same as above, but with tasers. src << 'sound/weapons/Taser.ogg' - //Rare audio - if(12) -//These sounds are (mostly) taken from Hidden: Source - var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/Heart Beat.ogg', 'sound/effects/screech.ogg',\ - 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\ - 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ - 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ - 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') - src << pick(creepyasssounds) - if(56 to 60) //5% chance - //Flashes of danger - //src << "Danger Flash" - if(!halbody) - var/list/possible_points = list() - for(var/turf/simulated/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/simulated/floor/target = pick(possible_points) - switch(rand(1,4)) - if(1) - halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER) - if(2,3) - halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER) - if(4) - halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER) - // if(5) - // halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER) + spawn(rand(10,30)) + src << 'sound/weapons/Taser.ogg' + //Rare audio + if(12) + //These sounds are (mostly) taken from Hidden: Source + var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/Heart Beat.ogg', 'sound/effects/screech.ogg',\ + 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\ + 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ + 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ + 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') + src << pick(creepyasssounds) + if(56 to 60) //5% chance + //Flashes of danger + //src << "Danger Flash" + if(!halbody) + var/list/possible_points = list() + for(var/turf/simulated/floor/F in view(src,world.view)) + possible_points += F + if(possible_points.len) + var/turf/simulated/floor/target = pick(possible_points) + switch(rand(1,4)) + if(1) + halbody = image('icons/mob/human.dmi',target,"husk_l",TURF_LAYER) + if(2,3) + halbody = image('icons/mob/human.dmi',target,"husk_s",TURF_LAYER) + if(4) + halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER) + // if(5) + // halbody = image('xcomalien.dmi',target,"chryssalid",TURF_LAYER) - if(client) client.images += halbody - spawn(rand(50,80)) //Only seen for a brief moment. - if(client) client.images -= halbody - halbody = null - if(61 to 85) //25% chance - //food - if(!halbody) - var/list/possible_points = list() - for(var/turf/simulated/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/simulated/floor/target = pick(possible_points) - switch(rand(1,10)) - if(1) - halbody = image('icons/mob/animal.dmi',target,"cow",TURF_LAYER) - if(2) - halbody = image('icons/mob/animal.dmi',target,"chicken",TURF_LAYER) - if(3) - halbody = image('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER) - if(4) - halbody = image('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER) - if(5) - halbody = image('icons/obj/food.dmi',target,"sausage",TURF_LAYER) - if(6) - halbody = image('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER) - if(7) - halbody = image('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER) - if(8) - halbody = image('icons/obj/food.dmi',target,"meat",TURF_LAYER) - if(9) - halbody = image('icons/obj/food.dmi',target,"meatstake",TURF_LAYER) - if(10) - halbody = image('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER) + if(client) client.images += halbody + spawn(rand(50,80)) //Only seen for a brief moment. + if(client) client.images -= halbody + halbody = null + if(61 to 85) //25% chance + //food + if(!halbody) + var/list/possible_points = list() + for(var/turf/simulated/floor/F in view(src,world.view)) + possible_points += F + if(possible_points.len) + var/turf/simulated/floor/target = pick(possible_points) + switch(rand(1,10)) + if(1) + halbody = image('icons/mob/animal.dmi',target,"cow",TURF_LAYER) + if(2) + halbody = image('icons/mob/animal.dmi',target,"chicken",TURF_LAYER) + if(3) + halbody = image('icons/obj/food.dmi',target,"bigbiteburger",TURF_LAYER) + if(4) + halbody = image('icons/obj/food.dmi',target,"meatbreadslice",TURF_LAYER) + if(5) + halbody = image('icons/obj/food.dmi',target,"sausage",TURF_LAYER) + if(6) + halbody = image('icons/obj/food.dmi',target,"bearmeat",TURF_LAYER) + if(7) + halbody = image('icons/obj/food.dmi',target,"fishfillet",TURF_LAYER) + if(8) + halbody = image('icons/obj/food.dmi',target,"meat",TURF_LAYER) + if(9) + halbody = image('icons/obj/food.dmi',target,"meatstake",TURF_LAYER) + if(10) + halbody = image('icons/obj/food.dmi',target,"monkeysdelight",TURF_LAYER) + + if(client) client.images += halbody + spawn(rand(50,80)) //Only seen for a brief moment. + if(client) client.images -= halbody + halbody = null + if(86 to 100) //15% chance + //hear voices. Could make the voice pick from nearby creatures, but nearby creatures make feral hallucinations rare so don't bother. + var/list/hiddenspeakers = list("Someone distant", "A voice nearby","A familiar voice", "An echoing voice", "A cautious voice", "A scared voice", "Someone around the corner", "Someone", "Something", "Something scary", "An urgent voice", "An angry voice") + var/list/speakerverbs = list("calls out", "yells", "screams", "exclaims", "shrieks", "shouts", "hisses", "snarls") + var/list/spookyphrases = list("It's over here!","Stop it!", "Hunt it down!", "Get it!", "Quick, over here!", "Anyone there?", "Who's there?", "Catch that thing!", "Stop it! Kill it!", "Anyone there?", "Where is it?", "Find it!", "There it is!") + to_chat(src, "[pick(hiddenspeakers)] [pick(speakerverbs)], \"[pick(spookyphrases)]\"") - if(client) client.images += halbody - spawn(rand(50,80)) //Only seen for a brief moment. - if(client) client.images -= halbody - halbody = null - if(86 to 100) //15% chance - //disorientation - if(client) - client.dir = pick(2,4,8) - spawn(rand(20,50)) - client.dir = 1 handling_hal = 0 return @@ -845,6 +782,6 @@ /mob/living/proc/toggle_pass_table() set name = "Toggle Agility" //Dunno a better name for this. You have to be pretty agile to hop over stuff!!! set desc = "Allows you to start/stop hopping over things such as hydroponics trays, tables, and railings." - set category = "IC" + set category = "Abilities" pass_flags ^= PASSTABLE //I dunno what this fancy ^= is but Aronai gave it to me. to_chat(src, "You [pass_flags&PASSTABLE ? "will" : "will NOT"] move over tables/railings/trays!") diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm index f5cb361465..9f74592b8e 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_vr.dm @@ -24,7 +24,6 @@ inherent_verbs = list( /mob/living/carbon/human/proc/begin_reconstitute_form, /mob/living/carbon/human/proc/sonar_ping, - /mob/living/carbon/human/proc/purge_impurities, /mob/living/carbon/human/proc/succubus_drain, /mob/living/carbon/human/proc/succubus_drain_finalize, /mob/living/carbon/human/proc/succubus_drain_lethal, @@ -48,7 +47,7 @@ //primitive_form = "Farwa" spawn_flags = SPECIES_CAN_JOIN | SPECIES_IS_WHITELISTED //Whitelisted as restricted is broken. - flags = NO_SCAN //Dying as a chimera is, quite literally, a death sentence. Well, if it wasn't for their revive, that is. + flags = NO_SCAN | NO_INFECT //Dying as a chimera is, quite literally, a death sentence. Well, if it wasn't for their revive, that is. appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR flesh_color = "#AFA59E" @@ -145,11 +144,9 @@ H << " Every movement, every flick, every sight and sound has your full attention, your hunting instincts on high alert... In fact, [M] looks extremely appetizing..." if(H.stat == CONSCIOUS) H.emote("twitch") - if(!H.handling_hal) - H.handle_feral() - else // nobody around - if(!H.handling_hal) H.handle_feral() + else // nobody around + H.handle_feral() if(prob(2)) //periodic nagmessages if(H.nutrition <= 100) //If hungry, nag them to go and find someone or something to eat. H << " Confusing sights and sounds and smells surround you - scary and disorienting it may be, but the drive to hunt, to feed, to survive, compels you." diff --git a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm index aed54a6b9c..f19eb0e1ea 100644 --- a/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm +++ b/code/modules/mob/living/carbon/human/species/xenomorphs/alien_species.dm @@ -38,6 +38,8 @@ speech_sounds = list('sound/voice/hiss1.ogg','sound/voice/hiss2.ogg','sound/voice/hiss3.ogg','sound/voice/hiss4.ogg') speech_chance = 100 + virus_immune = 1 + breath_type = null poison_type = null diff --git a/code/modules/mob/living/carbon/human/unarmed_attack.dm b/code/modules/mob/living/carbon/human/unarmed_attack.dm index 1c54a4258f..a7f80fb8f1 100644 --- a/code/modules/mob/living/carbon/human/unarmed_attack.dm +++ b/code/modules/mob/living/carbon/human/unarmed_attack.dm @@ -11,7 +11,7 @@ var/global/list/sparring_attack_cache = list() var/sharp = 0 var/edge = 0 - var/deal_halloss + var/damage_type = BRUTE var/sparring_variant_type = /datum/unarmed_attack/light_strike var/eye_attack_text @@ -131,7 +131,7 @@ var/global/list/sparring_attack_cache = list() /datum/unarmed_attack/punch/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage) var/obj/item/organ/external/affecting = target.get_organ(zone) var/organ = affecting.name - + var/datum/gender/TU = gender_datums[user.get_visible_gender()] var/datum/gender/TT = gender_datums[target.get_visible_gender()] @@ -258,10 +258,10 @@ var/global/list/sparring_attack_cache = list() if(5) user.visible_message("[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed [TU.his] [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/ /datum/unarmed_attack/light_strike - deal_halloss = 3 attack_noun = list("tap","light strike") attack_verb = list("tapped", "lightly struck") - damage = 2 + damage = 3 + damage_type = AGONY shredding = 0 damage = 0 sharp = 0 diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a4c2e6566d..f39126abd4 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -171,12 +171,12 @@ Please contact me on #coderbus IRC. ~Carn x ma_compiled.overlays += list_layers //4: Apply transforms based on situation - update_transform(ma_compiled, FALSE) + update_transform(ma_compiled) - //4.5 Set layer to PLANE_WORLD to make sure its not magically FLOAT_PLANE due to byond madness - ma_compiled.plane = PLANE_WORLD + //5: Do any species specific layering updates, such as when hiding. + update_icon_special(ma_compiled, FALSE) - //5: Set appearance once + //6: Set appearance once appearance = ma_compiled /mob/living/carbon/human/update_transform(var/mutable_appearance/passed_ma) @@ -235,6 +235,7 @@ Please contact me on #coderbus IRC. ~Carn x overlays += mobonback if(!passed_ma) + update_icon_special(ma) appearance = ma //Update the layers from the defines above @@ -269,6 +270,22 @@ Please contact me on #coderbus IRC. ~Carn x list_huds = hud_list.Copy() list_huds += backplane // Required to mask HUDs in context menus: http://www.byond.com/forum/?post=2336679 + //Typing indicator code + if(client && !stat) //They have a client & aren't dead/KO'd? Continue on! + if(typing_indicator && hud_typing) //They already have the indicator and are still typing + list_huds += typing_indicator + typing_indicator.invisibility = invisibility + + else if(!typing_indicator && hud_typing) //Are they in their body, NOT dead, have hud_typing, do NOT have a typing indicator. and have it enabled? + typing_indicator = new + typing_indicator.icon = 'icons/mob/talk_vr.dmi' //VOREStation Edit - talk_vr.dmi instead of talk.dmi for right-side icons + typing_indicator.icon_state = "[speech_bubble_appearance()]_typing" + list_huds += typing_indicator + + else if(typing_indicator && !hud_typing) //Did they stop typing? + typing = FALSE + hud_typing = FALSE + if(update_icons) update_icons() @@ -423,20 +440,24 @@ var/global/list/damage_icon_parts = list() var/icon/temp = part.get_icon(skeleton) //That part makes left and right legs drawn topmost and lowermost when human looks WEST or EAST //And no change in rendering for other parts (they icon_position is 0, so goes to 'else' part) - if(part.icon_position & (LEFT | RIGHT)) + if(part.icon_position == RIGHT) var/icon/temp2 = new('icons/mob/human.dmi',"blank") + var/icon/temp3 = new('icons/mob/human.dmi',"blank") temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH) temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH) - if(!(part.icon_position & LEFT)) - temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) - if(!(part.icon_position & RIGHT)) - temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) + temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) base_icon.Blend(temp2, ICON_OVERLAY) - if(part.icon_position & LEFT) - temp2.Insert(new/icon(temp,dir=EAST),dir=EAST) - if(part.icon_position & RIGHT) - temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) - base_icon.Blend(temp2, ICON_UNDERLAY) + temp3.Insert(new/icon(temp,dir=WEST),dir=WEST) + base_icon.Blend(temp3, ICON_UNDERLAY) + else if(part.icon_position == LEFT) + var/icon/temp2 = new('icons/mob/human.dmi',"blank") + var/icon/temp3 = new('icons/mob/human.dmi',"blank") + temp2.Insert(new/icon(temp,dir=NORTH),dir=NORTH) + temp2.Insert(new/icon(temp,dir=SOUTH),dir=SOUTH) + temp2.Insert(new/icon(temp,dir=WEST),dir=WEST) + base_icon.Blend(temp2, ICON_OVERLAY) + temp3.Insert(new/icon(temp,dir=EAST),dir=EAST) + base_icon.Blend(temp3, ICON_UNDERLAY) else if(part.icon_position & UNDER) base_icon.Blend(temp, ICON_UNDERLAY) else @@ -667,7 +688,7 @@ var/global/list/damage_icon_parts = list() update_fire(0) update_water(0) update_surgery(0) - UpdateDamageIcon() + UpdateDamageIcon(0) update_icons_layers(0) update_icons_huds(0) update_icons() @@ -1015,6 +1036,13 @@ var/global/list/damage_icon_parts = list() standing = image(base) else standing.color = head.color + + // Accessories - copied from uniform, BOILERPLATE because fuck this system. + var/obj/item/clothing/head/hat = head + if(istype(hat) && hat.accessories.len) + for(var/obj/item/clothing/accessory/A in hat.accessories) + standing.overlays |= A.get_mob_overlay() + overlays_standing[HEAD_LAYER] = standing else diff --git a/code/modules/mob/living/carbon/viruses.dm b/code/modules/mob/living/carbon/viruses.dm index b4d8297697..2f52dcd1cb 100644 --- a/code/modules/mob/living/carbon/viruses.dm +++ b/code/modules/mob/living/carbon/viruses.dm @@ -23,6 +23,13 @@ var/datum/disease2/disease/V = M.virus2[ID] infect_virus2(src,V) + else if(istype(O,/obj/effect/decal/cleanable/vomit)) + var/obj/effect/decal/cleanable/vomit/Vom = O + if(Vom.virus2.len) + for (var/ID in Vom.virus2) + var/datum/disease2/disease/V = Vom.virus2[ID] + infect_virus2(src,V) + if(virus2.len) for (var/ID in virus2) var/datum/disease2/disease/V = virus2[ID] diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 3dc35878ae..922923d5f2 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -209,13 +209,17 @@ return TRUE else if(glow_toggle) - set_light(2, l_color = glow_color) //2 is PDA brightness, so neutral in terms of balance + set_light(glow_range, glow_intensity, glow_color) else set_light(0) return FALSE /mob/living/proc/handle_darksight() + if(!seedarkness) //Cheap 'always darksight' var + dsoverlay.alpha = 255 + return + var/darksightedness = min(see_in_dark/world.view,1.0) //A ratio of how good your darksight is, from 'nada' to 'really darn good' var/current = dsoverlay.alpha/255 //Our current adjustedness diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index d68fd90efc..3f46e1812a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -119,7 +119,9 @@ default behaviour is: return // In case of micros, we don't swap positions; instead occupying the same square! - if (handle_micro_bump_helping(tmob)) return + if (handle_micro_bump_helping(tmob)) + now_pushing = 0 + return // TODO - Check if we need to do something about the slime.UpdateFeed() we are skipping below. // VOREStation Edit - End @@ -1134,3 +1136,79 @@ default behaviour is: else // No colors, so remove the client's color. animate(client, color = null, time = 10) +/mob/living/swap_hand() + src.hand = !( src.hand ) + if(hud_used.l_hand_hud_object && hud_used.r_hand_hud_object) + if(hand) //This being 1 means the left hand is in use + hud_used.l_hand_hud_object.icon_state = "l_hand_active" + hud_used.r_hand_hud_object.icon_state = "r_hand_inactive" + else + hud_used.l_hand_hud_object.icon_state = "l_hand_inactive" + hud_used.r_hand_hud_object.icon_state = "r_hand_active" + return + +/mob/living/proc/activate_hand(var/selhand) //0 or "r" or "right" for right hand; 1 or "l" or "left" for left hand. + + if(istext(selhand)) + selhand = lowertext(selhand) + + if(selhand == "right" || selhand == "r") + selhand = 0 + if(selhand == "left" || selhand == "l") + selhand = 1 + + if(selhand != src.hand) + swap_hand() + +/mob/living/throw_item(atom/target) + src.throw_mode_off() + if(usr.stat || !target) + return + if(target.type == /obj/screen) return + + var/atom/movable/item = src.get_active_hand() + + if(!item) return + + var/throw_range = item.throw_range + if (istype(item, /obj/item/weapon/grab)) + var/obj/item/weapon/grab/G = item + item = G.throw_held() //throw the person instead of the grab + if(ismob(item)) + var/mob/M = item + + //limit throw range by relative mob size + throw_range = round(M.throw_range * min(src.mob_size/M.mob_size, 1)) + + var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors + var/turf/end_T = get_turf(target) + if(start_T && end_T) + var/start_T_descriptor = "tile at [start_T.x], [start_T.y], [start_T.z] in area [get_area(start_T)]" + var/end_T_descriptor = "tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]" + + M.attack_log += text("\[[time_stamp()]\] Has been thrown by [usr.name] ([usr.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") + usr.attack_log += text("\[[time_stamp()]\] Has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor]") + msg_admin_attack("[usr.name] ([usr.ckey]) has thrown [M.name] ([M.ckey]) from [start_T_descriptor] with the target [end_T_descriptor] (JMP)") + + src.drop_from_inventory(item) + if(!item || !isturf(item.loc)) + return + + //actually throw it! + src.visible_message("[src] has thrown [item].") + + if(!src.lastarea) + src.lastarea = get_area(src.loc) + if((istype(src.loc, /turf/space)) || (src.lastarea.has_gravity == 0)) + src.inertia_dir = get_dir(target, src) + step(src, inertia_dir) + + +/* + if(istype(src.loc, /turf/space) || (src.flags & NOGRAV)) //they're in space, move em one space in the opposite direction + src.inertia_dir = get_dir(target, src) + step(src, inertia_dir) +*/ + + + item.throw_at(target, throw_range, item.throw_speed, src) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index d1deeebffd..f57957dd7d 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -45,10 +45,14 @@ var/failed_last_breath = 0 //This is used to determine if the mob failed a breath. If they did fail a brath, they will attempt to breathe each tick, otherwise just once per 4 ticks. var/lastpuke = 0 - var/evasion = 0 // Makes attacks harder to land. Each number equals 15% more likely to miss. Negative numbers increase hit chance. + var/evasion = 0 // Makes attacks harder to land. Negative numbers increase hit chance. var/force_max_speed = 0 // If 1, the mob runs extremely fast and cannot be slowed. - + var/image/dsoverlay = null //Overlay used for darksight eye adjustments var/glow_toggle = 0 // If they're glowing! + var/glow_range = 2 + var/glow_intensity = null var/glow_color = "#FFFFFF" // The color they're glowing! + + var/see_invisible_default = SEE_INVISIBLE_LIVING diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index 1a3ee31fc5..676c55da9a 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -292,18 +292,22 @@ proc/get_radio_key_from_channel(var/channel) sound_vol *= 0.5 //Obtain the mobs and objects in the message range - var/list/results = get_mobs_and_objs_in_view_fast(T, world.view) + var/list/results = get_mobs_and_objs_in_view_fast(T, world.view, remote_ghosts = client ? TRUE : FALSE) listening = results["mobs"] listening_obj = results["objs"] else return 1 //If we're in nullspace, then forget it. + //Remember the speech images so we can remove them later and they can get GC'd + var/list/images_to_clients = list() + //The 'post-say' static speech bubble var/speech_bubble_test = say_test(message) //var/image/speech_bubble = image('icons/mob/talk_vr.dmi',src,"h[speech_bubble_test]") //VOREStation Edit. Commented this out in case we need to reenable. var/speech_type = speech_bubble_appearance() var/image/speech_bubble = image('icons/mob/talk_vr.dmi',src,"[speech_type][speech_bubble_test]") //VOREStation Edit - talk_vr.dmi instead of talk.dmi for right-side icons - spawn(30) qdel(speech_bubble) + images_to_clients[speech_bubble] = list() + // Attempt Multi-Z Talking var/mob/above = src.shadow @@ -312,7 +316,7 @@ proc/get_radio_key_from_channel(var/channel) if(ST) var/list/results = get_mobs_and_objs_in_view_fast(ST, world.view) var/image/z_speech_bubble = image('icons/mob/talk_vr.dmi', above, "h[speech_bubble_test]") //VOREStation Edit - talk_vr.dmi instead of talk.dmi for right-side icons - spawn(30) qdel(z_speech_bubble) + images_to_clients[z_speech_bubble] = list() for(var/item in results["mobs"]) if(item != above && !(item in listening)) listening[item] = z_speech_bubble @@ -327,12 +331,17 @@ proc/get_radio_key_from_channel(var/channel) var/dst = get_dist(get_turf(M),get_turf(src)) if(dst <= message_range || (M.stat == DEAD && !forbid_seeing_deadchat)) //Inside normal message range, or dead with ears (handled in the view proc) - M << (listening[M] || speech_bubble) // Send the image attached to shadow mob if available + if(M.client) + var/image/I1 = listening[M] || speech_bubble + images_to_clients[I1] |= M.client + M << I1 M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol) - if(whispering) //Don't even bother with these unless whispering if(dst > message_range && dst <= w_scramble_range) //Inside whisper scramble range - M << (listening[M] || speech_bubble) // Send the image attached to shadow mob if available + if(M.client) + var/image/I2 = listening[M] || speech_bubble + images_to_clients[I2] |= M.client + M << I2 M.hear_say(stars(message), verb, speaking, alt_name, italics, src, speech_sound, sound_vol*0.2) if(dst > w_scramble_range && dst <= world.view) //Inside whisper 'visible' range M.show_message("[src.name] [w_not_heard].", 2) @@ -345,6 +354,17 @@ proc/get_radio_key_from_channel(var/channel) if(dst <= message_range) O.hear_talk(src, message, verb, speaking) + //Remove all those images. At least it's just ONE spawn this time. + spawn(30) + for(var/img in images_to_clients) + var/image/I = img + var/list/clients_from_image = images_to_clients[I] + for(var/client in clients_from_image) + var/client/C = client + if(C) //Could have disconnected after message sent, before removing bubble. + C.images -= I + qdel(I) + //Log the message to file log_say("[name]/[key][whispering ? " (W)" : ""]: [message]") return 1 diff --git a/code/modules/mob/living/silicon/pai/software_modules.dm b/code/modules/mob/living/silicon/pai/software_modules.dm index 6d34c4a969..b0b325f08d 100644 --- a/code/modules/mob/living/silicon/pai/software_modules.dm +++ b/code/modules/mob/living/silicon/pai/software_modules.dm @@ -445,6 +445,11 @@ toggle(mob/living/silicon/pai/user) user.secHUD = !user.secHUD + user.plane_holder.set_vis(VIS_CH_ID, user.secHUD) + user.plane_holder.set_vis(VIS_CH_WANTED, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPTRACK, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPLOYAL, user.secHUD) + user.plane_holder.set_vis(VIS_CH_IMPCHEM, user.secHUD) is_active(mob/living/silicon/pai/user) return user.secHUD @@ -456,6 +461,8 @@ toggle(mob/living/silicon/pai/user) user.medHUD = !user.medHUD + user.plane_holder.set_vis(VIS_CH_STATUS, user.medHUD) + user.plane_holder.set_vis(VIS_CH_HEALTH, user.medHUD) is_active(mob/living/silicon/pai/user) return user.medHUD diff --git a/code/modules/mob/living/silicon/robot/drone/drone_items.dm b/code/modules/mob/living/silicon/robot/drone/drone_items.dm index b370787ede..e8d3e0ad2c 100644 --- a/code/modules/mob/living/silicon/robot/drone/drone_items.dm +++ b/code/modules/mob/living/silicon/robot/drone/drone_items.dm @@ -58,7 +58,8 @@ /obj/item/weapon/reagent_containers/glass, /obj/item/weapon/storage/pill_bottle, /obj/item/weapon/reagent_containers/pill, - /obj/item/weapon/reagent_containers/blood + /obj/item/weapon/reagent_containers/blood, + /obj/item/stack/material/phoron ) /obj/item/weapon/gripper/research //A general usage gripper, used for toxins/robotics/xenobio/etc diff --git a/code/modules/mob/living/silicon/robot/life.dm b/code/modules/mob/living/silicon/robot/life.dm index 464ea514b7..aa1cf2d271 100644 --- a/code/modules/mob/living/silicon/robot/life.dm +++ b/code/modules/mob/living/silicon/robot/life.dm @@ -152,7 +152,7 @@ return 1 /mob/living/silicon/robot/handle_regular_hud_updates() - + var/fullbright = FALSE if (src.stat == 2 || (XRAY in mutations) || (src.sight_mode & BORGXRAY)) src.sight |= SEE_TURFS src.sight |= SEE_MOBS @@ -164,18 +164,22 @@ src.sight |= SEE_MOBS src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM + fullbright = TRUE else if (src.sight_mode & BORGMESON) src.sight |= SEE_TURFS src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM + fullbright = TRUE else if (src.sight_mode & BORGMATERIAL) src.sight |= SEE_OBJS src.see_in_dark = 8 see_invisible = SEE_INVISIBLE_MINIMUM + fullbright = TRUE else if (src.sight_mode & BORGTHERM) src.sight |= SEE_MOBS src.see_in_dark = 8 src.see_invisible = SEE_INVISIBLE_LEVEL_TWO + fullbright = TRUE else if (!seedarkness) src.sight &= ~SEE_MOBS src.sight &= ~SEE_TURFS @@ -189,7 +193,7 @@ src.see_in_dark = 8 // see_in_dark means you can FAINTLY see in the dark, humans have a range of 3 or so, tajaran have it at 8 src.see_invisible = SEE_INVISIBLE_LIVING // This is normal vision (25), setting it lower for normal vision means you don't "see" things like darkness since darkness // has a "invisible" value of 15 - + plane_holder.set_vis(VIS_FULLBRIGHT,fullbright) ..() if (src.healths) diff --git a/code/modules/mob/living/silicon/robot/login.dm b/code/modules/mob/living/silicon/robot/login.dm index da682c5195..07dd53917b 100644 --- a/code/modules/mob/living/silicon/robot/login.dm +++ b/code/modules/mob/living/silicon/robot/login.dm @@ -5,7 +5,8 @@ show_laws(0) - winset(src, null, "mainwindow.macro=borgmacro hotkey_toggle.is-checked=false input.focus=true input.background-color=#D3B5B5") + // Override the DreamSeeker macro with the borg version! + client.set_hotkeys_macro("borgmacro", "borghotkeymode") // Forces synths to select an icon relevant to their module if(!icon_selected) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 5d96f6feb2..1b481de923 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -892,6 +892,18 @@ cleaned_human.update_inv_shoes(0) cleaned_human.clean_blood(1) cleaned_human << "[src] cleans your face!" + + if((module_state_1 && istype(module_state_1, /obj/item/weapon/storage/bag/ore)) || (module_state_2 && istype(module_state_2, /obj/item/weapon/storage/bag/ore)) || (module_state_3 && istype(module_state_3, /obj/item/weapon/storage/bag/ore))) //Borgs and drones can use their mining bags ~automagically~ if they're deployed in a slot. Only mining bags, as they're optimized for mass use. + var/obj/item/weapon/storage/bag/ore/B = null + if(istype(module_state_1, /obj/item/weapon/storage/bag/ore)) //First orebag has priority, if they for some reason have multiple. + B = module_state_1 + else if(istype(module_state_2, /obj/item/weapon/storage/bag/ore)) + B = module_state_2 + else if(istype(module_state_3, /obj/item/weapon/storage/bag/ore)) + B = module_state_3 + var/turf/tile = loc + if(isturf(tile)) + B.gather_all(tile, src, 1) //Shhh, unless the bag fills, don't spam the borg's chat with stuff that's going on every time they move! return /mob/living/silicon/robot/proc/self_destruct() diff --git a/code/modules/mob/living/silicon/robot/robot_modules/station.dm b/code/modules/mob/living/silicon/robot/robot_modules/station.dm index bf8d9775cd..8f1d7c3257 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/station.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/station.dm @@ -247,10 +247,19 @@ var/global/list/robot_modules = list( src.modules += N src.modules += B -/obj/item/weapon/robot_module/medical/robot/surgeon/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) +/obj/item/weapon/robot_module/robot/medical/surgeon/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + + var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules + if(S.mode == 2) + S.reagents.clear_reagents() + S.mode = initial(S.mode) + S.desc = initial(S.desc) + S.update_icon() + if(src.emag) var/obj/item/weapon/reagent_containers/spray/PS = src.emag PS.reagents.add_reagent("pacid", 2 * amount) + ..() /obj/item/weapon/robot_module/robot/medical/crisis @@ -506,6 +515,7 @@ var/global/list/robot_modules = list( src.modules += new /obj/item/weapon/handcuffs/cyborg(src) src.modules += new /obj/item/weapon/melee/baton/robot(src) src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg(src) + // src.modules += new /obj/item/weapon/gun/energy/taser/xeno/sec/robot(src) // VOREStation Edit - We don't need these src.modules += new /obj/item/taperoll/police(src) src.modules += new /obj/item/weapon/reagent_containers/spray/pepper(src) src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src) @@ -753,6 +763,18 @@ var/global/list/robot_modules = list( C.synths = list(wire) src.modules += C +/obj/item/weapon/robot_module/robot/research/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + + var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules + if(S.mode == 2) + S.reagents.clear_reagents() + S.mode = initial(S.mode) + S.desc = initial(S.desc) + S.update_icon() + + ..() + + /obj/item/weapon/robot_module/robot/security/combat name = "combat robot module" hide_on_manifest = 1 diff --git a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm index 9967fa67dc..b3b88074b0 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules/syndicate.dm @@ -182,3 +182,13 @@ src.modules += O src.modules += B src.modules += S + +/obj/item/weapon/robot_module/robot/syndicate/combat_medic/respawn_consumable(var/mob/living/silicon/robot/R, var/amount) + + var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules + if(S.mode == 2) + S.reagents.clear_reagents() + S.mode = initial(S.mode) + S.desc = initial(S.desc) + S.update_icon() + ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 689d27dce8..09321af981 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -322,6 +322,8 @@ /mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised) if(!next_alarm_notice) next_alarm_notice = world.time + SecondsToTicks(10) + if(alarm.hidden) + return var/list/alarms = queued_alarms[alarm_handler] if(was_raised) diff --git a/code/modules/mob/living/simple_animal/aliens/alien.dm b/code/modules/mob/living/simple_animal/aliens/alien.dm index 3836a6abd2..0f7cc35c77 100644 --- a/code/modules/mob/living/simple_animal/aliens/alien.dm +++ b/code/modules/mob/living/simple_animal/aliens/alien.dm @@ -25,7 +25,7 @@ melee_damage_lower = 25 melee_damage_upper = 25 - attacktext = "slashed" + attacktext = list("slashed") attack_sound = 'sound/weapons/bladeslice.ogg' a_intent = I_HURT @@ -137,106 +137,4 @@ /mob/living/simple_animal/hostile/alien/death() ..() visible_message("[src] lets out a waning guttural screech, green blood bubbling from its maw...") - playsound(src, 'sound/voice/hiss6.ogg', 100, 1) - -// Xenoarch aliens. -/mob/living/simple_animal/hostile/samak - name = "samak" - desc = "A fast, armoured predator accustomed to hiding and ambushing in cold terrain." - faction = "samak" - icon_state = "samak" - icon_living = "samak" - icon_dead = "samak_dead" - icon = 'icons/jungle.dmi' - - faction = "samak" - - maxHealth = 125 - health = 125 - speed = 2 - move_to_delay = 2 - - melee_damage_lower = 5 - melee_damage_upper = 15 - - attacktext = "mauled" - cold_damage_per_tick = 0 - - speak_chance = 5 - speak = list("Hruuugh!","Hrunnph") - emote_see = list("paws the ground","shakes its mane","stomps") - emote_hear = list("snuffles") - -/mob/living/simple_animal/hostile/diyaab - name = "diyaab" - desc = "A small pack animal. Although omnivorous, it will hunt meat on occasion." - faction = "diyaab" - icon_state = "diyaab" - icon_living = "diyaab" - icon_dead = "diyaab_dead" - icon = 'icons/jungle.dmi' - - faction = "diyaab" - cooperative = 1 - - maxHealth = 25 - health = 25 - speed = 1 - move_to_delay = 1 - - melee_damage_lower = 1 - melee_damage_upper = 8 - - attacktext = "gouged" - cold_damage_per_tick = 0 - - speak_chance = 5 - speak = list("Awrr?","Aowrl!","Worrl") - emote_see = list("sniffs the air cautiously","looks around") - emote_hear = list("snuffles") - -/mob/living/simple_animal/hostile/shantak - name = "shantak" - desc = "A piglike creature with a bright iridiscent mane that sparkles as though lit by an inner light. Don't be fooled by its beauty though." - faction = "shantak" - icon_state = "shantak" - icon_living = "shantak" - icon_dead = "shantak_dead" - icon = 'icons/jungle.dmi' - - faction = "shantak" - - maxHealth = 75 - health = 75 - speed = 1 - move_to_delay = 1 - - melee_damage_lower = 3 - melee_damage_upper = 12 - - attacktext = "gouged" - cold_damage_per_tick = 0 - - speak_chance = 5 - speak = list("Shuhn","Shrunnph?","Shunpf") - emote_see = list("scratches the ground","shakes out its mane","clinks gently as it moves") - -/mob/living/simple_animal/yithian - name = "yithian" - desc = "A friendly creature vaguely resembling an oversized snail without a shell." - icon_state = "yithian" - icon_living = "yithian" - icon_dead = "yithian_dead" - icon = 'icons/jungle.dmi' - - faction = "yithian" - -/mob/living/simple_animal/tindalos - name = "tindalos" - desc = "It looks like a large, flightless grasshopper." - icon_state = "tindalos" - icon_living = "tindalos" - icon_dead = "tindalos_dead" - icon = 'icons/jungle.dmi' - - faction = "tindalos" + playsound(src, 'sound/voice/hiss6.ogg', 100, 1) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/aliens/creature.dm b/code/modules/mob/living/simple_animal/aliens/creature.dm index 3de6d687af..980623c017 100644 --- a/code/modules/mob/living/simple_animal/aliens/creature.dm +++ b/code/modules/mob/living/simple_animal/aliens/creature.dm @@ -16,7 +16,7 @@ melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "chomped" + attacktext = list("chomped") attack_sound = 'sound/weapons/bite.ogg' speak_emote = list("gibbers") diff --git a/code/modules/mob/living/simple_animal/aliens/drone.dm b/code/modules/mob/living/simple_animal/aliens/drone.dm index 81532ef62d..35e09030dd 100644 --- a/code/modules/mob/living/simple_animal/aliens/drone.dm +++ b/code/modules/mob/living/simple_animal/aliens/drone.dm @@ -25,6 +25,7 @@ projectiletype = /obj/item/projectile/beam/drone projectilesound = 'sound/weapons/laser3.ogg' destroy_surroundings = 0 + hovering = TRUE //Drones aren't affected by atmos. min_oxy = 0 @@ -275,3 +276,10 @@ /obj/item/projectile/beam/pulse/drone damage = 10 + +// A slightly easier drone, for POIs. +// Difference is that it should not be faster than you. +/mob/living/simple_animal/hostile/malf_drone/lesser + desc = "An automated combat drone with an aged apperance." + returns_home = TRUE + move_to_delay = 6 \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/aliens/faithless.dm b/code/modules/mob/living/simple_animal/aliens/faithless.dm index 24eacae40e..09de8a24fb 100644 --- a/code/modules/mob/living/simple_animal/aliens/faithless.dm +++ b/code/modules/mob/living/simple_animal/aliens/faithless.dm @@ -20,7 +20,7 @@ melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "gripped" + attacktext = list("gripped") attack_sound = 'sound/hallucinations/growl1.ogg' min_oxy = 0 diff --git a/code/modules/mob/living/simple_animal/aliens/hivebot.dm b/code/modules/mob/living/simple_animal/aliens/hivebot.dm index f09aeb1c22..28d58d64df 100644 --- a/code/modules/mob/living/simple_animal/aliens/hivebot.dm +++ b/code/modules/mob/living/simple_animal/aliens/hivebot.dm @@ -20,7 +20,7 @@ melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "clawed" + attacktext = list("clawed") projectilesound = 'sound/weapons/Gunshot.ogg' projectiletype = /obj/item/projectile/bullet/hivebot diff --git a/code/modules/mob/living/simple_animal/aliens/mimic.dm b/code/modules/mob/living/simple_animal/aliens/mimic.dm index 77ba92ff6a..8230256086 100644 --- a/code/modules/mob/living/simple_animal/aliens/mimic.dm +++ b/code/modules/mob/living/simple_animal/aliens/mimic.dm @@ -24,7 +24,7 @@ harm_intent_damage = 5 melee_damage_lower = 8 melee_damage_upper = 12 - attacktext = "attacked" + attacktext = list("attacked") attack_sound = 'sound/weapons/bite.ogg' min_oxy = 0 @@ -55,7 +55,7 @@ // Aggro when you try to open them. Will also pickup loot when spawns and drop it when dies. /mob/living/simple_animal/hostile/mimic/crate - attacktext = "bitten" + attacktext = list("bitten") stop_automated_movement = 1 wander = 0 diff --git a/code/modules/mob/living/simple_animal/aliens/shade.dm b/code/modules/mob/living/simple_animal/aliens/shade.dm index 2d502bc10a..e8da069e1d 100644 --- a/code/modules/mob/living/simple_animal/aliens/shade.dm +++ b/code/modules/mob/living/simple_animal/aliens/shade.dm @@ -20,7 +20,7 @@ melee_damage_lower = 5 melee_damage_upper = 15 - attacktext = "drained the life from" + attacktext = list("drained the life from") minbodytemp = 0 maxbodytemp = 4000 diff --git a/code/modules/mob/living/simple_animal/animals/bat.dm b/code/modules/mob/living/simple_animal/animals/bat.dm index a429b2ca7f..726c94f143 100644 --- a/code/modules/mob/living/simple_animal/animals/bat.dm +++ b/code/modules/mob/living/simple_animal/animals/bat.dm @@ -24,7 +24,7 @@ melee_damage_upper = 3 environment_smash = 1 - attacktext = "bites" + attacktext = list("bites") attack_sound = 'sound/weapons/bite.ogg' min_oxy = 0 diff --git a/code/modules/mob/living/simple_animal/animals/carp.dm b/code/modules/mob/living/simple_animal/animals/carp.dm index 9126642197..4dc4daffda 100644 --- a/code/modules/mob/living/simple_animal/animals/carp.dm +++ b/code/modules/mob/living/simple_animal/animals/carp.dm @@ -8,6 +8,7 @@ faction = "carp" intelligence_level = SA_ANIMAL + hovering = TRUE maxHealth = 25 health = 25 speed = 4 @@ -20,7 +21,7 @@ harm_intent_damage = 8 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "bitten" + attacktext = list("bitten") attack_sound = 'sound/weapons/bite.ogg' //Space carp aren't affected by atmos. diff --git a/code/modules/mob/living/simple_animal/animals/cat.dm b/code/modules/mob/living/simple_animal/animals/cat.dm index fa5915c33d..1f0c9c6d26 100644 --- a/code/modules/mob/living/simple_animal/animals/cat.dm +++ b/code/modules/mob/living/simple_animal/animals/cat.dm @@ -9,7 +9,6 @@ icon_dead = "cat2_dead" icon_rest = "cat2_rest" - hostile = 1 //To mice, anyway. investigates = 1 specific_targets = 1 //Only targets with Found() run_at_them = 0 //DOMESTICATED diff --git a/code/modules/mob/living/simple_animal/animals/cat_vr.dm b/code/modules/mob/living/simple_animal/animals/cat_vr.dm index ca645d5a37..f4c2644ad6 100644 --- a/code/modules/mob/living/simple_animal/animals/cat_vr.dm +++ b/code/modules/mob/living/simple_animal/animals/cat_vr.dm @@ -1,38 +1,39 @@ -/mob/living/simple_animal/cat/fluff/Runtime/New() - - if(!vore_organs.len) - var/datum/belly/B = new /datum/belly(src) - B.immutable = 1 - B.name = "Stomach" - B.inside_flavor = "The slimy wet insides of Runtime! Not quite as clean as the cat on the outside." - B.human_prey_swallow_time = swallowTime - B.nonhuman_prey_swallow_time = swallowTime - vore_organs[B.name] = B - vore_selected = B.name - - B.emote_lists[DM_HOLD] = list( - "Runtime's stomach kneads gently on you and you're fairly sure you can hear her start purring.", - "Most of what you can hear are slick noises, Runtime breathing, and distant purring.", - "Runtime seems perfectly happy to have you in there. She lays down for a moment to groom and squishes you against the walls.", - "The CMO's pet seems to have found a patient of her own, and is treating them with warm, wet kneading walls.", - "Runtime mostly just lazes about, and you're left to simmer in the hot, slick guts unharmed.", - "Runtime's master might let you out of this fleshy prison, eventually. Maybe. Hopefully?") - - B.emote_lists[DM_DIGEST] = list( - "Runtime's stomach is treating you rather like a mouse, kneading acids into you with vigor.", - "A thick dollop of bellyslime drips from above while the CMO's pet's gut works on churning you up.", - "Runtime seems to have decided you're food, based on the acrid air in her guts and the pooling fluids.", - "Runtime's stomach tries to claim you, kneading and pressing inwards again and again against your form.", - "Runtime flops onto their side for a minute, spilling acids over your form as you remain trapped in them.", - "The CMO's pet doesn't seem to think you're any different from any other meal. At least, their stomach doesn't.") - - B.digest_messages_prey = list( - "Runtime's stomach slowly melts your body away. Her stomach refuses to give up it's onslaught, continuing until you're nothing more than nutrients for her body to absorb.", - "After an agonizing amount of time, Runtime's stomach finally manages to claim you, melting you down and adding you to her stomach.", - "Runtime's stomach continues to slowly work away at your body before tightly squeezing around you once more, causing the remainder of your body to lose form and melt away into the digesting slop around you.", - "Runtime's slimy gut continues to constantly squeeze and knead away at your body, the bulge you create inside of her stomach growing smaller as time progresses before soon dissapearing completely as you melt away.", - "Runtime's belly lets off a soft groan as your body finally gives out, the cat's eyes growing heavy as it settles down to enjoy it's good meal.", - "Runtime purrs happily as you slowly slip away inside of her gut, your body's nutrients are then used to put a layer of padding on the now pudgy cat.", - "The acids inside of Runtime's stomach, aided by the constant motions of the smooth walls surrounding you finally manage to melt you away into nothing more mush. She curls up on the floor, slowly kneading the air as her stomach moves its contents — including you — deeper into her digestive system.", - "Your form begins to slowly soften and break apart, rounding out Runtime's swollen belly. The carnivorous cat rumbles and purrs happily at the feeling of such a filling meal.") +/mob/living/simple_animal/cat/fluff/Runtime/init_belly() ..() + var/datum/belly/B = vore_organs[vore_selected] + B.name = "Stomach" + B.inside_flavor = "The slimy wet insides of Runtime! Not quite as clean as the cat on the outside." + + B.emote_lists[DM_HOLD] = list( + "Runtime's stomach kneads gently on you and you're fairly sure you can hear her start purring.", + "Most of what you can hear are slick noises, Runtime breathing, and distant purring.", + "Runtime seems perfectly happy to have you in there. She lays down for a moment to groom and squishes you against the walls.", + "The CMO's pet seems to have found a patient of her own, and is treating them with warm, wet kneading walls.", + "Runtime mostly just lazes about, and you're left to simmer in the hot, slick guts unharmed.", + "Runtime's master might let you out of this fleshy prison, eventually. Maybe. Hopefully?") + + B.emote_lists[DM_DIGEST] = list( + "Runtime's stomach is treating you rather like a mouse, kneading acids into you with vigor.", + "A thick dollop of bellyslime drips from above while the CMO's pet's gut works on churning you up.", + "Runtime seems to have decided you're food, based on the acrid air in her guts and the pooling fluids.", + "Runtime's stomach tries to claim you, kneading and pressing inwards again and again against your form.", + "Runtime flops onto their side for a minute, spilling acids over your form as you remain trapped in them.", + "The CMO's pet doesn't seem to think you're any different from any other meal. At least, their stomach doesn't.") + + B.emote_lists[DM_ITEMWEAK] = list( + "Runtime's stomach is treating you rather like a mouse, kneading acids into you with vigor.", + "A thick dollop of bellyslime drips from above while the CMO's pet's gut works on churning you up.", + "Runtime seems to have decided you're food, based on the acrid air in her guts and the pooling fluids.", + "Runtime's stomach tries to claim you, kneading and pressing inwards again and again against your form.", + "Runtime flops onto their side for a minute, spilling acids over your form as you remain trapped in them.", + "The CMO's pet doesn't seem to think you're any different from any other meal. At least, their stomach doesn't.") + + B.digest_messages_prey = list( + "Runtime's stomach slowly melts your body away. Her stomach refuses to give up it's onslaught, continuing until you're nothing more than nutrients for her body to absorb.", + "After an agonizing amount of time, Runtime's stomach finally manages to claim you, melting you down and adding you to her stomach.", + "Runtime's stomach continues to slowly work away at your body before tightly squeezing around you once more, causing the remainder of your body to lose form and melt away into the digesting slop around you.", + "Runtime's slimy gut continues to constantly squeeze and knead away at your body, the bulge you create inside of her stomach growing smaller as time progresses before soon dissapearing completely as you melt away.", + "Runtime's belly lets off a soft groan as your body finally gives out, the cat's eyes growing heavy as it settles down to enjoy it's good meal.", + "Runtime purrs happily as you slowly slip away inside of her gut, your body's nutrients are then used to put a layer of padding on the now pudgy cat.", + "The acids inside of Runtime's stomach, aided by the constant motions of the smooth walls surrounding you finally manage to melt you away into nothing more mush. She curls up on the floor, slowly kneading the air as her stomach moves its contents — including you — deeper into her digestive system.", + "Your form begins to slowly soften and break apart, rounding out Runtime's swollen belly. The carnivorous cat rumbles and purrs happily at the feeling of such a filling meal.") diff --git a/code/modules/mob/living/simple_animal/animals/crab.dm b/code/modules/mob/living/simple_animal/animals/crab.dm index 35089275e5..0d485d859d 100644 --- a/code/modules/mob/living/simple_animal/animals/crab.dm +++ b/code/modules/mob/living/simple_animal/animals/crab.dm @@ -49,7 +49,7 @@ //Sif Crabs /mob/living/simple_animal/giant_crab - name = "Giant Crab" + name = "giant crab" desc = "A large, hard-shelled crustacean. This one is mostly grey." icon_state = "sif_crab" icon_living = "sif_crab" diff --git a/code/modules/mob/living/simple_animal/animals/farm_animals.dm b/code/modules/mob/living/simple_animal/animals/farm_animals.dm index 2fe58dc76f..213aff73bf 100644 --- a/code/modules/mob/living/simple_animal/animals/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/animals/farm_animals.dm @@ -19,7 +19,7 @@ melee_damage_lower = 1 melee_damage_upper = 5 - attacktext = "kicked" + attacktext = list("kicked") speak_chance = 1 speak = list("EHEHEHEHEH","eh?") @@ -98,7 +98,7 @@ response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" - attacktext = "kicked" + attacktext = list("kicked") speak_chance = 1 speak = list("moo?","moo","MOOOOOO") @@ -168,7 +168,7 @@ response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" - attacktext = "kicked" + attacktext = list("kicked") has_langs = list("Bird") speak_chance = 2 @@ -216,7 +216,7 @@ var/global/chicken_count = 0 response_help = "pets" response_disarm = "gently pushes aside" response_harm = "kicks" - attacktext = "kicked" + attacktext = list("kicked") has_langs = list("Bird") speak_chance = 2 diff --git a/code/modules/mob/living/simple_animal/animals/fox_vr.dm b/code/modules/mob/living/simple_animal/animals/fox_vr.dm index 76f4bb28c4..8a2bcdf390 100644 --- a/code/modules/mob/living/simple_animal/animals/fox_vr.dm +++ b/code/modules/mob/living/simple_animal/animals/fox_vr.dm @@ -7,7 +7,6 @@ icon_dead = "fox2_dead" icon_rest = "fox2_rest" - hostile = 1 //To mice, anyway. investigates = 1 specific_targets = 1 //Only targets with Found() run_at_them = 0 //DOMESTICATED @@ -39,33 +38,35 @@ var/turns_since_scan = 0 var/mob/flee_target -/mob/living/simple_animal/fox/New() - if(!vore_organs.len) - var/datum/belly/B = new /datum/belly(src) - B.immutable = 1 - B.name = "Stomach" - B.inside_flavor = "Slick foxguts. Cute on the outside, slimy on the inside!" - B.human_prey_swallow_time = swallowTime - B.nonhuman_prey_swallow_time = swallowTime - vore_organs[B.name] = B - vore_selected = B.name - - B.emote_lists[DM_HOLD] = list( - "The foxguts knead and churn around you harmlessly.", - "With a loud glorp, some air shifts inside the belly.", - "A thick drop of warm bellyslime drips onto you from above.", - "The fox turns suddenly, causing you to shift a little.", - "During a moment of relative silence, you can hear the fox breathing.", - "The slimey stomach walls squeeze you lightly, then relax.") - - B.emote_lists[DM_DIGEST] = list( - "The guts knead at you, trying to work you into thick soup.", - "You're ground on by the slimey walls, treated like a mouse.", - "The acrid air is hard to breathe, and stings at your lungs.", - "You can feel the acids coating you, ground in by the slick walls.", - "The fox's stomach churns hungrily over your form, trying to take you.", - "With a loud glorp, the stomach spills more acids onto you.") +/mob/living/simple_animal/fox/init_belly() ..() + var/datum/belly/B = vore_organs[vore_selected] + B.name = "Stomach" + B.inside_flavor = "Slick foxguts. Cute on the outside, slimy on the inside!" + + B.emote_lists[DM_HOLD] = list( + "The foxguts knead and churn around you harmlessly.", + "With a loud glorp, some air shifts inside the belly.", + "A thick drop of warm bellyslime drips onto you from above.", + "The fox turns suddenly, causing you to shift a little.", + "During a moment of relative silence, you can hear the fox breathing.", + "The slimey stomach walls squeeze you lightly, then relax.") + + B.emote_lists[DM_DIGEST] = list( + "The guts knead at you, trying to work you into thick soup.", + "You're ground on by the slimey walls, treated like a mouse.", + "The acrid air is hard to breathe, and stings at your lungs.", + "You can feel the acids coating you, ground in by the slick walls.", + "The fox's stomach churns hungrily over your form, trying to take you.", + "With a loud glorp, the stomach spills more acids onto you.") + + B.emote_lists[DM_ITEMWEAK] = list( + "The guts knead at you, trying to work you into thick soup.", + "You're ground on by the slimey walls, treated like a mouse.", + "The acrid air is hard to breathe, and stings at your lungs.", + "You can feel the acids coating you, ground in by the slick walls.", + "The fox's stomach churns hungrily over your form, trying to take you.", + "With a loud glorp, the stomach spills more acids onto you.") // All them complicated fox procedures. /mob/living/simple_animal/fox/Life() @@ -184,34 +185,35 @@ desc = "Renault, the Colony Director's trustworthy fox. I wonder what it says?" befriend_job = "Colony Director" -/mob/living/simple_animal/fox/fluff/Renault/New() - if(!vore_organs.len) - var/datum/belly/B = new /datum/belly(src) - B.immutable = 1 - B.name = "Stomach" - B.inside_flavor = "Slick foxguts. They seem somehow more regal than perhaps other foxes!" - B.human_prey_swallow_time = swallowTime - B.nonhuman_prey_swallow_time = swallowTime - vore_organs[B.name] = B - vore_selected = B.name - - B.emote_lists[DM_HOLD] = list( - "Renault's stomach walls squeeze around you more tightly for a moment, before relaxing, as if testing you a bit.", - "There's a sudden squeezing as Renault presses a forepaw against his gut over you, squeezng you against the slick walls.", - "The 'head fox' has a stomach that seems to think you belong to it. It might be hard to argue, as it kneads at your form.", - "If being in the captain's fox is a promotion, it might not feel like one. The belly just coats you with more thick foxslime.", - "It doesn't seem like Renault wants to let you out. The stomach and owner possessively squeeze around you.", - "Renault's stomach walls squeeze closer, as he belches quietly, before swallowing more air. Does he do that on purpose?") - - B.emote_lists[DM_DIGEST] = list( - "Renault's stomach walls grind hungrily inwards, kneading acids against your form, and treating you like any other food.", - "The captain's fox impatiently kneads and works acids against you, trying to claim your body for fuel.", - "The walls knead in firmly, squeezing and tossing you around briefly in disorienting aggression.", - "Renault belches, letting the remaining air grow more acrid. It burns your lungs with each breath.", - "A thick glob of acids drip down from above, adding to the pool of caustic fluids in Renault's belly.", - "There's a loud gurgle as the stomach declares the intent to make you a part of Renault.") - +/mob/living/simple_animal/fox/fluff/Renault/init_belly() ..() + var/datum/belly/B = vore_organs[vore_selected] + B.name = "Stomach" + B.inside_flavor = "Slick foxguts. They seem somehow more regal than perhaps other foxes!" + + B.emote_lists[DM_HOLD] = list( + "Renault's stomach walls squeeze around you more tightly for a moment, before relaxing, as if testing you a bit.", + "There's a sudden squeezing as Renault presses a forepaw against his gut over you, squeezing you against the slick walls.", + "The 'head fox' has a stomach that seems to think you belong to it. It might be hard to argue, as it kneads at your form.", + "If being in the captain's fox is a promotion, it might not feel like one. The belly just coats you with more thick foxslime.", + "It doesn't seem like Renault wants to let you out. The stomach and owner possessively squeeze around you.", + "Renault's stomach walls squeeze closer, as he belches quietly, before swallowing more air. Does he do that on purpose?") + + B.emote_lists[DM_DIGEST] = list( + "Renault's stomach walls grind hungrily inwards, kneading acids against your form, and treating you like any other food.", + "The captain's fox impatiently kneads and works acids against you, trying to claim your body for fuel.", + "The walls knead in firmly, squeezing and tossing you around briefly in disorienting aggression.", + "Renault belches, letting the remaining air grow more acrid. It burns your lungs with each breath.", + "A thick glob of acids drip down from above, adding to the pool of caustic fluids in Renault's belly.", + "There's a loud gurgle as the stomach declares the intent to make you a part of Renault.") + + B.emote_lists[DM_ITEMWEAK] = list( + "Renault's stomach walls grind hungrily inwards, kneading acids against your form, and treating you like any other food.", + "The captain's fox impatiently kneads and works acids against you, trying to claim your body for fuel.", + "The walls knead in firmly, squeezing and tossing you around briefly in disorienting aggression.", + "Renault belches, letting the remaining air grow more acrid. It burns your lungs with each breath.", + "A thick glob of acids drip down from above, adding to the pool of caustic fluids in Renault's belly.", + "There's a loud gurgle as the stomach declares the intent to make you a part of Renault.") /mob/living/simple_animal/fox/syndicate name = "syndi-fox" diff --git a/code/modules/mob/living/simple_animal/animals/giant_spider.dm b/code/modules/mob/living/simple_animal/animals/giant_spider.dm index 501c8cc9e1..78304a9333 100644 --- a/code/modules/mob/living/simple_animal/animals/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/animals/giant_spider.dm @@ -78,6 +78,18 @@ Nurse Family var/atom/cocoon_target var/egg_inject_chance = 5 +/mob/living/simple_animal/hostile/giant_spider/nurse/medical + desc = "Furry and beige, it makes you shudder to look at it. This one has brilliant green eyes and a tiny nurse hat." + icon_state = "nursemed" + icon_living = "nursemed" + icon_dead = "nursemed_dead" + + melee_damage_lower = 8 + melee_damage_upper = 16 + poison_type = "tramadol" + poison_chance = 15 + + /mob/living/simple_animal/hostile/giant_spider/nurse/queen desc = "Absolutely gigantic, this creature is horror itself." icon = 'icons/mob/64x64.dmi' diff --git a/code/modules/mob/living/simple_animal/animals/goose.dm b/code/modules/mob/living/simple_animal/animals/goose.dm index f2f7c18277..ce6dbdfda8 100644 --- a/code/modules/mob/living/simple_animal/animals/goose.dm +++ b/code/modules/mob/living/simple_animal/animals/goose.dm @@ -22,7 +22,7 @@ melee_damage_lower = 5 //they're meant to be annoying, not threatening. melee_damage_upper = 5 //unless there's like a dozen of them, then you're screwed. cooperative = 1 // mwahahahahahaaa // Vorestation Edit, temporary - attacktext = "pecked" + attacktext = list("pecked") attack_sound = 'sound/weapons/bite.ogg' //SPACE geese aren't affected by atmos. diff --git a/code/modules/mob/living/simple_animal/animals/lizard.dm b/code/modules/mob/living/simple_animal/animals/lizard.dm index e9032a96ef..38822faf0d 100644 --- a/code/modules/mob/living/simple_animal/animals/lizard.dm +++ b/code/modules/mob/living/simple_animal/animals/lizard.dm @@ -15,7 +15,7 @@ response_disarm = "shoos" response_harm = "stomps on" - attacktext = "bitten" + attacktext = list("bitten") melee_damage_lower = 1 melee_damage_upper = 2 diff --git a/code/modules/mob/living/simple_animal/animals/miscellaneous.dm b/code/modules/mob/living/simple_animal/animals/miscellaneous.dm new file mode 100644 index 0000000000..57fe09727b --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/miscellaneous.dm @@ -0,0 +1,19 @@ +/mob/living/simple_animal/yithian + name = "yithian" + desc = "A friendly creature vaguely resembling an oversized snail without a shell." + icon_state = "yithian" + icon_living = "yithian" + icon_dead = "yithian_dead" + icon = 'icons/jungle.dmi' + + faction = "yithian" + +/mob/living/simple_animal/tindalos + name = "tindalos" + desc = "It looks like a large, flightless grasshopper." + icon_state = "tindalos" + icon_living = "tindalos" + icon_dead = "tindalos_dead" + icon = 'icons/jungle.dmi' + + faction = "tindalos" \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/penguin.dm b/code/modules/mob/living/simple_animal/animals/penguin.dm index 13ecb0d0ca..4bb985d1ac 100644 --- a/code/modules/mob/living/simple_animal/animals/penguin.dm +++ b/code/modules/mob/living/simple_animal/animals/penguin.dm @@ -18,7 +18,7 @@ harm_intent_damage = 5 melee_damage_lower = 10 melee_damage_upper = 15 - attacktext = "pecked" + attacktext = list("pecked") has_langs = list("Bird") speak_chance = 0 diff --git a/code/modules/mob/living/simple_animal/animals/sif_wildlife/diyaab.dm b/code/modules/mob/living/simple_animal/animals/sif_wildlife/diyaab.dm new file mode 100644 index 0000000000..a39694d02c --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/sif_wildlife/diyaab.dm @@ -0,0 +1,27 @@ +/mob/living/simple_animal/retaliate/diyaab + name = "diyaab" + desc = "A small pack animal. Although omnivorous, it will hunt meat on occasion." + faction = "diyaab" + icon_state = "diyaab" + icon_living = "diyaab" + icon_dead = "diyaab_dead" + icon = 'icons/jungle.dmi' + + faction = "diyaab" + cooperative = 1 + + maxHealth = 25 + health = 25 + speed = 1 + move_to_delay = 1 + + melee_damage_lower = 1 + melee_damage_upper = 8 + + attacktext = list("gouged") + cold_damage_per_tick = 0 + + speak_chance = 5 + speak = list("Awrr?","Aowrl!","Worrl") + emote_see = list("sniffs the air cautiously","looks around") + emote_hear = list("snuffles") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/sif_wildlife/savik.dm b/code/modules/mob/living/simple_animal/animals/sif_wildlife/savik.dm new file mode 100644 index 0000000000..75ebd22bd1 --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/sif_wildlife/savik.dm @@ -0,0 +1,32 @@ +/mob/living/simple_animal/hostile/savik + name = "savik" + desc = "A fast, armoured predator accustomed to hiding and ambushing in cold terrain." + faction = "savik" + icon_state = "savik" + icon_living = "savik" + icon_dead = "savik_dead" + icon = 'icons/jungle.dmi' + + faction = "savik" + + maxHealth = 125 + health = 125 + speed = 2 + move_to_delay = 2 + + melee_damage_lower = 15 + melee_damage_upper = 25 + + attacktext = list("mauled") + cold_damage_per_tick = 0 + + speak_chance = 5 + speak = list("Hruuugh!","Hrunnph") + emote_see = list("paws the ground","shakes its mane","stomps") + emote_hear = list("snuffles") + +/mob/living/simple_animal/hostile/savik/handle_stance(var/new_stance) + ..(new_stance) + if(stance == STANCE_ATTACK || stance == STANCE_ATTACKING) + if((health / maxHealth) <= 0.5) // At half health, and fighting someone currently. + add_modifier(/datum/modifier/berserk, 30 SECONDS) \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/sif_wildlife/shantak.dm b/code/modules/mob/living/simple_animal/animals/sif_wildlife/shantak.dm new file mode 100644 index 0000000000..65db039108 --- /dev/null +++ b/code/modules/mob/living/simple_animal/animals/sif_wildlife/shantak.dm @@ -0,0 +1,25 @@ +/mob/living/simple_animal/hostile/shantak + name = "shantak" + desc = "A piglike creature with a bright iridiscent mane that sparkles as though lit by an inner light. Don't be fooled by its beauty though." + faction = "shantak" + icon_state = "shantak" + icon_living = "shantak" + icon_dead = "shantak_dead" + icon = 'icons/jungle.dmi' + + faction = "shantak" + + maxHealth = 75 + health = 75 + speed = 1 + move_to_delay = 1 + + melee_damage_lower = 3 + melee_damage_upper = 12 + + attacktext = list("gouged") + cold_damage_per_tick = 0 + + speak_chance = 5 + speak = list("Shuhn","Shrunnph?","Shunpf") + emote_see = list("scratches the ground","shakes out its mane","clinks gently as it moves") \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/animals/snake_vr.dm b/code/modules/mob/living/simple_animal/animals/snake_vr.dm index 9068ec7f67..041cd38d15 100644 --- a/code/modules/mob/living/simple_animal/animals/snake_vr.dm +++ b/code/modules/mob/living/simple_animal/animals/snake_vr.dm @@ -17,7 +17,7 @@ melee_damage_lower = 3 melee_damage_upper = 5 - attacktext = "bitten" + attacktext = list("bitten") speak_chance = 1 speak_emote = list("hisses") diff --git a/code/modules/mob/living/simple_animal/animals/spiderbot.dm b/code/modules/mob/living/simple_animal/animals/spiderbot.dm index ff3f03bf57..7ae8edfb7a 100644 --- a/code/modules/mob/living/simple_animal/animals/spiderbot.dm +++ b/code/modules/mob/living/simple_animal/animals/spiderbot.dm @@ -21,7 +21,7 @@ melee_damage_lower = 1 melee_damage_upper = 3 - attacktext = "shocked" + attacktext = list("shocked") min_oxy = 0 max_tox = 0 diff --git a/code/modules/mob/living/simple_animal/animals/tomato.dm b/code/modules/mob/living/simple_animal/animals/tomato.dm index d1bffc6fe1..48882fea57 100644 --- a/code/modules/mob/living/simple_animal/animals/tomato.dm +++ b/code/modules/mob/living/simple_animal/animals/tomato.dm @@ -18,6 +18,6 @@ harm_intent_damage = 5 melee_damage_upper = 15 melee_damage_lower = 10 - attacktext = "mauled" + attacktext = list("mauled") meat_type = /obj/item/weapon/reagent_containers/food/snacks/tomatomeat diff --git a/code/modules/mob/living/simple_animal/animals/tree.dm b/code/modules/mob/living/simple_animal/animals/tree.dm index 3db514345f..37169d42a1 100644 --- a/code/modules/mob/living/simple_animal/animals/tree.dm +++ b/code/modules/mob/living/simple_animal/animals/tree.dm @@ -22,7 +22,7 @@ harm_intent_damage = 5 melee_damage_lower = 8 melee_damage_upper = 12 - attacktext = "bitten" + attacktext = list("bitten") attack_sound = 'sound/weapons/bite.ogg' min_oxy = 0 diff --git a/code/modules/mob/living/simple_animal/animals/worm.dm b/code/modules/mob/living/simple_animal/animals/worm.dm index 48ed6039c5..da30dbf8fd 100644 --- a/code/modules/mob/living/simple_animal/animals/worm.dm +++ b/code/modules/mob/living/simple_animal/animals/worm.dm @@ -56,7 +56,7 @@ melee_damage_lower = 10 melee_damage_upper = 15 - attacktext = "bitten" + attacktext = list("bitten") animate_movement = SLIDE_STEPS diff --git a/code/modules/mob/living/simple_animal/borer/borer.dm b/code/modules/mob/living/simple_animal/borer/borer.dm index e18a345066..b89e2f2af6 100644 --- a/code/modules/mob/living/simple_animal/borer/borer.dm +++ b/code/modules/mob/living/simple_animal/borer/borer.dm @@ -16,7 +16,7 @@ a_intent = I_HURT stop_automated_movement = 1 status_flags = CANPUSH - attacktext = "nipped" + attacktext = list("nipped") friendly = "prods" wander = 0 pass_flags = PASSTABLE diff --git a/code/modules/mob/living/simple_animal/constructs/constructs.dm b/code/modules/mob/living/simple_animal/constructs/constructs.dm index 412f37f172..c0034b1908 100644 --- a/code/modules/mob/living/simple_animal/constructs/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs/constructs.dm @@ -8,6 +8,7 @@ response_disarm = "flailed at" response_harm = "punched" intelligence_level = SA_HUMANOID // Player controlled. + hovering = TRUE icon_dead = "shade_dead" speed = -1 a_intent = I_HURT @@ -100,7 +101,7 @@ harm_intent_damage = 0 melee_damage_lower = 30 melee_damage_upper = 30 - attacktext = "smashed their armoured gauntlet into" + attacktext = list("smashed their armoured gauntlet into") mob_size = MOB_HUGE speed = 3 environment_smash = 2 @@ -152,7 +153,7 @@ health = 75 melee_damage_lower = 25 melee_damage_upper = 25 - attacktext = "slashed" + attacktext = list("slashed") speed = -1 environment_smash = 1 see_in_dark = 7 @@ -177,7 +178,7 @@ harm_intent_damage = 5 melee_damage_lower = 5 melee_damage_upper = 5 - attacktext = "rammed" + attacktext = list("rammed") speed = 0 environment_smash = 1 attack_sound = 'sound/weapons/rapidslice.ogg' @@ -206,7 +207,7 @@ harm_intent_damage = 0 melee_damage_lower = 50 melee_damage_upper = 50 - attacktext = "brutally crushed" + attacktext = list("brutally crushed") speed = 5 environment_smash = 2 attack_sound = 'sound/weapons/heavysmash.ogg' @@ -230,7 +231,7 @@ health = 150 melee_damage_lower = 25 melee_damage_upper = 25 - attacktext = "violently stabbed" + attacktext = list("violently stabbed") speed = -1 environment_smash = 1 see_in_dark = 7 diff --git a/code/modules/mob/living/simple_animal/humanoids/clown.dm b/code/modules/mob/living/simple_animal/humanoids/clown.dm index ee1341ff38..5751a058c4 100644 --- a/code/modules/mob/living/simple_animal/humanoids/clown.dm +++ b/code/modules/mob/living/simple_animal/humanoids/clown.dm @@ -26,7 +26,7 @@ harm_intent_damage = 8 melee_damage_lower = 10 melee_damage_upper = 10 - attacktext = "attacked" + attacktext = list("attacked") attack_sound = 'sound/items/bikehorn.ogg' min_oxy = 5 diff --git a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm index 4d107d35fd..c7645d2352 100644 --- a/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm +++ b/code/modules/mob/living/simple_animal/humanoids/mechamobs.dm @@ -1,5 +1,5 @@ /mob/living/simple_animal/hostile/mecha - name = "syndicate gygax" + name = "mercenary gygax" desc = "Well that's forboding." icon = 'icons/mecha/mecha.dmi' icon_state = "darkgygax" @@ -28,7 +28,7 @@ harm_intent_damage = 0 melee_damage_lower = 35 melee_damage_upper = 35 - attacktext = "slashed" + attacktext = list("slashed") attack_sound = 'sound/weapons/bladeslice.ogg' min_oxy = 0 @@ -96,6 +96,8 @@ /mob/living/simple_animal/hostile/mecha/malf_drone + name = "autonomous mechanized drone" + desc = "It appears to be an exosuit, piloted by a drone intelligence. It looks scary." intelligence_level = SA_ROBOTIC faction = "malf_drone" speak_chance = 1 @@ -110,6 +112,7 @@ say_cannot = list("Denied.", "Negative.") say_maybe_target = list("Possible threat detected. Investigating.", "Motion detected.", "Investigating.") say_got_target = list("Threat detected.", "New task: Remove threat.", "Threat removal engaged.", "Engaging target.") + returns_home = TRUE /mob/living/simple_animal/hostile/mecha/malf_drone/isSynthetic() return TRUE diff --git a/code/modules/mob/living/simple_animal/humanoids/pirate.dm b/code/modules/mob/living/simple_animal/humanoids/pirate.dm index f0c7c05ddc..8921f3c519 100644 --- a/code/modules/mob/living/simple_animal/humanoids/pirate.dm +++ b/code/modules/mob/living/simple_animal/humanoids/pirate.dm @@ -28,7 +28,7 @@ harm_intent_damage = 5 melee_damage_lower = 30 melee_damage_upper = 30 - attacktext = "slashed" + attacktext = list("slashed") attack_sound = 'sound/weapons/bladeslice.ogg' min_oxy = 5 diff --git a/code/modules/mob/living/simple_animal/humanoids/russian.dm b/code/modules/mob/living/simple_animal/humanoids/russian.dm index 1589fe2a7d..2c3fc68c71 100644 --- a/code/modules/mob/living/simple_animal/humanoids/russian.dm +++ b/code/modules/mob/living/simple_animal/humanoids/russian.dm @@ -30,7 +30,7 @@ harm_intent_damage = 5 melee_damage_lower = 15 melee_damage_upper = 15 - attacktext = "punched" + attacktext = list("punched") min_oxy = 5 max_oxy = 0 diff --git a/code/modules/mob/living/simple_animal/humanoids/syndicate.dm b/code/modules/mob/living/simple_animal/humanoids/syndicate.dm index dd724a581c..e7f9d6d64d 100644 --- a/code/modules/mob/living/simple_animal/humanoids/syndicate.dm +++ b/code/modules/mob/living/simple_animal/humanoids/syndicate.dm @@ -31,7 +31,7 @@ melee_damage_lower = 10 melee_damage_upper = 15 environment_smash = 1 - attacktext = "punched" + attacktext = list("punched") min_oxy = 5 max_oxy = 0 @@ -75,7 +75,7 @@ melee_damage_lower = 20 melee_damage_upper = 25 - attacktext = "slashed" + attacktext = list("slashed") status_flags = 0 @@ -133,7 +133,7 @@ ranged = 1 rapid = 1 projectiletype = /obj/item/projectile/bullet/pistol/medium - casingtype = /obj/item/ammo_casing/spent +// casingtype = /obj/item/ammo_casing/spent //Makes infinite stacks of bullets when put in PoIs. projectilesound = 'sound/weapons/Gunshot_light.ogg' loot_list = list(/obj/item/weapon/gun/projectile/automatic/c20r = 100) @@ -168,6 +168,7 @@ icon_state = "viscerator_attack" icon_living = "viscerator_attack" intelligence_level = SA_ROBOTIC + hovering = TRUE faction = "syndicate" maxHealth = 15 @@ -178,7 +179,7 @@ melee_damage_lower = 15 melee_damage_upper = 15 attack_sound = 'sound/weapons/bladeslice.ogg' - attacktext = "cut" + attacktext = list("cut") min_oxy = 0 max_oxy = 0 diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 47abd27348..9f72e59a4b 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -16,6 +16,12 @@ //Settings for played mobs var/show_stat_health = 1 // Does the percentage health show in the stat panel for the mob var/ai_inactive = 0 // Set to 1 to turn off most AI actions + var/has_hands = 0 // Set to 1 to enable the use of hands and the hands hud + var/list/hud_gears // Slots to show on the hud (typically none) + var/ui_icons // Icon file path to use for the HUD, otherwise generic icons are used + var/r_hand_sprite // If they have hands, + var/l_hand_sprite // they could use some icons. + var/player_msg // Message to print to players about 'how' to play this mob on login. //Mob icon/appearance settings var/icon_living = "" // The iconstate if we're alive, required @@ -23,6 +29,8 @@ var/icon_gib = "generic_gib" // The iconstate for being gibbed, optional. Defaults to a generic gib animation. var/icon_rest = null // The iconstate for resting, optional var/image/modifier_overlay = null // Holds overlays from modifiers. + attack_icon = 'icons/effects/effects.dmi' //Just the default, played like the weapon attack anim + attack_icon_state = "slash" //Just the default //Mob talking settings universal_speak = 0 // Can all mobs in the entire universe understand this one? @@ -69,7 +77,7 @@ var/cold_damage_per_tick = 2 // Same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp var/fire_alert = 0 // 0 = fine, 1 = hot, 2 = cold - var/min_oxy = 5 // Oxygen in moles, minimum, 0 is 'no minimum + var/min_oxy = 5 // Oxygen in moles, minimum, 0 is 'no minimum' var/max_oxy = 0 // Oxygen in moles, maximum, 0 is 'no maximum' var/min_tox = 0 // Phoron min var/max_tox = 1 // Phoron max @@ -104,13 +112,17 @@ //Mob melee settings var/melee_damage_lower = 2 // Lower bound of randomized melee damage var/melee_damage_upper = 6 // Upper bound of randomized melee damage - var/attacktext = "attacked" // "You are [attacktext] by the mob!" - var/friendly = "nuzzles" // What mobs do to people when they aren't really hostile + var/list/attacktext = list("attacked") // "You are [attacktext] by the mob!" + var/list/friendly = list("nuzzles") // "The mob [friendly] the person." var/attack_sound = null // Sound to play when I attack var/environment_smash = 0 // How much environment damage do I do when I hit stuff? var/melee_miss_chance = 15 // percent chance to miss a melee attack. var/melee_attack_minDelay = 5 // How long between attacks at least var/melee_attack_maxDelay = 10 // How long between attacks at most + var/attack_armor_type = "melee" // What armor does this check? + var/attack_armor_pen = 0 // How much armor pen this attack has. + var/attack_sharp = 0 // Is the attack sharp? + var/attack_edge = 0 // Does the attack have an edge? //Special attacks var/spattack_prob = 0 // Chance of the mob doing a special attack (0 for never) @@ -125,14 +137,14 @@ //Damage resistances var/resistance = 0 // Damage reduction for all types - var/list/resistances = list( - HALLOSS = 0, - BRUTE = 1, - BURN = 1, - TOX = 1, - OXY = 0, - CLONE = 0 - ) + var/list/armor = list( // Values for normal getarmor() checks + "melee" = 0, + "bullet" = 0, + "laser" = 0, + "energy" = 0, + "bomb" = 0, + "bio" = 100, + "rad" = 100) //Scary debug things var/debug_ai = 0 // Logging level for this mob (1,2,3) @@ -169,6 +181,7 @@ home_turf = get_turf(src) path_overlay = new(path_icon,path_icon_state) move_to_delay = max(2,move_to_delay) //Protection against people coding things incorrectly and A* pathing 100% of the time + maxHealth = health for(var/L in has_langs) languages |= all_languages[L] @@ -207,21 +220,17 @@ //Client attached /mob/living/simple_animal/Login() - if(src && src.client) - src.client.screen = list() - src.client.screen += src.client.void - ai_inactive = 1 - handle_stance(STANCE_IDLE) - LoseTarget() - src.client << "Mob AI disabled while you are controlling the mob." - ..() + . = ..() + ai_inactive = 1 + handle_stance(STANCE_IDLE) + LoseTarget() + to_chat(src,"Mob AI disabled while you are controlling the mob." - - t += "Generated power : [round(lastgen)] W
" - + t += "Generated power : [DisplayPower(lastgen)]
" t += "Turbine: [round(compressor.rpm)] RPM
" - t += "Starter: [ compressor.starter ? "Off On" : "Off On"]" - t += "