From 967cb1ece712cc127dedb807cbf3ef9f917ff541 Mon Sep 17 00:00:00 2001 From: NanakoAC Date: Sat, 10 Sep 2016 20:37:38 +0100 Subject: [PATCH] Bee Fixes (#859) Fixes #526 Fixes #202 bugfix: "Attempting to grab or pull bee swarms no longer works" bugfix: "Fixed bee swarms still flying around when dead and appearing to be unkillable." tweak: "Bees now take double damage from fire." tweak: "Thick material clothing now protects against beestings." tweak: "Beekeeping crate is no longer contraband in cargo." --- code/datums/supplypacks.dm | 10 +- .../living/carbon/human/human_attackhand.dm | 5 + code/modules/mob/living/simple_animal/bees.dm | 149 ++++++++++++------ .../mob/living/simple_animal/simple_animal.dm | 15 +- code/modules/mob/mob.dm | 10 +- code/modules/mob/mob_grab.dm | 33 ++-- html/changelogs/Nanako-Bees.yml | 40 +++++ 7 files changed, 193 insertions(+), 69 deletions(-) create mode 100644 html/changelogs/Nanako-Bees.yml diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm index 9788dfcb60a..cd609cff6ac 100644 --- a/code/datums/supplypacks.dm +++ b/code/datums/supplypacks.dm @@ -1229,7 +1229,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee /obj/item/apiary, /obj/item/queen_bee) cost = 40 - contraband = 1 + //contraband = 1 containertype = /obj/structure/closet/crate/hydroponics containername = "Beekeeping crate" access = access_hydroponics @@ -1561,8 +1561,8 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containertype = /obj/structure/largecrate containername = "jukebox Crate" group = "Hospitality" - -//voidsuit crates + +//voidsuit crates /datum/supply_packs/voidsuitcrate_eng name = "Engineering Voidsuit Crate" @@ -1603,7 +1603,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "atmospherics voidsuit kit" access = access_atmospherics group = "Atmospherics" - + /datum/supply_packs/voidsuitcrate_minin name = "Mining Voidsuit Crate" contains = list(/obj/item/clothing/head/helmet/space/void/mining, @@ -1613,7 +1613,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee containername = "mining voidsuit kit" access = access_mining group = "Supply" - + //maglocks crates /datum/supply_packs/maglocks_engineering diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index 076cd0a21c8..542849eca08 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -131,6 +131,11 @@ if(G.assailant == M) M << "You already grabbed [src]." return + + if (!attempt_grab(M)) + return + + if(w_uniform) w_uniform.add_fingerprint(M) diff --git a/code/modules/mob/living/simple_animal/bees.dm b/code/modules/mob/living/simple_animal/bees.dm index fc2a1cd72ea..e1a2ce5ce5b 100644 --- a/code/modules/mob/living/simple_animal/bees.dm +++ b/code/modules/mob/living/simple_animal/bees.dm @@ -1,10 +1,13 @@ - +//Bees are spawned from an apiary, and will slowly die if it is destroyed. /mob/living/simple_animal/bee name = "bees" icon = 'icons/obj/apiary_bees_etc.dmi' icon_state = "bees1" icon_dead = "bees1" - mob_size = 1 + mob_size = 0.5 + unsuitable_atoms_damage = 2.5 + maxHealth = 20 + density = 0 var/strength = 1 var/feral = 0 var/mut = 0 @@ -25,6 +28,25 @@ parent.owned_bee_swarms.Remove(src) ..() + +//Special death behaviour. When bees accumulate enough damage to 'die', they don't outright die. Thus no call to parent +//Instead the swarm strength (ie, size, or quantity of bees) drops and their health is refilled +//Repeat until strength hits zero. only THEN do they die, and they qdel and leave no corpse in doing so +//Because we don't have sprites for a carpet made of bee corpses. +/mob/living/simple_animal/bee/death() + strength -= 1 + if (strength <= 0) + if (prob(35))//probability to reduce spam + src.visible_message("\red The bee swarm completely dissipates.") + qdel(src) + return + else + health = maxHealth + if (prob(35))//probability to reduce spam + src.visible_message("\red The bee swarm starts to thin out a little.") + + update_icons() + /mob/living/simple_animal/bee/Life() ..() @@ -32,26 +54,30 @@ //if we're strong enough, sting some people var/mob/living/carbon/human/M = target_mob var/sting_prob = 40 // Bees will always try to sting. - if(M in view(src,1)) // Can I see my target? - if(prob(max(feral * 10, 0))) // Am I mad enough to want to sting? And yes, when I initially appear, I AM mad enough - var/obj/item/clothing/worn_suit = M.wear_suit - var/obj/item/clothing/worn_helmet = M.head - if(worn_suit) // Are you wearing clothes? - sting_prob -= min(worn_suit.armor["bio"],70) // Is it sealed? I can't get to 70% of your body. - if(worn_helmet) - sting_prob -= min(worn_helmet.armor["bio"],30) // Is your helmet sealed? I can't get to 30% of your body. - if( prob(sting_prob) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25))) ) // Try to sting! If you're not moving, think about stinging. - M.apply_damage(min(strength,2)+mut, BRUTE, sharp=1) // Stinging. The more mutated I am, the harder I sting. - M.apply_damage((round(feral/10,1)*(max((round(strength/20,1)),1)))+toxic, TOX) // Bee venom based on how angry I am and how many there are of me! - M << "\red You have been stung!" - M.flash_pain() + var/prob_mult = 1 + if(M && M in view(src,1)) // Can I see my target? + var/obj/item/clothing/worn_suit = M.wear_suit + var/obj/item/clothing/worn_helmet = M.head + if(worn_suit) // Are you wearing clothes? + if ((worn_suit.flags & THICKMATERIAL)) + prob_mult -= 0.7 + else + prob_mult -= 0.01 * (min(worn_suit.armor["bio"],70)) // Is it sealed? I can't get to 70% of your body. + if(worn_helmet) + if ((worn_helmet.flags & THICKMATERIAL)) + prob_mult -= 0.3 + else + prob_mult -= 0.01 *(min(worn_helmet.armor["bio"],30))// Is your helmet sealed? I can't get to 30% of your body. + if( prob(sting_prob*prob_mult) && (M.stat == CONSCIOUS || (M.stat == UNCONSCIOUS && prob(25*prob_mult))) ) // Try to sting! If you're not moving, think about stinging. + M.apply_damage(min(strength,2)+mut, BURN, sharp=1) // Stinging. The more mutated I am, the harder I sting. + M.apply_damage(max(strength*2,(round(feral/10,1)*(max((round(strength/20,1)),1)))+toxic), TOX) // Bee venom based on how angry I am and how many there are of me! + M << "\red You have been stung!" + M.flash_pain() + - //if we're chasing someone, get a little bit angry - if(target_mob && prob(5)) - feral++ //calm down a little bit - if(feral > 0) + if(feral > 0 && !target_mob) if(prob(feral * 20)) feral -= 1 else @@ -64,23 +90,22 @@ target_turf = null if(strength > 5) //calm down and spread out a little - var/mob/living/simple_animal/bee/B = new(get_turf(pick(orange(src,1)))) + var/mob/living/simple_animal/bee/B = new(get_turf(src)) B.strength = rand(1,5) src.strength -= B.strength - if(src.strength <= 5) - src.icon_state = "bees[src.strength]" - B.icon_state = "bees[B.strength]" + update_icons() + B.update_icons() if(src.parent) B.parent = src.parent src.parent.owned_bee_swarms.Add(B) //make some noise - if(prob(0.5)) + if(prob(5)) src.visible_message("\blue [pick("Buzzzz.","Hmmmmm.","Bzzz.")]") //smoke, water and steam calms us down var/calming = 0 - var/list/calmers = list(/obj/effect/effect/smoke/chem, \ + var/list/calmers = list(/obj/effect/effect/smoke, \ /obj/effect/effect/water, \ /obj/effect/effect/foam, \ /obj/effect/effect/steam, \ @@ -108,9 +133,7 @@ if(feral > 0) src.strength += B.strength qdel(B) - src.icon_state = "bees[src.strength]" - if(strength > 5) - icon_state = "bees_swarm" + update_icons() else if(prob(10)) //make the other swarm of bees stronger, then move away var/total_bees = B.strength + src.strength @@ -118,11 +141,11 @@ B.strength = min(5, total_bees) src.strength = total_bees - B.strength - B.icon_state = "bees[B.strength]" + update_icons() + B.update_icons() if(src.strength <= 0) qdel(src) return - src.icon_state = "bees[B.strength]" var/turf/simulated/floor/T = get_turf(get_step(src, pick(1,2,4,8))) density = 1 if(T.Enter(src, get_turf(src))) @@ -130,20 +153,30 @@ density = 0 break - if(target_mob) - if(target_mob in view(src,7)) - target_turf = get_turf(target_mob) - wander = 0 - else // My target's gone! But I might still be pissed! You there. You look like a good stinging target! - for(var/mob/living/carbon/G in view(src,7)) - target_mob = G - break + if(target_mob)//If we have a target + if(target_mob in view(src,7))//Check that we can still see them + target_turf = get_turf(target_mob)//If so, update the location + wander = 0 + else//Otherwise, if our target is out of view, we clear them so we can pick a new one in the next step + target_mob = null + target_turf = null + wander = 1 + + //If we're angry but have no target, lets search for one + if (!target_mob && feral) + for(var/mob/living/carbon/G in view(src,7)) + target_mob = G + break + + //if we're chasing someone, get a little bit angry + if(target_mob && prob(5)) + feral++ if(target_turf) if (!(DirBlocked(get_step(src, get_dir(src,target_turf)),get_dir(src,target_turf)))) // Check for windows and doors! Move(get_step(src, get_dir(src,target_turf))) - if (prob(0.1)) + if (prob(10)) src.visible_message("\blue The bees swarm after [target_mob]!") if(src.loc == target_turf) target_turf = null @@ -166,14 +199,36 @@ pixel_x = rand(-12,12) pixel_y = rand(-12,12) - if(!parent && prob(10)) + if(!parent && prob(8-strength)) strength -= 1 if(strength <= 0) - qdel(src) - else if(strength <= 5) - icon_state = "bees[strength]" + death() + else + update_icons() - //debugging - /*icon_state = "[strength]" - if(strength > 5) - icon_state = "unknown"*/ + +/mob/living/simple_animal/bee/update_icons() + if(strength <= 5) + icon_state = "bees[strength]" + else + icon_state = "bees_swarm" + +//Kill it with fire! +/mob/living/simple_animal/bee/adjustFireLoss(damage) + damage *= 2 + ..() + + +//No more grabbing bee swarms +/mob/living/simple_animal/bee/attempt_grab(var/mob/living/grabber) + if (prob(strength*5))//if the swarm is big you might grab a few bees, you won't make a serious dent + grabber << "You attempt to grab the swarm, but only manage to snatch a scant handful of crushed bees." + adjustBruteLoss(strength*0.5) + else + grabber << "For some bizarre reason known only to yourself, you attempt to grab ahold of the swarm of bees. You come away with nothing but empty, slightly stung hands." + grabber.apply_damage(strength*0.5, BURN) + + return 0 + +/mob/living/simple_animal/bee/attempt_pull(var/mob/living/grabber) + return attempt_grab(grabber) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 0ee02f43c63..34ede21d6cf 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -100,9 +100,6 @@ src.client.screen = null ..() -/mob/living/simple_animal/updatehealth() - return - /mob/living/simple_animal/examine(mob/user) ..() @@ -318,6 +315,9 @@ if (!(status_flags & CANPUSH)) return + if (!attempt_grab(M)) + return + var/obj/item/weapon/grab/G = new /obj/item/weapon/grab(M, src) M.put_in_active_hand(G) @@ -375,7 +375,9 @@ if(supernatural && istype(O,/obj/item/weapon/nullrod)) damage *= 2 purge = 3 - adjustBruteLoss(damage) + + apply_damage(damage, O.damtype) + //adjustBruteLoss(damage) else usr << "It won't budge!" return - var/mob/M = AM - if(ismob(AM)) + var/mob/living/M + if(istype(AM, /mob/living)) + M = AM + if (!M.attempt_pull(src)) + return + if(!iscarbon(src)) M.LAssailant = null else @@ -631,7 +635,7 @@ src << "\red Pulling \the [H] in their current condition would probably be a bad idea." //Attempted fix for people flying away through space when cuffed and dragged. - if(ismob(AM)) + if(M) var/mob/pulled = AM pulled.inertia_dir = 0 diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index af17182d7fd..a27607da1a8 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -1,6 +1,19 @@ #define UPGRADE_COOLDOWN 40 #define UPGRADE_KILL_TIMER 100 + +//This is called from human_attackhand.dm before grabbing happens. +//IT is called when grabber tries to grab this mob +//Override this for special grab behaviour. +//Returning 0 will make grab fail, returning 1 will suceed +/mob/living/proc/attempt_grab(var/mob/living/grabber) + return 1 + +//As above, but called when someone tries to pull this mob +/mob/living/proc/attempt_pull(var/mob/living/grabber) + return 1 + + ///Process_Grab() ///Called by client/Move() ///Checks to see if you are grabbing anything and if moving will affect your grab. @@ -124,7 +137,7 @@ if(iscarbon(affecting)) handle_eye_mouth_covering(affecting, assailant, assailant.zone_sel.selecting) - + if(force_down) if(affecting.loc != assailant.loc) force_down = 0 @@ -148,7 +161,7 @@ /obj/item/weapon/grab/proc/handle_eye_mouth_covering(mob/living/carbon/target, mob/user, var/target_zone) var/announce = (target_zone != last_hit_zone) //only display messages when switching between different target zones last_hit_zone = target_zone - + switch(target_zone) if("mouth") if(announce) @@ -232,7 +245,7 @@ else assailant.visible_message("[assailant] pins [affecting] down to the ground (now hands)!") apply_pinning(affecting, assailant) - + state = GRAB_AGGRESSIVE icon_state = "grabbed1" hud.icon_state = "reinforce1" @@ -284,10 +297,10 @@ return if(world.time < (last_action + 20)) return - + last_action = world.time reset_kill_state() //using special grab moves will interrupt choking them - + //clicking on the victim while grabbing them if(M == affecting) if(ishuman(affecting)) @@ -300,10 +313,10 @@ force_down = 0 return inspect_organ(affecting, assailant, hit_zone) - + if(I_GRAB) jointlock(affecting, assailant, hit_zone) - + if(I_HURT) if(hit_zone == "eyes") attack_eye(affecting, assailant) @@ -311,10 +324,10 @@ headbut(affecting, assailant) else dislocate(affecting, assailant, hit_zone) - + if(I_DISARM) pin_down(affecting, assailant) - + //clicking on yourself while grabbing them if(M == assailant && state >= GRAB_AGGRESSIVE) devour(affecting, assailant) @@ -325,7 +338,7 @@ qdel(src) /obj/item/weapon/grab/proc/reset_kill_state() - if(state == GRAB_KILL) + if(state == GRAB_KILL) assailant.visible_message("[assailant] lost \his tight grip on [affecting]'s neck!") hud.icon_state = "kill" state = GRAB_NECK diff --git a/html/changelogs/Nanako-Bees.yml b/html/changelogs/Nanako-Bees.yml new file mode 100644 index 00000000000..30808c369eb --- /dev/null +++ b/html/changelogs/Nanako-Bees.yml @@ -0,0 +1,40 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: Nanako + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +# Any changes you've made. See valid prefix list above. +# INDENT WITH TWO SPACES. NOT TABS. SPACES. +# SCREW THIS UP AND IT WON'T WORK. +# Also, all entries are changed into a single [] after a master changelog generation. Just remove the brackets when you add new entries. +# Please surround your changes in double quotes ("), as certain characters otherwise screws up compiling. The quotes will not show up in the changelog. +changes: + - bugfix: "Attempting to grab or pull bee swarms no longer works" + - bugfix: "Fixed bee swarms still flying around when dead and appearing to be unkillable." + - tweak: "Bees now take double damage from fire." + - tweak: "Thick material clothing now protects against beestings." + - tweak: "Beekeeping crate is no longer contraband in cargo." \ No newline at end of file