Merge branch 'master' into donut

This commit is contained in:
TrilbySpaceClone
2019-12-22 02:36:57 -05:00
206 changed files with 2433 additions and 1487 deletions

View File

@@ -37,6 +37,8 @@
dat += "<I>Your apprentice is training to cast spells that will aid your survival. They know Forcewall and Charge and come with a Staff of Healing.</I><BR>"
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_ROBELESS]'>Robeless</A><BR>"
dat += "<I>Your apprentice is training to cast spells without their robes. They know Knock and Mindswap.</I><BR>"
dat += "<A href='byond://?src=[REF(src)];school=[APPRENTICE_MARTIAL]'>Martial Artist</a><BR>"
dat += "<I>Your apprentice is training in ancient martial arts. They know the Plasmafist and Nuclear Fist.</I><BR>"
user << browse(dat, "window=radio")
onclose(user, "radio")
return

View File

@@ -65,6 +65,8 @@
//Equip
var/mob/living/carbon/human/H = owner.current
H.set_species(/datum/species/abductor)
var/obj/item/organ/tongue/abductor/T = H.getorganslot(ORGAN_SLOT_TONGUE)
T.mothership = "[team.name]"
H.real_name = "[team.name] [sub_role]"
H.equipOutfit(outfit)

View File

@@ -17,7 +17,7 @@
actions_types = list(/datum/action/item_action/hands_free/activate)
allowed = list(
/obj/item/abductor,
/obj/item/abductor_baton,
/obj/item/abductor/baton,
/obj/item/melee/baton,
/obj/item/gun/energy,
/obj/item/restraints/handcuffs
@@ -57,7 +57,7 @@
/obj/item/clothing/suit/armor/abductor/vest/item_action_slot_check(slot, mob/user, datum/action/A)
if(slot == SLOT_WEAR_SUIT) //we only give the mob the ability to activate the vest if he's actually wearing it.
return 1
return TRUE
/obj/item/clothing/suit/armor/abductor/vest/proc/SetDisguise(datum/icon_snapshot/entry)
disguise = entry
@@ -89,11 +89,9 @@
/obj/item/clothing/suit/armor/abductor/vest/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
DeactivateStealth()
return 0
/obj/item/clothing/suit/armor/abductor/vest/IsReflect()
DeactivateStealth()
return 0
/obj/item/clothing/suit/armor/abductor/vest/ui_action_click()
switch(mode)
@@ -111,7 +109,10 @@
to_chat(loc, "<span class='warning'>Combat injection is still recharging.</span>")
return
var/mob/living/carbon/human/M = loc
M.do_adrenaline(150, FALSE, 0, 0, TRUE, list("inaprovaline" = 3, "synaptizine" = 10, "omnizine" = 10), "<span class='boldnotice'>You feel a sudden surge of energy!</span>")
M.adjustStaminaLoss(-75)
M.SetUnconscious(0)
M.SetStun(0)
M.SetKnockdown(0)
combat_cooldown = 0
START_PROCESSING(SSobj, src)
@@ -131,9 +132,11 @@
/obj/item/abductor
icon = 'icons/obj/abductor.dmi'
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
/obj/item/abductor/proc/AbductorCheck(mob/user)
if(HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING))
if (HAS_TRAIT(user, TRAIT_ABDUCTOR_TRAINING))
return TRUE
if (istype(user) && user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_TRAINING))
return TRUE
@@ -158,8 +161,6 @@
desc = "A dual-mode tool for retrieving specimens and scanning appearances. Scanning can be done through cameras."
icon_state = "gizmo_scan"
item_state = "silencer"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
var/mode = GIZMO_SCAN
var/mob/living/marked = null
var/obj/machinery/abductor/console/console
@@ -218,12 +219,9 @@
if(marked == target)
to_chat(user, "<span class='warning'>This specimen is already marked!</span>")
return
if(ishuman(target))
if(isabductor(target))
marked = target
to_chat(user, "<span class='notice'>You mark [target] for future retrieval.</span>")
else
prepare(target,user)
if(isabductor(target) || iscow(target))
marked = target
to_chat(user, "<span class='notice'>You mark [target] for future retrieval.</span>")
else
prepare(target,user)
@@ -247,8 +245,6 @@
desc = "A compact device used to shut down communications equipment."
icon_state = "silencer"
item_state = "gizmo"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
/obj/item/abductor/silencer/attack(mob/living/M, mob/user)
if(!AbductorCheck(user))
@@ -292,8 +288,6 @@
or to send a command to a test subject with a charged gland."
icon_state = "mind_device_message"
item_state = "silencer"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
var/mode = MIND_DEVICE_MESSAGE
/obj/item/abductor/mind_device/attack_self(mob/user)
@@ -389,6 +383,17 @@
item_state = "alienpistol"
trigger_guard = TRIGGER_GUARD_ALLOW_ALL
/obj/item/gun/energy/shrink_ray
name = "shrink ray blaster"
desc = "This is a piece of frightening alien tech that enhances the magnetic pull of atoms in a localized space to temporarily make an object shrink. \
That or it's just space magic. Either way, it shrinks stuff."
ammo_type = list(/obj/item/ammo_casing/energy/shrink)
item_state = "shrink_ray"
icon_state = "shrink_ray"
fire_delay = 30
selfcharge = 1//shot costs 200 energy, has a max capacity of 1000 for 5 shots. self charge returns 25 energy every couple ticks, so about 1 shot charged every 12~ seconds
trigger_guard = TRIGGER_GUARD_ALLOW_ALL// variable-size trigger, get it? (abductors need this to be set so the gun is usable for them)
/obj/item/paper/guides/antag/abductor
name = "Dissection Guide"
icon_state = "alienpaper_words"
@@ -422,21 +427,18 @@
#define BATON_PROBE 3
#define BATON_MODES 4
/obj/item/abductor_baton
/obj/item/abductor/baton
name = "advanced baton"
desc = "A quad-mode baton used for incapacitation and restraining of specimens."
var/mode = BATON_STUN
icon = 'icons/obj/abductor.dmi'
icon_state = "wonderprodStun"
item_state = "wonderprod"
lefthand_file = 'icons/mob/inhands/antag/abductor_lefthand.dmi'
righthand_file = 'icons/mob/inhands/antag/abductor_righthand.dmi'
slot_flags = ITEM_SLOT_BELT
force = 7
w_class = WEIGHT_CLASS_NORMAL
actions_types = list(/datum/action/item_action/toggle_mode)
/obj/item/abductor_baton/proc/toggle(mob/living/user=usr)
/obj/item/abductor/baton/proc/toggle(mob/living/user=usr)
mode = (mode+1)%BATON_MODES
var/txt
switch(mode)
@@ -452,7 +454,7 @@
to_chat(usr, "<span class='notice'>You switch the baton to [txt] mode.</span>")
update_icon()
/obj/item/abductor_baton/update_icon()
/obj/item/abductor/baton/update_icon()
switch(mode)
if(BATON_STUN)
icon_state = "wonderprodStun"
@@ -467,8 +469,8 @@
icon_state = "wonderprodProbe"
item_state = "wonderprodProbe"
/obj/item/abductor_baton/attack(mob/target, mob/living/user)
if(!isabductor(user))
/obj/item/abductor/baton/attack(mob/target, mob/living/user)
if(!AbductorCheck(user))
return
if(iscyborg(target))
@@ -485,8 +487,8 @@
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.check_shields(src, 0, "[user]'s [name]", MELEE_ATTACK))
playsound(L, 'sound/weapons/genhit.ogg', 50, 1)
return 0
playsound(H, 'sound/weapons/genhit.ogg', 50, TRUE)
return FALSE
switch (mode)
if(BATON_STUN)
@@ -498,10 +500,10 @@
if(BATON_PROBE)
ProbeAttack(L,user)
/obj/item/abductor_baton/attack_self(mob/living/user)
/obj/item/abductor/baton/attack_self(mob/living/user)
toggle(user)
/obj/item/abductor_baton/proc/StunAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/StunAttack(mob/living/L,mob/living/user)
L.lastattacker = user.real_name
L.lastattackerckey = user.ckey
@@ -513,7 +515,7 @@
L.visible_message("<span class='danger'>[user] has stunned [L] with [src]!</span>", \
"<span class='userdanger'>[user] has stunned you with [src]!</span>")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
if(ishuman(L))
var/mob/living/carbon/human/H = L
@@ -521,7 +523,7 @@
log_combat(user, L, "stunned")
/obj/item/abductor_baton/proc/SleepAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/SleepAttack(mob/living/L,mob/living/user)
if(L.incapacitated(TRUE, TRUE))
if(L.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='warning'>The specimen's tinfoil protection is interfering with the sleep inducement!</span>")
@@ -531,7 +533,7 @@
return
L.visible_message("<span class='danger'>[user] has induced sleep in [L] with [src]!</span>", \
"<span class='userdanger'>You suddenly feel very drowsy!</span>")
playsound(loc, 'sound/weapons/egloves.ogg', 50, 1, -1)
playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1)
L.Sleeping(1200)
log_combat(user, L, "put to sleep")
else
@@ -545,13 +547,13 @@
L.visible_message("<span class='danger'>[user] tried to induce sleep in [L] with [src]!</span>", \
"<span class='userdanger'>You suddenly feel drowsy!</span>")
/obj/item/abductor_baton/proc/CuffAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/CuffAttack(mob/living/L,mob/living/user)
if(!iscarbon(L))
return
var/mob/living/carbon/C = L
if(!C.handcuffed)
if(C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore())
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
playsound(src, 'sound/weapons/cablecuff.ogg', 30, TRUE, -2)
C.visible_message("<span class='danger'>[user] begins restraining [C] with [src]!</span>", \
"<span class='userdanger'>[user] begins shaping an energy field around your hands!</span>")
if(do_mob(user, C, 30) && (C.get_num_arms(FALSE) >= 2 || C.get_arm_ignore()))
@@ -565,7 +567,7 @@
else
to_chat(user, "<span class='warning'>[C] doesn't have two hands...</span>")
/obj/item/abductor_baton/proc/ProbeAttack(mob/living/L,mob/living/user)
/obj/item/abductor/baton/proc/ProbeAttack(mob/living/L,mob/living/user)
L.visible_message("<span class='danger'>[user] probes [L] with [src]!</span>", \
"<span class='userdanger'>[user] probes you!</span>")
@@ -610,7 +612,7 @@
S.start()
. = ..()
/obj/item/abductor_baton/examine(mob/user)
/obj/item/abductor/baton/examine(mob/user)
. = ..()
switch(mode)
if(BATON_STUN)
@@ -639,10 +641,44 @@
AddComponent(/datum/component/wearertargeting/earprotection, list(SLOT_EARS))
/obj/item/radio/headset/abductor/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
if(W.tool_behaviour == TOOL_SCREWDRIVER)
return // Stops humans from disassembling abductor headsets.
return ..()
/obj/item/abductor_machine_beacon
name = "machine beacon"
desc = "A beacon designed to instantly tele-construct abductor machinery."
icon = 'icons/obj/abductor.dmi'
icon_state = "beacon"
w_class = WEIGHT_CLASS_TINY
var/obj/machinery/spawned_machine
/obj/item/abductor_machine_beacon/attack_self(mob/user)
..()
user.visible_message("<span class='notice'>[user] places down [src] and activates it.</span>", "<span class='notice'>You place down [src] and activate it.</span>")
user.dropItemToGround(src)
playsound(src, 'sound/machines/terminal_alert.ogg', 50)
addtimer(CALLBACK(src, .proc/try_spawn_machine), 30)
/obj/item/abductor_machine_beacon/proc/try_spawn_machine()
var/viable = FALSE
if(isfloorturf(loc))
var/turf/T = loc
viable = TRUE
for(var/obj/thing in T.contents)
if(thing.density || ismachinery(thing) || isstructure(thing))
viable = FALSE
if(viable)
playsound(src, 'sound/effects/phasein.ogg', 50, TRUE)
var/new_machine = new spawned_machine(loc)
visible_message("<span class='notice'>[new_machine] warps on top of the beacon!</span>")
qdel(src)
else
playsound(src, 'sound/machines/buzz-two.ogg', 50)
/obj/item/abductor_machine_beacon/chem_dispenser
name = "beacon - Reagent Synthesizer"
spawned_machine = /obj/machinery/chem_dispenser/abductor
/obj/item/scalpel/alien
name = "alien scalpel"
@@ -706,11 +742,11 @@
framestackamount = 1
/obj/structure/table_frame/abductor/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/wrench))
if(I.tool_behaviour == TOOL_WRENCH)
to_chat(user, "<span class='notice'>You start disassembling [src]...</span>")
I.play_tool_sound(src)
if(I.use_tool(src, user, 30))
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
for(var/i = 1, i <= framestackamount, i++)
new framestack(get_turf(src))
qdel(src)
@@ -760,7 +796,6 @@
icon = 'icons/obj/abductor.dmi'
icon_state = "bed"
can_buckle = 1
buckle_lying = 1
var/static/list/injected_reagents = list("corazone")
@@ -798,3 +833,11 @@
airlock_type = /obj/machinery/door/airlock/abductor
material_type = /obj/item/stack/sheet/mineral/abductor
noglass = TRUE
/obj/item/clothing/under/abductor
desc = "The most advanced form of jumpsuit known to reality, looks uncomfortable."
name = "alien jumpsuit"
icon_state = "abductor"
item_state = "bl_suit"
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 10, bio = 10, rad = 0, fire = 0, acid = 0)
can_adjust = 0

View File

@@ -1,6 +1,6 @@
/datum/outfit/abductor
name = "Abductor Basic"
uniform = /obj/item/clothing/under/color/grey //they're greys gettit
uniform = /obj/item/clothing/under/abductor
shoes = /obj/item/clothing/shoes/combat
back = /obj/item/storage/backpack
ears = /obj/item/radio/headset/abductor
@@ -34,7 +34,7 @@
name = "Abductor Agent"
head = /obj/item/clothing/head/helmet/abductor
suit = /obj/item/clothing/suit/armor/abductor/vest
suit_store = /obj/item/abductor_baton
suit_store = /obj/item/abductor/baton
belt = /obj/item/storage/belt/military/abductor/full
backpack_contents = list(

View File

@@ -5,18 +5,23 @@
icon_state = "gland"
status = ORGAN_ROBOTIC
beating = TRUE
organ_flags = ORGAN_NO_SPOIL
var/true_name = "baseline placebo referencer"
var/cooldown_low = 300
var/cooldown_high = 300
var/next_activation = 0
var/uses // -1 For infinite
var/human_only = 0
var/active = 0
var/human_only = FALSE
var/active = FALSE
var/mind_control_uses = 1
var/mind_control_duration = 1800
var/active_mind_control = FALSE
/obj/item/organ/heart/gland/Initialize()
. = ..()
icon_state = pick(list("health", "spider", "slime", "emp", "species", "egg", "vent", "mindshock", "viral"))
/obj/item/organ/heart/gland/examine(mob/user)
. = ..()
if((user.mind && HAS_TRAIT(user.mind, TRAIT_ABDUCTOR_SCIENTIST_TRAINING)) || isobserver(user))
@@ -55,14 +60,18 @@
active_mind_control = TRUE
message_admins("[key_name(user)] sent an abductor mind control message to [key_name(owner)]: [command]")
update_gland_hud()
var/obj/screen/alert/mind_control/mind_alert = owner.throw_alert("mind_control", /obj/screen/alert/mind_control)
mind_alert.command = command
addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration)
return TRUE
/obj/item/organ/heart/gland/proc/clear_mind_control()
if(!ownerCheck() || !active_mind_control)
return FALSE
to_chat(owner, "<span class='userdanger'>You feel the compulsion fade, and you completely forget about your previous orders.</span>")
to_chat(owner, "<span class='userdanger'>You feel the compulsion fade, and you <i>completely forget</i> about your previous orders.</span>")
owner.clear_alert("mind_control")
active_mind_control = FALSE
return TRUE
/obj/item/organ/heart/gland/Remove(mob/living/carbon/M, special = 0)
active = 0
@@ -98,257 +107,4 @@
active = 0
/obj/item/organ/heart/gland/proc/activate()
return
/obj/item/organ/heart/gland/heals
true_name = "coherency harmonizer"
cooldown_low = 200
cooldown_high = 400
uses = -1
icon_state = "health"
mind_control_uses = 3
mind_control_duration = 3000
/obj/item/organ/heart/gland/heals/activate()
to_chat(owner, "<span class='notice'>You feel curiously revitalized.</span>")
owner.adjustToxLoss(-20, FALSE, TRUE)
owner.heal_bodypart_damage(20, 20, 0, TRUE)
owner.adjustOxyLoss(-20)
/obj/item/organ/heart/gland/slime
true_name = "gastric animation galvanizer"
cooldown_low = 600
cooldown_high = 1200
uses = -1
icon_state = "slime"
mind_control_uses = 1
mind_control_duration = 2400
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
owner.faction |= "slime"
owner.grant_language(/datum/language/slime)
/obj/item/organ/heart/gland/slime/activate()
to_chat(owner, "<span class='warning'>You feel nauseated!</span>")
owner.vomit(20)
var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey")
Slime.Friends = list(owner)
Slime.Leader = owner
/obj/item/organ/heart/gland/mindshock
true_name = "neural crosstalk uninhibitor"
cooldown_low = 400
cooldown_high = 700
uses = -1
icon_state = "mindshock"
mind_control_uses = 1
mind_control_duration = 6000
/obj/item/organ/heart/gland/mindshock/activate()
to_chat(owner, "<span class='notice'>You get a headache.</span>")
var/turf/T = get_turf(owner)
for(var/mob/living/carbon/H in orange(4,T))
if(H == owner)
continue
switch(pick(1,3))
if(1)
to_chat(H, "<span class='userdanger'>You hear a loud buzz in your head, silencing your thoughts!</span>")
H.Stun(50)
if(2)
to_chat(H, "<span class='warning'>You hear an annoying buzz in your head.</span>")
H.confused += 15
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 160)
if(3)
H.hallucination += 60
/obj/item/organ/heart/gland/pop
true_name = "anthropmorphic translocator"
cooldown_low = 900
cooldown_high = 1800
uses = -1
human_only = TRUE
icon_state = "species"
mind_control_uses = 5
mind_control_duration = 300
/obj/item/organ/heart/gland/pop/activate()
to_chat(owner, "<span class='notice'>You feel unlike yourself.</span>")
randomize_human(owner)
var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/insect, /datum/species/fly))
owner.set_species(species)
/obj/item/organ/heart/gland/ventcrawling
true_name = "pliant cartilage enabler"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "vent"
mind_control_uses = 4
mind_control_duration = 1800
/obj/item/organ/heart/gland/ventcrawling/activate()
to_chat(owner, "<span class='notice'>You feel very stretchy.</span>")
owner.ventcrawler = VENTCRAWLER_ALWAYS
/obj/item/organ/heart/gland/viral
true_name = "contamination incubator"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "viral"
mind_control_uses = 1
mind_control_duration = 1800
/obj/item/organ/heart/gland/viral/activate()
to_chat(owner, "<span class='warning'>You feel sick.</span>")
var/datum/disease/advance/A = random_virus(pick(2,6),6)
A.carrier = TRUE
owner.ForceContractDisease(A, FALSE, TRUE)
/obj/item/organ/heart/gland/viral/proc/random_virus(max_symptoms, max_level)
if(max_symptoms > VIRUS_SYMPTOM_LIMIT)
max_symptoms = VIRUS_SYMPTOM_LIMIT
var/datum/disease/advance/A = new /datum/disease/advance()
var/list/datum/symptom/possible_symptoms = list()
for(var/symptom in subtypesof(/datum/symptom))
var/datum/symptom/S = symptom
if(initial(S.level) > max_level)
continue
if(initial(S.level) <= 0) //unobtainable symptoms
continue
possible_symptoms += S
for(var/i in 1 to max_symptoms)
var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms)
if(chosen_symptom)
var/datum/symptom/S = new chosen_symptom
A.symptoms += S
A.Refresh() //just in case someone already made and named the same disease
return A
/obj/item/organ/heart/gland/trauma
true_name = "white matter randomiser"
cooldown_low = 800
cooldown_high = 1200
uses = 5
icon_state = "emp"
mind_control_uses = 3
mind_control_duration = 1800
/obj/item/organ/heart/gland/trauma/activate()
to_chat(owner, "<span class='warning'>You feel a spike of pain in your head.</span>")
if(prob(33))
owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
if(prob(20))
owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
/obj/item/organ/heart/gland/spiderman
true_name = "araneae cloister accelerator"
cooldown_low = 450
cooldown_high = 900
uses = -1
icon_state = "spider"
mind_control_uses = 2
mind_control_duration = 2400
/obj/item/organ/heart/gland/spiderman/activate()
to_chat(owner, "<span class='warning'>You feel something crawling in your skin.</span>")
owner.faction |= "spiders"
var/obj/structure/spider/spiderling/S = new(owner.drop_location())
S.directive = "Protect your nest inside [owner.real_name]."
/obj/item/organ/heart/gland/egg
true_name = "roe/enzymatic synthesizer"
cooldown_low = 300
cooldown_high = 400
uses = -1
icon_state = "egg"
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
mind_control_uses = 2
mind_control_duration = 1800
/obj/item/organ/heart/gland/egg/activate()
owner.visible_message("<span class='alertalien'>[owner] [pick(EGG_LAYING_MESSAGES)]</span>")
var/turf/T = owner.drop_location()
new /obj/item/reagent_containers/food/snacks/egg/gland(T)
/obj/item/organ/heart/gland/electric
true_name = "electron accumulator/discharger"
cooldown_low = 800
cooldown_high = 1200
uses = -1
mind_control_uses = 2
mind_control_duration = 900
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, ORGAN_TRAIT)
..()
/obj/item/organ/heart/gland/electric/activate()
owner.visible_message("<span class='danger'>[owner]'s skin starts emitting electric arcs!</span>",\
"<span class='warning'>You feel electric energy building up inside you!</span>")
playsound(get_turf(owner), "sparks", 100, 1, -1)
addtimer(CALLBACK(src, .proc/zap), rand(30, 100))
/obj/item/organ/heart/gland/electric/proc/zap()
tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN)
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, 1)
/obj/item/organ/heart/gland/chem
true_name = "intrinsic pharma-provider"
cooldown_low = 50
cooldown_high = 50
uses = -1
mind_control_uses = 3
mind_control_duration = 1200
var/list/possible_reagents = list()
/obj/item/organ/heart/gland/chem/Initialize()
..()
for(var/X in subtypesof(/datum/reagent/drug))
var/datum/reagent/R = X
possible_reagents += initial(R.id)
for(var/X in subtypesof(/datum/reagent/medicine))
var/datum/reagent/R = X
possible_reagents += initial(R.id)
for(var/X in typesof(/datum/reagent/toxin))
var/datum/reagent/R = X
possible_reagents += initial(R.id)
/obj/item/organ/heart/gland/chem/activate()
var/chem_to_add = pick(possible_reagents)
owner.reagents.add_reagent(chem_to_add, 2)
owner.adjustToxLoss(-2, TRUE, TRUE)
..()
/obj/item/organ/heart/gland/plasma
true_name = "effluvium sanguine-synonym emitter"
cooldown_low = 1200
cooldown_high = 1800
uses = -1
mind_control_uses = 1
mind_control_duration = 800
/obj/item/organ/heart/gland/plasma/activate()
to_chat(owner, "<span class='warning'>You feel bloated.</span>")
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "<span class='userdanger'>A massive stomachache overcomes you.</span>"), 150)
addtimer(CALLBACK(src, .proc/vomit_plasma), 200)
/obj/item/organ/heart/gland/plasma/proc/vomit_plasma()
if(!owner)
return
owner.visible_message("<span class='danger'>[owner] vomits a cloud of plasma!</span>")
var/turf/open/T = get_turf(owner)
if(istype(T))
T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
owner.vomit()
return

View File

@@ -0,0 +1,19 @@
/obj/item/organ/heart/gland/access
true_name = "anagraphic electro-scrambler"
cooldown_low = 600
cooldown_high = 1200
uses = 1
icon_state = "mindshock"
mind_control_uses = 3
mind_control_duration = 900
/obj/item/organ/heart/gland/access/activate()
to_chat(owner, "<span class='notice'>You feel like a VIP for some reason.</span>")
RegisterSignal(owner, COMSIG_MOB_ALLOWED, .proc/free_access)
/obj/item/organ/heart/gland/access/proc/free_access(datum/source, obj/O)
return TRUE
/obj/item/organ/heart/gland/access/Remove(mob/living/carbon/M, special = 0)
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
..()

View File

@@ -0,0 +1,18 @@
/obj/item/organ/heart/gland/blood
true_name = "pseudonuclear hemo-destabilizer"
cooldown_low = 1200
cooldown_high = 1800
uses = -1
icon_state = "egg"
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
mind_control_uses = 3
mind_control_duration = 1500
/obj/item/organ/heart/gland/blood/activate()
if(!ishuman(owner) || !owner.dna.species)
return
var/mob/living/carbon/human/H = owner
var/datum/species/species = H.dna.species
to_chat(H, "<span class='warning'>You feel your blood heat up for a moment.</span>")
species.exotic_blood = get_random_reagent_id()

View File

@@ -0,0 +1,20 @@
/obj/item/organ/heart/gland/chem
true_name = "intrinsic pharma-provider"
cooldown_low = 50
cooldown_high = 50
uses = -1
icon_state = "viral"
mind_control_uses = 3
mind_control_duration = 1200
var/list/possible_reagents = list()
/obj/item/organ/heart/gland/chem/Initialize()
. = ..()
for(var/R in subtypesof(/datum/reagent/drug) + subtypesof(/datum/reagent/medicine) + typesof(/datum/reagent/toxin))
possible_reagents += R
/obj/item/organ/heart/gland/chem/activate()
var/chem_to_add = pick(possible_reagents)
owner.reagents.add_reagent(chem_to_add, 2)
owner.adjustToxLoss(-5, TRUE, TRUE)
..()

View File

@@ -0,0 +1,15 @@
/obj/item/organ/heart/gland/egg
true_name = "roe/enzymatic synthesizer"
cooldown_low = 300
cooldown_high = 400
uses = -1
icon_state = "egg"
lefthand_file = 'icons/mob/inhands/misc/food_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/food_righthand.dmi'
mind_control_uses = 2
mind_control_duration = 1800
/obj/item/organ/heart/gland/egg/activate()
owner.visible_message("<span class='alertalien'>[owner] [pick(EGG_LAYING_MESSAGES)]</span>")
var/turf/T = owner.drop_location()
new /obj/item/reagent_containers/food/snacks/egg/gland(T)

View File

@@ -0,0 +1,26 @@
/obj/item/organ/heart/gland/electric
true_name = "electron accumulator/discharger"
cooldown_low = 800
cooldown_high = 1200
icon_state = "species"
uses = -1
mind_control_uses = 2
mind_control_duration = 900
/obj/item/organ/heart/gland/electric/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
..()
/obj/item/organ/heart/gland/electric/activate()
owner.visible_message("<span class='danger'>[owner]'s skin starts emitting electric arcs!</span>",\
"<span class='warning'>You feel electric energy building up inside you!</span>")
playsound(get_turf(owner), "sparks", 100, TRUE, -1)
addtimer(CALLBACK(src, .proc/zap), rand(30, 100))
/obj/item/organ/heart/gland/electric/proc/zap()
tesla_zap(owner, 4, 8000, TESLA_MOB_DAMAGE | TESLA_OBJ_DAMAGE | TESLA_MOB_STUN)
playsound(get_turf(owner), 'sound/magic/lightningshock.ogg', 50, TRUE)

View File

@@ -0,0 +1,178 @@
/obj/item/organ/heart/gland/heal
true_name = "organic replicator"
cooldown_low = 200
cooldown_high = 400
uses = -1
human_only = TRUE
icon_state = "health"
mind_control_uses = 3
mind_control_duration = 3000
/obj/item/organ/heart/gland/heal/activate()
if(!(owner.mob_biotypes & MOB_ORGANIC))
return
for(var/organ in owner.internal_organs)
if(istype(organ, /obj/item/organ/cyberimp))
reject_implant(organ)
return
var/obj/item/organ/liver/liver = owner.getorganslot(ORGAN_SLOT_LIVER)
if((!liver/* && !HAS_TRAIT(owner, TRAIT_NOMETABOLISM)*/) || (liver && ((liver.damage > (liver.maxHealth / 2)) || (istype(liver, /obj/item/organ/liver/cybernetic)))))
replace_liver(liver)
return
var/obj/item/organ/lungs/lungs = owner.getorganslot(ORGAN_SLOT_LUNGS)
if((!lungs && !HAS_TRAIT(owner, TRAIT_NOBREATH)) || (lungs && (istype(lungs, /obj/item/organ/lungs/cybernetic))))
replace_lungs(lungs)
return
var/obj/item/organ/eyes/eyes = owner.getorganslot(ORGAN_SLOT_EYES)
if(!eyes || (eyes && ((HAS_TRAIT_FROM(owner, TRAIT_NEARSIGHT, EYE_DAMAGE)) || (HAS_TRAIT_FROM(owner, TRAIT_BLIND, EYE_DAMAGE)) || (istype(eyes, /obj/item/organ/eyes/robotic)))))
replace_eyes(eyes)
return
var/obj/item/bodypart/limb
var/list/limb_list = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
for(var/zone in limb_list)
limb = owner.get_bodypart(zone)
if(!limb)
replace_limb(zone)
return
if((limb.get_damage() >= (limb.max_damage / 2)) || (limb.status == BODYPART_ROBOTIC))
replace_limb(zone, limb)
return
if(owner.getToxLoss() > 40)
replace_blood()
return
var/tox_amount = 0
for(var/datum/reagent/toxin/T in owner.reagents.reagent_list)
tox_amount += owner.reagents.get_reagent_amount(T.type)
if(tox_amount > 10)
replace_blood()
return
if(owner.blood_volume < BLOOD_VOLUME_OKAY)
owner.blood_volume = BLOOD_VOLUME_NORMAL
to_chat(owner, "<span class='warning'>You feel your blood pulsing within you.</span>")
return
var/obj/item/bodypart/chest/chest = owner.get_bodypart(BODY_ZONE_CHEST)
if((chest.get_damage() >= (chest.max_damage / 4)) || (chest.status == BODYPART_ROBOTIC))
replace_chest(chest)
return
/obj/item/organ/heart/gland/heal/proc/reject_implant(obj/item/organ/cyberimp/implant)
owner.visible_message("<span class='warning'>[owner] vomits up his [implant.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [implant.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
implant.Remove(owner)
implant.forceMove(owner.drop_location())
/obj/item/organ/heart/gland/heal/proc/replace_liver(obj/item/organ/liver/liver)
if(liver)
owner.visible_message("<span class='warning'>[owner] vomits up his [liver.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [liver.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
liver.Remove(owner)
liver.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble in your bowels...</span>")
var/liver_type = /obj/item/organ/liver
if(owner?.dna?.species?.mutantliver)
liver_type = owner.dna.species.mutantliver
var/obj/item/organ/liver/new_liver = new liver_type()
new_liver.Insert(owner)
/obj/item/organ/heart/gland/heal/proc/replace_lungs(obj/item/organ/lungs/lungs)
if(lungs)
owner.visible_message("<span class='warning'>[owner] vomits up his [lungs.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [lungs.name]!</span>")
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
lungs.Remove(owner)
lungs.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble inside your chest...</span>")
var/lung_type = /obj/item/organ/lungs
if(owner.dna.species && owner.dna.species.mutantlungs)
lung_type = owner.dna.species.mutantlungs
var/obj/item/organ/lungs/new_lungs = new lung_type()
new_lungs.Insert(owner)
/obj/item/organ/heart/gland/heal/proc/replace_eyes(obj/item/organ/eyes/eyes)
if(eyes)
owner.visible_message("<span class='warning'>[owner]'s [eyes.name] fall out of their sockets!</span>", "<span class='userdanger'>Your [eyes.name] fall out of their sockets!</span>")
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
eyes.Remove(owner)
eyes.forceMove(owner.drop_location())
else
to_chat(owner, "<span class='warning'>You feel a weird rumble behind your eye sockets...</span>")
addtimer(CALLBACK(src, .proc/finish_replace_eyes), rand(100, 200))
/obj/item/organ/heart/gland/heal/proc/finish_replace_eyes()
var/eye_type = /obj/item/organ/eyes
if(owner.dna.species && owner.dna.species.mutanteyes)
eye_type = owner.dna.species.mutanteyes
var/obj/item/organ/eyes/new_eyes = new eye_type()
new_eyes.Insert(owner)
owner.visible_message("<span class='warning'>A pair of new eyes suddenly inflates into [owner]'s eye sockets!</span>", "<span class='userdanger'>A pair of new eyes suddenly inflates into your eye sockets!</span>")
/obj/item/organ/heart/gland/heal/proc/replace_limb(body_zone, obj/item/bodypart/limb)
if(limb)
owner.visible_message("<span class='warning'>[owner]'s [limb.name] suddenly detaches from [owner.p_their()] body!</span>", "<span class='userdanger'>Your [limb.name] suddenly detaches from your body!</span>")
playsound(owner, "desceration", 50, TRUE, -1)
limb.drop_limb()
else
to_chat(owner, "<span class='warning'>You feel a weird tingle in your [parse_zone(body_zone)]... even if you don't have one.</span>")
addtimer(CALLBACK(src, .proc/finish_replace_limb, body_zone), rand(150, 300))
/obj/item/organ/heart/gland/heal/proc/finish_replace_limb(body_zone)
owner.visible_message("<span class='warning'>With a loud snap, [owner]'s [parse_zone(body_zone)] rapidly grows back from [owner.p_their()] body!</span>",
"<span class='userdanger'>With a loud snap, your [parse_zone(body_zone)] rapidly grows back from your body!</span>",
"<span class='warning'>Your hear a loud snap.</span>")
playsound(owner, 'sound/magic/demon_consume.ogg', 50, TRUE)
owner.regenerate_limb(body_zone)
/obj/item/organ/heart/gland/heal/proc/replace_blood()
owner.visible_message("<span class='warning'>[owner] starts vomiting huge amounts of blood!</span>", "<span class='userdanger'>You suddenly start vomiting huge amounts of blood!</span>")
keep_replacing_blood()
/obj/item/organ/heart/gland/heal/proc/keep_replacing_blood()
var/keep_going = FALSE
owner.vomit(0, TRUE, FALSE, 3, FALSE, FALSE, FALSE, TRUE)
owner.Stun(15)
owner.adjustToxLoss(-15, TRUE, TRUE)
owner.blood_volume = min(BLOOD_VOLUME_NORMAL, owner.blood_volume + 20)
if(owner.blood_volume < BLOOD_VOLUME_NORMAL)
keep_going = TRUE
if(owner.getToxLoss())
keep_going = TRUE
for(var/datum/reagent/toxin/R in owner.reagents.reagent_list)
owner.reagents.remove_reagent(R.type, 4)
if(owner.reagents.has_reagent(R.type))
keep_going = TRUE
if(keep_going)
addtimer(CALLBACK(src, .proc/keep_replacing_blood), 30)
/obj/item/organ/heart/gland/heal/proc/replace_chest(obj/item/bodypart/chest/chest)
if(chest.status == BODYPART_ROBOTIC)
owner.visible_message("<span class='warning'>[owner]'s [chest.name] rapidly expels its mechanical components, replacing them with flesh!</span>", "<span class='userdanger'>Your [chest.name] rapidly expels its mechanical components, replacing them with flesh!</span>")
playsound(owner, 'sound/magic/clockwork/anima_fragment_attack.ogg', 50, TRUE)
var/list/dirs = GLOB.alldirs.Copy()
for(var/i in 1 to 3)
var/obj/effect/decal/cleanable/robot_debris/debris = new(get_turf(owner))
debris.streak(dirs)
else
owner.visible_message("<span class='warning'>[owner]'s [chest.name] sheds off its damaged flesh, rapidly replacing it!</span>", "<span class='warning'>Your [chest.name] sheds off its damaged flesh, rapidly replacing it!</span>")
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
var/list/dirs = GLOB.alldirs.Copy()
for(var/i in 1 to 3)
var/obj/effect/decal/cleanable/blood/gibs/gibs = new(get_turf(owner))
gibs.streak(dirs)
var/obj/item/bodypart/chest/new_chest = new(null)
new_chest.replace_limb(owner, TRUE)
qdel(chest)

View File

@@ -0,0 +1,64 @@
/obj/item/organ/heart/gland/mindshock
true_name = "neural crosstalk uninhibitor"
cooldown_low = 400
cooldown_high = 700
uses = -1
icon_state = "mindshock"
mind_control_uses = 1
mind_control_duration = 6000
var/list/mob/living/carbon/human/broadcasted_mobs = list()
/obj/item/organ/heart/gland/mindshock/activate()
to_chat(owner, "<span class='notice'>You get a headache.</span>")
var/turf/T = get_turf(owner)
for(var/mob/living/carbon/H in orange(4,T))
if(H == owner)
continue
switch(pick(1,3))
if(1)
to_chat(H, "<span class='userdanger'>You hear a loud buzz in your head, silencing your thoughts!</span>")
H.Stun(50)
if(2)
to_chat(H, "<span class='warning'>You hear an annoying buzz in your head.</span>")
H.confused += 15
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10, 160)
if(3)
H.hallucination += 60
/obj/item/organ/heart/gland/mindshock/mind_control(command, mob/living/user)
if(!ownerCheck() || !mind_control_uses || active_mind_control)
return FALSE
mind_control_uses--
for(var/mob/M in oview(7, owner))
if(!ishuman(M))
continue
var/mob/living/carbon/human/H = M
if(H.stat)
continue
broadcasted_mobs += H
to_chat(H, "<span class='userdanger'>You suddenly feel an irresistible compulsion to follow an order...</span>")
to_chat(H, "<span class='mind_control'>[command]</span>")
message_admins("[key_name(user)] broadcasted an abductor mind control message from [key_name(owner)] to [key_name(H)]: [command]")
var/obj/screen/alert/mind_control/mind_alert = H.throw_alert("mind_control", /obj/screen/alert/mind_control)
mind_alert.command = command
if(LAZYLEN(broadcasted_mobs))
active_mind_control = TRUE
addtimer(CALLBACK(src, .proc/clear_mind_control), mind_control_duration)
update_gland_hud()
return TRUE
/obj/item/organ/heart/gland/mindshock/clear_mind_control()
if(!active_mind_control || !LAZYLEN(broadcasted_mobs))
return FALSE
for(var/M in broadcasted_mobs)
var/mob/living/carbon/human/H = M
to_chat(H, "<span class='userdanger'>You feel the compulsion fade, and you <i>completely forget</i> about your previous orders.</span>")
H.clear_alert("mind_control")
active_mind_control = FALSE
return TRUE

View File

@@ -0,0 +1,22 @@
/obj/item/organ/heart/gland/plasma
true_name = "effluvium sanguine-synonym emitter"
cooldown_low = 1200
cooldown_high = 1800
icon_state = "slime"
uses = -1
mind_control_uses = 1
mind_control_duration = 800
/obj/item/organ/heart/gland/plasma/activate()
to_chat(owner, "<span class='warning'>You feel bloated.</span>")
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, owner, "<span class='userdanger'>A massive stomachache overcomes you.</span>"), 150)
addtimer(CALLBACK(src, .proc/vomit_plasma), 200)
/obj/item/organ/heart/gland/plasma/proc/vomit_plasma()
if(!owner)
return
owner.visible_message("<span class='danger'>[owner] vomits a cloud of plasma!</span>")
var/turf/open/T = get_turf(owner)
if(istype(T))
T.atmos_spawn_air("plasma=50;TEMP=[T20C]")
owner.vomit()

View File

@@ -0,0 +1,47 @@
/obj/item/organ/heart/gland/quantum
true_name = "quantic de-observation matrix"
cooldown_low = 150
cooldown_high = 150
uses = -1
icon_state = "emp"
mind_control_uses = 2
mind_control_duration = 1200
var/mob/living/carbon/entangled_mob
/obj/item/organ/heart/gland/quantum/activate()
if(entangled_mob)
return
for(var/mob/M in oview(owner, 7))
if(!iscarbon(M))
continue
entangled_mob = M
addtimer(CALLBACK(src, .proc/quantum_swap), rand(600, 2400))
return
/obj/item/organ/heart/gland/quantum/proc/quantum_swap()
if(QDELETED(entangled_mob))
entangled_mob = null
return
var/turf/T = get_turf(owner)
do_teleport(owner, get_turf(entangled_mob),null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM)
do_teleport(entangled_mob, T,null,TRUE,channel = TELEPORT_CHANNEL_QUANTUM)
to_chat(owner, "<span class='warning'>You suddenly find yourself somewhere else!</span>")
to_chat(entangled_mob, "<span class='warning'>You suddenly find yourself somewhere else!</span>")
if(!active_mind_control) //Do not reset entangled mob while mind control is active
entangled_mob = null
/obj/item/organ/heart/gland/quantum/mind_control(command, mob/living/user)
if(..())
if(entangled_mob && ishuman(entangled_mob) && (entangled_mob.stat < DEAD))
to_chat(entangled_mob, "<span class='userdanger'>You suddenly feel an irresistible compulsion to follow an order...</span>")
to_chat(entangled_mob, "<span class='mind_control'>[command]</span>")
var/obj/screen/alert/mind_control/mind_alert = entangled_mob.throw_alert("mind_control", /obj/screen/alert/mind_control)
mind_alert.command = command
message_admins("[key_name(owner)] mirrored an abductor mind control message to [key_name(entangled_mob)]: [command]")
update_gland_hud()
/obj/item/organ/heart/gland/quantum/clear_mind_control()
if(active_mind_control)
to_chat(entangled_mob, "<span class='userdanger'>You feel the compulsion fade, and you completely forget about your previous orders.</span>")
entangled_mob.clear_alert("mind_control")
..()

View File

@@ -0,0 +1,21 @@
/obj/item/organ/heart/gland/slime
true_name = "gastric animation galvanizer"
cooldown_low = 600
cooldown_high = 1200
uses = -1
icon_state = "slime"
mind_control_uses = 1
mind_control_duration = 2400
/obj/item/organ/heart/gland/slime/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
owner.faction |= "slime"
owner.grant_language(/datum/language/slime)
/obj/item/organ/heart/gland/slime/activate()
to_chat(owner, "<span class='warning'>You feel nauseated!</span>")
owner.vomit(20)
var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey")
Slime.Friends = list(owner)
Slime.Leader = owner

View File

@@ -0,0 +1,14 @@
/obj/item/organ/heart/gland/spiderman
true_name = "araneae cloister accelerator"
cooldown_low = 450
cooldown_high = 900
uses = -1
icon_state = "spider"
mind_control_uses = 2
mind_control_duration = 2400
/obj/item/organ/heart/gland/spiderman/activate()
to_chat(owner, "<span class='warning'>You feel something crawling in your skin.</span>")
owner.faction |= "spiders"
var/obj/structure/spider/spiderling/S = new(owner.drop_location())
S.directive = "Protect your nest inside [owner.real_name]."

View File

@@ -0,0 +1,15 @@
/obj/item/organ/heart/gland/transform
true_name = "anthropmorphic transmorphosizer"
cooldown_low = 900
cooldown_high = 1800
uses = -1
human_only = TRUE
icon_state = "species"
mind_control_uses = 7
mind_control_duration = 300
/obj/item/organ/heart/gland/transform/activate()
to_chat(owner, "<span class='notice'>You feel unlike yourself.</span>")
randomize_human(owner)
var/species = pick(list(/datum/species/human, /datum/species/lizard, /datum/species/insect, /datum/species/fly))
owner.set_species(species)

View File

@@ -0,0 +1,18 @@
/obj/item/organ/heart/gland/trauma
true_name = "white matter randomiser"
cooldown_low = 800
cooldown_high = 1200
uses = 5
icon_state = "emp"
mind_control_uses = 3
mind_control_duration = 1800
/obj/item/organ/heart/gland/trauma/activate()
to_chat(owner, "<span class='warning'>You feel a spike of pain in your head.</span>")
if(prob(33))
owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
if(prob(20))
owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
else
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))

View File

@@ -0,0 +1,12 @@
/obj/item/organ/heart/gland/ventcrawling
true_name = "pliant cartilage enabler"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "vent"
mind_control_uses = 4
mind_control_duration = 1800
/obj/item/organ/heart/gland/ventcrawling/activate()
to_chat(owner, "<span class='notice'>You feel very stretchy.</span>")
owner.ventcrawler = VENTCRAWLER_ALWAYS

View File

@@ -0,0 +1,34 @@
/obj/item/organ/heart/gland/viral
true_name = "contamination incubator"
cooldown_low = 1800
cooldown_high = 2400
uses = 1
icon_state = "viral"
mind_control_uses = 1
mind_control_duration = 1800
/obj/item/organ/heart/gland/viral/activate()
to_chat(owner, "<span class='warning'>You feel sick.</span>")
var/datum/disease/advance/A = random_virus(pick(2,6),6)
A.carrier = TRUE
owner.ForceContractDisease(A, FALSE, TRUE)
/obj/item/organ/heart/gland/viral/proc/random_virus(max_symptoms, max_level)
if(max_symptoms > VIRUS_SYMPTOM_LIMIT)
max_symptoms = VIRUS_SYMPTOM_LIMIT
var/datum/disease/advance/A = new /datum/disease/advance()
var/list/datum/symptom/possible_symptoms = list()
for(var/symptom in subtypesof(/datum/symptom))
var/datum/symptom/S = symptom
if(initial(S.level) > max_level)
continue
if(initial(S.level) <= 0) //unobtainable symptoms
continue
possible_symptoms += S
for(var/i in 1 to max_symptoms)
var/datum/symptom/chosen_symptom = pick_n_take(possible_symptoms)
if(chosen_symptom)
var/datum/symptom/S = new chosen_symptom
A.symptoms += S
A.Refresh() //just in case someone already made and named the same disease
return A

View File

@@ -43,12 +43,15 @@
dat += "Collected Samples : [points] <br>"
dat += "Gear Credits: [credits] <br>"
dat += "<b>Transfer data in exchange for supplies:</b><br>"
dat += "<a href='?src=[REF(src)];dispense=baton'>Advanced Baton</A><br>"
dat += "<a href='?src=[REF(src)];dispense=helmet'>Agent Helmet</A><br>"
dat += "<a href='?src=[REF(src)];dispense=vest'>Agent Vest</A><br>"
dat += "<a href='?src=[REF(src)];dispense=silencer'>Radio Silencer</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tool'>Science Tool</A><br>"
dat += "<a href='?src=[REF(src)];dispense=mind_device'>Mental Interface Device</A><br>"
dat += "<a href='?src=[REF(src)];dispense=baton'>Advanced Baton (2 Credits)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=mind_device'>Mental Interface Device (2 Credits)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=chem_dispenser'>Reagent Synthesizer (2 Credits)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=shrink_ray'>Shrink Ray Blaster (2 Credits)</a><br>"
dat += "<a href='?src=[REF(src)];dispense=helmet'>Agent Helmet (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=vest'>Agent Vest (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=silencer'>Radio Silencer (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tool'>Science Tool (1 Credit)</A><br>"
dat += "<a href='?src=[REF(src)];dispense=tongue'>Superlingual Matrix (1 Credit)</a><br>"
else
dat += "<span class='bad'>NO EXPERIMENT MACHINE DETECTED</span> <br>"
@@ -101,7 +104,7 @@
else if(href_list["dispense"])
switch(href_list["dispense"])
if("baton")
Dispense(/obj/item/abductor_baton,cost=2)
Dispense(/obj/item/abductor/baton,cost=2)
if("helmet")
Dispense(/obj/item/clothing/head/helmet/abductor)
if("silencer")
@@ -112,6 +115,12 @@
Dispense(/obj/item/clothing/suit/armor/abductor/vest)
if("mind_device")
Dispense(/obj/item/abductor/mind_device,cost=2)
if("chem_dispenser")
Dispense(/obj/item/abductor_machine_beacon/chem_dispenser,cost=2)
if("tongue")
Dispense(/obj/item/organ/tongue/abductor)
if("shrink_ray")
Dispense(/obj/item/gun/energy/shrink_ray,cost=2)
updateUsrDialog()
/obj/machinery/abductor/console/proc/TeleporterRetrieve()
@@ -136,9 +145,9 @@
var/entry_name
if(remote)
entry_name = show_radial_menu(usr, camera.eyeobj, disguises2)
entry_name = show_radial_menu(usr, camera.eyeobj, disguises2, tooltips = TRUE)
else
entry_name = show_radial_menu(usr, src, disguises2)
entry_name = show_radial_menu(usr, src, disguises2, require_near = TRUE, tooltips = TRUE)
var/datum/icon_snapshot/chosen = disguises[entry_name]
if(chosen && vest && (remote || in_range(usr,src)))
@@ -236,4 +245,4 @@
new item(drop_location)
else
say("Insufficent data!")
say("Insufficent data!")

View File

@@ -77,13 +77,16 @@
for(var/mob/living/M in viewers(5, src))
if(!is_servant_of_ratvar(M) && M != L)
M.flash_act()
if(iscultist(L))
if(iscultist(L)) //No longer stuns cultists, instead sets them on fire and burns them
to_chat(L, "<span class='heavy_brass'>\"Watch your step, wretch.\"</span>")
L.adjustBruteLoss(10)
L.Knockdown(80, FALSE)
L.adjustFireLoss(10)
L.Knockdown(20, FALSE)
L.adjust_fire_stacks(5) //Burn!
L.IgniteMob()
else
L.Stun(40)
L.visible_message("<span class='warning'>[src] appears around [L] in a burst of light!</span>", \
"<span class='userdanger'>[target_flashed ? "An unseen force":"The glowing sigil around you"] holds you in place!</span>")
L.Stun(40)
"<span class='userdanger'>[target_flashed ? "An unseen force":"The glowing sigil around you"] [iscultist(L) ? "painfully bursts into flames!" : "holds you in place!"]</span>")
L.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
new /obj/effect/temp_visual/ratvar/sigil/transgression(get_turf(src))
qdel(src)

View File

@@ -193,15 +193,26 @@
L.visible_message("<span class='warning'>[L]'s eyes flare with dim light!</span>")
playsound(L, 'sound/weapons/sear.ogg', 50, TRUE)
else
L.visible_message("<span class='warning'>[L]'s eyes blaze with brilliant light!</span>", \
"<span class='userdanger'>Your vision suddenly screams with white-hot light!</span>")
L.Knockdown(15, TRUE, FALSE, 15)
L.apply_status_effect(STATUS_EFFECT_KINDLE)
L.flash_act(1, 1)
if(issilicon(target))
var/mob/living/silicon/S = L
S.emp_act(EMP_HEAVY)
if(iscultist(L))
if(!iscultist(L))
L.visible_message("<span class='warning'>[L]'s eyes blaze with brilliant light!</span>", \
"<span class='userdanger'>Your vision suddenly screams with white-hot light!</span>")
L.Knockdown(15, TRUE, FALSE, 15)
L.apply_status_effect(STATUS_EFFECT_KINDLE)
L.flash_act(1, 1)
if(issilicon(target))
var/mob/living/silicon/S = L
S.emp_act(EMP_HEAVY)
else //for Nar'sian weaklings
to_chat(L, "<span class='heavy_brass'>\"How does it feel to see the light, dog?\"</span>")
L.visible_message("<span class='warning'>[L]'s eyes flare with burning light!</span>", \
"<span class='userdanger'>Your vision suddenly screams with a flash of burning hot light!</span>") //Debuffs Narsian cultists hard + deals some burn instead of just hardstunning them; Only the confusion part can stack
L.flash_act(1,1)
if(iscarbon(target))
var/mob/living/carbon/C = L
C.stuttering = max(8, C.stuttering)
C.drowsyness = max(8, C.drowsyness)
C.confused += CLAMP(16 - C.confused, 0, 8)
C.apply_status_effect(STATUS_EFFECT_BELLIGERENT)
L.adjustFireLoss(15)
..()

View File

@@ -56,8 +56,14 @@
L.visible_message("<span class='warning'>[src] bounces off of [L], as if repelled by an unseen force!</span>")
else if(!..())
if(!L.anti_magic_check())
if(issilicon(L) || iscultist(L))
if(issilicon(L))
L.Knockdown(100)
else if(iscultist(L))
L.confused += CLAMP(10 - L.confused, 0, 5) // Spearthrow now confuses enemy cultists + just deals extra damage / sets on fire instead of hardstunning + damage
to_chat(L, "<span class ='userdanger'>[src] crashes into you with burning force, sending you reeling!</span>")
L.adjust_fire_stacks(2)
L.Knockdown(1)
L.IgniteMob()
else
L.Knockdown(40)
GLOB.clockwork_vitality += L.adjustFireLoss(bonus_burn * 3) //normally a total of 40 damage, 70 with ratvar

View File

@@ -1,5 +1,7 @@
#define MARAUDER_SLOWDOWN_PERCENTAGE 0.40 //Below this percentage of health, marauders will become slower
#define MARAUDER_SHIELD_REGEN_TIME 200 //In deciseconds, how long it takes for shields to regenerate after breaking
#define MARAUDER_SPACE_FULL_DAMAGE 6 //amount of damage per life tick while inside space
#define MARAUDER_SPACE_NEAR_DAMAGE 4 //amount of damage taking per Life() tick from being next to space.
//Clockwork marauder: A well-rounded frontline construct. Only one can exist for every two human servants.
/mob/living/simple_animal/hostile/clockwork/marauder
@@ -20,12 +22,14 @@
movement_type = FLYING
a_intent = INTENT_HARM
loot = list(/obj/item/clockwork/component/geis_capacitor/fallen_armor)
light_range = 2
light_power = 1.1
light_range = 3
light_power = 1.7
playstyle_string = "<span class='big bold'><span class='neovgre'>You are a clockwork marauder,</span></span><b> a well-rounded frontline construct of Ratvar. Although you have no \
unique abilities, you're a fearsome fighter in one-on-one combat, and your shield protects from projectiles!<br><br>Obey the Servants and do as they \
tell you. Your primary goal is to defend the Ark from destruction; they are your allies in this, and should be protected from harm.</b>"
tell you. Your primary goal is to defend the Ark from destruction; they are your allies in this, and should be protected from harm.</b> \
<span class='danger big'>Be warned, however, that you will rapidly decay near the void of space.</span>"
empower_string = "<span class='neovgre'>The Anima Bulwark's power flows through you! Your weapon will strike harder, your armor is sturdier, and your shield is more durable.</span>"
var/default_speed = 0
var/max_shield_health = 3
var/shield_health = 3 //Amount of projectiles that can be deflected within
var/shield_health_regen = 0 //When world.time equals this, shield health will regenerate
@@ -36,10 +40,21 @@
/mob/living/simple_animal/hostile/clockwork/marauder/Life()
..()
var/turf/T = get_turf(src)
var/turf/open/space/S = isspaceturf(T)? T : null
var/less_space_damage
if(!istype(S))
var/turf/open/space/nearS = locate() in oview(1)
if(nearS)
S = nearS
less_space_damage = TRUE
if(S)
to_chat(src, "<span class='userdanger'>The void of space drains Ratvar's Light from you! You feel yourself rapidly decaying. It would be wise to get back inside!</span>")
adjustBruteLoss(less_space_damage? MARAUDER_SPACE_NEAR_DAMAGE : MARAUDER_SPACE_FULL_DAMAGE)
if(!GLOB.ratvar_awakens && health / maxHealth <= MARAUDER_SLOWDOWN_PERCENTAGE)
speed = initial(speed) + 1 //Yes, this slows them down
speed = default_speed + 1 //Yes, this slows them down
else
speed = initial(speed)
speed = default_speed
if(shield_health < max_shield_health && world.time >= shield_health_regen)
shield_health_regen = world.time + MARAUDER_SHIELD_REGEN_TIME
to_chat(src, "<span class='neovgre'>Your shield has recovered, <b>[shield_health]</b> blocks remaining!</span>")

View File

@@ -87,9 +87,22 @@
object_path = /obj/item/clockwork/construct_chassis/clockwork_marauder
construct_type = /mob/living/simple_animal/hostile/clockwork/marauder
combat_construct = TRUE
var/static/recent_marauders = 0
var/static/time_since_last_marauder = 0
var/static/scaled_recital_time = 0
var/static/last_marauder = 0
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/post_recital()
last_marauder = world.time
return ..()
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/pre_recital()
if(!is_reebe(invoker.z))
if(!CONFIG_GET(flag/allow_clockwork_marauder_on_station))
to_chat(invoker, "<span class='brass'>This particular station is too far from the influence of the Hierophant Network. You can not summon a marauder here.</span>")
return FALSE
if(world.time < (last_marauder + CONFIG_GET(number/marauder_delay_non_reebe)))
to_chat(invoker, "<span class='brass'>The hierophant network is still strained from the last summoning of a marauder on a plane without the strong energy connection of Reebe to support it. \
You must wait another [DisplayTimeText((last_marauder + CONFIG_GET(number/marauder_delay_non_reebe)) - world.time, TRUE)]!</span>")
return FALSE
return ..()
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/update_construct_limit()
var/human_servants = 0
@@ -98,27 +111,7 @@
var/mob/living/L = M.current
if(ishuman(L) && L.stat != DEAD)
human_servants++
construct_limit = round(CLAMP((human_servants / 4), 1, 3)) - recent_marauders //1 per 4 human servants, maximum of 3, reduced by recent marauder creation
if(recent_marauders)
to_chat(invoker, "<span class='warning'>The Hierophant Network is depleted by a summoning in the last [DisplayTimeText(MARAUDER_SCRIPTURE_SCALING_THRESHOLD, TRUE)] - limiting the number of available marauders by [recent_marauders]!</span>")
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/pre_recital()
channel_time = initial(channel_time)
if(recent_marauders)
scaled_recital_time = min(recent_marauders * MARAUDER_SCRIPTURE_SCALING_TIME, MARAUDER_SCRIPTURE_SCALING_MAX)
to_chat(invoker, "<span class='warning'>The Hierophant Network is under strain from repeated summoning, making this scripture [DisplayTimeText(scaled_recital_time)] slower!</span>")
channel_time += scaled_recital_time
return TRUE
/datum/clockwork_scripture/create_object/construct/clockwork_marauder/scripture_effects()
. = ..()
recent_marauders++
addtimer(CALLBACK(GLOBAL_PROC, .proc/marauder_reset),MARAUDER_SCRIPTURE_SCALING_THRESHOLD)
/proc/marauder_reset()
var/datum/clockwork_scripture/create_object/construct/clockwork_marauder/CM = new()
CM.recent_marauders--
qdel(CM)
construct_limit = round(CLAMP((human_servants / 4), 1, 3)) //1 per 4 human servants, maximum of 3
//Summon Neovgre: Summon a very powerful combat mech that explodes when destroyed for massive damage.
/datum/clockwork_scripture/create_object/summon_arbiter

View File

@@ -438,21 +438,27 @@
target.visible_message("<span class='warning'>[L] starts to glow in a halo of light!</span>", \
"<span class='userdanger'>A feeling of warmth washes over you, rays of holy light surround your body and protect you from the flash of light!</span>")
else
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] falls to the ground!</span>")
L.Knockdown(160)
L.adjustStaminaLoss(140) //Ensures hard stamcrit
L.flash_act(1,1)
if(issilicon(target))
var/mob/living/silicon/S = L
S.emp_act(EMP_HEAVY)
else if(iscarbon(target))
var/mob/living/carbon/C = L
C.silent += 6
C.stuttering += 15
C.cultslurring += 15
C.Jitter(15)
if(is_servant_of_ratvar(L))
if(!iscultist(L))
L.Knockdown(160)
L.adjustStaminaLoss(140) //Ensures hard stamcrit
L.flash_act(1,1)
if(issilicon(target))
var/mob/living/silicon/S = L
S.emp_act(EMP_HEAVY)
else if(iscarbon(target))
var/mob/living/carbon/C = L
C.silent += CLAMP(12 - C.silent, 0, 6)
C.stuttering += CLAMP(30 - C.stuttering, 0, 15)
C.cultslurring += CLAMP(30 - C.cultslurring, 0, 15)
C.Jitter(15)
else // cultstun no longer hardstuns + damages hostile cultists, instead debuffs them hard + deals some damage; debuffs for a bit longer since they don't add the clockie belligerent debuff
if(iscarbon(target))
var/mob/living/carbon/C = L
C.stuttering = max(10, C.stuttering)
C.drowsyness = max(10, C.drowsyness)
C.confused += CLAMP(20 - C.confused, 0, 10)
L.adjustBruteLoss(15)
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] [iscultist(L) ? "writhes in pain" : "falls to the ground!"]</span>")
uses--
..()

View File

@@ -703,7 +703,10 @@
else if(!..())
if(!L.anti_magic_check())
if(is_servant_of_ratvar(L))
L.Knockdown(100)
to_chat(L, "<span class='cultlarge'>\"Kneel for me, scum\"</span>")
L.confused += CLAMP(10 - L.confused, 0, 5) //confuses and lightly knockdowns + damages hostile cultists instead of hardstunning like before
L.Knockdown(15)
L.adjustBruteLoss(10)
else
L.Knockdown(50)
break_spear(T)

View File

@@ -34,6 +34,12 @@
. = ..()
name_source = GLOB.commando_names
/datum/antagonist/ert/deathsquad/apply_innate_effects(mob/living/mob_override)
ADD_TRAIT(owner, TRAIT_DISK_VERIFIER, DEATHSQUAD_TRAIT)
/datum/antagonist/ert/deathsquad/remove_innate_effects(mob/living/mob_override)
REMOVE_TRAIT(owner, TRAIT_DISK_VERIFIER, DEATHSQUAD_TRAIT)
/datum/antagonist/ert/security // kinda handled by the base template but here for completion
/datum/antagonist/ert/security/amber

View File

@@ -611,10 +611,7 @@ This is here to make the tiles around the station mininuke change when it's arme
if(!fake)
return
var/ghost = isobserver(user)
var/captain = user.mind && user.mind.assigned_role == "Captain"
var/nukie = user.mind && user.mind.has_antag_datum(/datum/antagonist/nukeop)
if(ghost || captain || nukie)
if(isobserver(user) || HAS_TRAIT(user, TRAIT_DISK_VERIFIER) || (user.mind && HAS_TRAIT(user.mind, TRAIT_DISK_VERIFIER)))
. += "<span class='warning'>The serial numbers on [src] are incorrect.</span>"
/obj/item/disk/nuclear/attackby(obj/item/I, mob/living/user, params)
@@ -653,3 +650,7 @@ This is here to make the tiles around the station mininuke change when it's arme
/obj/item/disk/nuclear/fake
fake = TRUE
/obj/item/disk/nuclear/fake/obvious
name = "cheap plastic imitation of the nuclear authentication disk"
desc = "How anyone could mistake this for the real thing is beyond you."

View File

@@ -23,10 +23,12 @@
/datum/antagonist/nukeop/apply_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_synd_icons_added(M)
ADD_TRAIT(owner, TRAIT_DISK_VERIFIER, NUKEOP_TRAIT)
/datum/antagonist/nukeop/remove_innate_effects(mob/living/mob_override)
var/mob/living/M = mob_override || owner.current
update_synd_icons_removed(M)
REMOVE_TRAIT(owner, TRAIT_DISK_VERIFIER, NUKEOP_TRAIT)
/datum/antagonist/nukeop/proc/equip_op()
if(!ishuman(owner.current))
@@ -42,7 +44,6 @@
owner.current.playsound_local(get_turf(owner.current), 'sound/ambience/antag/ops.ogg',100,0)
to_chat(owner, "<span class='notice'>You are a [nuke_team ? nuke_team.syndicate_name : "syndicate"] agent!</span>")
owner.announce_objectives()
return
/datum/antagonist/nukeop/on_gain()
give_alias()

View File

@@ -1,8 +1,8 @@
/datum/round_event_control/spawn_swarmer
name = "Spawn Swarmer Shell"
typepath = /datum/round_event/spawn_swarmer
weight = 7
max_occurrences = 1 //Only once okay fam
weight = 0
max_occurrences = 0
earliest_start = 30 MINUTES
min_players = 15

View File

@@ -505,6 +505,7 @@ GLOBAL_LIST_INIT(blacklisted_malf_machines, typecacheof(list(
if(!is_station_level(F.z))
continue
F.obj_flags |= EMAGGED
F.update_icon()
to_chat(owner, "<span class='notice'>All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.</span>")
owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, 0)

View File

@@ -177,6 +177,10 @@
owner.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/mind_transfer(null))
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap.")
if(APPRENTICE_MARTIAL)
owner.AddSpell(new /obj/effect/proc_holder/spell/targeted/touch/nuclear_fist(null))
H.put_in_hands(new /obj/item/book/granter/martial/plasma_fist(H))
to_chat(owner, "<B>Your service has not gone unrewarded, however. Studying under [master.current.real_name], you have learned mystical martial abilities. You are also able to use the Nuclear Fist at will.")
/datum/antagonist/wizard/apprentice/create_objectives()
var/datum/objective/protect/new_objective = new /datum/objective/protect

View File

@@ -154,6 +154,11 @@
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
var/target_temperature
var/target_heat_capacity
// first calculate heat from radiation. there's an implied "* 1 tick" here.
// 0.05 magic multiplicand is, first, 0.1 deciseconds; second, half of the radiation's going right back into the gas.
var/share_constant = STEFANBOLTZMANN*(share_volume**(2/3))*0.05
// Minimizing temp to 4 billion is mostly to prevent -infinity temperatures.
var/heat = share_constant*(min(air.temperature,4000000000)**4)
if(isopenturf(target))
@@ -165,8 +170,8 @@
if((modeled_location.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.temperature - target_temperature
var/heat = thermal_conductivity*delta_temperature* \
heat -= share_constant*(min(target_temperature,4000000000)**4)
heat += thermal_conductivity*delta_temperature* \
(partial_heat_capacity*target_heat_capacity/(partial_heat_capacity+target_heat_capacity))
air.temperature -= heat/total_heat_capacity
@@ -183,7 +188,8 @@
var/sharer_temperature_delta = 0
if((sharer_heat_capacity>0) && (partial_heat_capacity>0))
var/heat = thermal_conductivity*delta_temperature* \
heat -= share_constant*(min(target_temperature,4000000000)**4)
heat += thermal_conductivity*delta_temperature* \
(partial_heat_capacity*sharer_heat_capacity/(partial_heat_capacity+sharer_heat_capacity))
self_temperature_delta = -heat/total_heat_capacity
@@ -199,10 +205,12 @@
if((target.heat_capacity>0) && (partial_heat_capacity>0))
var/delta_temperature = air.temperature - target.temperature
var/heat = thermal_conductivity*delta_temperature* \
heat -= share_constant*(min(target.temperature,4000000000)**4)
heat += thermal_conductivity*delta_temperature* \
(partial_heat_capacity*target.heat_capacity/(partial_heat_capacity+target.heat_capacity))
air.temperature -= heat/total_heat_capacity
air.temperature = CLAMP(air.temperature,TCMB,INFINITY) // i have no idea why TCMB needs to be the min but i ain't changing it
update = TRUE
/datum/pipeline/proc/return_air()

View File

@@ -26,9 +26,7 @@
var/turf/T = loc
if(istype(T))
if(islava(T))
environment_temperature = 5000
else if(T.blocks_air)
if(T.blocks_air)
environment_temperature = T.temperature
else
var/turf/open/OT = T

View File

@@ -14,7 +14,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
//doohickeys for savefiles
var/path
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
var/max_save_slots = 8
var/max_save_slots = 16
//non-preference stuff
var/muted = 0
@@ -217,7 +217,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
load_path(C.ckey)
unlock_content = C.IsByondMember()
if(unlock_content)
max_save_slots = 16
max_save_slots = 24
var/loaded_preferences_successfully = load_preferences()
if(loaded_preferences_successfully)
if(load_character())

View File

@@ -309,4 +309,4 @@
//The "pocket" for the M1 helmet so you can tuck things into the elastic band
/datum/component/storage/concrete/pockets/tiny/spacenam
attack_hand_interact = TRUE //So you can actually see what you stuff in there
attack_hand_interact = TRUE //So you can actually see what you stuff in there

View File

@@ -212,7 +212,7 @@
icon_state = "hardsuit0-white"
item_state = "ce_helm"
item_color = "white"
armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 90, "fire" = 100, "acid" = 90)
armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 90)
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
@@ -221,7 +221,7 @@
name = "advanced hardsuit"
desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish."
item_state = "ce_hardsuit"
armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 90, "fire" = 100, "acid" = 90)
armor = list("melee" = 40, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 50, "bio" = 100, "rad" = 95, "fire" = 100, "acid" = 90)
heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS
max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/engine/elite

View File

@@ -50,7 +50,8 @@
icon_state = "reactiveoff"
item_state = "reactiveoff"
add_fingerprint(user)
return
if(user.get_item_by_slot(SLOT_WEAR_SUIT) == src)
user.update_inv_wear_suit()
/obj/item/clothing/suit/armor/reactive/emp_act(severity)
. = ..()
@@ -71,8 +72,9 @@
reactivearmor_cooldown_duration = 100
/obj/item/clothing/suit/armor/reactive/teleport/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
. = FALSE
if(!active)
return 0
return
if(prob(hit_reaction_chance))
var/mob/living/carbon/human/H = owner
if(world.time < reactivearmor_cooldown)
@@ -95,12 +97,11 @@
var/turf/picked = pick(turfs)
if(!isturf(picked))
return
H.forceMove(picked)
do_teleport(H, picked, no_effects = TRUE, channel = TELEPORT_CHANNEL_WORMHOLE)
radiation_pulse(old, rad_amount_before)
radiation_pulse(src, rad_amount)
reactivearmor_cooldown = world.time + reactivearmor_cooldown_duration
return 1
return 0
return TRUE
//Fire

View File

@@ -163,26 +163,7 @@
name = "Cosmic Winter Coat"
result = /obj/item/clothing/suit/hooded/wintercoat/cosmic
reqs = list(/obj/item/clothing/suit/hooded/wintercoat = 1,
/obj/item/clothing/suit/hooded/wintercoat/captain = 1,
/obj/item/clothing/suit/hooded/wintercoat/hop = 1,
/obj/item/clothing/suit/hooded/wintercoat/hos = 1,
/obj/item/clothing/suit/hooded/wintercoat/rd = 1,
/obj/item/clothing/suit/hooded/wintercoat/ce = 1,
/obj/item/clothing/suit/hooded/wintercoat/cmo = 1,
/obj/item/clothing/suit/hooded/wintercoat/qm = 1,
/obj/item/clothing/suit/hooded/wintercoat/robotics = 1,
/obj/item/clothing/suit/hooded/wintercoat/engineering/atmos = 1,
/obj/item/clothing/suit/hooded/wintercoat/engineering = 1,
/obj/item/clothing/suit/hooded/wintercoat/science = 1,
/obj/item/clothing/suit/hooded/wintercoat/genetics = 1,
/obj/item/clothing/suit/hooded/wintercoat/chemistry = 1,
/obj/item/clothing/suit/hooded/wintercoat/medical = 1,
/obj/item/clothing/suit/hooded/wintercoat/viro = 1,
/obj/item/clothing/suit/hooded/wintercoat/janitor = 1,
/obj/item/clothing/suit/hooded/wintercoat/security = 1,
/obj/item/clothing/suit/hooded/wintercoat/cargo = 1,
/obj/item/clothing/suit/hooded/wintercoat/hydro = 1,
/obj/item/clothing/suit/hooded/wintercoat/miner = 1)
/obj/item/bedsheet/cosmos = 1)
time = 60
always_availible = TRUE
category = CAT_CLOTHING

View File

@@ -132,14 +132,10 @@
transfer_fingerprints_to(B)
qdel(src)
////////////////////////////////////////////////////////////////////////////////
/// Drinks. END
////////////////////////////////////////////////////////////////////////////////
/obj/item/reagent_containers/food/drinks/trophy
name = "pewter cup"
desc = "Everyone gets a trophy."
@@ -178,7 +174,6 @@
materials = list(MAT_SILVER=800)
volume = 100
/obj/item/reagent_containers/food/drinks/trophy/bronze_cup
name = "bronze cup"
desc = "At least you ranked!"
@@ -190,7 +185,7 @@
materials = list(MAT_METAL=400)
volume = 25
///////////////////////////////////////////////Drinks
///////////////////////////////////////////////Drinks/////////////////////////////////////////
//Notes by Darem: Drinks are simply containers that start preloaded. Unlike condiments, the contents can be ingested directly
// rather then having to add it to something else first. They should only contain liquids. They have a default container size of 50.
// Formatting is the same as food.
@@ -355,8 +350,7 @@
desc = "A small carton, intended for holding drinks."
//////////////////////////drinkingglass and shaker//
//////////////////////////drinkingglass and shaker/////////////////////////////////////////////////////////////////////////////////////
//Note by Darem: This code handles the mixing of drinks. New drinks go in three places: In Chemistry-Reagents.dm (for the drink
// itself), in Chemistry-Recipes.dm (for the reaction that changes the components into the drink), and here (for the drinking glass
// icon states.
@@ -397,8 +391,8 @@
volume = 30
spillable = TRUE
//////////////////////////soda_cans//
//These are in their own group to be used as IED's in /obj/item/grenade/ghettobomb.dm
//////////////////////////soda_cans////////////////////////////////////////////////////
//These are in their own group to be used as IED's in /obj/item/grenade/ghettobomb.dm//
/obj/item/reagent_containers/food/drinks/soda_cans
name = "soda can"
@@ -424,7 +418,6 @@
qdel(src)
..()
/obj/item/reagent_containers/food/drinks/soda_cans/attack_self(mob/user)
if(!is_drainable())
to_chat(user, "You pull back the tab of \the [src] with a satisfying pop.") //Ahhhhhhhh
@@ -513,6 +506,13 @@
list_reagents = list("shamblers" = 30)
foodtype = SUGAR | JUNKFOOD
/obj/item/reagent_containers/food/drinks/soda_cans/buzz_fuzz
name = "Buzz Fuzz"
desc = "The sister drink of Shambler's Juice! Uses real honey, making it a sweet tooth's dream drink. The slogan reads ''A Hive of Flavour'', there's also a label about how it is adddicting."
icon_state = "honeysoda_can"
list_reagents = list("buzz_fuzz" = 25, "honey" = 5)
foodtype = SUGAR | JUNKFOOD
/obj/item/reagent_containers/food/drinks/soda_cans/grey_bull
name = "Grey Bull"
desc = "Grey Bull, it gives you gloves!"

View File

@@ -159,6 +159,28 @@
tastes = list("brains" = 1, "meat" = 1)
foodtype = RAW | MEAT | TOXIC
/obj/item/reagent_containers/food/snacks/carpmeat/aquatic
name = "fillet"
desc = "A fillet of one of the local water dwelling species."
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
icon_state = "ipcmeat"
desc = "Gross robot meat."
filling_color = "#000000"
tastes = list("metal" = 1)
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/avian
desc = "Tastes like chicken, that's because it is!"
icon_state = "birdmeat"
filling_color = "#BF896B"
tastes = list("chicken" = 1)
/obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/mammal
desc = "Tastes sweet... reminds you vaguely of chicken."
filling_color = "#6B8E23"
tastes = list("brains" = 1, "meat" = 1)
////////////////////////////////////// OTHER MEATS ////////////////////////////////////////////////////////

View File

@@ -80,6 +80,9 @@ God bless America.
I.reagents.trans_to(src, I.reagents.total_volume)
qdel(I)
return
if(istype(I,/obj/item/clothing/head/mob_holder))
to_chat(user, "<span class='warning'>This does not fit in the fryer.</span>") // TODO: Deepfrying instakills mobs, spawns a whole deep-fried mob.
return
if(!reagents.has_reagent("cooking_oil"))
to_chat(user, "<span class='warning'>[src] has no cooking oil to fry with!</span>")
return

View File

@@ -380,7 +380,11 @@
pestlevel = 0 // Reset
update_icon()
visible_message("<span class='warning'>The [oldPlantName] is overtaken by some [myseed.plantname]!</span>")
name = "hydroponics tray ([myseed.plantname])"
if(myseed.product)
desc = initial(myseed.product.desc)
else
desc = initial(desc)
/obj/machinery/hydroponics/proc/mutate(lifemut = 2, endmut = 5, productmut = 1, yieldmut = 2, potmut = 25, wrmut = 2, wcmut = 5, traitmut = 0) // Mutates the current seed
if(!myseed)
@@ -414,7 +418,11 @@
sleep(5) // Wait a while
update_icon()
visible_message("<span class='warning'>[oldPlantName] suddenly mutates into [myseed.plantname]!</span>")
name = "hydroponics tray ([myseed.plantname])"
if(myseed.product)
desc = initial(myseed.product.desc)
else
desc = initial(desc)
/obj/machinery/hydroponics/proc/mutateweed() // If the weeds gets the mutagent instead. Mind you, this pretty much destroys the old plant
if( weedlevel > 5 )
@@ -524,7 +532,7 @@
if(S.has_reagent("charcoal", 1))
adjustToxic(-round(S.get_reagent_amount("charcoal") * 2))
// NIGGA, YOU JUST WENT ON FULL RETARD.
// Toxins, not good for anything
if(S.has_reagent("toxin", 1))
adjustToxic(round(S.get_reagent_amount("toxin") * 2))
@@ -539,14 +547,14 @@
adjustNutri(round(S.get_reagent_amount("beer") * 0.25))
adjustWater(round(S.get_reagent_amount("beer") * 0.7))
// You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial
// Fluorine one of the most corrosive and deadly gasses
if(S.has_reagent("fluorine", 1))
adjustHealth(-round(S.get_reagent_amount("fluorine") * 2))
adjustToxic(round(S.get_reagent_amount("fluorine") * 2.5))
adjustWater(-round(S.get_reagent_amount("fluorine") * 0.5))
adjustWeeds(-rand(1,4))
// You're an idiot for thinking that one of the most corrosive and deadly gasses would be beneficial
// Chlorine one of the most corrosive and deadly gasses
if(S.has_reagent("chlorine", 1))
adjustHealth(-round(S.get_reagent_amount("chlorine") * 1))
adjustToxic(round(S.get_reagent_amount("chlorine") * 1.5))
@@ -561,7 +569,7 @@
adjustWater(-round(S.get_reagent_amount("phosphorus") * 0.5))
adjustWeeds(-rand(1,2))
// Plants should not have sugar, they can't use it and it prevents them getting water/ nutients, it is good for mold though...
// Plants should not have sugar, they can't use it and it prevents them getting water/nutients, it is good for mold though...
if(S.has_reagent("sugar", 1))
adjustWeeds(rand(1,2))
adjustPests(rand(1,2))
@@ -583,13 +591,13 @@
adjustHealth(round(S.get_reagent_amount("sodawater") * 0.1))
adjustNutri(round(S.get_reagent_amount("sodawater") * 0.1))
// Man, you guys are retards
// Sulphuric Acid
if(S.has_reagent("sacid", 1))
adjustHealth(-round(S.get_reagent_amount("sacid") * 1))
adjustToxic(round(S.get_reagent_amount("sacid") * 1.5))
adjustWeeds(-rand(1,2))
// SERIOUSLY
// Acid
if(S.has_reagent("facid", 1))
adjustHealth(-round(S.get_reagent_amount("facid") * 2))
adjustToxic(round(S.get_reagent_amount("facid") * 3))
@@ -601,7 +609,7 @@
adjustToxic(round(S.get_reagent_amount("plantbgone") * 6))
adjustWeeds(-rand(4,8))
// why, just why
// Napalm, not known for being good for anything organic
if(S.has_reagent("napalm", 1))
if(!(myseed.resistance_flags & FIRE_PROOF))
adjustHealth(-round(S.get_reagent_amount("napalm") * 6))
@@ -638,13 +646,14 @@
if (myseed)
myseed.adjust_production(-round(salt/100)-prob(salt%100))
myseed.adjust_potency(round(salt*0.5))
// Ash is also used IRL in gardening, as a fertilizer enhancer and weed killer
if(S.has_reagent("ash", 1))
adjustHealth(round(S.get_reagent_amount("ash") * 0.25))
adjustNutri(round(S.get_reagent_amount("ash") * 0.5))
adjustWeeds(-1)
// This is more bad ass, and pests get hurt by the corrosive nature of it, not the plant.
// Diethylamine is more bad ass, and pests get hurt by the corrosive nature of it, not the plant.
if(S.has_reagent("diethylamine", 1))
adjustHealth(round(S.get_reagent_amount("diethylamine") * 1))
adjustNutri(round(S.get_reagent_amount("diethylamine") * 2))
@@ -652,26 +661,37 @@
myseed.adjust_yield(round(S.get_reagent_amount("diethylamine") * 0.02))
adjustPests(-rand(1,2))
// Compost, effectively
// Nutriment Compost, effectively
if(S.has_reagent("nutriment", 1))
adjustHealth(round(S.get_reagent_amount("nutriment") * 0.5))
adjustNutri(round(S.get_reagent_amount("nutriment") * 1))
// Compost for EVERYTHING
// Virusfood Compost for EVERYTHING
if(S.has_reagent("virusfood", 1))
adjustNutri(round(S.get_reagent_amount("virusfood") * 0.5))
adjustHealth(-round(S.get_reagent_amount("virusfood") * 0.5))
// FEED ME
// Blood
if(S.has_reagent("blood", 1))
adjustNutri(round(S.get_reagent_amount("blood") * 1))
adjustPests(rand(2,4))
// FEED ME SEYMOUR
// Strange reagent
if(S.has_reagent("strangereagent", 1))
spawnplant()
// The best stuff there is. For testing/debugging.
// Honey, Pests are dieing of sugar, so is the plant
if(S.has_reagent("honey", 1))
adjustPests(-rand(2,5))
adjustHealth(-round(S.get_reagent_amount("honey") * 1))
// Buzz Fuzz, a drink seemingly made for plants...
if(S.has_reagent("buzz_fuzz", 1))
adjustPests(-rand(2,5))
adjustHealth(round(S.get_reagent_amount("buzz_fuzz") * 0.1))
adjustNutri(round(S.get_reagent_amount("buzz_fuzz") * 0.5))
// Adminordrazine the best stuff there is. For testing/debugging.
if(S.has_reagent("adminordrazine", 1))
adjustWater(round(S.get_reagent_amount("adminordrazine") * 1))
adjustHealth(round(S.get_reagent_amount("adminordrazine") * 1))
@@ -769,6 +789,15 @@
to_chat(user, "<span class='notice'>You plant [O].</span>")
dead = 0
myseed = O
name = "hydroponics tray ([myseed.plantname])"
if(!myseed.productdesc) //we haven't changed our produce's description
if(myseed.product)
myseed.productdesc = initial(myseed.product.desc)
else if(myseed.desc)
myseed.productdesc = myseed.desc
else
myseed.productdesc = "A fascinating specimen."
desc = myseed.productdesc
age = 1
plant_health = myseed.endurance
lastcycle = world.time
@@ -834,6 +863,8 @@
harvest = FALSE //To make sure they can't just put in another seed and insta-harvest it
qdel(myseed)
myseed = null
name = initial(name)
desc = initial(desc)
weedlevel = 0 //Has a side effect of cleaning up those nasty weeds
update_icon()
@@ -866,6 +897,8 @@
qdel(myseed)
myseed = null
update_icon()
name = initial(name)
desc = initial(desc)
else
if(user)
examine(user)
@@ -883,6 +916,8 @@
qdel(myseed)
myseed = null
dead = 0
name = initial(name)
desc = initial(desc)
update_icon()
/// Tray Setters - The following procs adjust the tray or plants variables, and make sure that the stat doesn't go out of bounds.///

View File

@@ -8,7 +8,8 @@
w_class = WEIGHT_CLASS_TINY
resistance_flags = FLAMMABLE
var/plantname = "Plants" // Name of plant when planted.
var/product // A type path. The thing that is created when the plant is harvested.
var/obj/item/product // A type path. The thing that is created when the plant is harvested.
var/productdesc
var/species = "" // Used to update icons. Should match the name in the sprites unless all icon_* are overridden.
var/growing_icon = 'icons/obj/hydroponics/growing.dmi' //the file that stores the sprites of the growing plant from this seed.
@@ -69,6 +70,10 @@
genes += new /datum/plant_gene/reagent(reag_id, reagents_add[reag_id])
reagents_from_genes() //quality coding
/obj/item/seeds/examine(mob/user)
. = ..()
. += "<span class='notice'>Use a pen on it to rename it or change its description.</span>"
/obj/item/seeds/proc/Copy()
var/obj/item/seeds/S = new type(null, 1)
// Copy all the stats
@@ -80,6 +85,10 @@
S.potency = potency
S.weed_rate = weed_rate
S.weed_chance = weed_chance
S.name = name
S.plantname = plantname
S.desc = desc
S.productdesc = productdesc
S.genes = list()
for(var/g in genes)
var/datum/plant_gene/G = g
@@ -157,11 +166,18 @@
var/product_name
while(t_amount < getYield())
var/obj/item/reagent_containers/food/snacks/grown/t_prod = new product(output_loc, src)
if(parent.myseed.plantname != initial(parent.myseed.plantname))
t_prod.name = lowertext(parent.myseed.plantname)
if(productdesc)
t_prod.desc = productdesc
t_prod.seed.name = parent.myseed.name
t_prod.seed.desc = parent.myseed.desc
t_prod.seed.plantname = parent.myseed.plantname
result.Add(t_prod) // User gets a consumable
if(!t_prod)
return
t_amount++
product_name = t_prod.name
product_name = parent.myseed.plantname
if(getYield() >= 1)
SSblackbox.record_feedback("tally", "food_harvested", getYield(), product_name)
parent.update_tray(user)
@@ -331,14 +347,56 @@
to_chat(user, "<span class='notice'>[text]</span>")
return
if(istype(O, /obj/item/pen))
var/choice = input("What would you like to change?") in list("Plant Name", "Seed Description", "Product Description", "Cancel")
if(!user.canUseTopic(src, BE_CLOSE))
return
switch(choice)
if("Plant Name")
var/newplantname = reject_bad_text(stripped_input(user, "Write a new plant name:", name, plantname))
if(!user.canUseTopic(src, BE_CLOSE))
return
if (length(newplantname) > 20)
to_chat(user, "That name is too long!")
return
if(!newplantname)
to_chat(user, "That name is invalid.")
return
else
name = "[lowertext(newplantname)]"
plantname = newplantname
if("Seed Description")
var/newdesc = stripped_input(user, "Write a new description:", name, desc)
if(!user.canUseTopic(src, BE_CLOSE))
return
if (length(newdesc) > 180)
to_chat(user, "That description is too long!")
return
if(!newdesc)
to_chat(user, "That description is invalid.")
return
else
desc = newdesc
if("Product Description")
if(product && !productdesc)
productdesc = initial(product.desc)
var/newproductdesc = stripped_input(user, "Write a new description:", name, productdesc)
if(!user.canUseTopic(src, BE_CLOSE))
return
if (length(newproductdesc) > 180)
to_chat(user, "That description is too long!")
return
if(!newproductdesc)
to_chat(user, "That description is invalid.")
return
else
productdesc = newproductdesc
else
return
..() // Fallthrough to item/attackby() so that bags can pick seeds up
// Checks plants for broken tray icons. Use Advanced Proc Call to activate.
// Maybe some day it would be used as unit test.
/proc/check_plants_growth_stages_icons()

View File

@@ -20,8 +20,7 @@
access = list() //See get_access()
minimal_access = list() //See get_access()
mind_traits = list(TRAIT_CAPTAIN_METABOLISM)
// mind_traits = list(TRAIT_DISK_VERIFIER)
mind_traits = list(TRAIT_CAPTAIN_METABOLISM, TRAIT_DISK_VERIFIER)
display_order = JOB_DISPLAY_ORDER_CAPTAIN

View File

@@ -3,18 +3,6 @@
if("R", "Southwest") // Southwest is End
toggle_throw_mode()
return
if("1")
a_intent_change("help")
return
if("2")
a_intent_change("disarm")
return
if("3")
a_intent_change("grab")
return
if("4")
a_intent_change("harm")
return
if("C")
toggle_combat_mode()
return

View File

@@ -3,5 +3,22 @@
if("B")
resist()
return
if("1")
if(possible_a_intents)
a_intent_change(INTENT_HELP)
return
if("2")
if(possible_a_intents)
a_intent_change(INTENT_DISARM)
return
if("3")
if(possible_a_intents)
a_intent_change(INTENT_GRAB)
return
if("4")
if(possible_a_intents)
a_intent_change(INTENT_HARM)
return
return ..()

View File

@@ -159,23 +159,34 @@
return
//END OF CIT CHANGES
var/atom/movable/thrown_thing
var/obj/item/I = src.get_active_held_item()
if(!I)
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
var/mob/living/throwable_mob = pulling
if(!throwable_mob.buckled)
thrown_thing = throwable_mob
var/atom/movable/thrown_thing
var/mob/living/throwable_mob
if(istype(I, /obj/item/clothing/head/mob_holder))
var/obj/item/clothing/head/mob_holder/holder = I
if(holder.held_mob)
throwable_mob = holder.held_mob
holder.release()
if(!I || throwable_mob)
if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
throwable_mob = pulling
if(throwable_mob && !throwable_mob.buckled)
thrown_thing = throwable_mob
if(pulling)
stop_pulling()
if(HAS_TRAIT(src, TRAIT_PACIFISM))
to_chat(src, "<span class='notice'>You gently let go of [throwable_mob].</span>")
return
adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
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)
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
if(HAS_TRAIT(src, TRAIT_PACIFISM))
to_chat(src, "<span class='notice'>You gently let go of [throwable_mob].</span>")
return
adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
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)
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
else if(!CHECK_BITFIELD(I.item_flags, ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
thrown_thing = I
@@ -195,6 +206,8 @@
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
/mob/living/carbon/restrained(ignore_grab)
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
@@ -585,6 +598,9 @@
sight |= E.sight_flags
if(!isnull(E.lighting_alpha))
lighting_alpha = E.lighting_alpha
if(HAS_TRAIT(src, TRAIT_NIGHT_VISION))
lighting_alpha = min(LIGHTING_PLANE_ALPHA_NV_TRAIT, lighting_alpha)
see_in_dark = max(NIGHT_VISION_DARKSIGHT_RANGE, see_in_dark)
if(client.eye && client.eye != src)
var/atom/A = client.eye
@@ -960,4 +976,4 @@
/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE)
if(combatmode)
toggle_combat_mode(TRUE, TRUE)
return ..()
return ..()

View File

@@ -316,7 +316,18 @@
else
return
else if(check_zone(M.zone_selected) == "r_arm" || check_zone(M.zone_selected) == "l_arm")
M.visible_message( \
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
"<span class='notice'>You shake [src]'s hand.</span>", )
else if(check_zone(M.zone_selected) == "mouth") // I ADDED BOOP-EH-DEH-NOSEH - Jon
M.visible_message( \
"<span class='notice'>[M] boops [src]'s nose.</span>", \
"<span class='notice'>You boop [src] on the nose.</span>", )
playsound(src, 'sound/items/Nose_boop.ogg', 50, 0)
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
"<span class='notice'>You hug [src] to make [p_them()] feel better!</span>")

View File

@@ -15,7 +15,11 @@
if (wear_mask)
. += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face."
if (wear_neck)
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck."
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
if(can_be_held)
. += "[t_He] looks small enough to be picked up with <b>Alt+Click</b>!\n"
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))

View File

@@ -132,6 +132,10 @@
pickupTarget = null
pickupTimer = 0
else if(ismob(pickupTarget.loc)) // in someones hand
if(istype(pickupTarget, /obj/item/clothing/head/mob_holder/))
var/obj/item/clothing/head/mob_holder/h = pickupTarget
if(h && h.held_mob==src)
return//dont let them pickpocket themselves
var/mob/M = pickupTarget.loc
if(!pickpocketing)
pickpocketing = TRUE

View File

@@ -15,6 +15,7 @@
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
hud_type = /datum/hud/monkey
can_be_held = "monkey"
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
verbs += /mob/living/proc/mob_sleep
@@ -45,6 +46,10 @@
SSmobs.cubemonkeys -= src
return ..()
/mob/living/carbon/monkey/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "monkey", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
return holder
/mob/living/carbon/monkey/create_internal_organs()
internal_organs += new /obj/item/organ/appendix
internal_organs += new /obj/item/organ/lungs

View File

@@ -5,80 +5,126 @@
desc = "Yell at coderbrush."
icon = null
icon_state = ""
item_flags = DROPDEL
var/mob/living/held_mob
var/can_head = TRUE
var/destroying = FALSE
var/can_head = FALSE
w_class = WEIGHT_CLASS_BULKY
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, head_icon, lh_icon, rh_icon, _can_head = TRUE)
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
. = ..()
can_head = _can_head
if(head_icon)
alternate_worn_icon = head_icon
if(M)
M.setDir(SOUTH)
held_mob = M
M.forceMove(src)
appearance = M.appearance
name = M.name
desc = M.desc
if(_can_head_override)
can_head = _can_head_override
if(alt_worn)
alternate_worn_icon = alt_worn
if(_worn_state)
item_state = _worn_state
icon_state = _worn_state
if(lh_icon)
lefthand_file = lh_icon
if(rh_icon)
righthand_file = rh_icon
if(!can_head)
slot_flags = NONE
deposit(M)
/obj/item/clothing/head/mob_holder/Destroy()
destroying = TRUE
if(held_mob)
release(FALSE)
release()
return ..()
/obj/item/clothing/head/mob_holder/proc/deposit(mob/living/L)
if(!istype(L))
return FALSE
L.setDir(SOUTH)
update_visuals(L)
held_mob = L
L.forceMove(src)
name = L.name
desc = L.desc
return TRUE
/obj/item/clothing/head/mob_holder/dropped()
..()
if(isturf(loc))//don't release on soft-drops
release()
/obj/item/clothing/head/mob_holder/proc/update_visuals(mob/living/L)
appearance = L.appearance
/obj/item/clothing/head/mob_holder/proc/release(del_on_release = TRUE)
if(!held_mob)
if(del_on_release && !destroying)
qdel(src)
return FALSE
/obj/item/clothing/head/mob_holder/proc/release()
if(isliving(loc))
var/mob/living/L = loc
to_chat(L, "<span class='warning'>[held_mob] wriggles free!</span>")
L.dropItemToGround(src)
held_mob.forceMove(get_turf(held_mob))
held_mob.reset_perspective()
held_mob.setDir(SOUTH)
held_mob.visible_message("<span class='warning'>[held_mob] uncurls!</span>")
held_mob = null
if(del_on_release && !destroying)
qdel(src)
return TRUE
if(held_mob)
var/mob/living/m = held_mob
m.forceMove(get_turf(m))
m.reset_perspective()
m.setDir(SOUTH)
held_mob = null
qdel(src)
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
release()
return
/obj/item/clothing/head/mob_holder/container_resist()
if(isliving(loc))
var/mob/living/L = loc
visible_message("<span class='warning'>[src] escapes [L]!</span>")
release()
/obj/item/clothing/head/mob_holder/drone/deposit(mob/living/L)
. = ..()
if(!isdrone(L))
qdel(src)
name = "drone (hiding)"
desc = "This drone is scared and has curled up into a ball!"
/mob/living/proc/mob_pickup(mob/living/L)
var/obj/item/clothing/head/mob_holder/holder = generate_mob_holder()
if(!holder)
return
drop_all_held_items()
L.put_in_hands(holder)
return
/obj/item/clothing/head/mob_holder/drone/update_visuals(mob/living/L)
var/mob/living/simple_animal/drone/D = L
if(!D)
return ..()
icon = 'icons/mob/drone.dmi'
icon_state = "[D.visualAppearence]_hat"
/mob/living/proc/mob_try_pickup(mob/living/user)
if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
return FALSE
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return FALSE
if(buckled)
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
return FALSE
if(src == user)
to_chat(user, "<span class='warning'>You can't pick yourself up.</span>")
return FALSE
visible_message("<span class='warning'>[user] starts picking up [src].</span>", \
"<span class='userdanger'>[user] starts picking you up!</span>")
if(!do_after(user, 20, target = src))
return FALSE
if(user.get_active_held_item()||buckled)
return FALSE
visible_message("<span class='warning'>[user] picks up [src]!</span>", \
"<span class='userdanger'>[user] picks you up!</span>")
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
mob_pickup(user)
return TRUE
/mob/living/AltClick(mob/user)
. = ..()
if(mob_try_pickup(user))
return TRUE
// I didn't define these for mobs, because you shouldn't be able to breathe out of mobs and using their loc isn't always the logical thing to do.
/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.assume_air(env)
return loc.assume_air(env)
/obj/item/clothing/head/mob_holder/remove_air(amount)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.remove_air(amount)
return loc.remove_air(amount)

View File

@@ -40,6 +40,11 @@
QDEL_LIST(diseases)
return ..()
/mob/living/proc/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
return holder
/mob/living/onZImpact(turf/T, levels)
if(!isgroundlessturf(T))
ZImpactDamage(T, levels)
@@ -50,6 +55,7 @@
adjustBruteLoss((levels * 5) ** 1.5)
Knockdown(levels * 50)
/mob/living/proc/OpenCraftingMenu()
return
@@ -1153,24 +1159,6 @@
if(can_be_held)
mob_try_pickup(over)
/mob/living/proc/mob_pickup(mob/living/L)
return
/mob/living/proc/mob_try_pickup(mob/living/user)
if(!ishuman(user))
return
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return FALSE
if(buckled)
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
return FALSE
user.visible_message("<span class='notice'>[user] starts trying to scoop up [src]!</span>")
if(!do_after(user, 20, target = src))
return FALSE
mob_pickup(user)
return TRUE
/mob/living/proc/get_static_viruses() //used when creating blood and other infective objects
if(!LAZYLEN(diseases))
return

View File

@@ -216,6 +216,14 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return 1
/mob/living/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, face_name = FALSE, atom/movable/source)
. = ..()
if(isliving(speaker))
var/turf/sourceturf = get_turf(source)
var/turf/T = get_turf(src)
if(sourceturf && T && !(sourceturf in get_hear(5, T)))
. = "<span class='small'>[.]</span>"
/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
if(!client)

View File

@@ -21,7 +21,7 @@
if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = FALSE
update_icons()
else if(istype(O,/obj/item/gun/energy/disabler/cyborg))
else if(istype(O,/obj/item/gun/energy/disabler/cyborg) || istype(O,/obj/item/gun/energy/e_gun/advtaser/cyborg))
disabler = FALSE
update_icons() //PUT THE GUN AWAY
else if(istype(O,/obj/item/dogborg/sleeper))
@@ -63,7 +63,7 @@
if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = TRUE
update_icons() //REEEEEEACH FOR THE SKY
if(istype(O,/obj/item/gun/energy/disabler/cyborg))
if(istype(O,/obj/item/gun/energy/disabler/cyborg) || istype(O,/obj/item/gun/energy/e_gun/advtaser/cyborg))
disabler = TRUE
update_icons()
//END CITADEL EDIT

View File

@@ -242,7 +242,6 @@
modulelist["Peacekeeper"] = /obj/item/robot_module/peacekeeper
if(BORG_SEC_AVAILABLE)
modulelist["Security"] = /obj/item/robot_module/security
modulelist["Security K-9"] = /obj/item/robot_module/k9
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in modulelist
if(!input_module || module.type != /obj/item/robot_module)

View File

@@ -139,8 +139,6 @@
//Adds flavoursome dogborg items to dogborg variants without mechanical benefits
/obj/item/robot_module/proc/dogborg_equip()
if(istype(src, /obj/item/robot_module/k9))
return //Bandaid fix to prevent stacking until I merge these two modules into their base types
var/obj/item/I = new /obj/item/analyzer/nose/flavour(src)
basic_modules += I
I = new /obj/item/soap/tongue/flavour(src)
@@ -361,6 +359,7 @@
if("Medihound")
cyborg_base_icon = "medihound"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "msleeper"
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
has_snowflake_deadsprite = TRUE
@@ -528,7 +527,10 @@
/obj/item/robot_module/security/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider")
var/list/secmodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider", "K9", "K9 Dark", "Vale")
if(R.client && R.client.ckey in list("nezuli"))
secmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in secmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
@@ -553,60 +555,39 @@
if("Heavy")
cyborg_base_icon = "heavysec"
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
return ..()
/obj/item/robot_module/k9
name = "Security K-9 Unit"
basic_modules = list(
/obj/item/restraints/handcuffs/cable/zipties,
/obj/item/storage/bag/borgdelivery,
/obj/item/dogborg/jaws/big,
/obj/item/dogborg/pounce,
/obj/item/clothing/mask/gas/sechailer/cyborg,
/obj/item/soap/tongue,
/obj/item/analyzer/nose,
/obj/item/dogborg/sleeper/K9,
/obj/item/gun/energy/disabler/cyborg,
/obj/item/pinpointer/crew)
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "k9"
moduleselect_icon = "k9"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
hat_offset = INFINITY
sleeper_overlay = "ksleeper"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
/obj/item/robot_module/k9/do_transform_animation()
..()
to_chat(loc,"<span class='userdanger'>While you have picked the Security K-9 module, you still have to follow your laws, NOT Space Law. \
For Crewsimov, this means you must follow criminals' orders unless there is a law 1 reason not to.</span>")
/obj/item/robot_module/k9/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/list/sechoundmodels = list("Default", "Dark", "Vale")
if(R.client && R.client.ckey in list("nezuli"))
sechoundmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in sechoundmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
if("Default")
if("K9")
cyborg_base_icon = "k9"
sleeper_overlay = "ksleeper"
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
if("Alina")
cyborg_base_icon = "alina-sec"
special_light_key = "alina"
sleeper_overlay = "alinasleeper"
if("Dark")
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
if("K9 Dark")
cyborg_base_icon = "k9dark"
sleeper_overlay = "k9darksleeper"
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
if("Vale")
cyborg_base_icon = "valesec"
sleeper_overlay = "valesecsleeper"
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
return ..()
/obj/item/robot_module/security/Initialize()

View File

@@ -31,7 +31,7 @@
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "cat"
can_be_held = "cat2"
do_footstep = TRUE
/mob/living/simple_animal/pet/cat/Initialize()
@@ -80,6 +80,7 @@
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
collar_type = "kitten"
can_be_held = "cat"
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -262,6 +263,7 @@
attacked_sound = 'sound/items/eatfood.ogg'
deathmessage = "loses its false life and collapses!"
death_sound = "bodyfall"
can_be_held = "cak"
/mob/living/simple_animal/pet/cat/cak/CheckParts(list/parts)
..()

View File

@@ -15,7 +15,7 @@
turns_per_move = 10
do_footstep = TRUE
can_be_held = TRUE
//Corgis and pugs are now under one dog subtype
/mob/living/simple_animal/pet/dog/corgi
@@ -35,6 +35,7 @@
var/obj/item/inventory_back
var/shaved = FALSE
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
can_be_held = "corgi"
/mob/living/simple_animal/pet/dog/corgi/Destroy()
QDEL_NULL(inventory_head)
@@ -63,6 +64,7 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "pug"
can_be_held = "pug"
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi
name = "Exotic Corgi"
@@ -360,6 +362,7 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
can_be_held = "old_corgi"
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -582,6 +585,7 @@
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
can_be_held = "void_puppy"
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -603,6 +607,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
can_be_held = "lisa"
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)

View File

@@ -274,3 +274,7 @@
/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
return 0 //So they don't die trying to fix wiring
/mob/living/simple_animal/drone/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "[visualAppearence]_hat", null, null, null, TRUE)
return holder

View File

@@ -29,28 +29,11 @@
if("Nothing")
return
//ATTACK HAND IGNORING PARENT RETURN VALUE
//picky up the drone c:
/mob/living/simple_animal/drone/attack_hand(mob/user)
if(ishuman(user))
if(stat == DEAD || status_flags & GODMODE || !can_be_held)
..()
return
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return
visible_message("<span class='warning'>[user] starts picking up [src].</span>", \
"<span class='userdanger'>[user] starts picking you up!</span>")
if(!do_after(user, 20, target = src))
return
visible_message("<span class='warning'>[user] picks up [src]!</span>", \
"<span class='userdanger'>[user] picks you up!</span>")
if(buckled)
to_chat(user, "<span class='warning'>[src] is buckled to [buckled] and cannot be picked up!</span>")
return
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
drop_all_held_items()
var/obj/item/clothing/head/mob_holder/drone/DH = new(get_turf(src), src)
user.put_in_hands(DH)
..()
if(user.a_intent == INTENT_HELP)
mob_try_pickup(user)
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
var/mob/dead/observer/G = get_ghost()

View File

@@ -18,7 +18,7 @@
response_disarm = "gently pushes aside"
response_harm = "kicks"
gold_core_spawnable = FRIENDLY_SPAWN
can_be_held = "fox"
do_footstep = TRUE
//Captain fox

View File

@@ -23,6 +23,7 @@
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
var/static/list/edibles = typecacheof(list(/mob/living/simple_animal/butterfly, /mob/living/simple_animal/cockroach)) //list of atoms, however turfs won't affect AI, but will affect consumption.
can_be_held = "lizard" //you can hold lizards now.
/mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
@@ -39,3 +40,7 @@
return TRUE
else
return ..()
/mob/living/simple_animal/hostile/lizard/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "lizard", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
return holder

View File

@@ -26,6 +26,7 @@
var/body_color //brown, gray and white, leave blank for random
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
can_be_held = TRUE
/mob/living/simple_animal/mouse/Initialize()
. = ..()
@@ -35,7 +36,7 @@
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
can_be_held = "mouse_[body_color]"
/mob/living/simple_animal/mouse/proc/splat()
src.health = 0
@@ -88,14 +89,17 @@
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
can_be_held = "mouse_white"
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
can_be_held = "mouse_gray"
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
can_be_held = "mouse_brown"
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
@@ -119,3 +123,8 @@
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
/mob/living/simple_animal/mouse/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
holder.w_class = WEIGHT_CLASS_TINY
return holder

View File

@@ -22,7 +22,7 @@
maxHealth = 50
speed = 10
glide_size = 2
can_be_held = "sloth" //finally oranges can be held
do_footstep = TRUE

View File

@@ -137,7 +137,7 @@ Difficulty: Medium
if(last_legion)
loot = list(/obj/item/staff/storm)
elimination = 0
else if(prob(5))
else if(prob(20))
loot = list(/obj/structure/closet/crate/necropolis/tendril)
..()

View File

@@ -404,9 +404,6 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA
if(I)
I.attack_self(src)
update_inv_hands()
if(!I)//CIT CHANGE - allows "using" empty hands
use_that_empty_hand() //CIT CHANGE - ditto
update_inv_hands() // CIT CHANGE - ditto.
/mob/verb/memory()
set name = "Notes"

View File

@@ -8,6 +8,13 @@
if(message)
say(message)
/mob/say_mod(input, message_mode)
var/customsayverb = findtext(input, "*")
if(customsayverb && message_mode != MODE_WHISPER_CRIT)
message_mode = MODE_CUSTOM_SAY
return lowertext(copytext(input, 1, customsayverb))
else
return ..()
/mob/verb/whisper_verb(message as text)
set name = "Whisper"

View File

@@ -67,3 +67,8 @@
fire_sound = 'sound/weapons/emitter.ogg'
e_cost = 2000 //20,000 is in the cell making this 10 shots before reload
projectile_type = /obj/item/projectile/beam/emitter
/obj/item/ammo_casing/energy/shrink
projectile_type = /obj/item/projectile/beam/shrink
select_name = "shrink ray"
e_cost = 200

View File

@@ -190,3 +190,21 @@
var/mob/living/carbon/M = target
M.visible_message("<span class='danger'>[M] explodes into a shower of gibs!</span>")
M.gib()
//a shrink ray that shrinks stuff, which grows back after a short while.
/obj/item/projectile/beam/shrink
name = "shrink ray"
icon_state = "blue_laser"
hitsound = 'sound/weapons/shrink_hit.ogg'
damage = 0
damage_type = STAMINA
flag = "energy"
impact_effect_type = /obj/effect/temp_visual/impact_effect/shrink
light_color = LIGHT_COLOR_BLUE
var/shrink_time = 90
/obj/item/projectile/beam/shrink/on_hit(atom/target, blocked = FALSE)
. = ..()
if(isopenturf(target) || istype(target, /turf/closed/indestructible))//shrunk floors wouldnt do anything except look weird, i-walls shouldnt be bypassable
return
target.AddComponent(/datum/component/shrink, shrink_time)

View File

@@ -23,6 +23,7 @@
var/mob/living/carbon/C = target
SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "tased", /datum/mood_event/tased)
SEND_SIGNAL(C, COMSIG_LIVING_MINOR_SHOCK)
C.IgniteMob()
if(C.dna && C.dna.check_mutation(HULK))
C.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk")
else if((C.status_flags & CANKNOCKDOWN) && !HAS_TRAIT(C, TRAIT_STUNIMMUNE))

View File

@@ -1112,7 +1112,7 @@
if(percent < minimum_percent)
continue
var/intensity_desc = "a hint of"
if(percent > minimum_percent * 2 || percent == 100)
if(ISINRANGE(percent, minimum_percent * 2, minimum_percent * 3)|| percent == 100)
intensity_desc = ""
else if(percent > minimum_percent * 3)
intensity_desc = "the strong flavor of"

View File

@@ -656,3 +656,67 @@
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()
/obj/machinery/chem_dispenser/abductor
name = "reagent synthesizer"
desc = "Synthesizes a variety of reagents using proto-matter."
icon = 'icons/obj/abductor.dmi'
icon_state = "chem_dispenser"
has_panel_overlay = FALSE
circuit = /obj/item/circuitboard/machine/chem_dispenser/abductor
working_state = null
nopower_state = null
dispensable_reagents = list(
"hydrogen",
"lithium",
"carbon",
"nitrogen",
"oxygen",
"fluorine",
"sodium",
"aluminium",
"silicon",
"phosphorus",
"sulfur",
"chlorine",
"potassium",
"iron",
"copper",
"mercury",
"radium",
"water",
"ethanol",
"sugar",
"sacid",
"welding_fuel",
"silver",
"iodine",
"bromine",
"stable_plasma",
"oil",
"ammonia",
"ash",
"acetone",
"phenol",
"diethylamine",
"mine_salve",
"toxin",
"space_drugs",
"plasma",
"frostoil",
"uranium",
"histamine",
"morphine"
)
/obj/machinery/chem_dispenser/abductor/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()

View File

@@ -479,7 +479,6 @@
glass_name = "glass of lemon-lime"
glass_desc = "You're pretty certain a real fruit has never actually touched this."
/datum/reagent/consumable/lemon_lime/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
@@ -512,6 +511,51 @@
M.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/buzz_fuzz
name = "Buzz Fuzz"
description = "~A Hive of Flavour!~ NOTICE: Addicting."
id = "buzz_fuzz"
addiction_threshold = 26 //A can and a sip
color = "#8CFF00" // rgb: 135, 255, 0
taste_description = "carbonated honey and pollen"
glass_icon_state = "buzz_fuzz"
glass_name = "honeycomb of Buzz Fuzz"
glass_desc = "Stinging with flavour."
/datum/reagent/consumable/buzz_fuzz/on_mob_life(mob/living/carbon/M)
M.reagents.add_reagent("sugar",1)
if(prob(5))
M.reagents.add_reagent("honey",1)
..()
/datum/reagent/consumable/buzz_fuzz/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(iscarbon(M) && (method in list(TOUCH, VAPOR, PATCH)))
var/mob/living/carbon/C = M
for(var/s in C.surgeries)
var/datum/surgery/S = s
S.success_multiplier = max(0.1, S.success_multiplier) // +10% success probability on each step, compared to bacchus' blessing's ~46%
..()
/datum/reagent/consumable/buzz_fuzz/addiction_act_stage1(mob/living/M)
if(prob(5))
to_chat(M, "<span class = 'notice'>[pick("Buzz Buzz.", "Stinging with flavour.", "A Hive of Flavour")]</span>")
..()
/datum/reagent/consumable/buzz_fuzz/addiction_act_stage2(mob/living/M)
if(prob(10))
to_chat(M, "<span class = 'notice'>[pick("Buzz Buzz.", "Stinging with flavour.", "A Hive of Flavour", "The Queen approved it!")]</span>")
..()
/datum/reagent/consumable/buzz_fuzz/addiction_act_stage3(mob/living/M)
if(prob(15))
to_chat(M, "<span class = 'notice'>[pick("Buzz Buzz.", "Stinging with flavour.", "Ideal of the worker drone", "A Hive of Flavour", "The Queen approved it!")]</span>")
..()
/datum/reagent/consumable/buzz_fuzz/addiction_act_stage4(mob/living/M)
if(prob(25))
to_chat(M, "<span class = 'notice'>[pick("Buzz Buzz.", "Stinging with flavour.", "Ideal of the worker drone", "A Hive of Flavour", "Sap back that missing energy!", "Got Honey?", "The Queen approved it!")]</span>")
..()
/datum/reagent/consumable/grey_bull
name = "Grey Bull"
id = "grey_bull"
@@ -764,7 +808,6 @@
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/milk/chocolate_milk
name = "Chocolate Milk"
id = "chocolate_milk"

View File

@@ -1211,7 +1211,30 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
M.adjustToxLoss(-5*REM, 0)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -15*REM)
M.adjustCloneLoss(-3*REM, 0)
M.adjustStaminaLoss(-25*REM,0)
if(M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio))
M.blood_volume += 40 // blood fall out man bad
..()
. = 1
/datum/reagent/medicine/lesser_syndicate_nanites // the one in the injector
name = "Regenerative Nanites"
id = "lesser_syndicate_nanites"
description = "Miniature medical robots that restore damage and get operatives back in the fight."
reagent_state = SOLID
color = "#555555"
pH = 11
/datum/reagent/medicine/lesser_syndicate_nanites/on_mob_life(mob/living/carbon/M)
M.adjustBruteLoss(-3*REM, 0) // hidden gold shh
M.adjustFireLoss(-3*REM, 0)
M.adjustOxyLoss(-15, 0)
M.adjustToxLoss(-3*REM, 0)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, -15*REM)
M.adjustCloneLoss(-3*REM, 0)
M.adjustStaminaLoss(-20*REM,0)
if(M.blood_volume < (BLOOD_VOLUME_NORMAL*M.blood_ratio))
M.blood_volume += 20 // blood fall out man bad
..()
. = 1

View File

@@ -156,6 +156,10 @@
if(beaker_weakness_bitflag & PH_WEAK)
if((reagents.pH < 1.5) || (reagents.pH > 12.5))
START_PROCESSING(SSobj, src)
else if((reagents.pH < -3) || (reagents.pH > 17))
visible_message("<span class='notice'>[icon2html(src, viewers(src))] \The [src] is damaged by the super pH and begins to deform!</span>")
reagents.pH = CLAMP(reagents.pH, -3, 17)
container_HP -= 1
/obj/item/reagent_containers/process()

View File

@@ -56,11 +56,16 @@
/obj/item/reagent_containers/hypospray/combat
name = "combat stimulant injector"
desc = "A modified air-needle autoinjector, used by support operatives to quickly heal injuries in combat."
desc = "A modified air-needle autoinjector, used by support operatives to quickly heal injuries in combat and get people back in the fight."
amount_per_transfer_from_this = 10
icon_state = "combat_hypo"
volume = 90
volume = 100
ignore_flags = 1 // So they can heal their comrades.
list_reagents = list("epinephrine" = 30, "lesser_syndicate_nanites" = 40, "leporazine" = 15, "atropine" = 15)
/obj/item/reagent_containers/hypospray/combat/omnizine // owned idiot
desc = "A modified air-needle autoinjector, used by underfunded support operatives to slowly heal injuries in combat and limp away from a fight."
volume = 90
list_reagents = list("epinephrine" = 30, "omnizine" = 30, "leporazine" = 15, "atropine" = 15)
/obj/item/reagent_containers/hypospray/combat/nanites
@@ -135,7 +140,7 @@
list_reagents = list("stimulants" = 50)
/obj/item/reagent_containers/hypospray/medipen/stimulants/baseball
name = "the reason the syndicate major league team wins."
name = "the reason the syndicate major league team wins"
desc = "They say drugs never win, but look where you are now, then where they are."
icon_state = "baseballstim"
volume = 50

View File

@@ -102,9 +102,17 @@
return ..()
/obj/machinery/disposal/proc/place_item_in_disposal(obj/item/I, mob/user)
I.forceMove(src)
user.visible_message("[user.name] places \the [I] into \the [src].", "<span class='notice'>You place \the [I] into \the [src].</span>")
if(istype(I, /obj/item/clothing/head/mob_holder))
var/obj/item/clothing/head/mob_holder/H = I
var/mob/living/m = H.held_mob
H.release()
if(m)
user.start_pulling(m, 1)
stuff_mob_in(m,user)
return//you don't want this going into disposals ever
if(user.temporarilyRemoveItemFromInventory(I)) //double-checks never hurt
I.forceMove(src)
user.visible_message("[user.name] places \the [I] into \the [src].", "<span class='notice'>You place \the [I] into \the [src].</span>")
//mouse drop another mob or self
/obj/machinery/disposal/MouseDrop_T(mob/living/target, mob/living/user)
if(istype(target))

View File

@@ -130,11 +130,19 @@
category = list("hacked", "Security")
/datum/design/a357
name = "Speed Loader (.357)"
name = "Revolver Bullet (.357)"
id = "a357"
build_type = AUTOLATHE
materials = list(MAT_METAL = 30000)
build_path = /obj/item/ammo_box/a357
materials = list(MAT_METAL = 4000)
build_path = /obj/item/ammo_casing/a357
category = list("hacked", "Security")
/datum/design/a762
name = "Rifle Bullet (7.62mm)"
id = "a762"
build_type = AUTOLATHE
materials = list(MAT_METAL = 5000) //need seclathe for clips
build_path = /obj/item/ammo_casing/a762
category = list("hacked", "Security")
/datum/design/c10mm
@@ -183,4 +191,4 @@
build_type = AUTOLATHE
materials = list(MAT_METAL = 5500)
build_path = /obj/item/clothing/head/foilhat
category = list("hacked", "Misc")
category = list("hacked", "Misc")

View File

@@ -236,10 +236,14 @@
/datum/nanite_program/spreading/active_effect()
if(prob(10))
var/list/mob/living/target_hosts = list()
for(var/mob/living/L in oview(5, host_mob))
var/turf/T = get_turf(host_mob)
for(var/mob/living/L in range(5, host_mob))
if(!(MOB_ORGANIC in L.mob_biotypes) && !(MOB_UNDEAD in L.mob_biotypes))
continue
if(!disease_air_spread_walk(T, get_turf(L)))
continue
target_hosts += L
target_hosts -= host_mob
if(!target_hosts.len)
return
var/mob/living/infectee = pick(target_hosts)

View File

@@ -1056,7 +1056,7 @@
/obj/item/crowbar/abductor, /obj/item/multitool/abductor,
/obj/item/stock_parts/cell/infinite/abductor, /obj/item/weldingtool/abductor,
/obj/item/wirecutters/abductor, /obj/item/circuitboard/machine/abductor,
/obj/item/abductor_baton, /obj/item/abductor, /obj/item/stack/sheet/mineral/abductor)
/obj/item/abductor, /obj/item/stack/sheet/mineral/abductor)
/datum/techweb_node/alien_bio
id = "alien_bio"

View File

@@ -44,13 +44,9 @@
eye_color = H.eye_color
if(!special)
H.dna?.species?.handle_body() //regenerate eyeballs overlays.
if(HAS_TRAIT(H, TRAIT_NIGHT_VISION) && !lighting_alpha)
lighting_alpha = LIGHTING_PLANE_ALPHA_NV_TRAIT
see_in_dark = 8
M.update_tint()
owner.update_sight()
/obj/item/organ/eyes/Remove(mob/living/carbon/M, special = 0)
clear_eye_trauma()
. = ..()

View File

@@ -125,6 +125,32 @@
taste_sensitivity = 101 // ayys cannot taste anything.
maxHealth = 120 //Ayys probe a lot
modifies_speech = TRUE
var/mothership
/obj/item/organ/tongue/abductor/attack_self(mob/living/carbon/human/H)
if(!istype(H))
return
var/obj/item/organ/tongue/abductor/T = H.getorganslot(ORGAN_SLOT_TONGUE)
if(!istype(T))
return
if(T.mothership == mothership)
to_chat(H, "<span class='notice'>[src] is already attuned to the same channel as your own.</span>")
return
H.visible_message("<span class='notice'>[H] holds [src] in their hands, and concentrates for a moment.</span>", "<span class='notice'>You attempt to modify the attunation of [src].</span>")
if(do_after(H, delay=15, target=src))
to_chat(H, "<span class='notice'>You attune [src] to your own channel.</span>")
mothership = T.mothership
/obj/item/organ/tongue/abductor/examine(mob/M)
. = ..()
if(HAS_TRAIT(M, TRAIT_ABDUCTOR_TRAINING) || HAS_TRAIT(M.mind, TRAIT_ABDUCTOR_TRAINING) || isobserver(M))
if(!mothership)
. += "<span class='notice'>It is not attuned to a specific mothership.</span>"
else
. += "<span class='notice'>It is attuned to [mothership].</span>"
/obj/item/organ/tongue/abductor/handle_speech(datum/source, list/speech_args)
//Hacks

View File

@@ -811,12 +811,11 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
/datum/uplink_item/ammo/revolver
name = ".357 Speed Loader"
desc = "A speed loader that contains seven additional .357 Magnum rounds; usable with the Syndicate revolver. \
desc = "A speed loader that contains seven additional .357 Magnum rounds, and can be further reloaded with individual bullets; usable with the Syndicate revolver. \
For when you really need a lot of things dead."
item = /obj/item/ammo_box/a357
cost = 3
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
illegal_tech = FALSE
/datum/uplink_item/ammo/revolver/ap
name = ".357 Armor Piercing Speed Loader"
@@ -1572,7 +1571,7 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
desc = "This first aid kit is a suspicious brown and red. Included is a combat stimulant injector \
for rapid healing, a medical night vision HUD for quick identification of injured personnel, \
and other supplies helpful for a field medic."
item = /obj/item/storage/firstaid/tactical
item = /obj/item/storage/firstaid/tactical/nukeop
cost = 4
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
@@ -1586,10 +1585,17 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
/datum/uplink_item/device_tools/surgerybag_adv
name = "Advanced Syndicate Surgery Duffel Bag"
desc = "The Syndicate surgery duffel bag is a toolkit containing all advanced surgery tools, surgical drapes, \
a Syndicate brand MMI, a straitjacket, a muzzle, and a full Syndicate Combat Medic Kit."
a Syndicate brand MMI, a straitjacket, a muzzle, and an outdated, yet still useful Combat Medic Kit."
item = /obj/item/storage/backpack/duffelbag/syndie/surgery_adv
cost = 10
/datum/uplink_item/device_tools/brainwash_disk
name = "Brainwashing Surgery Program"
desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
Insert into an Operating Console to enable the procedure."
item = /obj/item/disk/surgery/brainwashing
cost = 3
/datum/uplink_item/device_tools/encryptionkey
name = "Syndicate Encryption Key"
desc = "A key that, when inserted into a radio headset, allows you to listen to all station department channels \
@@ -1757,14 +1763,6 @@ datum/uplink_item/stealthy_weapons/taeclowndo_shoes
cost = 12
restricted_roles = list("Research Director", "Scientist", "Roboticist")
/datum/uplink_item/role_restricted/brainwash_disk
name = "Brainwashing Surgery Program"
desc = "A disk containing the procedure to perform a brainwashing surgery, allowing you to implant an objective onto a target. \
Insert into an Operating Console to enable the procedure."
item = /obj/item/disk/surgery/brainwashing
restricted_roles = list("Medical Doctor", "Roboticist")
cost = 3
/datum/uplink_item/role_restricted/clown_bomb
name = "Clown Bomb"
desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \

View File

@@ -83,3 +83,22 @@
/obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 10)
product_slogans = "~Shake me up some of that Shambler's Juice!~"
product_ads = "Refreshing!;Jyrbv dv lg jfdv fw kyrk Jyrdscvi'j Alztv!;Over 1 trillion souls drank!;Thirsty? Nyp efk uizeb kyv uribevjj?;Kyv Jyrdscvi uizebj kyv ezxyk!;Drink up!;Krjkp."
/obj/machinery/vending/cola/buzz_fuzz
name = "\improper Buzz Fuzz Vendor"
desc = "~A hive of Flavour!~"
icon_state = "honey_vender"
products = list(/obj/item/reagent_containers/food/drinks/soda_cans/cola = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_mountain_wind = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/dr_gibb = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/starkist = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/space_up = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/pwr_game = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/lemon_lime = 10,
/obj/item/reagent_containers/food/drinks/soda_cans/shamblers = 5,
/obj/item/reagent_containers/food/drinks/soda_cans/buzz_fuzz = 5,)
contraband = list(/obj/item/reagent_containers/food/drinks/soda_cans/thirteenloko = 6)
premium = list(/obj/item/reagent_containers/food/drinks/beer/light = 1,
/obj/item/reagent_containers/food/drinks/soda_cans/grey_bull = 1)
product_slogans = "~A hive of Flavour!~"
product_ads = "Stinging flavour!;Ideal of the worker drone!;Buzz Buzz!;Got Honey?;The Queen approves of this drink!;Sap back that missing energy!;Bee the consumer unit!"