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