Merge branch 'master' of https://github.com/ParadiseSS13/Paradise into turfs

# Conflicts:
#	code/modules/mob/living/simple_animal/hostile/hostile.dm
This commit is contained in:
Mark van Alphen
2019-04-04 22:04:55 +02:00
73 changed files with 846 additions and 577 deletions
+2 -2
View File
@@ -35,7 +35,7 @@
/mob/proc/put_in_l_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!l_hand)
if(!l_hand && has_left_hand())
W.forceMove(src) //TODO: move to equipped?
l_hand = W
W.layer = 20 //TODO: move to equipped?
@@ -51,7 +51,7 @@
/mob/proc/put_in_r_hand(var/obj/item/W)
if(!put_in_hand_check(W))
return 0
if(!r_hand)
if(!r_hand && has_right_hand())
W.forceMove(src)
r_hand = W
W.layer = 20
+18 -30
View File
@@ -4,22 +4,15 @@
if(!iscarbon(target)) //something is bypassing the give arguments, no clue what, adding a sanity check JIC
to_chat(usr, "<span class='danger'>Wait a second... \the [target] HAS NO HANDS! AHH!</span>")//cheesy messages ftw
return
if(target.incapacitated() || usr.incapacitated() || target.client == null)
return
if(target.stat == 2 || usr.stat == 2|| target.client == null)
return
var/obj/item/I
if(!usr.hand && usr.r_hand == null)
to_chat(usr, "<span class='warning'> You don't have anything in your right hand to give to [target.name]</span>")
return
if(usr.hand && usr.l_hand == null)
to_chat(usr, "<span class='warning'> You don't have anything in your left hand to give to [target.name]</span>")
return
if(usr.hand)
I = usr.l_hand
else if(!usr.hand)
I = usr.r_hand
var/obj/item/I = get_active_hand()
if(!I)
to_chat(usr, "<span class='warning'> You don't have anything in your hand to give to [target.name]</span>")
return
if((I.flags & NODROP) || (I.flags & ABSTRACT))
to_chat(usr, "<span class='notice'>That's not exactly something you can give.</span>")
@@ -29,35 +22,30 @@
if("Yes")
if(!I)
return
if(target.incapacitated() || usr.incapacitated())
return
if(!Adjacent(target))
to_chat(usr, "<span class='warning'> You need to stay in reaching distance while giving an object.</span>")
to_chat(target, "<span class='warning'> [usr.name] moved too far away.</span>")
return
if((usr.hand && usr.l_hand != I) || (!usr.hand && usr.r_hand != I))
if((I.flags & NODROP) || (I.flags & ABSTRACT))
to_chat(usr, "<span class='warning'>[I] stays stuck to your hand when you try to give it!</span>")
to_chat(target, "<span class='warning'>[I] stays stuck to [usr.name]'s hand when you try to take it!</span>")
return
if(I != get_active_hand())
to_chat(usr, "<span class='warning'> You need to keep the item in your active hand.</span>")
to_chat(target, "<span class='warning'> [usr.name] seem to have given up on giving \the [I.name] to you.</span>")
to_chat(target, "<span class='warning'> [usr.name] seem to have given up on giving [I] to you.</span>")
return
if(target.r_hand != null && target.l_hand != null)
to_chat(target, "<span class='warning'> Your hands are full.</span>")
to_chat(usr, "<span class='warning'> Their hands are full.</span>")
return
else
usr.drop_item()
if(target.r_hand == null)
target.r_hand = I
else
target.l_hand = I
I.loc = target
I.layer = 20
I.plane = HUD_PLANE
usr.unEquip(I)
target.put_in_hands(I)
I.add_fingerprint(target)
src.update_inv_l_hand()
src.update_inv_r_hand()
target.update_inv_l_hand()
target.update_inv_r_hand()
target.visible_message("<span class='notice'> [usr.name] handed \the [I.name] to [target.name].</span>")
target.visible_message("<span class='notice'> [usr.name] handed [I] to [target.name].</span>")
I.on_give(usr, target)
if("No")
target.visible_message("<span class='warning'> [usr.name] tried to hand [I.name] to [target.name] but [target.name] didn't want it.</span>")
target.visible_message("<span class='warning'> [usr.name] tried to hand [I] to [target.name] but [target.name] didn't want it.</span>")
else
to_chat(usr, "<span class='warning'> [target.name]'s hands are full.</span>")
@@ -172,6 +172,7 @@
// Defined here solely to take species flags into account without having to recast at mob/living level.
/mob/living/carbon/human/adjustOxyLoss(amount)
if(NO_BREATHE in dna.species.species_traits)
oxyloss = 0
return FALSE
if(dna.species && amount > 0)
amount = amount * dna.species.oxy_mod
@@ -179,6 +180,7 @@
/mob/living/carbon/human/setOxyLoss(amount)
if(NO_BREATHE in dna.species.species_traits)
oxyloss = 0
return FALSE
if(dna.species && amount > 0)
amount = amount * dna.species.oxy_mod
@@ -434,11 +434,11 @@
if(slot_l_hand)
if(l_hand)
return 0
return 1
return !incapacitated()
if(slot_r_hand)
if(r_hand)
return 0
return 1
return !incapacitated()
if(slot_wear_mask)
if(wear_mask)
return 0
@@ -1,5 +1,6 @@
/mob/living/carbon/human/SetLoseBreath(amount)
if(NO_BREATHE in dna.species.species_traits)
losebreath = 0
return FALSE
. = ..()
+4
View File
@@ -122,8 +122,10 @@
/mob/living/proc/adjustOxyLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
oxyloss = 0
return FALSE //godmode
if(BREATHLESS in mutations)
oxyloss = 0
return FALSE
var/old_oxyloss = oxyloss
oxyloss = max(oxyloss + amount, 0)
@@ -137,8 +139,10 @@
/mob/living/proc/setOxyLoss(amount, updating_health = TRUE)
if(status_flags & GODMODE)
oxyloss = 0
return FALSE //godmode
if(BREATHLESS in mutations)
oxyloss = 0
return FALSE
var/old_oxyloss = oxyloss
oxyloss = amount
+1 -1
View File
@@ -759,7 +759,7 @@
if(!silent)
visible_message("<span class='notice'>[src] tries to put [what] on [who].</span>")
if(do_mob(src, who, what.put_on_delay))
if(what && Adjacent(who))
if(what && Adjacent(who) && !(what.flags & NODROP))
unEquip(what)
who.equip_to_slot_if_possible(what, where, 0, 1)
add_attack_logs(src, who, "Equipped [what]")
@@ -429,6 +429,7 @@
modules += new /obj/item/bonesetter(src)
modules += new /obj/item/surgicaldrill(src)
modules += new /obj/item/gripper/medical(src)
modules += new /obj/item/gun/medbeam(src)
modules += new /obj/item/melee/energy/sword/cyborg/saw(src) //Energy saw -- primary weapon
modules += new /obj/item/card/emag(src)
modules += new /obj/item/crowbar/cyborg(src)
@@ -11,7 +11,7 @@
/mob/living/simple_animal/hostile/poison/bees
name = "bee"
desc = "buzzy buzzy bee, stingy sti- Ouch!"
desc = "Buzzy buzzy bee, stingy sti- Ouch!"
icon_state = ""
icon_living = ""
icon = 'icons/mob/bees.dmi'
@@ -33,25 +33,28 @@
environment_smash = 0
mouse_opacity = MOUSE_OPACITY_OPAQUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
flying = 1
search_objects = 1 //have to find those plant trays!
density = 0
density = FALSE
mob_size = MOB_SIZE_TINY
flying = TRUE
search_objects = TRUE //have to find those plant trays!
//Spaceborn beings don't get hurt by space
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
del_on_death = 1
del_on_death = TRUE
var/datum/reagent/beegent = null //hehe, beegent
var/obj/structure/beebox/beehome = null
var/isqueen = FALSE
var/idle = 0
var/isqueen = FALSE
var/bee_syndicate = FALSE
var/icon_base = "bee"
var/static/list/bee_icons = list()
var/static/beehometypecache = typecacheof(/obj/structure/beebox)
var/static/hydroponicstypecache = typecacheof(/obj/machinery/hydroponics)
/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(movement_dir = 0)
return 1
return TRUE
/mob/living/simple_animal/hostile/poison/bees/New()
..()
@@ -65,6 +68,20 @@
beehome = null
return ..()
/mob/living/simple_animal/hostile/poison/bees/death(gibbed)
. = ..()
if(!.)
return
if(beehome)
if(beehome.bees)
beehome.bees.Remove(src)
beehome = null
/mob/living/simple_animal/hostile/poison/bees/examine(mob/user)
..()
if(!bee_syndicate && !beehome)
to_chat(user, "<span class='warning'>This bee is homeless!</span>")
/mob/living/simple_animal/hostile/poison/bees/proc/generate_bee_visuals()
overlays.Cut()
@@ -94,21 +111,45 @@
//We don't attack beekeepers/people dressed as bees//Todo: bee costume
/mob/living/simple_animal/hostile/poison/bees/CanAttack(atom/the_target)
. = ..()
return .
if(!.)
return FALSE
if(!bee_syndicate && isliving(the_target))
var/mob/living/H = the_target
return !H.bee_friendly()
/mob/living/simple_animal/hostile/poison/bees/Found(atom/A)
if(isliving(A))
var/mob/living/L = A
return !L.bee_friendly()
return 0
var/mob/living/H = A
return !H.bee_friendly()
if(istype(A, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/Hydro = A
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit)
wanted_objects |= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
return TRUE
return FALSE
/mob/living/simple_animal/hostile/poison/bees/AttackingTarget()
if(beegent && isliving(target))
var/mob/living/L = target
if(!isnull(target.reagents))
beegent.reaction_mob(L, INGEST)
L.reagents.add_reagent(beegent.id, rand(1,5))
target.attack_animal(src)
//Pollinate
if(istype(target, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/Hydro = target
pollinate(Hydro)
else if(istype(target, /obj/structure/beebox))
if(target == beehome)
var/obj/structure/beebox/BB = target
forceMove(BB)
target = null
wanted_objects -= beehometypecache //so we don't attack beeboxes when not going home
return //no don't attack the goddamm box
else
..()
if(isliving(target))
var/mob/living/L = target
if(L.reagents)
if(beegent)
beegent.reaction_mob(L, INGEST)
L.reagents.add_reagent(beegent.id, rand(1, 5))
else
L.reagents.add_reagent("spidertoxin", 5)
/mob/living/simple_animal/hostile/poison/bees/proc/assign_reagent(datum/reagent/R)
if(istype(R))
@@ -116,81 +157,13 @@
name = "[initial(name)] ([R.name])"
generate_bee_visuals()
/mob/living/simple_animal/hostile/poison/bees/handle_automated_action()
. = ..()
if(!.)
return
/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B)
if(!B)
return 0
if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent)
return 1
return 0
//Botany Worker Bees
/mob/living/simple_animal/hostile/poison/bees/worker
//Blank type define in case we need to give them special stuff later, plus organization (currently they are same as base type bee)
/mob/living/simple_animal/hostile/poison/bees/worker/Destroy()
if(beehome)
if(beehome.bees)
beehome.bees.Remove(src)
beehome = null
return ..()
/mob/living/simple_animal/hostile/poison/bees/worker/death(gibbed)
. = ..()
if(!.)
return
if(beehome)
if(beehome.bees)
beehome.bees.Remove(src)
beehome = null
/mob/living/simple_animal/hostile/poison/bees/worker/examine(mob/user)
..()
if(!beehome)
to_chat(user, "<span class='warning'>This bee is homeless!</span>")
/mob/living/simple_animal/hostile/poison/bees/worker/Found(atom/A)
if(istype(A, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/Hydro = A
if(Hydro.myseed && !Hydro.dead && !Hydro.recent_bee_visit && !Hydro.lid_state)
wanted_objects |= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted and uncovered
return 1
..()
/mob/living/simple_animal/hostile/poison/bees/worker/CanAttack(atom/the_target)
. = ..()
if(!.)
return 0
if(isliving(the_target)) //Should ignore ghosts and camera mobs already, but just in case
var/mob/living/L = the_target
return !L.bee_friendly()
/mob/living/simple_animal/hostile/poison/bees/worker/AttackingTarget()
//Pollinate
if(istype(target, /obj/machinery/hydroponics))
var/obj/machinery/hydroponics/Hydro = target
pollinate(Hydro)
else if(target == beehome)
var/obj/structure/beebox/BB = target
forceMove(BB)
target = null
wanted_objects -= /obj/structure/beebox //so we don't attack beeboxes when not going home
else
..()
/mob/living/simple_animal/hostile/poison/bees/worker/proc/pollinate(obj/machinery/hydroponics/Hydro)
/mob/living/simple_animal/hostile/poison/bees/proc/pollinate(obj/machinery/hydroponics/Hydro)
if(!istype(Hydro) || !Hydro.myseed || Hydro.dead || Hydro.recent_bee_visit || Hydro.lid_state)
target = null
return
target = null //so we pick a new hydro tray next FindTarget(), instead of loving the same plant for eternity
wanted_objects -= /obj/machinery/hydroponics //so we only hunt them while they're alive/seeded/not visisted and uncovered
wanted_objects -= hydroponicstypecache //so we only hunt them while they're alive/seeded/not visisted
Hydro.recent_bee_visit = TRUE
spawn(BEE_TRAY_RECENT_VISIT)
if(Hydro)
@@ -210,68 +183,79 @@
if(beehome)
beehome.bee_resources = min(beehome.bee_resources + growth, 100)
/mob/living/simple_animal/hostile/poison/bees/worker/handle_automated_action()
/mob/living/simple_animal/hostile/poison/bees/handle_automated_action()
. = ..()
if(!.)
return
if(!isqueen)
if(loc == beehome)
idle = min(100, ++idle)
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
forceMove(get_turf(beehome))
else
idle = max(0, --idle)
if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
if(!FindTarget())
wanted_objects += /obj/structure/beebox //so we don't attack beeboxes when not going home
target = beehome
if(!beehome) //add outselves to a beebox (of the same reagent) if we have no home
for(var/obj/structure/beebox/BB in view(vision_range, src))
if(reagent_incompatible(BB.queen_bee) || BB.bees.len >= BB.get_max_bees())
continue
BB.bees |= src
beehome = BB
if(!bee_syndicate)
if(!isqueen)
if(loc == beehome)
idle = min(100, ++idle)
if(idle >= BEE_IDLE_ROAMING && prob(BEE_PROB_GOROAM))
forceMove(beehome.drop_location())
else
idle = max(0, --idle)
if(idle <= BEE_IDLE_GOHOME && prob(BEE_PROB_GOHOME))
if(!FindTarget())
wanted_objects |= beehometypecache //so we don't attack beeboxes when not going home
target = beehome
if(!beehome) //add ourselves to a beebox (of the same reagent) if we have no home
for(var/obj/structure/beebox/BB in view(vision_range, src))
if(reagent_incompatible(BB.queen_bee) || BB.bees.len >= BB.get_max_bees())
continue
BB.bees |= src
beehome = BB
break // End loop after the first compatible find.
//Botany Queen Bee
/mob/living/simple_animal/hostile/poison/bees/queen
name = "queen bee"
desc = "she's the queen of bees, BZZ BZZ"
desc = "She's the queen of bees, BZZ BZZ"
icon_base = "queen"
isqueen = TRUE
//the Queen doesn't leave the box on her own, and she CERTAINLY doesn't pollinate by herself
//the Queen doesn't leave the box on her own, and she CERTAINLY doesn't pollinate by herself
/mob/living/simple_animal/hostile/poison/bees/queen/Found(atom/A)
return 0
return FALSE
//leave pollination for the peasent bees
/mob/living/simple_animal/hostile/poison/bees/queen/AttackingTarget()
..()
if(beegent && isliving(target))
var/mob/living/L = target
beegent.reaction_mob(L, TOUCH)
L.reagents.add_reagent(beegent.id, rand(1, 5))
//PEASENT BEES
/mob/living/simple_animal/hostile/poison/bees/queen/pollinate()
return
/mob/living/simple_animal/hostile/poison/bees/proc/reagent_incompatible(mob/living/simple_animal/hostile/poison/bees/B)
if(!B)
return FALSE
if(B.beegent && beegent && B.beegent.id != beegent.id || B.beegent && !beegent || !B.beegent && beegent)
return TRUE
return FALSE
/mob/living/simple_animal/hostile/poison/bees/queen/CanAttack(atom/the_target)
. = ..()
if(!.)
return 0
if(isliving(the_target)) //Should ignore ghosts and camera mobs already, but just in case
var/mob/living/L = the_target
return !L.bee_friendly()
/obj/item/queen_bee
name = "queen bee"
desc = "she's the queen of bees, BZZ BZZ"
desc = "She's the queen of bees, BZZ BZZ"
icon_state = "queen_item"
item_state = ""
icon = 'icons/mob/bees.dmi'
var/mob/living/simple_animal/hostile/poison/bees/queen/queen
/obj/item/queen_bee/attackby(obj/item/I, mob/user, params)
if(istype(I,/obj/item/reagent_containers/syringe))
if(istype(I, /obj/item/reagent_containers/syringe))
var/obj/item/reagent_containers/syringe/S = I
if(S.reagents.has_reagent("royal_bee_jelly")) //checked twice, because I really don't want royal bee jelly to be duped
if(S.reagents.has_reagent("royal_bee_jelly",5))
if(S.reagents.has_reagent("royal_bee_jelly", 5))
S.reagents.remove_reagent("royal_bee_jelly", 5)
if(!queen.beegent.can_synth)
to_chat(user, "<span class='warning'>You inject [src] with the royal bee jelly. It's ineffective! Maybe it's something to do with the [src] reagent.</span>")
return
var/obj/item/queen_bee/qb = new(get_turf(user))
var/obj/item/queen_bee/qb = new(user.drop_location())
qb.queen = new(qb)
if(queen && queen.beegent)
qb.queen.assign_reagent(queen.beegent) //Bees use the global singleton instances of reagents, so we don't need to worry about one bee being deleted and her copies losing their reagents.
@@ -282,16 +266,17 @@
else
var/datum/reagent/R = GLOB.chemical_reagents_list[S.reagents.get_master_reagent_id()]
if(R && S.reagents.has_reagent(R.id, 5))
S.reagents.remove_reagent(R.id,5)
S.reagents.remove_reagent(R.id, 5)
queen.assign_reagent(R)
user.visible_message("<span class='warning'>[user] injects [src]'s genome with [R.name], mutating it's DNA!</span>","<span class='warning'>You inject [src]'s genome with [R.name], mutating it's DNA!</span>")
user.visible_message("<span class='warning'>[user] injects [src]'s genome with [R.name], mutating its DNA!</span>", "<span class='warning'>You inject [src]'s genome with [R.name], mutating its DNA!</span>")
name = queen.name
else
to_chat(user, "<span class='warning'>You don't have enough units of that chemical to modify the bee's DNA!</span>")
..()
else
return ..()
/obj/item/queen_bee/bought/New()
..()
/obj/item/queen_bee/bought/Initialize(mapload)
. = ..()
queen = new(src)
/obj/item/queen_bee/Destroy()
@@ -299,7 +284,6 @@
return ..()
//Syndicate Bees
/mob/living/simple_animal/hostile/poison/bees/syndi
name = "syndi-bee"
@@ -309,10 +293,14 @@
maxHealth = 25
health = 25
faction = list("hostile", "syndicate")
search_objects = 0 //these bees don't care about trivial things like plants, especially when there is havoc to sow
beegent = new /datum/reagent/facid() //prepare to die
search_objects = FALSE //these bees don't care about trivial things like plants, especially when there is havoc to sow
bee_syndicate = TRUE
var/list/master_and_friends = list()
/mob/living/simple_animal/hostile/poison/bees/syndi/New()
beegent = GLOB.chemical_reagents_list["facid"] //Prepare to die
..()
/mob/living/simple_animal/hostile/poison/bees/syndi/Destroy()
master_and_friends.Cut()
return ..()
@@ -320,24 +308,27 @@
/mob/living/simple_animal/hostile/poison/bees/syndi/assign_reagent(datum/reagent/R)
return
/mob/living/simple_animal/hostile/poison/bees/syndi/Found(atom/A)
return CanAttack(A)
/mob/living/simple_animal/hostile/poison/bees/syndi/pollinate() // No Pollination
return
/mob/living/simple_animal/hostile/poison/bees/syndi/Found(atom/A) //Typical usual hostile mob targeting list
return
/mob/living/simple_animal/hostile/poison/bees/syndi/CanAttack(atom/the_target)
. = ..()
if(!.)
return 0
return FALSE
if(isliving(the_target))
var/mob/living/L = the_target
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H in master_and_friends)
return 0
return 1
return FALSE
return TRUE
/mob/living/simple_animal/hostile/poison/bees/syndi/AttackingTarget()
..()
if(target && isliving(target))
var/mob/living/L = target
if(L.stat)
LoseTarget()
LoseTarget()
@@ -58,6 +58,7 @@
if(!targets_from)
targets_from = src
environment_target_typecache = typecacheof(environment_target_typecache)
wanted_objects = typecacheof(wanted_objects)
/mob/living/simple_animal/hostile/Destroy()
targets_from = null
+1
View File
@@ -298,6 +298,7 @@
/mob/living/SetLoseBreath(amount)
if(BREATHLESS in mutations)
losebreath = 0
return FALSE
losebreath = max(amount, 0)