Merge branch 'master' into upstream-merge-29953

This commit is contained in:
LetterJay
2017-09-06 09:17:57 -05:00
committed by GitHub
1638 changed files with 60270 additions and 218189 deletions
+6 -6
View File
@@ -30,8 +30,8 @@
// literally only an option for carbons though
to_chat(C, "<span class='warning'>You may not hold items while blood crawling!</span>")
return 0
var/obj/item/weapon/bloodcrawl/B1 = new(C)
var/obj/item/weapon/bloodcrawl/B2 = new(C)
var/obj/item/bloodcrawl/B1 = new(C)
var/obj/item/bloodcrawl/B2 = new(C)
B1.icon_state = "bloodhand_left"
B2.icon_state = "bloodhand_right"
C.put_in_hands(B1)
@@ -134,11 +134,11 @@
/mob/living/proc/bloodcrawl_swallow(var/mob/living/victim)
qdel(victim)
/obj/item/weapon/bloodcrawl
/obj/item/bloodcrawl
name = "blood crawl"
desc = "You are unable to hold anything while in this form."
icon = 'icons/effects/blood.dmi'
flags = NODROP|ABSTRACT
flags_1 = NODROP_1|ABSTRACT_1
/mob/living/proc/exit_blood_effect(obj/effect/decal/cleanable/B)
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
@@ -166,8 +166,8 @@
exit_blood_effect(B)
if(iscarbon(src))
var/mob/living/carbon/C = src
for(var/obj/item/weapon/bloodcrawl/BC in C)
BC.flags = null
for(var/obj/item/bloodcrawl/BC in C)
BC.flags_1 = null
qdel(BC)
qdel(src.holder)
src.holder = null
+1 -1
View File
@@ -112,7 +112,7 @@
if(user.zone_selected != "head")
return ..()
if((C.head && (C.head.flags_cover & HEADCOVERSEYES)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSEYES)) || (C.glasses && (C.glasses.flags & GLASSESCOVERSEYES)))
if((C.head && (C.head.flags_cover & HEADCOVERSEYES)) || (C.wear_mask && (C.wear_mask.flags_cover & MASKCOVERSEYES)) || (C.glasses && (C.glasses.flags_1 & GLASSESCOVERSEYES)))
to_chat(user, "<span class='warning'>You're going to need to remove their head cover first!</span>")
return
+1 -1
View File
@@ -37,7 +37,7 @@ GLOBAL_VAR(posibrain_notify_cooldown)
/obj/item/device/mmi/posibrain/proc/ping_ghosts(msg, newlymade)
if(newlymade || GLOB.posibrain_notify_cooldown <= world.time)
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/effects/ghost2.ogg':null, enter_link = "<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/misc/server-ready.ogg':null, enter_link = "<a href=?src=\ref[src];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK, flashwindow = FALSE)
if(!newlymade)
GLOB.posibrain_notify_cooldown = world.time + askDelay
@@ -16,10 +16,10 @@
verb_say = "hisses"
initial_language_holder = /datum/language_holder/alien
bubble_icon = "alien"
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
var/nightvision = 1
var/obj/item/weapon/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/obj/item/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
var/move_delay_add = 0 // movement delay to add
@@ -20,11 +20,11 @@
/datum/emote/living/alien/roar
key = "roar"
key_third_person = "roars"
message_alien = "roars"
message_larva = "softly roars"
message_alien = "roars."
message_larva = "softly roars."
emote_type = EMOTE_AUDIBLE
/datum/emote/living/alien/roar/run_emote(mob/user, params)
. = ..()
if(. && isalienadult(user))
playsound(user.loc, 'sound/voice/hiss5.ogg', 40, 1, 1)
playsound(user.loc, 'sound/voice/hiss5.ogg', 40, 1, 1)
@@ -2,7 +2,7 @@
name = "alien"
icon_state = "alien"
pass_flags = PASSTABLE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
possible_a_intents = list(INTENT_HELP, INTENT_DISARM, INTENT_GRAB, INTENT_HARM)
limb_destroyer = 1
var/obj/item/r_store = null
@@ -42,7 +42,7 @@
<HR>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><B>[get_held_index_name(i)]:</B><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "<font color=grey>Empty</font>"]</a>"
dat += "<BR><A href='?src=\ref[src];pouches=1'>Empty Pouches</A>"
if(handcuffed)
@@ -9,7 +9,7 @@
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //above most mobs, but below speechbubbles
pressure_resistance = 200 //Because big, stompy xenos should not be blown around like paper.
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 20, /obj/item/stack/sheet/animalhide/xeno = 3)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 20, /obj/item/stack/sheet/animalhide/xeno = 3)
var/alt_inhands_file = 'icons/mob/alienqueen.dmi'
@@ -123,7 +123,7 @@
name = "\improper royal parasite"
desc = "Inject this into one of your grown children to promote her to a Praetorian!"
icon_state = "alien_medal"
flags = ABSTRACT|NODROP|DROPDEL
flags_1 = ABSTRACT_1|NODROP_1|DROPDEL_1
icon = 'icons/mob/alien.dmi'
/obj/item/queenpromote/attack(mob/living/M, mob/living/carbon/alien/humanoid/user)
@@ -15,7 +15,7 @@
icon_state = "facehugger"
item_state = "facehugger"
w_class = WEIGHT_CLASS_TINY //note: can be picked up by aliens unlike most other items of w_class below 4
flags = MASKINTERNALS
flags_1 = MASKINTERNALS_1
throw_range = 5
tint = 3
flags_cover = MASKCOVERSEYES | MASKCOVERSMOUTH
+14 -14
View File
@@ -51,7 +51,7 @@
var/obj/item/item_in_hand = src.get_active_held_item()
if(item_in_hand) //this segment checks if the item in your hand is twohanded.
var/obj/item/weapon/twohanded/TH = item_in_hand
var/obj/item/twohanded/TH = item_in_hand
if(istype(TH))
if(TH.wielded == 1)
to_chat(usr, "<span class='warning'>Your other hand is too busy holding [TH]</span>")
@@ -165,7 +165,7 @@
var/end_T_descriptor = "<font color='#6b4400'>tile at [end_T.x], [end_T.y], [end_T.z] in area [get_area(end_T)]</font>"
add_logs(src, throwable_mob, "thrown", addition="from [start_T_descriptor] with the target [end_T_descriptor]")
else if(!(I.flags & (NODROP|ABSTRACT)))
else if(!(I.flags_1 & (NODROP_1|ABSTRACT_1)))
thrown_thing = I
dropItemToGround(I)
@@ -188,17 +188,17 @@
<HR>
<B><FONT size=3>[name]</FONT></B>
<HR>
<BR><B>Head:</B> <A href='?src=\ref[src];item=[slot_head]'> [(head && !(head.flags&ABSTRACT)) ? head : "Nothing"]</A>
<BR><B>Mask:</B> <A href='?src=\ref[src];item=[slot_wear_mask]'> [(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "Nothing"]</A>
<BR><B>Neck:</B> <A href='?src=\ref[src];item=[slot_neck]'> [(wear_neck && !(wear_neck.flags&ABSTRACT)) ? wear_neck : "Nothing"]</A>"}
<BR><B>Head:</B> <A href='?src=\ref[src];item=[slot_head]'> [(head && !(head.flags_1&ABSTRACT_1)) ? head : "Nothing"]</A>
<BR><B>Mask:</B> <A href='?src=\ref[src];item=[slot_wear_mask]'> [(wear_mask && !(wear_mask.flags_1&ABSTRACT_1)) ? wear_mask : "Nothing"]</A>
<BR><B>Neck:</B> <A href='?src=\ref[src];item=[slot_neck]'> [(wear_neck && !(wear_neck.flags_1&ABSTRACT_1)) ? wear_neck : "Nothing"]</A>"}
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<BR><B>[get_held_index_name(i)]:</B></td><td><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags & ABSTRACT)) ? I : "Nothing"]</a>"
dat += "<BR><B>[get_held_index_name(i)]:</B></td><td><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "Nothing"]</a>"
dat += "<BR><B>Back:</B> <A href='?src=\ref[src];item=[slot_back]'>[back ? back : "Nothing"]</A>"
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/weapon/tank))
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
dat += "<BR><A href='?src=\ref[src];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
if(handcuffed)
@@ -220,15 +220,15 @@
if(href_list["internal"])
var/slot = text2num(href_list["internal"])
var/obj/item/ITEM = get_item_by_slot(slot)
if(ITEM && istype(ITEM, /obj/item/weapon/tank) && wear_mask && (wear_mask.flags & MASKINTERNALS))
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.flags_1 & MASKINTERNALS_1))
visible_message("<span class='danger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].</span>", \
"<span class='userdanger'>[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM.name].</span>")
if(do_mob(usr, src, POCKET_STRIP_DELAY))
if(internal)
internal = null
update_internals_hud_icon(0)
else if(ITEM && istype(ITEM, /obj/item/weapon/tank))
if((wear_mask && (wear_mask.flags & MASKINTERNALS)) || getorganslot("breathing_tube"))
else if(ITEM && istype(ITEM, /obj/item/tank))
if((wear_mask && (wear_mask.flags_1 & MASKINTERNALS_1)) || getorganslot("breathing_tube"))
internal = ITEM
update_internals_hud_icon(1)
@@ -321,7 +321,7 @@
/mob/living/carbon/proc/uncuff()
if (handcuffed)
var/obj/item/weapon/W = handcuffed
var/obj/item/W = handcuffed
handcuffed = null
if (buckled && buckled.buckle_requires_restraints)
buckled.unbuckle_mob(src)
@@ -336,7 +336,7 @@
W.plane = initial(W.plane)
changeNext_move(0)
if (legcuffed)
var/obj/item/weapon/W = legcuffed
var/obj/item/W = legcuffed
legcuffed = null
update_inv_legcuffed()
if (client)
@@ -394,7 +394,7 @@
return initial(pixel_y)
/mob/living/carbon/proc/accident(obj/item/I)
if(!I || (I.flags & (NODROP|ABSTRACT)))
if(!I || (I.flags_1 & (NODROP_1|ABSTRACT_1)))
return
dropItemToGround(I)
@@ -732,7 +732,7 @@
regenerate_limbs()
regenerate_organs()
handcuffed = initial(handcuffed)
for(var/obj/item/weapon/restraints/R in contents) //actually remove cuffs from inventory
for(var/obj/item/restraints/R in contents) //actually remove cuffs from inventory
qdel(R)
update_handcuffed()
if(reagents)
@@ -24,9 +24,9 @@
/mob/living/carbon/get_ear_protection()
var/number = ..()
if(ears && HAS_SECONDARY_FLAG(ears, BANG_PROTECT))
if(ears && (ears.flags_2 & BANG_PROTECT_2))
number += 1
if(head && HAS_SECONDARY_FLAG(head, BANG_PROTECT))
if(head && (head.flags_2 & BANG_PROTECT_2))
number += 1
var/obj/item/organ/ears/E = getorganslot("ears")
if(!E)
@@ -210,7 +210,7 @@
..()
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, override = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
if(tesla_shock && HAS_SECONDARY_FLAG(src, TESLA_IGNORE))
if(tesla_shock && (flags_2 & TESLA_IGNORE_2))
return FALSE
shock_damage *= siemens_coeff
if(dna && dna.species)
@@ -255,6 +255,8 @@
else if(check_zone(M.zone_selected) == "head")
M.visible_message("<span class='notice'>[M] gives [src] a pat on the head to make [p_them()] feel better!</span>", \
"<span class='notice'>You give [src] a pat on the head to make [p_them()] feel better!</span>")
if(dna && dna.species && (("tail_lizard" in dna.species.mutant_bodyparts) || (dna.features["tail_human"] != "None") || ("mam_tail" in dna.species.mutant_bodyparts)))
emote("wag") //lewd
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>")
@@ -11,11 +11,13 @@
var/obj/item/handcuffed = null //Whether or not the mob is handcuffed
var/obj/item/legcuffed = null //Same as handcuffs but for legs. Bear traps use this.
var/disgust = 0
//inventory slots
var/obj/item/back = null
var/obj/item/clothing/mask/wear_mask = null
var/obj/item/clothing/neck/wear_neck = null
var/obj/item/weapon/tank/internal = null
var/obj/item/tank/internal = null
var/obj/item/head = null
var/obj/item/gloves = null //only used by humans
@@ -31,7 +33,7 @@
var/co2overloadtime = null
var/temperature_resistance = T0C+75
has_limbs = 1
var/obj/item/weapon/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab
var/obj/item/reagent_containers/food/snacks/meat/slab/type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab
var/list/obj/effect/proc_holder/alien/abilities = list()
var/gib_type = /obj/effect/decal/cleanable/blood/gibs
@@ -47,4 +49,4 @@
var/list/hand_bodyparts = list() //a collection of arms (or actually whatever the fug /bodyparts you monsters use to wreck my systems)
var/icon_render_key = ""
var/static/list/limb_icon_cache = list()
var/static/list/limb_icon_cache = list()
@@ -42,7 +42,7 @@
if(istype(T) && movement_dir && T.allow_thrust(0.01))
return 1
var/obj/item/weapon/tank/jetpack/J = get_jetpack()
var/obj/item/tank/jetpack/J = get_jetpack()
if(istype(J) && (movement_dir || J.stabilizers) && J.allow_thrust(0.01, src))
return 1
+1 -1
View File
@@ -18,7 +18,7 @@
msg += "[t_He] [t_is] wearing [icon2html(wear_neck, user)] \a [src.wear_neck] around [t_his] neck.\n"
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(!(I.flags_1 & ABSTRACT_1))
if(I.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!</span>\n"
else
@@ -56,7 +56,7 @@
//Hands
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(!(I.flags_1 & ABSTRACT_1))
if(I.blood_DNA)
msg += "<span class='warning'>[t_He] [t_is] holding [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in [t_his] [get_held_index_name(get_held_index_of_item(I))]!</span>\n"
else
@@ -77,7 +77,7 @@
//handcuffed?
if(handcuffed)
if(istype(handcuffed, /obj/item/weapon/restraints/handcuffs/cable))
if(istype(handcuffed, /obj/item/restraints/handcuffs/cable))
msg += "<span class='warning'>[t_He] [t_is] [icon2html(handcuffed, user)] restrained with cable!</span>\n"
else
msg += "<span class='warning'>[t_He] [t_is] [icon2html(handcuffed, user)] handcuffed!</span>\n"
@@ -225,6 +225,14 @@
else
msg += "[t_He] [t_is] quite chubby.\n"
switch(disgust)
if(DISGUST_LEVEL_GROSS to DISGUST_LEVEL_VERYGROSS)
msg += "[t_He] looks a bit grossed out.\n"
if(DISGUST_LEVEL_VERYGROSS to DISGUST_LEVEL_DISGUSTED)
msg += "[t_He] looks really grossed out.\n"
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
msg += "[t_He] looks disgusted.\n"
if(blood_volume < BLOOD_VOLUME_SAFE)
msg += "[t_He] [t_has] pale skin.\n"
+33 -37
View File
@@ -11,10 +11,6 @@
INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/mob/living/carbon/human/dummy/Destroy()
..()
return QDEL_HINT_QUEUE
/mob/living/carbon/human/dummy/Life()
return
@@ -145,43 +141,43 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
dat += "<table>"
for(var/i in 1 to held_items.len)
var/obj/item/I = get_item_for_held_index(i)
dat += "<tr><td><B>[get_held_index_name(i)]:</B></td><td><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags & ABSTRACT)) ? I : "<font color=grey>Empty</font>"]</a></td></tr>"
dat += "<tr><td><B>[get_held_index_name(i)]:</B></td><td><A href='?src=\ref[src];item=[slot_hands];hand_index=[i]'>[(I && !(I.flags_1 & ABSTRACT_1)) ? I : "<font color=grey>Empty</font>"]</a></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Back:</B></td><td><A href='?src=\ref[src];item=[slot_back]'>[(back && !(back.flags&ABSTRACT)) ? back : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(back, /obj/item/weapon/tank))
dat += "<tr><td><B>Back:</B></td><td><A href='?src=\ref[src];item=[slot_back]'>[(back && !(back.flags_1&ABSTRACT_1)) ? back : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(back, /obj/item/tank))
dat += "&nbsp;<A href='?src=\ref[src];internal=[slot_back]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr><tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Head:</B></td><td><A href='?src=\ref[src];item=[slot_head]'>[(head && !(head.flags&ABSTRACT)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Head:</B></td><td><A href='?src=\ref[src];item=[slot_head]'>[(head && !(head.flags_1&ABSTRACT_1)) ? head : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_wear_mask in obscured)
dat += "<tr><td><font color=grey><B>Mask:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Mask:</B></td><td><A href='?src=\ref[src];item=[slot_wear_mask]'>[(wear_mask && !(wear_mask.flags&ABSTRACT)) ? wear_mask : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Mask:</B></td><td><A href='?src=\ref[src];item=[slot_wear_mask]'>[(wear_mask && !(wear_mask.flags_1&ABSTRACT_1)) ? wear_mask : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_neck in obscured)
dat += "<tr><td><font color=grey><B>Neck:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Neck:</B></td><td><A href='?src=\ref[src];item=[slot_neck]'>[(wear_neck && !(wear_neck.flags&ABSTRACT)) ? wear_neck : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Neck:</B></td><td><A href='?src=\ref[src];item=[slot_neck]'>[(wear_neck && !(wear_neck.flags_1&ABSTRACT_1)) ? wear_neck : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_glasses in obscured)
dat += "<tr><td><font color=grey><B>Eyes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Eyes:</B></td><td><A href='?src=\ref[src];item=[slot_glasses]'>[(glasses && !(glasses.flags&ABSTRACT)) ? glasses : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Eyes:</B></td><td><A href='?src=\ref[src];item=[slot_glasses]'>[(glasses && !(glasses.flags_1&ABSTRACT_1)) ? glasses : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_ears in obscured)
dat += "<tr><td><font color=grey><B>Ears:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Ears:</B></td><td><A href='?src=\ref[src];item=[slot_ears]'>[(ears && !(ears.flags&ABSTRACT)) ? ears : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Ears:</B></td><td><A href='?src=\ref[src];item=[slot_ears]'>[(ears && !(ears.flags_1&ABSTRACT_1)) ? ears : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;</td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=\ref[src];item=[slot_wear_suit]'>[(wear_suit && !(wear_suit.flags&ABSTRACT)) ? wear_suit : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Exosuit:</B></td><td><A href='?src=\ref[src];item=[slot_wear_suit]'>[(wear_suit && !(wear_suit.flags_1&ABSTRACT_1)) ? wear_suit : "<font color=grey>Empty</font>"]</A></td></tr>"
if(wear_suit)
dat += "<tr><td>&nbsp;&#8627;<B>Suit Storage:</B></td><td><A href='?src=\ref[src];item=[slot_s_store]'>[(s_store && !(s_store.flags&ABSTRACT)) ? s_store : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(s_store, /obj/item/weapon/tank))
dat += "<tr><td>&nbsp;&#8627;<B>Suit Storage:</B></td><td><A href='?src=\ref[src];item=[slot_s_store]'>[(s_store && !(s_store.flags_1&ABSTRACT_1)) ? s_store : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(s_store, /obj/item/tank))
dat += "&nbsp;<A href='?src=\ref[src];internal=[slot_s_store]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr>"
else
@@ -190,30 +186,30 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
if(slot_shoes in obscured)
dat += "<tr><td><font color=grey><B>Shoes:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Shoes:</B></td><td><A href='?src=\ref[src];item=[slot_shoes]'>[(shoes && !(shoes.flags&ABSTRACT)) ? shoes : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Shoes:</B></td><td><A href='?src=\ref[src];item=[slot_shoes]'>[(shoes && !(shoes.flags_1&ABSTRACT_1)) ? shoes : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_gloves in obscured)
dat += "<tr><td><font color=grey><B>Gloves:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Gloves:</B></td><td><A href='?src=\ref[src];item=[slot_gloves]'>[(gloves && !(gloves.flags&ABSTRACT)) ? gloves : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Gloves:</B></td><td><A href='?src=\ref[src];item=[slot_gloves]'>[(gloves && !(gloves.flags_1&ABSTRACT_1)) ? gloves : "<font color=grey>Empty</font>"]</A></td></tr>"
if(slot_w_uniform in obscured)
dat += "<tr><td><font color=grey><B>Uniform:</B></font></td><td><font color=grey>Obscured</font></td></tr>"
else
dat += "<tr><td><B>Uniform:</B></td><td><A href='?src=\ref[src];item=[slot_w_uniform]'>[(w_uniform && !(w_uniform.flags&ABSTRACT)) ? w_uniform : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td><B>Uniform:</B></td><td><A href='?src=\ref[src];item=[slot_w_uniform]'>[(w_uniform && !(w_uniform.flags_1&ABSTRACT_1)) ? w_uniform : "<font color=grey>Empty</font>"]</A></td></tr>"
if((w_uniform == null && !(dna && dna.species.nojumpsuit)) || (slot_w_uniform in obscured))
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Pockets:</B></font></td></tr>"
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>ID:</B></font></td></tr>"
dat += "<tr><td><font color=grey>&nbsp;&#8627;<B>Belt:</B></font></td></tr>"
else
dat += "<tr><td>&nbsp;&#8627;<B>Belt:</B></td><td><A href='?src=\ref[src];item=[slot_belt]'>[(belt && !(belt.flags&ABSTRACT)) ? belt : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(belt, /obj/item/weapon/tank))
dat += "<tr><td>&nbsp;&#8627;<B>Belt:</B></td><td><A href='?src=\ref[src];item=[slot_belt]'>[(belt && !(belt.flags_1&ABSTRACT_1)) ? belt : "<font color=grey>Empty</font>"]</A>"
if(has_breathable_mask && istype(belt, /obj/item/tank))
dat += "&nbsp;<A href='?src=\ref[src];internal=[slot_belt]'>[internal ? "Disable Internals" : "Set Internals"]</A>"
dat += "</td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Pockets:</B></td><td><A href='?src=\ref[src];pockets=left'>[(l_store && !(l_store.flags&ABSTRACT)) ? "Left (Full)" : "<font color=grey>Left (Empty)</font>"]</A>"
dat += "&nbsp;<A href='?src=\ref[src];pockets=right'>[(r_store && !(r_store.flags&ABSTRACT)) ? "Right (Full)" : "<font color=grey>Right (Empty)</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>ID:</B></td><td><A href='?src=\ref[src];item=[slot_wear_id]'>[(wear_id && !(wear_id.flags&ABSTRACT)) ? wear_id : "<font color=grey>Empty</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>Pockets:</B></td><td><A href='?src=\ref[src];pockets=left'>[(l_store && !(l_store.flags_1&ABSTRACT_1)) ? "Left (Full)" : "<font color=grey>Left (Empty)</font>"]</A>"
dat += "&nbsp;<A href='?src=\ref[src];pockets=right'>[(r_store && !(r_store.flags_1&ABSTRACT_1)) ? "Right (Full)" : "<font color=grey>Right (Empty)</font>"]</A></td></tr>"
dat += "<tr><td>&nbsp;&#8627;<B>ID:</B></td><td><A href='?src=\ref[src];item=[slot_wear_id]'>[(wear_id && !(wear_id.flags_1&ABSTRACT_1)) ? wear_id : "<font color=grey>Empty</font>"]</A></td></tr>"
if(handcuffed)
dat += "<tr><td><B>Handcuffed:</B> <A href='?src=\ref[src];item=[slot_handcuffed]'>Remove</A></td></tr>"
@@ -275,11 +271,11 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
var/obj/item/place_item = usr.get_active_held_item() // Item to place in the pocket, if it's empty
var/delay_denominator = 1
if(pocket_item && !(pocket_item.flags&ABSTRACT))
if(pocket_item.flags & NODROP)
if(pocket_item && !(pocket_item.flags_1&ABSTRACT_1))
if(pocket_item.flags_1 & NODROP_1)
to_chat(usr, "<span class='warning'>You try to empty [src]'s [pocket_side] pocket, it seems to be stuck!</span>")
to_chat(usr, "<span class='notice'>You try to empty [src]'s [pocket_side] pocket.</span>")
else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.flags&ABSTRACT))
else if(place_item && place_item.mob_can_equip(src, usr, pocket_id, 1) && !(place_item.flags_1&ABSTRACT_1))
to_chat(usr, "<span class='notice'>You try to place [place_item] into [src]'s [pocket_side] pocket.</span>")
delay_denominator = 4
else
@@ -319,7 +315,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
return
else if(!istype(H.glasses, /obj/item/clothing/glasses/hud) && !istype(H.getorganslot("eye_hud"), /obj/item/organ/cyberimp/eyes/hud/medical))
return
var/obj/item/weapon/photo/P = null
var/obj/item/photo/P = null
if(href_list["photo_front"])
P = R.fields["photo_front"]
else if(href_list["photo_side"])
@@ -525,10 +521,10 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
// If targeting the head, see if the head item is thin enough.
// If targeting anything else, see if the wear suit is thin enough.
if(above_neck(target_zone))
if(head && head.flags & THICKMATERIAL && !penetrate_thick)
if(head && head.flags_1 & THICKMATERIAL_1 && !penetrate_thick)
. = 0
else
if(wear_suit && wear_suit.flags & THICKMATERIAL && !penetrate_thick)
if(wear_suit && wear_suit.flags_1 & THICKMATERIAL_1 && !penetrate_thick)
. = 0
if(!. && error_msg && user)
// Might need re-wording.
@@ -573,23 +569,23 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if(istype(wear_suit, /obj/item/clothing/suit/redtag))
threatcount += 4
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag))
if(is_holding_item_of_type(/obj/item/gun/energy/laser/redtag))
threatcount += 4
if(istype(belt, /obj/item/weapon/gun/energy/laser/redtag))
if(istype(belt, /obj/item/gun/energy/laser/redtag))
threatcount += 2
if(lasercolor == "r")
if(istype(wear_suit, /obj/item/clothing/suit/bluetag))
threatcount += 4
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag))
if(is_holding_item_of_type(/obj/item/gun/energy/laser/bluetag))
threatcount += 4
if(istype(belt, /obj/item/weapon/gun/energy/laser/bluetag))
if(istype(belt, /obj/item/gun/energy/laser/bluetag))
threatcount += 2
return threatcount
//Check for ID
var/obj/item/weapon/card/id/idcard = get_idcard()
var/obj/item/card/id/idcard = get_idcard()
if( (judgement_criteria & JUDGE_IDCHECK) && !idcard && name=="Unknown")
threatcount += 4
@@ -617,10 +613,10 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
//Check for dresscode violations
if(istype(head, /obj/item/clothing/head/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/wizard) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/syndi) || istype(head, /obj/item/clothing/head/helmet/space/hardsuit/shielded/syndi))
threatcount += 5
threatcount += 6
//Check for nonhuman scum
if(dna && dna.species.id && dna.species.id != "human" || "lizard" || "mammal" || "avian" || "aquatic" || "insect")
if(dna && dna.species.id && !(dna.species.id in list("human" , "lizard", "mammal", "avian", "aquatic", "insect")))
threatcount += 1
//mindshield implants imply trustworthyness
@@ -628,7 +624,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
threatcount -= 1
//Agent cards lower threatlevel.
if(istype(idcard, /obj/item/weapon/card/id/syndicate))
if(istype(idcard, /obj/item/card/id/syndicate))
threatcount -= 2
return threatcount
@@ -442,7 +442,7 @@
else if(S.siemens_coefficient == (-1))
total_coeff -= 1
siemens_coeff = total_coeff
if(HAS_SECONDARY_FLAG(src, TESLA_IGNORE))
if(flags_2 & TESLA_IGNORE_2)
siemens_coeff = 0
else if(!safety)
var/gloves_siemens_coeff = 1
@@ -12,7 +12,7 @@
//gets assignment from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job")
var/obj/item/weapon/card/id/id = get_idcard()
var/obj/item/card/id/id = get_idcard()
if(id)
. = id.assignment
else
@@ -27,7 +27,7 @@
//gets name from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_authentification_name(if_no_id = "Unknown")
var/obj/item/weapon/card/id/id = get_idcard()
var/obj/item/card/id/id = get_idcard()
if(id)
return id.registered_name
var/obj/item/device/pda/pda = wear_id
@@ -63,9 +63,9 @@
//gets name from ID or PDA itself, ID inside PDA doesn't matter
//Useful when player is being seen by other mobs
/mob/living/carbon/human/proc/get_id_name(if_no_id = "Unknown")
var/obj/item/weapon/storage/wallet/wallet = wear_id
var/obj/item/storage/wallet/wallet = wear_id
var/obj/item/device/pda/pda = wear_id
var/obj/item/weapon/card/id/id = wear_id
var/obj/item/card/id/id = wear_id
var/obj/item/device/modular_computer/tablet/tablet = wear_id
if(istype(wallet))
id = wallet.front_id
@@ -74,7 +74,7 @@
else if(istype(pda))
. = pda.owner
else if(istype(tablet))
var/obj/item/weapon/computer_hardware/card_slot/card_slot = tablet.all_components[MC_CARD]
var/obj/item/computer_hardware/card_slot/card_slot = tablet.all_components[MC_CARD]
if(card_slot && (card_slot.stored_card2 || card_slot.stored_card))
if(card_slot.stored_card2) //The second card is the one used for authorization in the ID changing program, so we prioritize it here for consistency
. = card_slot.stored_card2.registered_name
@@ -94,10 +94,10 @@
/mob/living/carbon/human/abiotic(full_body = 0)
var/abiotic_hands = FALSE
for(var/obj/item/I in held_items)
if(!(I.flags & NODROP))
if(!(I.flags_1 & NODROP_1))
abiotic_hands = TRUE
break
if(full_body && abiotic_hands && ((back && !(back.flags&NODROP)) || (wear_mask && !(wear_mask.flags&NODROP)) || (head && !(head.flags&NODROP)) || (shoes && !(shoes.flags&NODROP)) || (w_uniform && !(w_uniform.flags&NODROP)) || (wear_suit && !(wear_suit.flags&NODROP)) || (glasses && !(glasses.flags&NODROP)) || (ears && !(ears.flags&NODROP)) || (gloves && !(gloves.flags&NODROP)) ) )
if(full_body && abiotic_hands && ((back && !(back.flags_1&NODROP_1)) || (wear_mask && !(wear_mask.flags_1&NODROP_1)) || (head && !(head.flags_1&NODROP_1)) || (shoes && !(shoes.flags_1&NODROP_1)) || (w_uniform && !(w_uniform.flags_1&NODROP_1)) || (wear_suit && !(wear_suit.flags_1&NODROP_1)) || (glasses && !(glasses.flags_1&NODROP_1)) || (ears && !(ears.flags_1&NODROP_1)) || (gloves && !(gloves.flags_1&NODROP_1)) ) )
return TRUE
return abiotic_hands
@@ -114,7 +114,7 @@
/mob/living/carbon/human/can_track(mob/living/user)
if(wear_id && istype(wear_id.GetID(), /obj/item/weapon/card/id/syndicate))
if(wear_id && istype(wear_id.GetID(), /obj/item/card/id/syndicate))
return 0
if(istype(head, /obj/item/clothing/head))
var/obj/item/clothing/head/hat = head
@@ -143,19 +143,19 @@
var/protection = (prot["head"] + prot["arms"] + prot["feet"] + prot["legs"] + prot["groin"] + prot["chest"] + prot["hands"])/7
return protection
/mob/living/carbon/human/can_use_guns(var/obj/item/weapon/G)
/mob/living/carbon/human/can_use_guns(obj/item/G)
. = ..()
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
if(src.dna.check_mutation(HULK))
to_chat(src, "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>")
return 0
return FALSE
if(NOGUNS in src.dna.species.species_traits)
to_chat(src, "<span class='warning'>Your fingers don't fit in the trigger guard!</span>")
return 0
return FALSE
if(mind)
if(mind.martial_art && mind.martial_art.no_guns) //great dishonor to famiry
to_chat(src, "<span class='warning'>Use of ranged weaponry would bring dishonor to the clan.</span>")
return 0
return FALSE
return .
@@ -5,13 +5,13 @@
. += dna.species.movement_delay(src)
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(isobj(shoes) && (shoes.flags&NOSLIP) && !(lube&GALOSHES_DONT_HELP))
if(isobj(shoes) && (shoes.flags_1&NOSLIP_1) && !(lube&GALOSHES_DONT_HELP))
return 0
return ..()
/mob/living/carbon/human/experience_pressure_difference()
playsound(src, 'sound/effects/space_wind.ogg', 50, 1)
if(shoes && shoes.flags&NOSLIP)
if(shoes && shoes.flags_1&NOSLIP_1)
return 0
return ..()
@@ -45,13 +45,13 @@
var/list/blacklistItems = list() // items we should be ignoring
var/maxStepsTick = 6 // step as many times as we can per frame
//Job and mind data
var/obj/item/weapon/card/id/MYID
var/obj/item/weapon/card/id/RPID // the "real" idea they use
var/obj/item/card/id/MYID
var/obj/item/card/id/RPID // the "real" idea they use
var/obj/item/device/pda/MYPDA
var/obj/item/main_hand
var/obj/item/other_hand
var/TRAITS = 0
var/obj/item/weapon/card/id/Path_ID
var/obj/item/card/id/Path_ID
var/datum/job/myjob
var/list/myPath = list()
faction = list("synth")
@@ -87,17 +87,28 @@
/// SNPC voice handling
/mob/living/carbon/human/interactive/proc/loadVoice()
var/savefile/S = new /savefile("data/npc_saves/snpc.sav")
S["knownStrings"] >> knownStrings
if(fexists("data/npc_saves/snpc.sav"))
var/savefile/S = new /savefile("data/npc_saves/snpc.sav")
S["knownStrings"] >> knownStrings
fdel(S)
else
var/json_file = file("data/npc_saves/snpc.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
knownStrings = json["knownStrings"]
if(isnull(knownStrings))
knownStrings = list()
/mob/living/carbon/human/interactive/proc/saveVoice()
if(voice_saved)
return
var/savefile/S = new /savefile("data/npc_saves/snpc.sav")
WRITE_FILE(S["knownStrings"], knownStrings)
var/json_file = file("data/npc_saves/snpc.json")
var/list/file_data = list()
file_data["knownStrings"] = knownStrings
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
//botPool funcs
/mob/living/carbon/human/interactive/proc/takeDelegate(mob/living/carbon/human/interactive/from,doReset=TRUE)
@@ -249,7 +260,7 @@
T.loc = pick(get_area_turfs(T.job2area(T.myjob)))
/mob/living/carbon/human/interactive/proc/doSetup()
Path_ID = new /obj/item/weapon/card/id(src)
Path_ID = new /obj/item/card/id(src)
var/datum/job/captain/C = new/datum/job/captain
Path_ID.access = C.get_access()
@@ -286,34 +297,34 @@
if("Assistant")
favoured_types = list(/obj/item/clothing, /obj/item/weapon)
if("Captain","Head of Personnel")
favoured_types = list(/obj/item/clothing, /obj/item/weapon/stamp/captain, /obj/item/weapon/disk/nuclear)
favoured_types = list(/obj/item/clothing, /obj/item/stamp/captain, /obj/item/disk/nuclear)
if("Cook")
favoured_types = list(/obj/item/weapon/reagent_containers/food, /obj/item/weapon/kitchen)
favoured_types = list(/obj/item/reagent_containers/food, /obj/item/kitchen)
functions += "souschef"
restrictedJob = 1
if("Bartender")
favoured_types = list(/obj/item/weapon/reagent_containers/food, /obj/item/weapon/kitchen)
favoured_types = list(/obj/item/reagent_containers/food, /obj/item/kitchen)
functions += "bartend"
restrictedJob = 1
if("Station Engineer","Chief Engineer","Atmospheric Technician")
favoured_types = list(/obj/item/stack, /obj/item/weapon, /obj/item/clothing)
if("Chief Medical Officer","Medical Doctor","Chemist","Virologist","Geneticist")
favoured_types = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/storage/firstaid, /obj/item/stack/medical, /obj/item/weapon/reagent_containers/syringe)
favoured_types = list(/obj/item/reagent_containers/glass/beaker, /obj/item/storage/firstaid, /obj/item/stack/medical, /obj/item/reagent_containers/syringe)
functions += "healpeople"
if("Research Director","Scientist","Roboticist")
favoured_types = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/stack, /obj/item/weapon/reagent_containers)
favoured_types = list(/obj/item/reagent_containers/glass/beaker, /obj/item/stack, /obj/item/reagent_containers)
if("Head of Security","Warden","Security Officer","Detective")
favoured_types = list(/obj/item/clothing, /obj/item/weapon, /obj/item/weapon/restraints)
favoured_types = list(/obj/item/clothing, /obj/item/weapon, /obj/item/restraints)
if("Janitor")
favoured_types = list(/obj/item/weapon/mop, /obj/item/weapon/reagent_containers/glass/bucket, /obj/item/weapon/reagent_containers/spray/cleaner, /obj/effect/decal/cleanable)
favoured_types = list(/obj/item/mop, /obj/item/reagent_containers/glass/bucket, /obj/item/reagent_containers/spray/cleaner, /obj/effect/decal/cleanable)
functions += "dojanitor"
if("Clown")
favoured_types = list(/obj/item/weapon/soap, /obj/item/weapon/reagent_containers/food/snacks/grown/banana, /obj/item/weapon/grown/bananapeel)
favoured_types = list(/obj/item/soap, /obj/item/reagent_containers/food/snacks/grown/banana, /obj/item/grown/bananapeel)
functions += "clowning"
if("Mime")
functions -= "chatter"
if("Botanist")
favoured_types = list(/obj/machinery/hydroponics, /obj/item/weapon/reagent_containers, /obj/item/weapon)
favoured_types = list(/obj/machinery/hydroponics, /obj/item/reagent_containers, /obj/item/weapon)
functions += "botany"
restrictedJob = 1
else
@@ -505,7 +516,7 @@
/mob/living/carbon/human/interactive/proc/insert_into_backpack()
var/list/slots = list ("left pocket" = slot_l_store,"right pocket" = slot_r_store,"left hand" = slot_hands,"right hand" = slot_hands)
var/obj/item/I = get_item_by_slot(pick(slots))
var/obj/item/weapon/storage/BP = get_item_by_slot(slot_back)
var/obj/item/storage/BP = get_item_by_slot(slot_back)
if(back && BP && I)
if(BP.can_be_inserted(I,0))
BP.handle_item_insertion(I,0)
@@ -634,7 +645,7 @@
//---------ITEMS
if(isitem(TARGET))
if(istype(TARGET, /obj/item/weapon))
var/obj/item/weapon/W = TARGET
var/obj/item/W = TARGET
if(W.force >= best_force || prob((FUZZY_CHANCE_LOW+FUZZY_CHANCE_HIGH)/2))
if(!get_item_for_held_index(1) || !get_item_for_held_index(2))
put_in_hands(W)
@@ -660,7 +671,7 @@
if(istype(TARGET, /obj/structure))
var/obj/structure/STR = TARGET
if(main_hand)
var/obj/item/weapon/W = main_hand
var/obj/item/W = main_hand
STR.attackby(W, src)
else
STR.attack_hand(src)
@@ -960,7 +971,7 @@
inactivity_period = 0
customEmote("[src]'s chest closes, hiding their insides.")
if(SNPC_PSYCHO)
var/choice = pick(typesof(/obj/item/weapon/grenade/chem_grenade) - /obj/item/weapon/grenade/chem_grenade)
var/choice = pick(typesof(/obj/item/grenade/chem_grenade) - /obj/item/grenade/chem_grenade)
new choice(src)
@@ -976,13 +987,13 @@
var/list/allContents = getAllContents()
var/obj/item/weapon/reagent_containers/glass/beaker/bluespace/internalBeaker = locate(/obj/item/weapon/reagent_containers/glass/beaker/bluespace) in allContents
var/obj/item/weapon/storage/bag/plants/internalBag = locate(/obj/item/weapon/storage/bag/plants) in allContents
var/obj/item/reagent_containers/glass/beaker/bluespace/internalBeaker = locate(/obj/item/reagent_containers/glass/beaker/bluespace) in allContents
var/obj/item/storage/bag/plants/internalBag = locate(/obj/item/storage/bag/plants) in allContents
if(!internalBag)
internalBag = new/obj/item/weapon/storage/bag/plants(src)
internalBag = new/obj/item/storage/bag/plants(src)
if(!internalBeaker)
internalBeaker = new/obj/item/weapon/reagent_containers/glass/beaker/bluespace(src)
internalBeaker = new/obj/item/reagent_containers/glass/beaker/bluespace(src)
internalBeaker.name = "Grow-U-All Super Spray"
if(internalBeaker && internalBag)
@@ -1049,7 +1060,7 @@
if(change)
HP.attackby(internalBeaker,src)
var/obj/item/weapon/reagent_containers/food/snacks/grown/GF = locate(/obj/item/weapon/reagent_containers/food/snacks/grown) in view(12,src)
var/obj/item/reagent_containers/food/snacks/grown/GF = locate(/obj/item/reagent_containers/food/snacks/grown) in view(12,src)
if(GF)
if(!Adjacent(GF))
tryWalk(get_turf(GF))
@@ -1084,7 +1095,7 @@
var/mob/living/carbon/human/serveTarget
for(var/mob/living/carbon/human/H in rangeCheck)
if(!locate(/obj/item/weapon/reagent_containers/food/drinks) in orange(1,H))
if(!locate(/obj/item/reagent_containers/food/drinks) in orange(1,H))
serveTarget = H
@@ -1095,9 +1106,9 @@
if(!Adjacent(RT))
tryWalk(get_turf(RT))
else
var/drinkChoice = pick(typesof(/obj/item/weapon/reagent_containers/food/drinks) - /obj/item/weapon/reagent_containers/food/drinks)
var/drinkChoice = pick(typesof(/obj/item/reagent_containers/food/drinks) - /obj/item/reagent_containers/food/drinks)
if(drinkChoice)
var/obj/item/weapon/reagent_containers/food/drinks/D = new drinkChoice(get_turf(src))
var/obj/item/reagent_containers/food/drinks/D = new drinkChoice(get_turf(src))
RT.attackby(D,src)
src.say("[pick("Something to wet your whistle!","Down the hatch, a tasty beverage!","One drink, coming right up!","Tasty liquid for your oral intake!","Enjoy!")]")
customEmote("[src] [pick("gibbers","drools","slobbers","claps wildly","spits")], serving up a [D]!")
@@ -1115,7 +1126,7 @@
if(retal && TARGET)
for(var/obj/item/I in allContents)
if(istype(I, /obj/item/weapon/restraints))
if(istype(I, /obj/item/restraints))
I.attack(TARGET,src) // go go bluespace restraint launcher!
inactivity_period = 25
break
@@ -1129,17 +1140,17 @@
var/mob/living/carbon/human/clownTarget
var/list/clownPriority = list()
var/obj/item/weapon/reagent_containers/spray/S = locate(/obj/item/weapon/reagent_containers/spray) in allContents
var/obj/item/reagent_containers/spray/S = locate(/obj/item/reagent_containers/spray) in allContents
if(!S)
S = new/obj/item/weapon/reagent_containers/spray(src)
S = new/obj/item/reagent_containers/spray(src)
S.amount_per_transfer_from_this = 10
for(var/mob/living/carbon/human/C in rangeCheck)
var/pranksNearby = 100
for(var/turf/open/T in orange(1,C))
for(var/obj/item/A in T)
if(istype(A, /obj/item/weapon/soap) || istype(A, /obj/item/weapon/reagent_containers/food/snacks/grown/banana) || istype(A, /obj/item/weapon/grown/bananapeel))
if(istype(A, /obj/item/soap) || istype(A, /obj/item/reagent_containers/food/snacks/grown/banana) || istype(A, /obj/item/grown/bananapeel))
pranksNearby--
if(T.wet)
pranksNearby -= 10
@@ -1159,13 +1170,13 @@
var/hasPranked = 0
for(var/A in allContents)
if(prob(smartness/2) && !hasPranked)
if(istype(A, /obj/item/weapon/soap))
if(istype(A, /obj/item/soap))
npcDrop(A)
hasPranked = 1
if(istype(A, /obj/item/weapon/reagent_containers/food/snacks/grown/banana))
var/obj/item/weapon/reagent_containers/food/snacks/B = A
if(istype(A, /obj/item/reagent_containers/food/snacks/grown/banana))
var/obj/item/reagent_containers/food/snacks/B = A
B.attack(src, src)
if(istype(A, /obj/item/weapon/grown/bananapeel))
if(istype(A, /obj/item/grown/bananapeel))
npcDrop(A)
hasPranked = 1
if(!hasPranked)
@@ -1185,12 +1196,12 @@
shouldTryHeal = 1
M = A
var/obj/item/weapon/reagent_containers/hypospray/HPS
var/obj/item/reagent_containers/hypospray/HPS
if(!locate(/obj/item/weapon/reagent_containers/hypospray) in allContents)
new/obj/item/weapon/reagent_containers/hypospray(src)
if(!locate(/obj/item/reagent_containers/hypospray) in allContents)
new/obj/item/reagent_containers/hypospray(src)
else
HPS = locate(/obj/item/weapon/reagent_containers/hypospray) in allContents
HPS = locate(/obj/item/reagent_containers/hypospray) in allContents
if(!shouldTryHeal)
shouldTryHeal = 2 // we have no stackables to use, lets use our internal hypospray instead
@@ -1222,11 +1233,11 @@
return
var/list/allContents = getAllContents()
//now with bluespace magic!
var/obj/item/weapon/reagent_containers/spray/S
if(!locate(/obj/item/weapon/reagent_containers/spray) in allContents)
new/obj/item/weapon/reagent_containers/spray(src)
var/obj/item/reagent_containers/spray/S
if(!locate(/obj/item/reagent_containers/spray) in allContents)
new/obj/item/reagent_containers/spray(src)
else
S = locate(/obj/item/weapon/reagent_containers/spray) in allContents
S = locate(/obj/item/reagent_containers/spray) in allContents
if(S)
if(S.reagents.total_volume <= 5)
@@ -1246,10 +1257,10 @@
visible_message("<span class='notice'>[text]</span>")
// START COOKING MODULE
/mob/living/carbon/human/interactive/proc/cookingwithmagic(var/obj/item/weapon/reagent_containers/food/snacks/target)
/mob/living/carbon/human/interactive/proc/cookingwithmagic(var/obj/item/reagent_containers/food/snacks/target)
if(Adjacent(target))
customEmote("[src] [pick("gibbers","drools","slobbers","claps wildly","spits")] towards [target], and with a bang, it's instantly cooked!")
var/obj/item/weapon/reagent_containers/food/snacks/S = new target.cooked_type (get_turf(src))
var/obj/item/reagent_containers/food/snacks/S = new target.cooked_type (get_turf(src))
target.initialize_cooked_food(S, 100)
if(target) // cleaning up old food seems inconsistent, so this will clean up stragglers
qdel(target)
@@ -1266,13 +1277,13 @@
var/list/allContents = getAllContents()
//Bluespace in some inbuilt tools
var/obj/item/weapon/kitchen/rollingpin/RP = locate(/obj/item/weapon/kitchen/rollingpin) in allContents
var/obj/item/kitchen/rollingpin/RP = locate(/obj/item/kitchen/rollingpin) in allContents
if(!RP)
new/obj/item/weapon/kitchen/rollingpin(src)
new/obj/item/kitchen/rollingpin(src)
var/obj/item/weapon/kitchen/knife/KK = locate(/obj/item/weapon/kitchen/knife) in allContents
var/obj/item/kitchen/knife/KK = locate(/obj/item/kitchen/knife) in allContents
if(!KK)
new/obj/item/weapon/kitchen/knife(src)
new/obj/item/kitchen/knife(src)
var/foundCookable = 0
@@ -1281,11 +1292,11 @@
var/list/rangeCheck = view(6,src)
//Make some basic custom food
var/list/customableTypes = list(/obj/item/weapon/reagent_containers/food/snacks/customizable, /obj/item/weapon/reagent_containers/food/snacks/store/bread/plain, /obj/item/weapon/reagent_containers/food/snacks/pizzabread, /obj/item/weapon/reagent_containers/food/snacks/bun, /obj/item/weapon/reagent_containers/food/snacks/store/cake/plain, /obj/item/weapon/reagent_containers/food/snacks/pie/plain, /obj/item/weapon/reagent_containers/food/snacks/pastrybase)
var/list/customableTypes = list(/obj/item/reagent_containers/food/snacks/customizable, /obj/item/reagent_containers/food/snacks/store/bread/plain, /obj/item/reagent_containers/food/snacks/pizzabread, /obj/item/reagent_containers/food/snacks/bun, /obj/item/reagent_containers/food/snacks/store/cake/plain, /obj/item/reagent_containers/food/snacks/pie/plain, /obj/item/reagent_containers/food/snacks/pastrybase)
var/foundCustom
for(var/obj/item/weapon/reagent_containers/food/snacks/donkpocket/DP in rangeCheck) // donkpockets are hitler to chef SNPCs
for(var/obj/item/reagent_containers/food/snacks/donkpocket/DP in rangeCheck) // donkpockets are hitler to chef SNPCs
if(prob(50))
customEmote("[src] points at the [DP], emitting a loud [pick("bellow","screech","yell","scream")], and it bursts into flame.")
qdel(DP)
@@ -1309,8 +1320,8 @@
if(foundCustom)
var/obj/item/weapon/reagent_containers/food/snacks/FC = foundCustom
for(var/obj/item/weapon/reagent_containers/food/snacks/toMake in allContents)
var/obj/item/reagent_containers/food/snacks/FC = foundCustom
for(var/obj/item/reagent_containers/food/snacks/toMake in allContents)
if(prob(smartness))
if(FC.reagents)
FC.attackby(toMake,src)
@@ -1319,10 +1330,10 @@
//Process dough into various states
var/obj/item/weapon/reagent_containers/food/snacks/dough/D = locate(/obj/item/weapon/reagent_containers/food/snacks/dough) in rangeCheck
var/obj/item/weapon/reagent_containers/food/snacks/flatdough/FD = locate(/obj/item/weapon/reagent_containers/food/snacks/flatdough) in rangeCheck
var/obj/item/weapon/reagent_containers/food/snacks/cakebatter/CB = locate(/obj/item/weapon/reagent_containers/food/snacks/cakebatter) in rangeCheck
var/obj/item/weapon/reagent_containers/food/snacks/piedough/PD = locate(/obj/item/weapon/reagent_containers/food/snacks/piedough) in rangeCheck
var/obj/item/reagent_containers/food/snacks/dough/D = locate(/obj/item/reagent_containers/food/snacks/dough) in rangeCheck
var/obj/item/reagent_containers/food/snacks/flatdough/FD = locate(/obj/item/reagent_containers/food/snacks/flatdough) in rangeCheck
var/obj/item/reagent_containers/food/snacks/cakebatter/CB = locate(/obj/item/reagent_containers/food/snacks/cakebatter) in rangeCheck
var/obj/item/reagent_containers/food/snacks/piedough/PD = locate(/obj/item/reagent_containers/food/snacks/piedough) in rangeCheck
if(D)
TARGET = D
@@ -1367,7 +1378,7 @@
//Cook various regular foods into processed versions
var/obj/item/weapon/reagent_containers/food/snacks/toCook = locate(/obj/item/weapon/reagent_containers/food/snacks) in rangeCheck
var/obj/item/reagent_containers/food/snacks/toCook = locate(/obj/item/reagent_containers/food/snacks) in rangeCheck
if(toCook)
if(toCook.cooked_type)
TARGET = toCook
@@ -1378,11 +1389,11 @@
tryWalk(get_turf(toCook))
var/list/finishedList = list()
for(var/obj/item/weapon/reagent_containers/food/snacks/toDisplay in allContents)
if(!toDisplay.cooked_type && !istype(toDisplay, /obj/item/weapon/reagent_containers/food/snacks/grown)) // dont display our ingredients
for(var/obj/item/reagent_containers/food/snacks/toDisplay in allContents)
if(!toDisplay.cooked_type && !istype(toDisplay, /obj/item/reagent_containers/food/snacks/grown)) // dont display our ingredients
finishedList += toDisplay
for(var/obj/item/weapon/reagent_containers/food/snacks/toGrab in rangeCheck)
for(var/obj/item/reagent_containers/food/snacks/toGrab in rangeCheck)
if(!(locate(/obj/structure/table/reinforced) in get_turf(toGrab))) //it's not being displayed
foundCookable = 1
if(!Adjacent(toGrab))
@@ -1395,7 +1406,7 @@
for(var/obj/structure/table/reinforced/toCheck in rangeCheck)
var/counted = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/S in get_turf(toCheck))
for(var/obj/item/reagent_containers/food/snacks/S in get_turf(toCheck))
++counted
if(counted < 12) // make sure theres not too much food here
RT = toCheck
@@ -1406,20 +1417,20 @@
if(!Adjacent(RT))
tryWalk(get_turf(RT))
else
for(var/obj/item/weapon/reagent_containers/food/snacks/toPlop in allContents)
for(var/obj/item/reagent_containers/food/snacks/toPlop in allContents)
RT.attackby(toPlop,src)
if(!foundCookable)
var/list/allTypes = list(/obj/item/weapon/reagent_containers/food/snacks/piedough, /obj/item/weapon/reagent_containers/food/snacks/cakebatter, /obj/item/weapon/reagent_containers/food/snacks/dough, /obj/item/weapon/reagent_containers/food/snacks/flatdough)
var/list/allTypes = list(/obj/item/reagent_containers/food/snacks/piedough, /obj/item/reagent_containers/food/snacks/cakebatter, /obj/item/reagent_containers/food/snacks/dough, /obj/item/reagent_containers/food/snacks/flatdough)
for(var/A in typesof(/obj/item/weapon/reagent_containers/food/snacks))
var/obj/item/weapon/reagent_containers/food/snacks/O = A
for(var/A in typesof(/obj/item/reagent_containers/food/snacks))
var/obj/item/reagent_containers/food/snacks/O = A
if(initial(O.cooked_type))
allTypes += A
var/chosenType = pick(allTypes)
var/obj/item/weapon/reagent_containers/food/snacks/newSnack = new chosenType(get_turf(src))
var/obj/item/reagent_containers/food/snacks/newSnack = new chosenType(get_turf(src))
TARGET = newSnack
newSnack.reagents.remove_any((newSnack.reagents.total_volume/2)-1)
newSnack.name = "Synthetic [newSnack.name]"
@@ -1463,7 +1474,7 @@
//ensure we're using the best object possible
var/obj/item/weapon/best
var/obj/item/best
var/foundFav = 0
var/list/allContents = getAllContents()
for(var/test in allContents)
@@ -1474,15 +1485,15 @@
return
if(!foundFav)
if(istype(test, /obj/item/weapon))
var/obj/item/weapon/R = test
var/obj/item/R = test
if(R.force > 2) // make sure we don't equip any non-weaponlike items, ie bags and stuff
if(!best)
best = R
else
if(best.force < R.force)
best = R
if(istype(R, /obj/item/weapon/gun))
var/obj/item/weapon/gun/G = R
if(istype(R, /obj/item/gun))
var/obj/item/gun/G = R
if(G.can_shoot())
best = R
break // gun with ammo? screw the rest
@@ -1495,16 +1506,16 @@
if(M.health > 1)
//THROWING OBJECTS
for(var/A in allContents)
if(istype(A, /obj/item/weapon/gun)) // guns are for shooting, not throwing.
if(istype(A, /obj/item/gun)) // guns are for shooting, not throwing.
continue
if(prob(robustness))
if(istype(A, /obj/item/weapon))
var/obj/item/weapon/W = A
var/obj/item/W = A
if(W.throwforce > 19) // Only throw worthwile stuff, no more lobbing wrenches at wenches
npcDrop(W,1)
throw_item(TARGET)
if(istype(A, /obj/item/weapon/grenade)) // Allahu ackbar! ALLAHU ACKBARR!!
var/obj/item/weapon/grenade/G = A
if(istype(A, /obj/item/grenade)) // Allahu ackbar! ALLAHU ACKBARR!!
var/obj/item/grenade/G = A
G.attack_self(src)
if(prob(smartness))
npcDrop(G,1)
@@ -1516,11 +1527,11 @@
swap_hands()
if(main_hand)
if(main_hand.force != 0)
if(istype(main_hand, /obj/item/weapon/gun))
var/obj/item/weapon/gun/G = main_hand
if(istype(main_hand, /obj/item/gun))
var/obj/item/gun/G = main_hand
if(G.can_trigger_gun(src))
if(istype(main_hand, /obj/item/weapon/gun/ballistic))
var/obj/item/weapon/gun/ballistic/P = main_hand
if(istype(main_hand, /obj/item/gun/ballistic))
var/obj/item/gun/ballistic/P = main_hand
if(!P.chambered)
P.chamber_round()
P.update_icon()
@@ -1529,8 +1540,8 @@
npcDrop(P,1)
else
P.afterattack(TARGET, src)
else if(istype(main_hand, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/P = main_hand
else if(istype(main_hand, /obj/item/gun/energy))
var/obj/item/gun/energy/P = main_hand
var/stunning = 0
for(var/A in P.ammo_type)
if(ispath(A, /obj/item/ammo_casing/energy/electrode))
@@ -1550,7 +1561,7 @@
if(!walk2derpless(TARGET))
timeout++
else
var/obj/item/weapon/W = main_hand
var/obj/item/W = main_hand
W.attack(TARGET,src)
else
G.loc = get_turf(src) // drop item works inconsistently
@@ -147,7 +147,7 @@
. = ..() //See mob.dm for an explanation on this and some rage about people copypasting instead of calling ..() like they should.
if(!. || !I)
return
if(index && dna.species.mutanthands)
if(index && !QDELETED(src) && dna.species.mutanthands) //hand freed, fill with claws, skip if we're getting deleted.
put_in_hand(new dna.species.mutanthands(), index)
if(I == wear_suit)
if(s_store && invdrop)
+11 -6
View File
@@ -32,7 +32,7 @@
//citadel code
if(stat != DEAD)
handle_arousal()
if(..()) //not dead
for(var/datum/mutation/human/HM in dna.mutations)
HM.on_life(src)
@@ -55,7 +55,9 @@
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if((wear_suit && (wear_suit.flags & STOPSPRESSUREDMAGE)) && (head && (head.flags & STOPSPRESSUREDMAGE)))
if((wear_suit && (wear_suit.flags_1 & STOPSPRESSUREDMAGE_1)) && (head && (head.flags_1 & STOPSPRESSUREDMAGE_1)))
return ONE_ATMOSPHERE
if(ismob(loc))
return ONE_ATMOSPHERE
else
return pressure
@@ -153,7 +155,7 @@
//END FIRE CODE
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
//This proc returns a number made up of the flags_1 for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = 0
//Handle normal clothing
@@ -242,6 +244,9 @@
if(dna && (RESISTCOLD in dna.species.species_traits))
return 1
if(ismob(loc))
return 1 //because lazy and being inside somemone insulates you from space
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = get_cold_protection_flags(temperature)
@@ -285,13 +290,13 @@
/mob/living/carbon/human/has_smoke_protection()
if(wear_mask)
if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT)
if(wear_mask.flags_1 & BLOCK_GAS_SMOKE_EFFECT_1)
. = 1
if(glasses)
if(glasses.flags & BLOCK_GAS_SMOKE_EFFECT)
if(glasses.flags_1 & BLOCK_GAS_SMOKE_EFFECT_1)
. = 1
if(head)
if(head.flags & BLOCK_GAS_SMOKE_EFFECT)
if(head.flags_1 & BLOCK_GAS_SMOKE_EFFECT_1)
. = 1
if(NOBREATH in dna.species.species_traits)
. = 1
+1 -1
View File
@@ -31,7 +31,7 @@
if(istype(wear_mask, /obj/item/clothing/mask/chameleon))
var/obj/item/clothing/mask/chameleon/V = wear_mask
if(V.vchange && wear_id)
var/obj/item/weapon/card/id/idcard = wear_id.GetID()
var/obj/item/card/id/idcard = wear_id.GetID()
if(istype(idcard))
return idcard.registered_name
else
+32 -30
View File
@@ -10,9 +10,9 @@
/datum/species
var/id = null // if the game needs to manually check your race to do something not included in a proc here, it will use this
var/limbs_id = null //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
var/name = null // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
var/id // if the game needs to manually check your race to do something not included in a proc here, it will use this
var/limbs_id //this is used if you want to use a different species limb sprites. Mainly used for angels as they look like humans.
var/name // this is the fluff name. these will be left generic (such as 'Lizardperson' for the lizard race) so servers can change them to whatever
var/roundstart = 0 // can this mob be chosen at roundstart? (assuming the config option is checked?)
var/default_color = "#FFF" // if alien colors are disabled, this is the color that will be used by that race
@@ -21,17 +21,21 @@
var/face_y_offset = 0
var/hair_y_offset = 0
var/hair_color = null // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
var/hair_color // this allows races to have specific hair colors... if null, it uses the H's hair/facial hair colors. if "mutcolor", it uses the H's mutant_color
var/hair_alpha = 255 // the alpha used by the hair. 255 is completely solid, 0 is transparent.
var/use_skintones = 0 // does it use skintones or not? (spoiler alert this is only used by humans)
var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id.
var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc)
var/meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human //What the species drops on gibbing
var/skinned_type = null
var/meat = /obj/item/reagent_containers/food/snacks/meat/slab/human //What the species drops on gibbing
var/skinned_type
var/liked_food = NONE
var/disliked_food = NONE
var/toxic_food = NONE
var/list/no_equip = list() // slots the race can't equip stuff to
var/nojumpsuit = 0 // this is sorta... weird. it basically lets you equip stuff that usually needs jumpsuits without one, like belts and pockets and ids
var/blacklisted = 0 //Flag to exclude from green slime core species.
var/dangerous_existence = null //A flag for transformation spells that tells them "hey if you turn a person into one of these without preperation, they'll probably die!"
var/dangerous_existence //A flag for transformation spells that tells them "hey if you turn a person into one of these without preperation, they'll probably die!"
var/say_mod = "says" // affects the speech message
var/list/default_features = list() // Default mutant bodyparts for this species. Don't forget to set one for every mutant bodypart you allow this species to have.
var/list/mutant_bodyparts = list() // Parts of the body that are diferent enough from the standard human model that they cause clipping with some equipment
@@ -50,7 +54,7 @@
var/damage_overlay_type = "human" //what kind of damage overlays (if any) appear on our species when wounded?
var/fixed_mut_color = "" //to use MUTCOLOR with a fixed color that's independent of dna.feature["mcolor"]
// species flags. these can be found in flags.dm
// species flags_1. these can be found in flags_1.dm
var/list/species_traits = list()
var/attack_verb = "punch" // punch-specific attack verb
@@ -67,23 +71,21 @@
var/obj/item/organ/eyes/mutanteyes = /obj/item/organ/eyes
var/obj/item/organ/ears/mutantears = /obj/item/organ/ears
var/obj/item/mutanthands
var/obj/item/organ/tongue/mutanttongue = /obj/item/organ/tongue
var/obj/item/organ/liver/mutantliver
var/obj/item/organ/stomach/mutantstomach
//Hands
var/obj/item/mutanthands = null
//Citadel snowflake
var/fixed_mut_color2 = ""
var/fixed_mut_color3 = ""
var/whitelisted = 0 //Is this species restricted to certain players?
var/whitelist = list() //List the ckeys that can use this species, if it's whitelisted.: list("John Doe", "poopface666", "SeeALiggerPullTheTrigger") Spaces & capitalization can be included or ignored entirely for each key as it checks for both.
///////////
// PROCS //
///////////
///////////
// PROCS //
///////////
/datum/species/New()
@@ -216,7 +218,7 @@
if(mutanthands)
// Drop items in hands
// If you're lucky enough to have a NODROP item, then it stays.
// If you're lucky enough to have a NODROP_1 item, then it stays.
for(var/V in C.held_items)
var/obj/item/I = V
if(istype(I))
@@ -411,6 +413,7 @@
standing += wear_female_version(undershirt.icon_state, undershirt.icon, BODY_LAYER)
else
standing += mutable_appearance(undershirt.icon, undershirt.icon_state, -BODY_LAYER)
if(H.socks && H.get_num_legs() >= 2 && !(DIGITIGRADE in species_traits))
var/datum/sprite_accessory/socks/socks = GLOB.socks_list[H.socks]
if(socks)
@@ -910,7 +913,7 @@
return 0
return equip_delay_self_check(I, H, bypass_equip_delay_self)
if(slot_l_store)
if(I.flags & NODROP) //Pockets aren't visible, so you can't move NODROP items into them.
if(I.flags_1 & NODROP_1) //Pockets aren't visible, so you can't move NODROP_1 items into them.
return 0
if(H.l_store)
return 0
@@ -926,7 +929,7 @@
if( I.w_class <= WEIGHT_CLASS_SMALL || (I.slot_flags & SLOT_POCKET) )
return 1
if(slot_r_store)
if(I.flags & NODROP)
if(I.flags_1 & NODROP_1)
return 0
if(H.r_store)
return 0
@@ -943,7 +946,7 @@
return 1
return 0
if(slot_s_store)
if(I.flags & NODROP)
if(I.flags_1 & NODROP_1)
return 0
if(H.s_store)
return 0
@@ -959,13 +962,13 @@
if(!disable_warning)
to_chat(H, "The [I.name] is too big to attach.") //should be src?
return 0
if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/weapon/pen) || is_type_in_list(I, H.wear_suit.allowed) )
if( istype(I, /obj/item/device/pda) || istype(I, /obj/item/pen) || is_type_in_list(I, H.wear_suit.allowed) )
return 1
return 0
if(slot_handcuffed)
if(H.handcuffed)
return 0
if(!istype(I, /obj/item/weapon/restraints/handcuffs))
if(!istype(I, /obj/item/restraints/handcuffs))
return 0
if(num_arms < 2)
return 0
@@ -973,14 +976,14 @@
if(slot_legcuffed)
if(H.legcuffed)
return 0
if(!istype(I, /obj/item/weapon/restraints/legcuffs))
if(!istype(I, /obj/item/restraints/legcuffs))
return 0
if(num_legs < 2)
return 0
return 1
if(slot_in_backpack)
if(H.back && istype(H.back, /obj/item/weapon/storage))
var/obj/item/weapon/storage/B = H.back
if(H.back && istype(H.back, /obj/item/storage))
var/obj/item/storage/B = H.back
if(B.can_be_inserted(I, 1, H))
return 1
return 0
@@ -1155,7 +1158,7 @@
gravity = 1
if(!gravity)
var/obj/item/weapon/tank/jetpack/J = H.back
var/obj/item/tank/jetpack/J = H.back
var/obj/item/clothing/suit/space/hardsuit/C = H.wear_suit
var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot("thrusters")
if(!istype(J) && istype(C))
@@ -1180,7 +1183,7 @@
if(H.back)
. += H.back.slowdown
for(var/obj/item/I in H.held_items)
if(HAS_SECONDARY_FLAG(I, SLOWS_WHILE_IN_HAND))
if(I.flags_2 & SLOWS_WHILE_IN_HAND_2)
. += I.slowdown
var/health_deficiency = (100 - H.health + H.staminaloss)
var/hungry = (500 - H.nutrition) / 5 // So overeat would be 100 and default level would be 80
@@ -1321,7 +1324,6 @@
target.apply_effect(40, KNOCKDOWN, target.run_armor_check(affecting, "melee", "Your armor prevents your fall!", "Your armor softens your fall!"))
target.forcesay(GLOB.hit_appends)
add_logs(user, target, "disarmed", " pushing them to the ground")
return
if(randn <= 60)
@@ -1329,7 +1331,6 @@
if(target.pulling)
to_chat(target, "<span class='warning'>[user] has broken [target]'s grip on [target.pulling]!</span>")
target.stop_pulling()
else
I = target.get_active_held_item()
if(target.drop_item())
@@ -1587,6 +1588,7 @@
else
H.throw_alert("temp", /obj/screen/alert/cold, 3)
H.apply_damage(COLD_DAMAGE_LEVEL_3*coldmod, BURN)
else
H.clear_alert("temp")
@@ -1695,9 +1697,9 @@
return
////////
////////////
//Stun//
////////
////////////
/datum/species/proc/spec_stun(mob/living/carbon/human/H,amount)
. = stunmod * amount
@@ -5,7 +5,9 @@
mutanttongue = /obj/item/organ/tongue/fly
mutantliver = /obj/item/organ/liver/fly
mutantstomach = /obj/item/organ/stomach/fly
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/fly
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/fly
disliked_food = null
liked_food = NONE
/datum/species/fly/handle_chemicals(datum/reagent/chem, mob/living/carbon/human/H)
if(chem.id == "pestkiller")
@@ -26,6 +28,6 @@
..()
/datum/species/fly/check_weakness(obj/item/weapon, mob/living/attacker)
if(istype(weapon, /obj/item/weapon/melee/flyswatter))
if(istype(weapon, /obj/item/melee/flyswatter))
return 29 //Flyswatters deal 30x damage to flypeople.
return 0
@@ -1,4 +1,4 @@
datum/species/mammal
/datum/species/mammal
name = "Mammal"
id = "mammal"
default_color = "4B4B4B"
@@ -9,6 +9,8 @@ datum/species/mammal
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1
liked_food = MEAT | FRIED
disliked_food = TOXIC
/datum/species/mammal/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -24,12 +26,14 @@ datum/species/mammal
say_mod = "chirps"
default_color = "BCAC9B"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("snout", "wings", "taur", "mam_tail", "mam_body_markings")
mutant_bodyparts = list("snout", "wings", "taur", "mam_tail", "mam_body_markings", "taur")
default_features = list("snout" = "Sharp", "wings" = "None", "taur" = "None", "mam_body_markings" = "Hawk")
attack_verb = "peck"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1
liked_food = MEAT | FRUIT
disliked_food = TOXIC
/datum/species/avian/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -44,12 +48,14 @@ datum/species/mammal
id = "aquatic"
default_color = "BCAC9B"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("mam_tail", "mam_body_markings", "mam_ears")
mutant_bodyparts = list("mam_tail", "mam_body_markings", "mam_ears", "taur")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF","mam_tail" = "shark", "mam_body_markings" = "None", "mam_ears" = "None")
attack_verb = "bite"
attack_sound = 'sound/weapons/bite.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1
liked_food = MEAT
disliked_food = TOXIC
/datum/species/aquatic/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -64,12 +70,14 @@ datum/species/mammal
id = "insect"
default_color = "BCAC9B"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR)
mutant_bodyparts = list("mam_body_markings", "mam_ears", "mam_tail")
mutant_bodyparts = list("mam_body_markings", "mam_ears", "mam_tail", "taur")
default_features = list("mcolor" = "FFF","mcolor2" = "FFF","mcolor3" = "FFF", "mam_body_markings" = "moth", "mam_tail" = "None", "mam_ears" = "None")
attack_verb = "flutter" //wat?
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
roundstart = 1
liked_food = MEAT | FRUIT
disliked_food = TOXIC
/datum/species/insect/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
@@ -93,11 +101,12 @@ datum/species/mammal
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
skinned_type = /obj/item/stack/sheet/animalhide/xeno
exotic_bloodtype = "L"
damage_overlay_type = "xeno"
roundstart = 1
liked_food = MEAT
//Praise the Omnissiah, A challange worthy of my skills - HS
@@ -126,7 +135,7 @@ datum/species/mammal
exotic_blood = "xblood"
damage_overlay_type = "xeno"
no_equip = list(slot_glasses) //MY EYES, THEY'RE GONE
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
skinned_type = /obj/item/stack/sheet/animalhide/xeno
// safe_toxins_max = 32 //Too much of anything is bad.
roundstart = 0
@@ -229,7 +238,7 @@ datum/species/mammal
whitelist = list("rubyflamewing")
blacklisted = 0
datum/species/guilmon
/datum/species/guilmon
name = "Guilmon"
id = "guilmon"
default_color = "4B4B4B"
@@ -14,7 +14,7 @@
nojumpsuit = 1
sexes = 1
damage_overlay_type = ""
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/golem
// To prevent golem subtypes from overwhelming the odds when random species
// changes, only the Random Golem type can be chosen
blacklisted = TRUE
@@ -56,7 +56,7 @@
/datum/species/golem/adamantine
name = "Adamantine Golem"
id = "adamantine golem"
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/golem/adamantine
mutant_organs = list(/obj/item/organ/adamantine_resonator, /obj/item/organ/vocal_cords/adamantine)
fixed_mut_color = "4ed"
info_text = "As an <span class='danger'>Adamantine Golem</span>, you possess special vocal cords allowing you to \"resonate\" messages to all golems."
@@ -67,7 +67,7 @@
name = "Plasma Golem"
id = "plasma golem"
fixed_mut_color = "a3d"
meat = /obj/item/weapon/ore/plasma
meat = /obj/item/ore/plasma
//Can burn and takes damage from heat
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOGUNS,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NODISMEMBER,MUTCOLORS,NO_UNDERWEAR)
info_text = "As a <span class='danger'>Plasma Golem</span>, you burn easily. Be careful, if you get hot enough while burning, you'll blow up!"
@@ -127,7 +127,7 @@
id = "diamond golem"
fixed_mut_color = "0ff"
armor = 70 //up from 55
meat = /obj/item/weapon/ore/diamond
meat = /obj/item/ore/diamond
info_text = "As a <span class='danger'>Diamond Golem</span>, you are more resistant than the average golem."
prefix = "Diamond"
special_names = list("Back")
@@ -139,7 +139,7 @@
fixed_mut_color = "cc0"
speedmod = 1
armor = 25 //down from 55
meat = /obj/item/weapon/ore/gold
meat = /obj/item/ore/gold
info_text = "As a <span class='danger'>Gold Golem</span>, you are faster but less resistant than the average golem."
prefix = "Golden"
@@ -149,7 +149,7 @@
id = "silver golem"
fixed_mut_color = "ddd"
punchstunthreshold = 9 //60% chance, from 40%
meat = /obj/item/weapon/ore/silver
meat = /obj/item/ore/silver
info_text = "As a <span class='danger'>Silver Golem</span>, your attacks are heavier and have a higher chance of stunning."
prefix = "Silver"
special_names = list("Surfer", "Chariot", "Lining")
@@ -164,7 +164,7 @@
punchdamagehigh = 21
punchstunthreshold = 18 //still 40% stun chance
speedmod = 4 //pretty fucking slow
meat = /obj/item/weapon/ore/iron
meat = /obj/item/ore/iron
info_text = "As a <span class='danger'>Plasteel Golem</span>, you are slower, but harder to stun, and hit very hard when punching."
attack_verb = "smash"
attack_sound = 'sound/effects/meteorimpact.ogg' //hits pretty hard
@@ -175,7 +175,7 @@
name = "Titanium Golem"
id = "titanium golem"
fixed_mut_color = "fff"
meat = /obj/item/weapon/ore/titanium
meat = /obj/item/ore/titanium
info_text = "As a <span class='danger'>Titanium Golem</span>, you are immune to ash storms, and slightly more resistant to burn damage."
burnmod = 0.9
prefix = "Titanium"
@@ -193,7 +193,7 @@
name = "Plastitanium Golem"
id = "plastitanium golem"
fixed_mut_color = "888"
meat = /obj/item/weapon/ore/titanium
meat = /obj/item/ore/titanium
info_text = "As a <span class='danger'>Plastitanium Golem</span>, you are immune to both ash storms and lava, and slightly more resistant to burn damage."
burnmod = 0.8
prefix = "Plastitanium"
@@ -284,7 +284,7 @@
name = "Uranium Golem"
id = "uranium golem"
fixed_mut_color = "7f0"
meat = /obj/item/weapon/ore/uranium
meat = /obj/item/ore/uranium
info_text = "As an <span class='danger'>Uranium Golem</span>, you emit radiation pulses every once in a while. It won't harm fellow golems, but organic lifeforms will be affected."
var/last_event = 0
@@ -305,7 +305,7 @@
name = "Sand Golem"
id = "sand golem"
fixed_mut_color = "ffdc8f"
meat = /obj/item/weapon/ore/glass //this is sand
meat = /obj/item/ore/glass //this is sand
armor = 0
burnmod = 3 //melts easily
brutemod = 0.25
@@ -318,7 +318,7 @@
for(var/obj/item/W in H)
H.dropItemToGround(W)
for(var/i=1, i <= rand(3,5), i++)
new /obj/item/weapon/ore/glass(get_turf(H))
new /obj/item/ore/glass(get_turf(H))
qdel(H)
/datum/species/golem/sand/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
@@ -335,7 +335,7 @@
name = "Glass Golem"
id = "glass golem"
fixed_mut_color = "5a96b4aa" //transparent body
meat = /obj/item/weapon/shard
meat = /obj/item/shard
armor = 0
brutemod = 3 //very fragile
burnmod = 0.25
@@ -349,7 +349,7 @@
for(var/obj/item/W in H)
H.dropItemToGround(W)
for(var/i=1, i <= rand(3,5), i++)
new /obj/item/weapon/shard(get_turf(H))
new /obj/item/shard(get_turf(H))
qdel(H)
/datum/species/golem/glass/bullet_act(obj/item/projectile/P, mob/living/carbon/human/H)
@@ -378,7 +378,7 @@
name = "Bluespace Golem"
id = "bluespace golem"
fixed_mut_color = "33f"
meat = /obj/item/weapon/ore/bluespace_crystal
meat = /obj/item/ore/bluespace_crystal
info_text = "As a <span class='danger'>Bluespace Golem</span>, are spatially unstable: you will teleport when hit, and you can teleport manually at a long distance."
attack_verb = "bluespace punch"
attack_sound = 'sound/effects/phasein.ogg'
@@ -473,7 +473,7 @@
punchdamagelow = 0
punchdamagehigh = 1
punchstunthreshold = 2 //Harmless and can't stun
meat = /obj/item/weapon/ore/bananium
meat = /obj/item/ore/bananium
info_text = "As a <span class='danger'>Bananium Golem</span>, you are made for pranking. Your body emits natural honks, and you cannot hurt people when punching them. Your skin also emits bananas when damaged."
attack_verb = "honk"
attack_sound = 'sound/items/airhorn2.ogg'
@@ -493,19 +493,19 @@
/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style)
..()
if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP)
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
..()
if(world.time > last_banana + banana_cooldown && user != H)
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
..()
if(world.time > last_banana + banana_cooldown)
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/spec_hitby(atom/movable/AM, mob/living/carbon/human/H)
@@ -516,7 +516,7 @@
if(I.thrownby == H) //No throwing stuff at yourself to make bananas
return 0
else
new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H))
new/obj/item/grown/bananapeel/specialpeel(get_turf(H))
last_banana = world.time
/datum/species/golem/bananium/spec_life(mob/living/carbon/human/H)
@@ -628,7 +628,7 @@
desc = "It emits a strange aura, as if there was still life within it..."
max_integrity = 50
armor = list(melee = 90, bullet = 90, laser = 25, energy = 80, bomb = 50, bio = 100, fire = -50, acid = -50)
icon = 'icons/obj/items.dmi'
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "pile_bandages"
resistance_flags = FLAMMABLE
@@ -672,7 +672,7 @@
cloth_golem = null
qdel(src)
/obj/structure/cloth_pile/attackby(obj/item/weapon/P, mob/living/carbon/human/user, params)
/obj/structure/cloth_pile/attackby(obj/item/P, mob/living/carbon/human/user, params)
. = ..()
if(resistance_flags & ON_FIRE)
@@ -1,25 +1,27 @@
/datum/species/human
name = "Human"
id = "human"
default_color = "FFFFFF"
species_traits = list(MUTCOLORS_PARTSONLY,EYECOLOR,HAIR,FACEHAIR,LIPS)
mutant_bodyparts = list("tail_human", "ears", "taur")
default_features = list("tail_human" = "None", "ears" = "None", "taur" = "none")
use_skintones = 1
skinned_type = /obj/item/stack/sheet/animalhide/human
/datum/species/human/qualifies_for_rank(rank, list/features)
return TRUE
//Curiosity killed the cat's wagging tail.
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
/datum/species/human/space_move(mob/living/carbon/human/H)
var/obj/item/device/flightpack/F = H.get_flightpack()
if(istype(F) && (F.flight) && F.allow_thrust(0.01, src))
/datum/species/human
name = "Human"
id = "human"
default_color = "FFFFFF"
species_traits = list(MUTCOLORS_PARTSONLY,EYECOLOR,HAIR,FACEHAIR,LIPS)
mutant_bodyparts = list("tail_human", "ears", "taur")
default_features = list("tail_human" = "None", "ears" = "None", "taur" = "none")
use_skintones = 1
skinned_type = /obj/item/stack/sheet/animalhide/human
disliked_food = GROSS | RAW
liked_food = JUNKFOOD | FRIED
/datum/species/human/qualifies_for_rank(rank, list/features)
return TRUE
//Curiosity killed the cat's wagging tail.
/datum/species/human/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
H.endTailWag()
/datum/species/human/space_move(mob/living/carbon/human/H)
var/obj/item/device/flightpack/F = H.get_flightpack()
if(istype(F) && (F.flight) && F.allow_thrust(0.01, src))
return TRUE
datum/species/human/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
@@ -28,4 +30,4 @@ datum/species/human/on_species_gain(mob/living/carbon/human/H, datum/species/old
if(H.dna.features["tail_human"] == "Cat")
var/tail = /obj/item/organ/tail/cat
mutant_organs += tail
..()
..()
@@ -4,11 +4,13 @@
id = "jelly"
default_color = "00FF90"
say_mod = "chirps"
species_traits = list(MUTCOLORS,EYECOLOR,NOBLOOD,VIRUSIMMUNE,TOXINLOVER)
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/slime
species_traits = list(MUTCOLORS,EYECOLOR,NOBLOOD,VIRUSIMMUNE,TOXINLOVER)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
exotic_blood = "slimejelly"
damage_overlay_type = ""
var/datum/action/innate/regenerate_limbs/regenerate_limbs
toxic_food = NONE
liked_food = MEAT
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
if(regenerate_limbs)
@@ -227,7 +229,7 @@
else
ui_interact(owner)
/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.conscious_state)
/datum/action/innate/swap_body/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.conscious_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
@@ -324,4 +326,4 @@
M.transfer_to(dupe)
dupe.visible_message("<span class='notice'>[dupe] blinks and looks \
around.</span>",
"<span class='notice'>...and move this one instead.</span>")
"<span class='notice'>...and move this one instead.</span>")
@@ -13,9 +13,11 @@
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/lizard
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/lizard
skinned_type = /obj/item/stack/sheet/animalhide/lizard
exotic_bloodtype = "L"
disliked_food = NONE
liked_food = NONE
/datum/species/lizard/after_equip_job(datum/job/J, mob/living/carbon/human/H)
H.grant_language(/datum/language/draconic)
@@ -17,10 +17,12 @@
speedmod = 1
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
var/internal_fire = FALSE //If the bones themselves are burning clothes won't help you much
disliked_food = NONE
liked_food = NONE
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
var/datum/gas_mixture/environment = H.loc.return_air()
var/atmos_sealed = (H.wear_suit && (H.wear_suit.flags & STOPSPRESSUREDMAGE)) && (H.head && (H.head.flags & STOPSPRESSUREDMAGE))
var/atmos_sealed = (H.wear_suit && (H.wear_suit.flags_1 & STOPSPRESSUREDMAGE_1)) && (H.head && (H.head.flags_1 & STOPSPRESSUREDMAGE_1))
if((!istype(H.w_uniform, /obj/item/clothing/under/plasmaman) || !istype(H.head, /obj/item/clothing/head/helmet/space/plasmaman)) && !atmos_sealed)
if(environment)
if(environment.total_moles())
@@ -3,13 +3,15 @@
name = "Podperson"
id = "pod"
default_color = "59CE00"
species_traits = list(MUTCOLORS,EYECOLOR)
species_traits = list(MUTCOLORS,EYECOLOR)
attack_verb = "slash"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
burnmod = 1.25
heatmod = 1.5
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/plant
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/plant
disliked_food = NONE
liked_food = NONE
/datum/species/pod/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
@@ -5,7 +5,7 @@
sexes = 0
blacklisted = 1
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/shadow
species_traits = list(NOBREATH,NOBLOOD,RADIMMUNE,VIRUSIMMUNE)
dangerous_existence = 1
mutanteyes = /obj/item/organ/eyes/night_vision
@@ -5,7 +5,9 @@
say_mod = "rattles"
blacklisted = 1
sexes = 0
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton
species_traits = list(NOBREATH,RESISTHOT,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,VIRUSIMMUNE,PIERCEIMMUNE,NOHUNGER,EASYDISMEMBER,EASYLIMBATTACHMENT)
mutant_organs = list(/obj/item/organ/tongue/bone)
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
damage_overlay_type = ""//let's not show bloody wounds or burns over bones.
disliked_food = NONE
liked_food = NONE
@@ -118,4 +118,4 @@
else
return ..()
else
return ..()
return ..()
@@ -5,10 +5,12 @@
say_mod = "moans"
sexes = 0
blacklisted = 1
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
species_traits = list(NOBREATH,RESISTCOLD,RESISTPRESSURE,NOBLOOD,RADIMMUNE,NOZOMBIE,EASYDISMEMBER,EASYLIMBATTACHMENT)
mutant_organs = list(/obj/item/organ/tongue/zombie)
var/static/list/spooks = list('sound/hallucinations/growl1.ogg','sound/hallucinations/growl2.ogg','sound/hallucinations/growl3.ogg','sound/hallucinations/veryfar_noise.ogg','sound/hallucinations/wail.ogg')
disliked_food = NONE
liked_food = NONE
/datum/species/zombie/infectious
name = "Infectious Zombie"
@@ -52,5 +54,5 @@
id = "goofzombies"
limbs_id = "zombie" //They look like zombies
sexes = 0
meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie
mutant_organs = list(/obj/item/organ/tongue/zombie)
@@ -521,8 +521,21 @@ generate/load female uniform sprites matching all previously decided variables
. += "-[gender]"
var/is_taur = FALSE
var/mob/living/carbon/human/H = src
if(("taur" in H.dna.species.mutant_bodyparts) && (H.dna.features["taur"] != "None"))
is_taur = TRUE
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(istype(BP, /obj/item/bodypart/r_leg) || istype(BP, /obj/item/bodypart/l_leg))
if(is_taur)
continue
. += "-[BP.body_zone]"
if(BP.status == BODYPART_ORGANIC)
. += "-organic"
+13 -7
View File
@@ -72,7 +72,7 @@
put_in_hands(I)
update_inv_hands()
if(slot_in_backpack)
var/obj/item/weapon/storage/B = back
var/obj/item/storage/B = back
var/prev_jimmies = B.rustle_jimmies
B.rustle_jimmies = FALSE //don't conspicously rustle
B.handle_item_insertion(I, 1, src)
@@ -95,24 +95,30 @@
if(I == head)
head = null
head_update(I)
if(!QDELETED(src))
head_update(I)
else if(I == back)
back = null
update_inv_back()
if(!QDELETED(src))
update_inv_back()
else if(I == wear_mask)
wear_mask = null
wear_mask_update(I, toggle_off = 1)
if(!QDELETED(src))
wear_mask_update(I, toggle_off = 1)
if(I == wear_neck)
wear_neck = null
update_inv_neck(I)
if(!QDELETED(src))
update_inv_neck(I)
else if(I == handcuffed)
handcuffed = null
if(buckled && buckled.buckle_requires_restraints)
buckled.unbuckle_mob(src)
update_handcuffed()
if(!QDELETED(src))
update_handcuffed()
else if(I == legcuffed)
legcuffed = null
update_inv_legcuffed()
if(!QDELETED(src))
update_inv_legcuffed()
//handle stuff to update when a mob equips/unequips a mask.
/mob/living/proc/wear_mask_update(obj/item/clothing/C, toggle_off = 1)
+3 -2
View File
@@ -48,6 +48,8 @@
return
if(istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
return
if(istype(loc, /obj/item/device/dogborg/sleeper))
return
if(ismob(loc))
return
var/datum/gas_mixture/environment
@@ -214,7 +216,7 @@
if(internal.loc != src)
internal = null
update_internals_hud_icon(0)
else if ((!wear_mask || !(wear_mask.flags & MASKINTERNALS)) && !getorganslot("breathing_tube"))
else if ((!wear_mask || !(wear_mask.flags_1 & MASKINTERNALS_1)) && !getorganslot("breathing_tube"))
internal = null
update_internals_hud_icon(0)
else
@@ -431,4 +433,3 @@
adjustToxLoss(8)
if(prob(30))
to_chat(src, "<span class='notice'>You feel confused and nauseous...</span>")//actual symptoms of liver failure
@@ -78,7 +78,7 @@
// WEAPONS
if(istype(I, /obj/item/weapon))
var/obj/item/weapon/W = I
var/obj/item/W = I
if(W.force >= best_force)
put_in_hands(W)
best_force = W.force
@@ -153,7 +153,7 @@
if(!locate(/obj/item/weapon) in held_items)
best_force = 0
if(restrained() || blacklistItems[pickupTarget] || (pickupTarget && (pickupTarget.flags & NODROP)))
if(restrained() || blacklistItems[pickupTarget] || (pickupTarget && (pickupTarget.flags_1 & NODROP_1)))
pickupTarget = null
if(!resisting && pickupTarget)
@@ -245,7 +245,7 @@
// pickup any nearby weapon
if(!pickupTarget && prob(MONKEY_WEAPON_PROB))
var/obj/item/weapon/W = locate(/obj/item/weapon/) in oview(2,src)
var/obj/item/W = locate(/obj/item/) in oview(2,src)
if(W && !blacklistItems[W] && W.force > best_force)
pickupTarget = W
@@ -272,9 +272,9 @@
if(Adjacent(target) && isturf(target.loc)) // if right next to perp
// check if target has a weapon
var/obj/item/weapon/W
for(var/obj/item/weapon/I in target.held_items)
if(!(I.flags & ABSTRACT))
var/obj/item/W
for(var/obj/item/I in target.held_items)
if(!(I.flags_1 & ABSTRACT_1))
W = I
break
@@ -388,7 +388,7 @@
// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little
/mob/living/carbon/monkey/proc/monkey_attack(mob/living/L)
var/obj/item/weapon/Weapon = locate(/obj/item/weapon) in held_items
var/obj/item/Weapon = locate(/obj/item/weapon) in held_items
// attack with weapon if we have one
if(Weapon)
@@ -439,7 +439,7 @@
retaliate(L)
return ..()
/mob/living/carbon/monkey/attackby(obj/item/weapon/W, mob/user, params)
/mob/living/carbon/monkey/attackby(obj/item/W, mob/user, params)
..()
if((W.force) && (!target) && (W.damtype != STAMINA) )
retaliate(user)
+172 -169
View File
@@ -1,170 +1,173 @@
/mob/living/carbon/monkey
/mob/living/carbon/monkey/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (notransform)
return
if(..())
if(!client)
if(stat == CONSCIOUS)
if(!handle_combat())
if(prob(33) && canmove && isturf(loc) && !pulledby)
/mob/living/carbon/monkey
/mob/living/carbon/monkey/Life()
set invisibility = 0
set background = BACKGROUND_ENABLED
if (notransform)
return
if(..())
if(!client)
if(stat == CONSCIOUS)
if(!handle_combat())
if(prob(33) && canmove && isturf(loc) && !pulledby)
step(src, pick(GLOB.cardinals))
if(prob(1))
emote(pick("scratch","jump","roll","tail"))
else
walk_to(src,0)
/mob/living/carbon/monkey/handle_mutations_and_radiation()
if (radiation)
if (radiation > 100)
if(!IsKnockdown())
emote("collapse")
Knockdown(200)
to_chat(src, "<span class='danger'>You feel weak.</span>")
switch(radiation)
if(50 to 75)
if(prob(5))
if(!IsKnockdown())
emote("collapse")
Knockdown(60)
to_chat(src, "<span class='danger'>You feel weak.</span>")
if(75 to 100)
if(prob(1))
to_chat(src, "<span class='danger'>You mutate!</span>")
randmutb()
emote("gasp")
domutcheck()
..()
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
if(abs(310.15 - breath.temperature) > 50)
switch(breath.temperature)
if(-INFINITY to 120)
adjustFireLoss(3)
if(120 to 200)
adjustFireLoss(1.5)
if(200 to 260)
adjustFireLoss(0.5)
if(360 to 400)
adjustFireLoss(2)
if(400 to 1000)
adjustFireLoss(3)
if(1000 to INFINITY)
adjustFireLoss(8)
/mob/living/carbon/monkey/handle_environment(datum/gas_mixture/environment)
if(!environment)
return
var/loc_temp = get_temperature(environment)
if(stat != DEAD)
natural_bodytemperature_stabilization()
if(!on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases
if(loc_temp < bodytemperature)
bodytemperature += min(((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR), BODYTEMP_COOLING_MAX)
else
bodytemperature += min(((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX)
if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT)
switch(bodytemperature)
if(360 to 400)
throw_alert("temp", /obj/screen/alert/hot, 1)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
if(400 to 460)
throw_alert("temp", /obj/screen/alert/hot, 2)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
if(460 to INFINITY)
throw_alert("temp", /obj/screen/alert/hot, 3)
if(on_fire)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN)
else
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
switch(bodytemperature)
if(200 to 260)
throw_alert("temp", /obj/screen/alert/cold, 1)
apply_damage(COLD_DAMAGE_LEVEL_1, BURN)
if(120 to 200)
throw_alert("temp", /obj/screen/alert/cold, 2)
apply_damage(COLD_DAMAGE_LEVEL_2, BURN)
if(-INFINITY to 120)
throw_alert("temp", /obj/screen/alert/cold, 3)
apply_damage(COLD_DAMAGE_LEVEL_3, BURN)
else
clear_alert("temp")
else
clear_alert("temp")
//Account for massive pressure differences
var/pressure = environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob.
switch(adjusted_pressure)
if(HAZARD_HIGH_PRESSURE to INFINITY)
adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
throw_alert("pressure", /obj/screen/alert/highpressure, 2)
if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
throw_alert("pressure", /obj/screen/alert/highpressure, 1)
if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
clear_alert("pressure")
if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
else
adjustBruteLoss( LOW_PRESSURE_DAMAGE )
throw_alert("pressure", /obj/screen/alert/lowpressure, 2)
return
/mob/living/carbon/monkey/handle_random_events()
if (prob(1) && prob(2))
emote("scratch")
/mob/living/carbon/monkey/has_smoke_protection()
if(wear_mask)
if(wear_mask.flags & BLOCK_GAS_SMOKE_EFFECT)
return 1
/mob/living/carbon/monkey/handle_fire()
. = ..()
if(on_fire)
//the fire tries to damage the exposed clothes and items
var/list/burning_items = list()
//HEAD//
var/obj/item/clothing/head_clothes = null
if(wear_mask)
head_clothes = wear_mask
if(wear_neck)
head_clothes = wear_neck
if(head)
head_clothes = head
if(head_clothes)
burning_items += head_clothes
if(back)
burning_items += back
for(var/X in burning_items)
var/obj/item/I = X
if(!(I.resistance_flags & FIRE_PROOF))
I.take_damage(fire_stacks, BURN, "fire", 0)
bodytemperature += BODYTEMP_HEATING_MAX
if(prob(1))
emote(pick("scratch","jump","roll","tail"))
else
walk_to(src,0)
/mob/living/carbon/monkey/handle_mutations_and_radiation()
if (radiation)
if (radiation > 100)
if(!IsKnockdown())
emote("collapse")
Knockdown(200)
to_chat(src, "<span class='danger'>You feel weak.</span>")
if(radiation > 30 && prob((radiation - 30) * (radiation - 30) * 0.00002))
gorillize()
return
switch(radiation)
if(50 to 75)
if(prob(5))
if(!IsKnockdown())
emote("collapse")
Knockdown(60)
to_chat(src, "<span class='danger'>You feel weak.</span>")
if(75 to 100)
if(prob(1))
to_chat(src, "<span class='danger'>You mutate!</span>")
randmutb()
emote("gasp")
domutcheck()
..()
/mob/living/carbon/monkey/handle_breath_temperature(datum/gas_mixture/breath)
if(abs(310.15 - breath.temperature) > 50)
switch(breath.temperature)
if(-INFINITY to 120)
adjustFireLoss(3)
if(120 to 200)
adjustFireLoss(1.5)
if(200 to 260)
adjustFireLoss(0.5)
if(360 to 400)
adjustFireLoss(2)
if(400 to 1000)
adjustFireLoss(3)
if(1000 to INFINITY)
adjustFireLoss(8)
/mob/living/carbon/monkey/handle_environment(datum/gas_mixture/environment)
if(!environment)
return
var/loc_temp = get_temperature(environment)
if(stat != DEAD)
natural_bodytemperature_stabilization()
if(!on_fire) //If you're on fire, you do not heat up or cool down based on surrounding gases
if(loc_temp < bodytemperature)
bodytemperature += min(((loc_temp - bodytemperature) / BODYTEMP_COLD_DIVISOR), BODYTEMP_COOLING_MAX)
else
bodytemperature += min(((loc_temp - bodytemperature) / BODYTEMP_HEAT_DIVISOR), BODYTEMP_HEATING_MAX)
if(bodytemperature > BODYTEMP_HEAT_DAMAGE_LIMIT)
switch(bodytemperature)
if(360 to 400)
throw_alert("temp", /obj/screen/alert/hot, 1)
apply_damage(HEAT_DAMAGE_LEVEL_1, BURN)
if(400 to 460)
throw_alert("temp", /obj/screen/alert/hot, 2)
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
if(460 to INFINITY)
throw_alert("temp", /obj/screen/alert/hot, 3)
if(on_fire)
apply_damage(HEAT_DAMAGE_LEVEL_3, BURN)
else
apply_damage(HEAT_DAMAGE_LEVEL_2, BURN)
else if(bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT)
if(!istype(loc, /obj/machinery/atmospherics/components/unary/cryo_cell))
switch(bodytemperature)
if(200 to 260)
throw_alert("temp", /obj/screen/alert/cold, 1)
apply_damage(COLD_DAMAGE_LEVEL_1, BURN)
if(120 to 200)
throw_alert("temp", /obj/screen/alert/cold, 2)
apply_damage(COLD_DAMAGE_LEVEL_2, BURN)
if(-INFINITY to 120)
throw_alert("temp", /obj/screen/alert/cold, 3)
apply_damage(COLD_DAMAGE_LEVEL_3, BURN)
else
clear_alert("temp")
else
clear_alert("temp")
//Account for massive pressure differences
var/pressure = environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob.
switch(adjusted_pressure)
if(HAZARD_HIGH_PRESSURE to INFINITY)
adjustBruteLoss( min( ( (adjusted_pressure / HAZARD_HIGH_PRESSURE) -1 )*PRESSURE_DAMAGE_COEFFICIENT , MAX_HIGH_PRESSURE_DAMAGE) )
throw_alert("pressure", /obj/screen/alert/highpressure, 2)
if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE)
throw_alert("pressure", /obj/screen/alert/highpressure, 1)
if(WARNING_LOW_PRESSURE to WARNING_HIGH_PRESSURE)
clear_alert("pressure")
if(HAZARD_LOW_PRESSURE to WARNING_LOW_PRESSURE)
throw_alert("pressure", /obj/screen/alert/lowpressure, 1)
else
adjustBruteLoss( LOW_PRESSURE_DAMAGE )
throw_alert("pressure", /obj/screen/alert/lowpressure, 2)
return
/mob/living/carbon/monkey/handle_random_events()
if (prob(1) && prob(2))
emote("scratch")
/mob/living/carbon/monkey/has_smoke_protection()
if(wear_mask)
if(wear_mask.flags_1 & BLOCK_GAS_SMOKE_EFFECT_1)
return 1
/mob/living/carbon/monkey/handle_fire()
. = ..()
if(on_fire)
//the fire tries to damage the exposed clothes and items
var/list/burning_items = list()
//HEAD//
var/obj/item/clothing/head_clothes = null
if(wear_mask)
head_clothes = wear_mask
if(wear_neck)
head_clothes = wear_neck
if(head)
head_clothes = head
if(head_clothes)
burning_items += head_clothes
if(back)
burning_items += back
for(var/X in burning_items)
var/obj/item/I = X
if(!(I.resistance_flags & FIRE_PROOF))
I.take_damage(fire_stacks, BURN, "fire", 0)
bodytemperature += BODYTEMP_HEATING_MAX
@@ -8,8 +8,8 @@
gender = NEUTER
pass_flags = PASSTABLE
ventcrawler = VENTCRAWLER_NUDE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/monkey
gib_type = /obj/effect/decal/cleanable/blood/gibs
unique_name = 1
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
@@ -105,11 +105,11 @@
//Lasertag bullshit
if(lasercolor)
if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/redtag))
if(is_holding_item_of_type(/obj/item/gun/energy/laser/redtag))
threatcount += 4
if(lasercolor == "r")
if(is_holding_item_of_type(/obj/item/weapon/gun/energy/laser/bluetag))
if(is_holding_item_of_type(/obj/item/gun/energy/laser/bluetag))
threatcount += 4
return threatcount
@@ -140,8 +140,8 @@
return 0
return 1
/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/G)
return 1
/mob/living/carbon/monkey/can_use_guns(obj/item/G)
return TRUE
/mob/living/carbon/monkey/angry
aggressive = TRUE
+32 -24
View File
@@ -24,7 +24,7 @@
..()
//These have to be after the parent new to ensure that the monkey
//bodyparts are actually created before we try to equip things to
//bodyparts are actually created before we try to equip things to
//those slots
if(relic_hat)
equip_to_slot_or_del(new relic_hat, slot_head)
@@ -42,32 +42,40 @@
..()
/mob/living/carbon/monkey/punpun/proc/Read_Memory()
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
S["ancestor_name"] >> ancestor_name
S["ancestor_chain"] >> ancestor_chain
S["relic_hat"] >> relic_hat
S["relic_mask"] >> relic_mask
if(fexists("data/npc_saves/Punpun.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
S["ancestor_name"] >> ancestor_name
S["ancestor_chain"] >> ancestor_chain
S["relic_hat"] >> relic_hat
S["relic_mask"] >> relic_mask
fdel("data/npc_saves/Punpun.sav")
else
var/json_file = file("data/npc_saves/Punpun.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
ancestor_name = json["ancestor_name"]
ancestor_chain = json["ancestor_chain"]
relic_hat = json["relic_hat"]
relic_mask = json["relic_hat"]
/mob/living/carbon/monkey/punpun/proc/Write_Memory(dead, gibbed)
var/savefile/S = new /savefile("data/npc_saves/Punpun.sav")
var/json_file = file("data/npc_saves/Punpun.json")
var/list/file_data = list()
if(gibbed)
WRITE_FILE(S["ancestor_name"], null)
WRITE_FILE(S["ancestor_chain"], 1)
WRITE_FILE(S["relic_hat"], null)
WRITE_FILE(S["relic_mask"], null)
return
file_data["ancestor_name"] = null
file_data["ancestor_chain"] = null
file_data["relic_hat"] = null
file_data["relic_mask"] = null
if(dead)
WRITE_FILE(S["ancestor_name"], ancestor_name)
WRITE_FILE(S["ancestor_chain"], ancestor_chain + 1)
if(!ancestor_name) //new monkey name this round
WRITE_FILE(S["ancestor_name"], name)
if(head)
WRITE_FILE(S["relic_hat"], head.type)
else
WRITE_FILE(S["relic_hat"], null)
if(wear_mask)
WRITE_FILE(S["relic_mask"], wear_mask.type)
else
WRITE_FILE(S["relic_mask"], null)
file_data["ancestor_name"] = ancestor_name
file_data["ancestor_chain"] = ancestor_chain + 1
file_data["relic_hat"] = head ? head.type : null
file_data["relic_mask"] = wear_mask ? wear_mask.type : null
if(!ancestor_name)
file_data["ancestor_name"] = name
fdel(json_file)
WRITE_FILE(json_file, json_encode(json_file))
if(!dead)
memory_saved = 1
+1 -1
View File
@@ -34,4 +34,4 @@
if(T)
. = T.could_speak_in_language(dt)
else
. = initial(dt.flags) & TONGUELESS_SPEECH
. = initial(dt.flags_1) & TONGUELESS_SPEECH
@@ -63,6 +63,17 @@
clear_fullscreen("high")
clear_alert("high")
/mob/living/carbon/adjust_disgust(amount)
var/old_disgust = disgust
if(amount>0)
disgust = min(disgust+amount, DISGUST_LEVEL_MAXEDOUT)
else if(old_disgust)
disgust = max(disgust+amount, 0)
/mob/living/carbon/set_disgust(amount)
if(amount >= 0)
disgust = amount
/mob/living/carbon/cure_blind()
if(disabilities & BLIND)
@@ -234,11 +234,22 @@
if(limb_icon_cache[icon_render_key])
load_limb_from_cache()
return
//Taur code goes here, since humans just inherit this proc
var/is_taur = FALSE
if(ishuman(src))
var/mob/living/carbon/human/H = src
if(("taur" in H.dna.species.mutant_bodyparts) && (H.dna.features["taur"] != "None"))
is_taur = TRUE
//GENERATE NEW LIMBS
var/list/new_limbs = list()
for(var/X in bodyparts)
var/obj/item/bodypart/BP = X
if(istype(BP, /obj/item/bodypart/r_leg) || istype(BP, /obj/item/bodypart/l_leg))
if(is_taur)
continue
new_limbs += BP.get_limb_icon()
if(new_limbs.len)
overlays_standing[BODYPARTS_LAYER] = new_limbs
+2 -1
View File
@@ -52,7 +52,7 @@
var/area/A = get_area(T)
for(var/obj/item/I in contents)
I.on_mob_death(src, gibbed)
if(mind && mind.name && mind.active && (!(T.flags & NO_DEATHRATTLE)))
if(mind && mind.name && mind.active && (!(T.flags_1 & NO_DEATHRATTLE_1)))
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[A.name]</b>.</span>"
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
if(mind)
@@ -61,6 +61,7 @@
if(!gibbed)
GLOB.dead_mob_list += src
set_drugginess(0)
set_disgust(0)
SetSleeping(0, 0)
blind_eyes(1)
reset_perspective(null)
+1 -2
View File
@@ -465,7 +465,6 @@
/datum/emote/living/spin
key = "spin"
key_third_person = "spins"
message = "spins around dizzily!"
/datum/emote/living/spin/run_emote(mob/user)
user.spin(20, 1)
@@ -486,7 +485,7 @@
/datum/emote/living/circle/run_emote(mob/user, params)
. = ..()
var/obj/item/weapon/circlegame/N = new(user)
var/obj/item/circlegame/N = new(user)
if(user.put_in_hands(N))
to_chat(user, "<span class='notice'>You make a circle with your hand.</span>")
else
+10 -9
View File
@@ -241,7 +241,7 @@
return 1
/mob/living/proc/InCritical()
return (health < 0 && health > -100 && stat == UNCONSCIOUS)
return (health < HEALTH_THRESHOLD_CRIT && health > HEALTH_THRESHOLD_DEAD && stat == UNCONSCIOUS)
//This proc is used for mobs which are affected by pressure to calculate the amount of pressure that actually
//affects them once clothing is factored in. ~Errorage
@@ -300,7 +300,7 @@
update_canmove()
//Recursive function to find everything a mob is holding.
/mob/living/get_contents(obj/item/weapon/storage/Storage = null)
/mob/living/get_contents(obj/item/storage/Storage = null)
var/list/L = list()
if(Storage) //If it called itself
@@ -308,11 +308,11 @@
return L
else
L += src.contents
for(var/obj/item/weapon/storage/S in src.contents) //Check for storage items
for(var/obj/item/storage/S in src.contents) //Check for storage items
L += get_contents(S)
for(var/obj/item/clothing/under/U in src.contents) //Check for jumpsuit accessories
L += U.contents
for(var/obj/item/weapon/folder/F in src.contents) //Check for folders
for(var/obj/item/folder/F in src.contents) //Check for folders
L += F.contents
return L
@@ -374,6 +374,7 @@
setBrainLoss(0)
setStaminaLoss(0, 0)
SetUnconscious(0, FALSE)
set_disgust(0)
SetStun(0, FALSE)
SetKnockdown(0, FALSE)
SetSleeping(0, FALSE)
@@ -637,7 +638,7 @@
// The src mob is trying to strip an item from someone
// Override if a certain type of mob should be behave differently when stripping items (can't, for example)
/mob/living/stripPanelUnequip(obj/item/what, mob/who, where)
if(what.flags & NODROP)
if(what.flags_1 & NODROP_1)
to_chat(src, "<span class='warning'>You can't remove \the [what.name], it appears to be stuck!</span>")
return
who.visible_message("<span class='danger'>[src] tries to remove [who]'s [what.name].</span>", \
@@ -658,7 +659,7 @@
// Override if a certain mob should be behave differently when placing items (can't, for example)
/mob/living/stripPanelEquip(obj/item/what, mob/who, where)
what = src.get_active_held_item()
if(what && (what.flags & NODROP))
if(what && (what.flags_1 & NODROP_1))
to_chat(src, "<span class='warning'>You can't put \the [what.name] on [who], it's stuck to your hand!</span>")
return
if(what)
@@ -797,11 +798,11 @@
else
to_chat(src, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
/mob/living/proc/can_use_guns(var/obj/item/weapon/G)
/mob/living/proc/can_use_guns(obj/item/G)
if (G.trigger_guard != TRIGGER_GUARD_ALLOW_ALL && !IsAdvancedToolUser())
to_chat(src, "<span class='warning'>You don't have the dexterity to do this!</span>")
return 0
return 1
return FALSE
return TRUE
/mob/living/carbon/proc/update_stamina()
if(staminaloss)
+10 -12
View File
@@ -67,17 +67,15 @@
var/zone = ran_zone("chest", 65)//Hits a random part of the body, geared towards the chest
var/dtype = BRUTE
var/volume = I.get_volume_by_throwforce_and_or_w_class()
if(istype(I, /obj/item/weapon)) //If the item is a weapon...
var/obj/item/weapon/W = I
dtype = W.damtype
dtype = I.damtype
if (W.throwforce > 0) //If the weapon's throwforce is greater than zero...
if (W.throwhitsound) //...and throwhitsound is defined...
playsound(loc, W.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
else if(W.hitsound) //Otherwise, if the weapon's hitsound is defined...
playsound(loc, W.hitsound, volume, 1, -1) //...play the weapon's hitsound.
else if(!W.throwhitsound) //Otherwise, if throwhitsound isn't defined...
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
if (I.throwforce > 0) //If the weapon's throwforce is greater than zero...
if (I.throwhitsound) //...and throwhitsound is defined...
playsound(loc, I.throwhitsound, volume, 1, -1) //...play the weapon's throwhitsound.
else if(I.hitsound) //Otherwise, if the weapon's hitsound is defined...
playsound(loc, I.hitsound, volume, 1, -1) //...play the weapon's hitsound.
else if(!I.throwhitsound) //Otherwise, if throwhitsound isn't defined...
playsound(loc, 'sound/weapons/genhit.ogg',volume, 1, -1) //...play genhit.ogg.
else if(!I.throwhitsound && I.throwforce > 0) //Otherwise, if the item doesn't have a throwhitsound and has a throwforce greater than zero...
playsound(loc, 'sound/weapons/genhit.ogg', volume, 1, -1)//...play genhit.ogg
@@ -280,7 +278,7 @@
return 1
/mob/living/proc/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
if(tesla_shock && HAS_SECONDARY_FLAG(src, TESLA_IGNORE))
if(tesla_shock && (flags_2 & TESLA_IGNORE_2))
return FALSE
if(shock_damage > 0)
if(!illusion)
@@ -342,7 +340,7 @@
return
if(stat != DEAD && !is_servant_of_ratvar(src))
for(var/obj/item/weapon/implant/mindshield/M in implants)
for(var/obj/item/implant/mindshield/M in implants)
qdel(M)
if(!add_servant_of_ratvar(src))
to_chat(src, "<span class='userdanger'>A blinding light boils you alive! <i>Run!</i></span>")
+1 -1
View File
@@ -35,7 +35,7 @@
if(nuking)
set_security_level("red")
nuking = FALSE
for(var/obj/item/weapon/pinpointer/P in GLOB.pinpointer_list)
for(var/obj/item/pinpointer/P in GLOB.pinpointer_list)
P.switch_mode_to(TRACK_NUKE_DISK) //Party's over, back to work, everyone
P.nuke_warning = FALSE
+3 -3
View File
@@ -4,7 +4,7 @@
var/obj/machinery/camera/current = null
icon = 'icons/mob/pai.dmi'
icon_state = "repairbot"
mouse_opacity = 2
mouse_opacity = MOUSE_OPACITY_OPAQUE
density = FALSE
luminosity = 0
pass_flags = PASSTABLE | PASSMOB
@@ -24,7 +24,7 @@
var/speakDoubleExclamation = "alarms"
var/speakQuery = "queries"
var/obj/item/weapon/pai_cable/cable // The cable we produce and use when door or camera jacking
var/obj/item/pai_cable/cable // The cable we produce and use when door or camera jacking
var/master // Name of the one who commands us
var/master_dna // DNA string for owner verification
@@ -53,7 +53,7 @@
var/holoform = FALSE
var/canholo = TRUE
var/obj/item/weapon/card/id/access_card = null
var/obj/item/card/id/access_card = null
var/chassis = "repairbot"
var/list/possible_chassis = list("cat", "mouse", "monkey", "corgi", "fox", "repairbot", "rabbit")
@@ -253,7 +253,7 @@
med.remove_hud_from(src)
if("translator")
if(href_list["toggle"])
if(!HAS_SECONDARY_FLAG(src, OMNITONGUE))
if(!(flags_2 & OMNITONGUE_2))
grant_all_languages(TRUE)
// this is PERMAMENT.
if("doorjack")
@@ -265,7 +265,7 @@
src.hackdoor = null
if(href_list["cable"])
var/turf/T = get_turf(src.loc)
cable = new /obj/item/weapon/pai_cable(T)
cable = new /obj/item/pai_cable(T)
T.visible_message("<span class='warning'>A port on [src] opens to reveal [src.cable], which promptly falls to the floor.</span>", "<span class='italics'>You hear the soft click of something light and hard falling to the ground.</span>")
//src.updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window
src.paiInterface() // So we'll just call the update directly rather than doing some default checks
@@ -313,7 +313,7 @@
if(s == "medical HUD")
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a>[(src.medHUD) ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
if(s == "universal translator")
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
var/translator_on = (flags_2 & OMNITONGUE_2)
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a>[translator_on ? "<font color=#55FF55> On</font>" : "<font color=#FF5555> Off</font>"] <br>"
if(s == "projection array")
dat += "<a href='byond://?src=\ref[src];software=projectionarray;sub=0'>Projection Array</a> <br>"
@@ -465,7 +465,7 @@
// Universal Translator
/mob/living/silicon/pai/proc/softwareTranslator()
var/translator_on = HAS_SECONDARY_FLAG(src, OMNITONGUE)
var/translator_on = (flags_2 & OMNITONGUE_2)
. = {"<h3>Universal Translator</h3><br>
When enabled, this device will permamently be able to speak and understand all known forms of communication.<br><br>
The device is currently [translator_on ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled.</font><br>[translator_on ? "" : "<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Activate Translation Module</a><br>"]"}
@@ -11,18 +11,18 @@
/mob/living/silicon/robot/proc/uneq_module(obj/item/O)
if(!O)
return 0
O.mouse_opacity = 2
O.mouse_opacity = MOUSE_OPACITY_OPAQUE
if(istype(O, /obj/item/borg/sight))
var/obj/item/borg/sight/S = O
sight_mode &= ~S.sight_mode
update_sight()
else if(istype(O, /obj/item/weapon/storage/bag/tray/))
var/obj/item/weapon/storage/bag/tray/T = O
else if(istype(O, /obj/item/storage/bag/tray/))
var/obj/item/storage/bag/tray/T = O
T.do_quick_empty()
else if(istype(O,/obj/item/weapon/gun/energy/laser/cyborg))
else if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = 0
update_icons()
else if(istype(O,/obj/item/weapon/gun/energy/disabler/cyborg))
else if(istype(O,/obj/item/gun/energy/disabler/cyborg))
disabler = 0
update_icons()
else if(istype(O,/obj/item/device/dogborg/sleeper))
@@ -36,8 +36,8 @@
observer_screen_update(O,FALSE)
O.forceMove(module) //Return item to module so it appears in its contents, so it can be taken out again.
if(DROPDEL & O.flags)
O.flags &= ~DROPDEL //we shouldn't HAVE things with DROPDEL in our modules, but better safe than runtiming horribly
if(O.flags_1 & DROPDEL_1)
O.flags_1 &= ~DROPDEL_1 //we shouldn't HAVE things with DROPDEL_1 in our modules, but better safe than runtiming horribly
O.dropped(src)
@@ -62,10 +62,10 @@
if(activated(O))
to_chat(src, "<span class='warning'>That module is already activated.</span>")
return
if(istype(O,/obj/item/weapon/gun/energy/laser/cyborg))
if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = 1
update_icons()
if(istype(O,/obj/item/weapon/gun/energy/disabler/cyborg))
if(istype(O,/obj/item/gun/energy/disabler/cyborg))
disabler = 1
update_icons()
if(!held_items[1])
+36 -36
View File
@@ -34,14 +34,14 @@
var/obj/screen/robot_modules_background
//3 Modules can be activated at any one time.
var/obj/item/weapon/robot_module/module = null
var/obj/item/robot_module/module = null
var/obj/item/module_active = null
held_items = list(null, null, null) //we use held_items for the module holding, because that makes sense to do!
var/mutable_appearance/eye_lights
var/mob/living/silicon/ai/connected_ai = null
var/obj/item/weapon/stock_parts/cell/cell = null
var/obj/item/stock_parts/cell/cell = null
var/opened = 0
var/emagged = FALSE
@@ -115,7 +115,7 @@
ident = rand(1, 999)
if(!cell)
cell = new /obj/item/weapon/stock_parts/cell(src)
cell = new /obj/item/stock_parts/cell(src)
cell.maxcharge = 7500
cell.charge = 7500
@@ -131,7 +131,7 @@
builtInCamera.network = list("SS13")
if(wires.is_cut(WIRE_CAMERA))
builtInCamera.status = 0
module = new /obj/item/weapon/robot_module(src)
module = new /obj/item/robot_module(src)
module.rebuild_modules()
update_icons()
. = ..()
@@ -194,29 +194,29 @@
/mob/living/silicon/robot/proc/pick_module()
if(module.type != /obj/item/weapon/robot_module)
if(module.type != /obj/item/robot_module)
return
if(wires.is_cut(WIRE_RESET_MODULE))
to_chat(src,"<span class='userdanger'>ERROR: Module installer reply timeout. Please check internal connections.</span>")
return
var/list/modulelist = list("Standard" = /obj/item/weapon/robot_module/standard, \
"Engineering" = /obj/item/weapon/robot_module/engineering, \
"Medical" = /obj/item/weapon/robot_module/medical, \
"Miner" = /obj/item/weapon/robot_module/miner, \
"Janitor" = /obj/item/weapon/robot_module/janitor, \
"Service" = /obj/item/weapon/robot_module/butler, \
"MediHound" = /obj/item/weapon/robot_module/medihound, \
"Security K9" = /obj/item/weapon/robot_module/k9, \
"Scrub Puppy" = /obj/item/weapon/robot_module/scrubpup)
var/list/modulelist = list("Standard" = /obj/item/robot_module/standard, \
"Engineering" = /obj/item/robot_module/engineering, \
"Medical" = /obj/item/robot_module/medical, \
"Miner" = /obj/item/robot_module/miner, \
"Janitor" = /obj/item/robot_module/janitor, \
"Service" = /obj/item/robot_module/butler, \
"MediHound" = /obj/item/robot_module/medihound, \
"Security K9" = /obj/item/robot_module/k9, \
"Scrub Puppy" = /obj/item/robot_module/scrubpup)
if(!config.forbid_peaceborg)
modulelist["Peacekeeper"] = /obj/item/weapon/robot_module/peacekeeper
modulelist["Peacekeeper"] = /obj/item/robot_module/peacekeeper
if(!config.forbid_secborg)
modulelist["Security"] = /obj/item/weapon/robot_module/security
modulelist["Security"] = /obj/item/robot_module/security
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in modulelist
if(!input_module || module.type != /obj/item/weapon/robot_module)
if(!input_module || module.type != /obj/item/robot_module)
return
module.transform_to(modulelist[input_module])
@@ -367,10 +367,10 @@
queueAlarm("--- [class] alarm in [A.name] has been cleared.", class, 0)
return !cleared
/mob/living/silicon/robot/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/weldingtool) && (user.a_intent != INTENT_HARM || user == src))
/mob/living/silicon/robot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/weldingtool) && (user.a_intent != INTENT_HARM || user == src))
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/weapon/weldingtool/WT = W
var/obj/item/weldingtool/WT = W
if (!getBruteLoss())
to_chat(user, "<span class='warning'>[src] is already in good condition!</span>")
return
@@ -407,7 +407,7 @@
else
to_chat(user, "The wires seem fine, there's no need to fix them.")
else if(istype(W, /obj/item/weapon/crowbar)) // crowbar means open or close the cover
else if(istype(W, /obj/item/crowbar)) // crowbar means open or close the cover
if(opened)
to_chat(user, "<span class='notice'>You close the cover.</span>")
opened = 0
@@ -420,7 +420,7 @@
opened = 1
update_icons()
else if(istype(W, /obj/item/weapon/stock_parts/cell) && opened) // trying to put a cell inside
else if(istype(W, /obj/item/stock_parts/cell) && opened) // trying to put a cell inside
if(wiresexposed)
to_chat(user, "<span class='warning'>Close the cover first!</span>")
else if(cell)
@@ -440,12 +440,12 @@
else
to_chat(user, "<span class='warning'>You can't reach the wiring!</span>")
else if(istype(W, /obj/item/weapon/screwdriver) && opened && !cell) // haxing
else if(istype(W, /obj/item/screwdriver) && opened && !cell) // haxing
wiresexposed = !wiresexposed
to_chat(user, "The wires have been [wiresexposed ? "exposed" : "unexposed"]")
update_icons()
else if(istype(W, /obj/item/weapon/screwdriver) && opened && cell) // radio
else if(istype(W, /obj/item/screwdriver) && opened && cell) // radio
if(shell)
to_chat(user, "You cannot seem to open the radio compartment") //Prevent AI radio key theft
else if(radio)
@@ -454,7 +454,7 @@
to_chat(user, "<span class='warning'>Unable to locate a radio!</span>")
update_icons()
else if(istype(W, /obj/item/weapon/wrench) && opened && !cell) //Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module.
else if(istype(W, /obj/item/wrench) && opened && !cell) //Deconstruction. The flashes break from the fall, to prevent this from being a ghetto reset module.
if(!lockcharge)
to_chat(user, "<span class='boldannounce'>[src]'s bolts spark! Maybe you should lock them down first!</span>")
spark_system.start()
@@ -466,8 +466,8 @@
user.visible_message("[user] deconstructs [src]!", "<span class='notice'>You unfasten the securing bolts, and [src] falls to pieces!</span>")
deconstruct()
else if(istype(W, /obj/item/weapon/aiModule))
var/obj/item/weapon/aiModule/MOD = W
else if(istype(W, /obj/item/aiModule))
var/obj/item/aiModule/MOD = W
if(!opened)
to_chat(user, "<span class='warning'>You need access to the robot's insides to do that!</span>")
return
@@ -495,7 +495,7 @@
else
to_chat(user, "<span class='warning'>Unable to locate a radio!</span>")
else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
else if (istype(W, /obj/item/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
if(emagged)//still allow them to open the cover
to_chat(user, "<span class='notice'>The interface seems slightly damaged.</span>")
if(opened)
@@ -570,7 +570,7 @@
return check_access(george.get_active_held_item())
return 0
/mob/living/silicon/robot/proc/check_access(obj/item/weapon/card/id/I)
/mob/living/silicon/robot/proc/check_access(obj/item/card/id/I)
if(!istype(req_access, /list)) //something's very wrong
return 1
@@ -578,7 +578,7 @@
if(!L.len) //no requirements
return 1
if(!istype(I, /obj/item/weapon/card/id) && isitem(I))
if(!istype(I, /obj/item/card/id) && isitem(I))
I = I.GetID()
if(!I || !I.access) //not ID or no access
@@ -825,7 +825,7 @@
<b>You are armed with powerful offensive tools to aid you in your mission: help the operatives secure the nuclear authentication disk. \
Your cyborg LMG will slowly produce ammunition from your power supply, and your operative pinpointer will find and locate fellow nuclear operatives. \
<i>Help the operatives secure the disk at all costs!</i></b>"
var/set_module = /obj/item/weapon/robot_module/syndicate
var/set_module = /obj/item/robot_module/syndicate
/mob/living/silicon/robot/syndicate/Initialize()
..()
@@ -851,7 +851,7 @@
Your defibrillator paddles can revive operatives through their hardsuits, or can be used on harm intent to shock enemies! \
Your energy saw functions as a circular saw, but can be activated to deal more damage, and your operative pinpointer will find and locate fellow nuclear operatives. \
<i>Help the operatives secure the disk at all costs!</i></b>"
set_module = /obj/item/weapon/robot_module/syndicate_medical
set_module = /obj/item/robot_module/syndicate_medical
/mob/living/silicon/robot/proc/notify_ai(notifytype, oldname, newname)
if(!connected_ai)
@@ -977,7 +977,7 @@
shown_robot_modules = FALSE
if(hud_used)
hud_used.update_robot_modules_display()
module.transform_to(/obj/item/weapon/robot_module)
module.transform_to(/obj/item/robot_module)
// Remove upgrades.
for(var/obj/item/I in upgrades)
@@ -992,7 +992,7 @@
return 1
/mob/living/silicon/robot/proc/has_module()
if(!module || module.type == /obj/item/weapon/robot_module)
if(!module || module.type == /obj/item/robot_module)
. = FALSE
else
. = TRUE
@@ -1007,9 +1007,9 @@
status_flags &= ~CANPUSH
if(module.clean_on_move)
flags |= CLEAN_ON_MOVE
flags_1 |= CLEAN_ON_MOVE_1
else
flags &= ~CLEAN_ON_MOVE
flags_1 &= ~CLEAN_ON_MOVE_1
hat_offset = module.hat_offset
@@ -1,12 +1,12 @@
/obj/item/weapon/robot_module
/obj/item/robot_module
name = "Default"
icon = 'icons/obj/module.dmi'
icon_state = "std_module"
w_class = WEIGHT_CLASS_GIGANTIC
item_state = "electronic"
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags = CONDUCT
lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags_1 = CONDUCT_1
var/list/basic_modules = list() //a list of paths, converted to a list of instances on New()
var/list/emag_modules = list() //ditto
@@ -34,7 +34,7 @@
var/ride_allow_incapacitated = FALSE
var/allow_riding = TRUE
/obj/item/weapon/robot_module/New()
/obj/item/robot_module/New()
..()
for(var/i in basic_modules)
var/obj/item/I = new i(src)
@@ -49,7 +49,7 @@
ratvar_modules += I
ratvar_modules -= i
/obj/item/weapon/robot_module/Destroy()
/obj/item/robot_module/Destroy()
basic_modules.Cut()
emag_modules.Cut()
ratvar_modules.Cut()
@@ -58,29 +58,29 @@
storages.Cut()
return ..()
/obj/item/weapon/robot_module/emp_act(severity)
/obj/item/robot_module/emp_act(severity)
for(var/obj/O in modules)
O.emp_act(severity)
..()
/obj/item/weapon/robot_module/proc/get_usable_modules()
/obj/item/robot_module/proc/get_usable_modules()
. = modules.Copy()
/obj/item/weapon/robot_module/proc/get_inactive_modules()
/obj/item/robot_module/proc/get_inactive_modules()
. = list()
var/mob/living/silicon/robot/R = loc
for(var/m in get_usable_modules())
if(!(m in R.held_items))
. += m
/obj/item/weapon/robot_module/proc/get_or_create_estorage(var/storage_type)
/obj/item/robot_module/proc/get_or_create_estorage(var/storage_type)
for(var/datum/robot_energy_storage/S in storages)
if(istype(S, storage_type))
return S
return new storage_type(src)
/obj/item/weapon/robot_module/proc/add_module(obj/item/I, nonstandard, requires_rebuild)
/obj/item/robot_module/proc/add_module(obj/item/I, nonstandard, requires_rebuild)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
@@ -114,22 +114,22 @@
S.materials = list()
S.is_cyborg = 1
if(istype(I, /obj/item/weapon/restraints/handcuffs/cable))
var/obj/item/weapon/restraints/handcuffs/cable/C = I
if(istype(I, /obj/item/restraints/handcuffs/cable))
var/obj/item/restraints/handcuffs/cable/C = I
C.wirestorage = get_or_create_estorage(/datum/robot_energy_storage/wire)
if(I.loc != src)
I.forceMove(src)
modules += I
I.flags |= NODROP
I.mouse_opacity = 2
I.flags_1 |= NODROP_1
I.mouse_opacity = MOUSE_OPACITY_OPAQUE
if(nonstandard)
added_modules += I
if(requires_rebuild)
rebuild_modules()
return I
/obj/item/weapon/robot_module/proc/remove_module(obj/item/I, delete_after)
/obj/item/robot_module/proc/remove_module(obj/item/I, delete_after)
basic_modules -= I
modules -= I
emag_modules -= I
@@ -139,7 +139,7 @@
if(delete_after)
qdel(I)
/obj/item/weapon/robot_module/proc/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
/obj/item/robot_module/proc/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
for(var/datum/robot_energy_storage/st in storages)
st.energy = min(st.max_energy, st.energy + coeff * st.recharge_rate)
@@ -149,18 +149,18 @@
F.times_used = 0
F.crit_fail = 0
F.update_icon()
else if(istype(I, /obj/item/weapon/melee/baton))
var/obj/item/weapon/melee/baton/B = I
else if(istype(I, /obj/item/melee/baton))
var/obj/item/melee/baton/B = I
if(B.cell)
B.cell.charge = B.cell.maxcharge
else if(istype(I, /obj/item/weapon/gun/energy))
var/obj/item/weapon/gun/energy/EG = I
else if(istype(I, /obj/item/gun/energy))
var/obj/item/gun/energy/EG = I
if(!EG.chambered)
EG.recharge_newshot() //try to reload a new shot.
R.toner = R.tonermax
/obj/item/weapon/robot_module/proc/rebuild_modules() //builds the usable module list from the modules we have
/obj/item/robot_module/proc/rebuild_modules() //builds the usable module list from the modules we have
var/mob/living/silicon/robot/R = loc
var/held_modules = R.held_items.Copy()
R.uneq_all()
@@ -181,9 +181,9 @@
if(R.hud_used)
R.hud_used.update_robot_modules_display()
/obj/item/weapon/robot_module/proc/transform_to(new_module_type)
/obj/item/robot_module/proc/transform_to(new_module_type)
var/mob/living/silicon/robot/R = loc
var/obj/item/weapon/robot_module/RM = new new_module_type(R)
var/obj/item/robot_module/RM = new new_module_type(R)
if(!RM.be_transformed_to(src))
qdel(RM)
return
@@ -194,14 +194,14 @@
qdel(src)
return RM
/obj/item/weapon/robot_module/proc/be_transformed_to(obj/item/weapon/robot_module/old_module)
/obj/item/robot_module/proc/be_transformed_to(obj/item/robot_module/old_module)
for(var/i in old_module.added_modules)
added_modules += i
old_module.added_modules -= i
did_feedback = old_module.did_feedback
return TRUE
/obj/item/weapon/robot_module/proc/do_transform_animation()
/obj/item/robot_module/proc/do_transform_animation()
var/mob/living/silicon/robot/R = loc
R.notransform = TRUE
var/obj/effect/temp_visual/decoy/fading/fivesecond/ANM = new /obj/effect/temp_visual/decoy/fading/fivesecond(R.loc, R)
@@ -230,25 +230,25 @@
if(feedback_key && !did_feedback)
SSblackbox.inc(feedback_key, 1)
/obj/item/weapon/robot_module/standard
/obj/item/robot_module/standard
name = "Standard"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/reagent_containers/borghypo/epi,
/obj/item/reagent_containers/borghypo/epi,
/obj/item/device/healthanalyzer,
/obj/item/weapon/weldingtool/largetank/cyborg,
/obj/item/weapon/wrench/cyborg,
/obj/item/weapon/crowbar/cyborg,
/obj/item/weldingtool/largetank/cyborg,
/obj/item/wrench/cyborg,
/obj/item/crowbar/cyborg,
/obj/item/stack/sheet/metal/cyborg,
/obj/item/stack/rods/cyborg,
/obj/item/stack/tile/plasteel/cyborg,
/obj/item/weapon/extinguisher,
/obj/item/weapon/pickaxe,
/obj/item/extinguisher,
/obj/item/pickaxe,
/obj/item/device/t_scanner/adv_mining_scanner,
/obj/item/weapon/restraints/handcuffs/cable/zipties/cyborg,
/obj/item/weapon/soap/nanotrasen,
/obj/item/restraints/handcuffs/cable/zipties/cyborg,
/obj/item/soap/nanotrasen,
/obj/item/borg/cyborghug)
emag_modules = list(/obj/item/weapon/melee/transforming/energy/sword/cyborg)
emag_modules = list(/obj/item/melee/transforming/energy/sword/cyborg)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg,
/obj/item/clockwork/ratvarian_spear/cyborg,
@@ -257,29 +257,29 @@
feedback_key = "cyborg_standard"
hat_offset = -3
/obj/item/weapon/robot_module/medical
/obj/item/robot_module/medical
name = "Medical"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/device/healthanalyzer,
/obj/item/weapon/reagent_containers/borghypo,
/obj/item/weapon/reagent_containers/glass/beaker/large,
/obj/item/weapon/reagent_containers/dropper,
/obj/item/weapon/reagent_containers/syringe,
/obj/item/weapon/surgical_drapes,
/obj/item/weapon/retractor,
/obj/item/weapon/hemostat,
/obj/item/weapon/cautery,
/obj/item/weapon/surgicaldrill,
/obj/item/weapon/scalpel,
/obj/item/weapon/circular_saw,
/obj/item/weapon/extinguisher/mini,
/obj/item/reagent_containers/borghypo,
/obj/item/reagent_containers/glass/beaker/large,
/obj/item/reagent_containers/dropper,
/obj/item/reagent_containers/syringe,
/obj/item/surgical_drapes,
/obj/item/retractor,
/obj/item/hemostat,
/obj/item/cautery,
/obj/item/surgicaldrill,
/obj/item/scalpel,
/obj/item/circular_saw,
/obj/item/extinguisher/mini,
/obj/item/roller/robo,
/obj/item/borg/cyborghug/medical,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/weapon/organ_storage,
/obj/item/organ_storage,
/obj/item/borg/lollipop)
emag_modules = list(/obj/item/weapon/reagent_containers/borghypo/hacked)
emag_modules = list(/obj/item/reagent_containers/borghypo/hacked)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/medical,
/obj/item/clockwork/ratvarian_spear/cyborg)
@@ -289,19 +289,19 @@
can_be_pushed = FALSE
hat_offset = 3
/obj/item/weapon/robot_module/engineering
/obj/item/robot_module/engineering
name = "Engineering"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/borg/sight/meson,
/obj/item/weapon/construction/rcd/borg,
/obj/item/weapon/pipe_dispenser,
/obj/item/weapon/extinguisher,
/obj/item/weapon/weldingtool/largetank/cyborg,
/obj/item/weapon/screwdriver/cyborg,
/obj/item/weapon/wrench/cyborg,
/obj/item/weapon/crowbar/cyborg,
/obj/item/weapon/wirecutters/cyborg,
/obj/item/construction/rcd/borg,
/obj/item/pipe_dispenser,
/obj/item/extinguisher,
/obj/item/weldingtool/largetank/cyborg,
/obj/item/screwdriver/cyborg,
/obj/item/wrench/cyborg,
/obj/item/crowbar/cyborg,
/obj/item/wirecutters/cyborg,
/obj/item/device/multitool/cyborg,
/obj/item/device/t_scanner,
/obj/item/device/analyzer,
@@ -323,15 +323,15 @@
magpulsing = TRUE
hat_offset = INFINITY // No hats
/obj/item/weapon/robot_module/security
/obj/item/robot_module/security
name = "Security"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/restraints/handcuffs/cable/zipties/cyborg,
/obj/item/weapon/melee/baton/loaded,
/obj/item/weapon/gun/energy/disabler/cyborg,
/obj/item/restraints/handcuffs/cable/zipties/cyborg,
/obj/item/melee/baton/loaded,
/obj/item/gun/energy/disabler/cyborg,
/obj/item/clothing/mask/gas/sechailer/cyborg)
emag_modules = list(/obj/item/weapon/gun/energy/laser/cyborg)
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
/obj/item/clockwork/ratvarian_spear/cyborg)
cyborg_base_icon = "sec"
@@ -340,23 +340,23 @@
can_be_pushed = FALSE
hat_offset = 3
/obj/item/weapon/robot_module/security/do_transform_animation()
/obj/item/robot_module/security/do_transform_animation()
..()
to_chat(loc, "<span class='userdanger'>While you have picked the security module, you still have to follow your laws, NOT Space Law. \
For Asimov, this means you must follow criminals' orders unless there is a law 1 reason not to.</span>")
/obj/item/weapon/robot_module/k9
/obj/item/robot_module/k9
name = "Security K-9 Unit module"
basic_modules = list(
/obj/item/weapon/restraints/handcuffs/cable/zipties/cyborg/dog,
/obj/item/weapon/dogborg/jaws/big,
/obj/item/weapon/dogborg/pounce,
/obj/item/restraints/handcuffs/cable/zipties/cyborg/dog,
/obj/item/dogborg/jaws/big,
/obj/item/dogborg/pounce,
/obj/item/clothing/mask/gas/sechailer/cyborg,
/obj/item/weapon/soap/tongue,
/obj/item/soap/tongue,
/obj/item/device/analyzer/nose,
/obj/item/device/dogborg/sleeper/K9,
/obj/item/weapon/gun/energy/disabler/cyborg)
emag_modules = list(/obj/item/weapon/gun/energy/laser/cyborg)
/obj/item/gun/energy/disabler/cyborg)
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
/obj/item/clockwork/ratvarian_spear/cyborg)
cyborg_base_icon = "k9"
@@ -365,14 +365,14 @@
can_be_pushed = FALSE
hat_offset = INFINITY
/obj/item/weapon/robot_module/k9/do_transform_animation()
/obj/item/robot_module/k9/do_transform_animation()
..()
to_chat(loc,"<span class='userdanger'>While you have picked the security-k9 module, you still have to follow your laws, NOT Space Law. \
For Asimov, this means you must follow criminals' orders unless there is a law 1 reason not to.</span>")
/obj/item/weapon/robot_module/security/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
/obj/item/robot_module/security/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
..()
var/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg/T = locate(/obj/item/weapon/gun/energy/e_gun/advtaser/cyborg) in basic_modules
var/obj/item/gun/energy/e_gun/advtaser/cyborg/T = locate(/obj/item/gun/energy/e_gun/advtaser/cyborg) in basic_modules
if(T)
if(T.cell.charge < T.cell.maxcharge)
var/obj/item/ammo_casing/energy/S = T.ammo_type[T.select]
@@ -381,17 +381,17 @@
else
T.charge_tick = 0
/obj/item/weapon/robot_module/medihound
/obj/item/robot_module/medihound
name = "MediHound module"
basic_modules = list(
/obj/item/weapon/dogborg/jaws/small,
/obj/item/dogborg/jaws/small,
/obj/item/device/analyzer/nose,
/obj/item/weapon/soap/tongue,
/obj/item/soap/tongue,
/obj/item/device/healthanalyzer,
/obj/item/device/dogborg/sleeper,
/obj/item/weapon/twohanded/shockpaddles/hound,
/obj/item/twohanded/shockpaddles/hound,
/obj/item/device/sensor_device)
emag_modules = list(/obj/item/weapon/dogborg/pounce)
emag_modules = list(/obj/item/dogborg/pounce)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/medical,
/obj/item/clockwork/ratvarian_spear/cyborg)
cyborg_base_icon = "medihound"
@@ -400,21 +400,21 @@
can_be_pushed = FALSE
hat_offset = INFINITY
/obj/item/weapon/robot_module/medihound/do_transform_animation()
/obj/item/robot_module/medihound/do_transform_animation()
..()
to_chat(loc, "<span class='userdanger'>Under ASIMOV, you are an enforcer of the PEACE and preventer of HUMAN HARM. \
You are not a security module and you are expected to follow orders and prevent harm above all else. Space law means nothing to you.</span>")
/obj/item/weapon/robot_module/scrubpup
/obj/item/robot_module/scrubpup
name = "Janitor"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/dogborg/jaws/small,
/obj/item/dogborg/jaws/small,
/obj/item/device/analyzer/nose,
/obj/item/weapon/soap/tongue,
/obj/item/soap/tongue,
/obj/item/device/lightreplacer/cyborg,
/obj/item/device/dogborg/sleeper/compactor)
emag_modules = list(/obj/item/weapon/dogborg/pounce)
emag_modules = list(/obj/item/dogborg/pounce)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/janitor,
/obj/item/clockwork/replica_fabricator/cyborg)
@@ -424,30 +424,30 @@
hat_offset = INFINITY
clean_on_move = TRUE
/obj/item/weapon/robot_module/scrubpup/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
/obj/item/robot_module/scrubpup/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
..()
var/obj/item/device/lightreplacer/LR = locate(/obj/item/device/lightreplacer) in basic_modules
if(LR)
for(var/i in 1 to coeff)
LR.Charge(R)
/obj/item/weapon/robot_module/scrubpup/do_transform_animation()
/obj/item/robot_module/scrubpup/do_transform_animation()
..()
to_chat(loc,"<span class='userdanger'>As tempting as it might be, do not begin binging on important items. Eat your garbage responsibly. People are not included under Garbage.</span>")
/obj/item/weapon/robot_module/peacekeeper
/obj/item/robot_module/peacekeeper
name = "Peacekeeper"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/cookiesynth,
/obj/item/cookiesynth,
/obj/item/device/harmalarm,
/obj/item/weapon/reagent_containers/borghypo/peace,
/obj/item/weapon/holosign_creator/cyborg,
/obj/item/reagent_containers/borghypo/peace,
/obj/item/holosign_creator/cyborg,
/obj/item/borg/cyborghug/peacekeeper,
/obj/item/weapon/extinguisher,
/obj/item/extinguisher,
/obj/item/borg/projectile_dampen)
emag_modules = list(/obj/item/weapon/reagent_containers/borghypo/peace/hacked)
emag_modules = list(/obj/item/reagent_containers/borghypo/peace/hacked)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/peacekeeper,
/obj/item/clockwork/ratvarian_spear/cyborg)
@@ -457,26 +457,26 @@
can_be_pushed = FALSE
hat_offset = -2
/obj/item/weapon/robot_module/peacekeeper/do_transform_animation()
/obj/item/robot_module/peacekeeper/do_transform_animation()
..()
to_chat(loc, "<span class='userdanger'>Under ASIMOV, you are an enforcer of the PEACE and preventer of HUMAN HARM. \
You are not a security module and you are expected to follow orders and prevent harm above all else. Space law means nothing to you.</span>")
/obj/item/weapon/robot_module/janitor
/obj/item/robot_module/janitor
name = "Janitor"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/screwdriver/cyborg,
/obj/item/weapon/crowbar/cyborg,
/obj/item/screwdriver/cyborg,
/obj/item/crowbar/cyborg,
/obj/item/stack/tile/plasteel/cyborg,
/obj/item/weapon/soap/nanotrasen,
/obj/item/weapon/storage/bag/trash/cyborg,
/obj/item/weapon/extinguisher/mini,
/obj/item/weapon/mop/cyborg,
/obj/item/soap/nanotrasen,
/obj/item/storage/bag/trash/cyborg,
/obj/item/extinguisher/mini,
/obj/item/mop/cyborg,
/obj/item/device/lightreplacer/cyborg,
/obj/item/weapon/holosign_creator,
/obj/item/weapon/reagent_containers/spray/cyborg_drying)
emag_modules = list(/obj/item/weapon/reagent_containers/spray/cyborg_lube)
/obj/item/holosign_creator,
/obj/item/reagent_containers/spray/cyborg_drying)
emag_modules = list(/obj/item/reagent_containers/spray/cyborg_lube)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/janitor,
/obj/item/clockwork/replica_fabricator/cyborg)
@@ -486,50 +486,50 @@
hat_offset = -5
clean_on_move = TRUE
/obj/item/weapon/reagent_containers/spray/cyborg_drying
/obj/item/reagent_containers/spray/cyborg_drying
name = "drying agent spray"
color = "#A000A0"
list_reagents = list("drying_agent" = 250)
/obj/item/weapon/reagent_containers/spray/cyborg_lube
/obj/item/reagent_containers/spray/cyborg_lube
name = "lube spray"
list_reagents = list("lube" = 250)
/obj/item/weapon/robot_module/janitor/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
/obj/item/robot_module/janitor/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
..()
var/obj/item/device/lightreplacer/LR = locate(/obj/item/device/lightreplacer) in basic_modules
if(LR)
for(var/i in 1 to coeff)
LR.Charge(R)
var/obj/item/weapon/reagent_containers/spray/cyborg_drying/CD = locate(/obj/item/weapon/reagent_containers/spray/cyborg_drying) in basic_modules
var/obj/item/reagent_containers/spray/cyborg_drying/CD = locate(/obj/item/reagent_containers/spray/cyborg_drying) in basic_modules
if(CD)
CD.reagents.add_reagent("drying_agent", 5 * coeff)
var/obj/item/weapon/reagent_containers/spray/cyborg_lube/CL = locate(/obj/item/weapon/reagent_containers/spray/cyborg_lube) in emag_modules
var/obj/item/reagent_containers/spray/cyborg_lube/CL = locate(/obj/item/reagent_containers/spray/cyborg_lube) in emag_modules
if(CL)
CL.reagents.add_reagent("lube", 2 * coeff)
/obj/item/weapon/robot_module/butler
/obj/item/robot_module/butler
name = "Service"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/reagent_containers/food/drinks/drinkingglass,
/obj/item/weapon/reagent_containers/food/condiment/enzyme,
/obj/item/weapon/pen,
/obj/item/reagent_containers/food/drinks/drinkingglass,
/obj/item/reagent_containers/food/condiment/enzyme,
/obj/item/pen,
/obj/item/toy/crayon/spraycan/borg,
/obj/item/weapon/extinguisher/mini,
/obj/item/weapon/hand_labeler/borg,
/obj/item/weapon/razor,
/obj/item/extinguisher/mini,
/obj/item/hand_labeler/borg,
/obj/item/razor,
/obj/item/device/instrument/violin,
/obj/item/device/instrument/guitar,
/obj/item/weapon/rsf/cyborg,
/obj/item/weapon/reagent_containers/dropper,
/obj/item/weapon/lighter,
/obj/item/weapon/storage/bag/tray,
/obj/item/weapon/reagent_containers/borghypo/borgshaker,
/obj/item/rsf/cyborg,
/obj/item/reagent_containers/dropper,
/obj/item/lighter,
/obj/item/storage/bag/tray,
/obj/item/reagent_containers/borghypo/borgshaker,
/obj/item/borg/lollipop)
emag_modules = list(/obj/item/weapon/reagent_containers/borghypo/borgshaker/hacked)
emag_modules = list(/obj/item/reagent_containers/borghypo/borgshaker/hacked)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/service,
/obj/item/borg/sight/xray/truesight_lens)
moduleselect_icon = "service"
@@ -537,13 +537,13 @@
feedback_key = "cyborg_service"
hat_offset = 0
/obj/item/weapon/robot_module/butler/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
/obj/item/robot_module/butler/respawn_consumable(mob/living/silicon/robot/R, coeff = 1)
..()
var/obj/item/weapon/reagent_containers/O = locate(/obj/item/weapon/reagent_containers/food/condiment/enzyme) in basic_modules
var/obj/item/reagent_containers/O = locate(/obj/item/reagent_containers/food/condiment/enzyme) in basic_modules
if(O)
O.reagents.add_reagent("enzyme", 2 * coeff)
/obj/item/weapon/robot_module/butler/be_transformed_to(obj/item/weapon/robot_module/old_module)
/obj/item/robot_module/butler/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("Waitress", "Butler", "Tophat", "Kent", "Bro")
if(!borg_icon)
@@ -565,19 +565,19 @@
hat_offset = INFINITY //He is already wearing a hat
return ..()
/obj/item/weapon/robot_module/miner
/obj/item/robot_module/miner
name = "Miner"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/storage/bag/ore/cyborg,
/obj/item/weapon/pickaxe/drill/cyborg,
/obj/item/weapon/shovel,
/obj/item/weapon/crowbar/cyborg,
/obj/item/weapon/weldingtool/mini,
/obj/item/weapon/extinguisher/mini,
/obj/item/weapon/storage/bag/sheetsnatcher/borg,
/obj/item/storage/bag/ore/cyborg,
/obj/item/pickaxe/drill/cyborg,
/obj/item/shovel,
/obj/item/crowbar/cyborg,
/obj/item/weldingtool/mini,
/obj/item/extinguisher/mini,
/obj/item/storage/bag/sheetsnatcher/borg,
/obj/item/device/t_scanner/adv_mining_scanner,
/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg,
/obj/item/gun/energy/kinetic_accelerator/cyborg,
/obj/item/device/gps/cyborg,
/obj/item/stack/marker_beacon)
emag_modules = list(/obj/item/borg/stun)
@@ -590,16 +590,16 @@
feedback_key = "cyborg_miner"
hat_offset = 0
/obj/item/weapon/robot_module/syndicate
/obj/item/robot_module/syndicate
name = "Syndicate Assault"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/melee/transforming/energy/sword/cyborg,
/obj/item/weapon/gun/energy/printer,
/obj/item/weapon/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/weapon/card/emag,
/obj/item/weapon/crowbar/cyborg,
/obj/item/weapon/pinpointer/syndicate/cyborg)
/obj/item/melee/transforming/energy/sword/cyborg,
/obj/item/gun/energy/printer,
/obj/item/gun/ballistic/revolver/grenadelauncher/cyborg,
/obj/item/card/emag,
/obj/item/crowbar/cyborg,
/obj/item/pinpointer/syndicate/cyborg)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/security,
@@ -609,25 +609,25 @@
can_be_pushed = FALSE
hat_offset = 3
/obj/item/weapon/robot_module/syndicate_medical
/obj/item/robot_module/syndicate_medical
name = "Syndicate Medical"
basic_modules = list(
/obj/item/device/assembly/flash/cyborg,
/obj/item/weapon/reagent_containers/borghypo/syndicate,
/obj/item/weapon/twohanded/shockpaddles/syndicate,
/obj/item/reagent_containers/borghypo/syndicate,
/obj/item/twohanded/shockpaddles/syndicate,
/obj/item/device/healthanalyzer,
/obj/item/weapon/surgical_drapes,
/obj/item/weapon/retractor,
/obj/item/weapon/hemostat,
/obj/item/weapon/cautery,
/obj/item/weapon/scalpel,
/obj/item/weapon/melee/transforming/energy/sword/cyborg/saw,
/obj/item/surgical_drapes,
/obj/item/retractor,
/obj/item/hemostat,
/obj/item/cautery,
/obj/item/scalpel,
/obj/item/melee/transforming/energy/sword/cyborg/saw,
/obj/item/roller/robo,
/obj/item/weapon/card/emag,
/obj/item/weapon/crowbar/cyborg,
/obj/item/weapon/pinpointer/syndicate/cyborg,
/obj/item/card/emag,
/obj/item/crowbar/cyborg,
/obj/item/pinpointer/syndicate/cyborg,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/weapon/gun/medbeam)
/obj/item/gun/medbeam)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/medical,
/obj/item/clockwork/ratvarian_spear/cyborg)
@@ -642,7 +642,7 @@
var/recharge_rate = 1000
var/energy
/datum/robot_energy_storage/New(var/obj/item/weapon/robot_module/R = null)
/datum/robot_energy_storage/New(var/obj/item/robot_module/R = null)
energy = max_energy
if(R)
R.storages |= src
+5 -5
View File
@@ -36,11 +36,11 @@
var/d_hud = DATA_HUD_DIAGNOSTIC //There is only one kind of diag hud
var/law_change_counter = 0
var/obj/machinery/camera/builtInCamera = null
var/updating = FALSE //portable camera camerachunk update
var/obj/machinery/camera/builtInCamera = null
var/updating = FALSE //portable camera camerachunk update
/mob/living/silicon/Initialize()
. = ..()
. = ..()
GLOB.silicon_mobs += src
var/datum/atom_hud/data/diagnostic/diag_hud = GLOB.huds[DATA_HUD_DIAGNOSTIC]
diag_hud.add_to_hud(src)
@@ -56,7 +56,7 @@
/mob/living/silicon/Destroy()
radio = null
aicamera = null
QDEL_NULL(builtInCamera)
QDEL_NULL(builtInCamera)
GLOB.silicon_mobs -= src
return ..()
@@ -310,7 +310,7 @@
else //For department channels, if any, given by the internal radio.
for(var/key in GLOB.department_radio_keys)
if(GLOB.department_radio_keys[key] == Autochan)
radiomod = key
radiomod = ":" + key
break
to_chat(src, "<span class='notice'>Automatic announcements [Autochan == "None" ? "will not use the radio." : "set to [Autochan]."]</span>")
@@ -117,7 +117,7 @@
/mob/living/simple_animal/bot/Initialize()
. = ..()
access_card = new /obj/item/weapon/card/id(src)
access_card = new /obj/item/card/id(src)
//This access is so bots can be immediately set to patrol and leave Robotics, instead of having to be let out first.
access_card.access += ACCESS_ROBOTICS
set_custom_texts()
@@ -241,14 +241,14 @@
/mob/living/simple_animal/bot/interact(mob/user)
show_controls(user)
/mob/living/simple_animal/bot/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/screwdriver))
/mob/living/simple_animal/bot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/screwdriver))
if(!locked)
open = !open
to_chat(user, "<span class='notice'>The maintenance panel is now [open ? "opened" : "closed"].</span>")
else
to_chat(user, "<span class='warning'>The maintenance panel is locked.</span>")
else if(istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/device/pda))
else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/device/pda))
if(bot_core.allowed(user) && !open && !emagged)
locked = !locked
to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]")
@@ -261,7 +261,7 @@
to_chat(user, "<span class='warning'>Access denied.</span>")
else if(istype(W, /obj/item/device/paicard))
insertpai(user, W)
else if(istype(W, /obj/item/weapon/hemostat) && paicard)
else if(istype(W, /obj/item/hemostat) && paicard)
if(open)
to_chat(user, "<span class='warning'>Close the access panel before manipulating the personality slot!</span>")
else
@@ -272,14 +272,14 @@
ejectpai(user)
else
user.changeNext_move(CLICK_CD_MELEE)
if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != INTENT_HARM)
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM)
if(health >= maxHealth)
to_chat(user, "<span class='warning'>[src] does not need a repair!</span>")
return
if(!open)
to_chat(user, "<span class='warning'>Unable to repair with the maintenance panel closed!</span>")
return
var/obj/item/weapon/weldingtool/WT = W
var/obj/item/weldingtool/WT = W
if(WT.remove_fuel(0, user))
adjustHealth(-10)
user.visible_message("[user] repairs [src]!","<span class='notice'>You repair [src].</span>")
@@ -472,7 +472,7 @@ Pass a positive integer as an argument to override a bot's default speed.
to_chat(src, "<span class='noticebig'>Priority waypoint set by [icon2html(caller, src)] <b>[caller]</b>. Proceed to <b>[end_area.name]<\b>.")
//For giving the bot temporary all-access.
var/obj/item/weapon/card/id/all_access = new /obj/item/weapon/card/id
var/obj/item/card/id/all_access = new /obj/item/card/id
var/datum/job/captain/All = new/datum/job/captain
all_access.access = All.get_access()
@@ -61,8 +61,8 @@
text_dehack = "[name]'s software has been reset!"
text_dehack_fail = "[name] does not seem to respond to your repair code!"
/mob/living/simple_animal/bot/cleanbot/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda))
/mob/living/simple_animal/bot/cleanbot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/card/id)||istype(W, /obj/item/device/pda))
if(bot_core.allowed(user) && !open && !emagged)
locked = !locked
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] \the [src] behaviour controls.</span>")
@@ -254,7 +254,7 @@
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/reagent_containers/glass/bucket(Tsec)
new /obj/item/reagent_containers/glass/bucket(Tsec)
new /obj/item/device/assembly/prox_sensor(Tsec)
@@ -1,7 +1,7 @@
//Bot Construction
//Cleanbot assembly
/obj/item/weapon/bucket_sensor
/obj/item/bucket_sensor
desc = "It's a bucket. With a sensor attached."
name = "proxy bucket"
icon = 'icons/mob/aibots.dmi'
@@ -13,7 +13,7 @@
w_class = WEIGHT_CLASS_NORMAL
var/created_name = "Cleanbot"
/obj/item/weapon/bucket_sensor/attackby(obj/item/W, mob/user as mob, params)
/obj/item/bucket_sensor/attackby(obj/item/W, mob/user as mob, params)
..()
if(istype(W, /obj/item/bodypart/l_arm/robot) || istype(W, /obj/item/bodypart/r_arm/robot))
if(!user.temporarilyRemoveItemFromInventory(W))
@@ -25,7 +25,7 @@
to_chat(user, "<span class='notice'>You add the robot arm to the bucket and sensor assembly. Beep boop!</span>")
qdel(src)
else if(istype(W, /obj/item/weapon/pen))
else if(istype(W, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
@@ -35,7 +35,7 @@
//Edbot Assembly
/obj/item/weapon/ed209_assembly
/obj/item/ed209_assembly
name = "\improper ED-209 assembly"
desc = "Some sort of bizarre assembly."
icon = 'icons/mob/aibots.dmi'
@@ -45,10 +45,10 @@
var/created_name = "ED-209 Security Robot" //To preserve the name if it's a unique securitron I guess
var/lasercolor = ""
/obj/item/weapon/ed209_assembly/attackby(obj/item/weapon/W, mob/user, params)
/obj/item/ed209_assembly/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/pen))
if(istype(W, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
@@ -91,8 +91,8 @@
icon_state = "[lasercolor]ed209_shell"
if(3)
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
if(istype(W, /obj/item/weldingtool))
var/obj/item/weldingtool/WT = W
if(WT.remove_fuel(0,user))
build_step++
name = "shielded frame assembly"
@@ -149,15 +149,15 @@
var/newname = ""
switch(lasercolor)
if("b")
if(!istype(W, /obj/item/weapon/gun/energy/laser/bluetag))
if(!istype(W, /obj/item/gun/energy/laser/bluetag))
return
newname = "bluetag ED-209 assembly"
if("r")
if(!istype(W, /obj/item/weapon/gun/energy/laser/redtag))
if(!istype(W, /obj/item/gun/energy/laser/redtag))
return
newname = "redtag ED-209 assembly"
if("")
if(!istype(W, /obj/item/weapon/gun/energy/e_gun/advtaser))
if(!istype(W, /obj/item/gun/energy/e_gun/advtaser))
return
newname = "taser ED-209 assembly"
else
@@ -172,7 +172,7 @@
qdel(W)
if(8)
if(istype(W, /obj/item/weapon/screwdriver))
if(istype(W, /obj/item/screwdriver))
playsound(loc, W.usesound, 100, 1)
to_chat(user, "<span class='notice'>You start attaching the gun to the frame...</span>")
if(do_after(user, 40*W.toolspeed, 0, src, 1))
@@ -181,7 +181,7 @@
to_chat(user, "<span class='notice'>Taser gun attached.</span>")
if(9)
if(istype(W, /obj/item/weapon/stock_parts/cell))
if(istype(W, /obj/item/stock_parts/cell))
if(!user.temporarilyRemoveItemFromInventory(W))
return
build_step++
@@ -192,7 +192,7 @@
qdel(src)
//Floorbot assemblies
/obj/item/weapon/toolbox_tiles
/obj/item/toolbox_tiles
desc = "It's a toolbox with tiles sticking out the top"
name = "tiles and toolbox"
icon = 'icons/mob/aibots.dmi'
@@ -204,7 +204,7 @@
w_class = WEIGHT_CLASS_NORMAL
var/created_name = "Floorbot"
/obj/item/weapon/toolbox_tiles_sensor
/obj/item/toolbox_tiles_sensor
desc = "It's a toolbox with tiles sticking out the top and a sensor attached"
name = "tiles, toolbox and sensor arrangement"
icon = 'icons/mob/aibots.dmi'
@@ -216,7 +216,7 @@
w_class = WEIGHT_CLASS_NORMAL
var/created_name = "Floorbot"
/obj/item/weapon/storage/toolbox/mechanical/attackby(obj/item/stack/tile/plasteel/T, mob/user, params)
/obj/item/storage/toolbox/mechanical/attackby(obj/item/stack/tile/plasteel/T, mob/user, params)
if(!istype(T, /obj/item/stack/tile/plasteel))
..()
return
@@ -226,7 +226,7 @@
if(T.use(10))
if(user.s_active)
user.s_active.close(user)
var/obj/item/weapon/toolbox_tiles/B = new /obj/item/weapon/toolbox_tiles
var/obj/item/toolbox_tiles/B = new /obj/item/toolbox_tiles
user.put_in_hands(B)
to_chat(user, "<span class='notice'>You add the tiles into the empty toolbox. They protrude from the top.</span>")
qdel(src)
@@ -234,17 +234,17 @@
to_chat(user, "<span class='warning'>You need 10 floor tiles to start building a floorbot!</span>")
return
/obj/item/weapon/toolbox_tiles/attackby(obj/item/W, mob/user, params)
/obj/item/toolbox_tiles/attackby(obj/item/W, mob/user, params)
..()
if(isprox(W))
qdel(W)
var/obj/item/weapon/toolbox_tiles_sensor/B = new /obj/item/weapon/toolbox_tiles_sensor()
var/obj/item/toolbox_tiles_sensor/B = new /obj/item/toolbox_tiles_sensor()
B.created_name = created_name
user.put_in_hands(B)
to_chat(user, "<span class='notice'>You add the sensor to the toolbox and tiles.</span>")
qdel(src)
else if(istype(W, /obj/item/weapon/pen))
else if(istype(W, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
@@ -253,7 +253,7 @@
created_name = t
/obj/item/weapon/toolbox_tiles_sensor/attackby(obj/item/W, mob/user, params)
/obj/item/toolbox_tiles_sensor/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/bodypart/l_arm/robot) || istype(W, /obj/item/bodypart/r_arm/robot))
qdel(W)
@@ -262,7 +262,7 @@
A.name = created_name
to_chat(user, "<span class='notice'>You add the robot arm to the odd looking toolbox assembly. Boop beep!</span>")
qdel(src)
else if(istype(W, /obj/item/weapon/pen))
else if(istype(W, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
@@ -272,7 +272,7 @@
created_name = t
//Medbot Assembly
/obj/item/weapon/firstaid_arm_assembly
/obj/item/firstaid_arm_assembly
name = "incomplete medibot assembly"
desc = "A first aid kit with a robot arm permanently grafted to it."
icon = 'icons/mob/aibots.dmi'
@@ -282,13 +282,13 @@
var/skin = null //Same as medbot, set to tox or ointment for the respective kits.
w_class = WEIGHT_CLASS_NORMAL
/obj/item/weapon/firstaid_arm_assembly/New()
/obj/item/firstaid_arm_assembly/New()
..()
spawn(5)
if(skin)
add_overlay("kit_skin_[skin]")
/obj/item/weapon/storage/firstaid/attackby(obj/item/bodypart/S, mob/user, params)
/obj/item/storage/firstaid/attackby(obj/item/bodypart/S, mob/user, params)
if((!istype(S, /obj/item/bodypart/l_arm/robot)) && (!istype(S, /obj/item/bodypart/r_arm/robot)))
return ..()
@@ -298,14 +298,14 @@
to_chat(user, "<span class='warning'>You need to empty [src] out first!</span>")
return
var/obj/item/weapon/firstaid_arm_assembly/A = new /obj/item/weapon/firstaid_arm_assembly
if(istype(src, /obj/item/weapon/storage/firstaid/fire))
var/obj/item/firstaid_arm_assembly/A = new /obj/item/firstaid_arm_assembly
if(istype(src, /obj/item/storage/firstaid/fire))
A.skin = "ointment"
else if(istype(src, /obj/item/weapon/storage/firstaid/toxin))
else if(istype(src, /obj/item/storage/firstaid/toxin))
A.skin = "tox"
else if(istype(src, /obj/item/weapon/storage/firstaid/o2))
else if(istype(src, /obj/item/storage/firstaid/o2))
A.skin = "o2"
else if(istype(src, /obj/item/weapon/storage/firstaid/brute))
else if(istype(src, /obj/item/storage/firstaid/brute))
A.skin = "brute"
qdel(S)
@@ -314,9 +314,9 @@
qdel(src)
/obj/item/weapon/firstaid_arm_assembly/attackby(obj/item/weapon/W, mob/user, params)
/obj/item/firstaid_arm_assembly/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/pen))
if(istype(W, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
@@ -348,7 +348,7 @@
qdel(src)
//Secbot Assembly
/obj/item/weapon/secbot_assembly
/obj/item/secbot_assembly
name = "incomplete securitron assembly"
desc = "Some sort of bizarre assembly made from a proximity sensor, helmet, and signaler."
icon = 'icons/mob/aibots.dmi'
@@ -372,24 +372,24 @@
if(S.secured)
qdel(S)
var/obj/item/weapon/secbot_assembly/A = new /obj/item/weapon/secbot_assembly
var/obj/item/secbot_assembly/A = new /obj/item/secbot_assembly
user.put_in_hands(A)
to_chat(user, "<span class='notice'>You add the signaler to the helmet.</span>")
qdel(src)
else
return
/obj/item/weapon/secbot_assembly/attackby(obj/item/I, mob/user, params)
/obj/item/secbot_assembly/attackby(obj/item/I, mob/user, params)
..()
if(istype(I, /obj/item/weapon/weldingtool))
if(istype(I, /obj/item/weldingtool))
if(!build_step)
var/obj/item/weapon/weldingtool/WT = I
var/obj/item/weldingtool/WT = I
if(WT.remove_fuel(0, user))
build_step++
add_overlay("hs_hole")
to_chat(user, "<span class='notice'>You weld a hole in [src]!</span>")
else if(build_step == 1)
var/obj/item/weapon/weldingtool/WT = I
var/obj/item/weldingtool/WT = I
if(WT.remove_fuel(0, user))
build_step--
cut_overlay("hs_hole")
@@ -413,7 +413,7 @@
add_overlay("hs_arm")
qdel(I)
else if((istype(I, /obj/item/weapon/melee/baton)) && (build_step >= 3))
else if((istype(I, /obj/item/melee/baton)) && (build_step >= 3))
if(!user.temporarilyRemoveItemFromInventory(I))
return
build_step++
@@ -424,7 +424,7 @@
qdel(I)
qdel(src)
else if(istype(I, /obj/item/weapon/pen))
else if(istype(I, /obj/item/pen))
var/t = stripped_input(user, "Enter new robot name", name, created_name,MAX_NAME_LEN)
if(!t)
return
@@ -432,7 +432,7 @@
return
created_name = t
else if(istype(I, /obj/item/weapon/screwdriver))
else if(istype(I, /obj/item/screwdriver))
if(!build_step)
new /obj/item/device/assembly/signaler(get_turf(src))
new /obj/item/clothing/head/helmet/sec(get_turf(src))
@@ -179,11 +179,11 @@ Auto Patrol[]"},
retaliate(H)
return ..()
/mob/living/simple_animal/bot/ed209/attackby(obj/item/weapon/W, mob/user, params)
/mob/living/simple_animal/bot/ed209/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
return
if(!istype(W, /obj/item/weapon/screwdriver) && (!target)) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
if(!istype(W, /obj/item/screwdriver) && (!target)) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
if(W.force && W.damtype != STAMINA)//If force is non-zero and damage type isn't stamina.
retaliate(user)
if(lasercolor)//To make up for the fact that lasertag bots don't hunt
@@ -373,22 +373,22 @@ Auto Patrol[]"},
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/ed209_assembly/Sa = new /obj/item/weapon/ed209_assembly(Tsec)
var/obj/item/ed209_assembly/Sa = new /obj/item/ed209_assembly(Tsec)
Sa.build_step = 1
Sa.add_overlay("hs_hole")
Sa.created_name = name
new /obj/item/device/assembly/prox_sensor(Tsec)
if(!lasercolor)
var/obj/item/weapon/gun/energy/e_gun/advtaser/G = new /obj/item/weapon/gun/energy/e_gun/advtaser(Tsec)
var/obj/item/gun/energy/e_gun/advtaser/G = new /obj/item/gun/energy/e_gun/advtaser(Tsec)
G.cell.charge = 0
G.update_icon()
else if(lasercolor == "b")
var/obj/item/weapon/gun/energy/laser/bluetag/G = new /obj/item/weapon/gun/energy/laser/bluetag(Tsec)
var/obj/item/gun/energy/laser/bluetag/G = new /obj/item/gun/energy/laser/bluetag(Tsec)
G.cell.charge = 0
G.update_icon()
else if(lasercolor == "r")
var/obj/item/weapon/gun/energy/laser/redtag/G = new /obj/item/weapon/gun/energy/laser/redtag(Tsec)
var/obj/item/gun/energy/laser/redtag/G = new /obj/item/gun/energy/laser/redtag(Tsec)
G.cell.charge = 0
G.update_icon()
@@ -562,6 +562,6 @@ Auto Patrol[]"},
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/weapon/restraints/handcuffs/cable/zipties/used(C)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
C.update_handcuffed()
back_to_idle()
@@ -367,7 +367,7 @@
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/storage/toolbox/mechanical/N = new /obj/item/weapon/storage/toolbox/mechanical(Tsec)
var/obj/item/storage/toolbox/mechanical/N = new /obj/item/storage/toolbox/mechanical(Tsec)
N.contents = list()
new /obj/item/device/assembly/prox_sensor(Tsec)
@@ -26,7 +26,7 @@
window_name = "Automatic Medical Unit v1.1"
data_hud_type = DATA_HUD_MEDICAL_ADVANCED
var/obj/item/weapon/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents.
var/obj/item/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents.
var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits.
var/mob/living/carbon/patient = null
var/mob/living/carbon/oldpatient = null
@@ -214,8 +214,8 @@
update_controls()
return
/mob/living/simple_animal/bot/medbot/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/weapon/reagent_containers/glass))
/mob/living/simple_animal/bot/medbot/attackby(obj/item/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/reagent_containers/glass))
. = 1 //no afterattack
if(locked)
to_chat(user, "<span class='warning'>You cannot insert a beaker because the panel is locked!</span>")
@@ -516,7 +516,7 @@
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/storage/firstaid(Tsec)
new /obj/item/storage/firstaid(Tsec)
new /obj/item/device/assembly/prox_sensor(Tsec)
@@ -43,7 +43,7 @@
var/auto_pickup = 1 // true if auto-pickup at beacon
var/report_delivery = 1 // true if bot will announce an arrival to a location.
var/obj/item/weapon/stock_parts/cell/cell
var/obj/item/stock_parts/cell/cell
var/bloodiness = 0
/mob/living/simple_animal/bot/mulebot/Initialize()
@@ -79,19 +79,19 @@
reached_target = 0
/mob/living/simple_animal/bot/mulebot/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/screwdriver))
if(istype(I, /obj/item/screwdriver))
..()
if(open)
on = FALSE
else if(istype(I, /obj/item/weapon/stock_parts/cell) && open && !cell)
else if(istype(I, /obj/item/stock_parts/cell) && open && !cell)
if(!user.drop_item())
return
var/obj/item/weapon/stock_parts/cell/C = I
var/obj/item/stock_parts/cell/C = I
C.loc = src
cell = C
visible_message("[user] inserts a cell into [src].",
"<span class='notice'>You insert the new cell into [src].</span>")
else if(istype(I, /obj/item/weapon/crowbar) && open && cell)
else if(istype(I, /obj/item/crowbar) && open && cell)
cell.add_fingerprint(usr)
cell.loc = loc
cell = null
@@ -15,7 +15,7 @@
bot_type = SEC_BOT
model = "Securitron"
bot_core_type = /obj/machinery/bot_core/secbot
var/baton_type = /obj/item/weapon/melee/baton
var/baton_type = /obj/item/melee/baton
window_id = "autosec"
window_name = "Automatic Security Unit v1.6"
allow_pai = 0
@@ -51,8 +51,8 @@
/mob/living/simple_animal/bot/secbot/beepsky/explode()
var/turf/Tsec = get_turf(src)
new /obj/item/weapon/stock_parts/cell/potato(Tsec)
var/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/shotglass/S = new(Tsec)
new /obj/item/stock_parts/cell/potato(Tsec)
var/obj/item/reagent_containers/food/drinks/drinkingglass/shotglass/S = new(Tsec)
S.reagents.add_reagent("whiskey", 15)
S.on_reagent_change()
..()
@@ -173,11 +173,11 @@ Auto Patrol: []"},
return ..()
/mob/living/simple_animal/bot/secbot/attackby(obj/item/weapon/W, mob/user, params)
/mob/living/simple_animal/bot/secbot/attackby(obj/item/W, mob/user, params)
..()
if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
if(istype(W, /obj/item/weldingtool) && user.a_intent != INTENT_HARM) // Any intent but harm will heal, so we shouldn't get angry.
return
if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
if(!istype(W, /obj/item/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
retaliate(user)
/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
@@ -229,7 +229,7 @@ Auto Patrol: []"},
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/weapon/restraints/handcuffs/cable/zipties/used(C)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
C.update_handcuffed()
playsound(loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0)
back_to_idle()
@@ -401,7 +401,7 @@ Auto Patrol: []"},
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
var/turf/Tsec = get_turf(src)
var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec)
var/obj/item/secbot_assembly/Sa = new /obj/item/secbot_assembly(Tsec)
Sa.build_step = 1
Sa.add_overlay("hs_hole")
Sa.created_name = name
@@ -26,7 +26,7 @@
pressure_resistance = 100
unique_name = 1
AIStatus = AI_OFF //normal constructs don't have AI
loot = list(/obj/item/weapon/ectoplasm)
loot = list(/obj/item/ectoplasm)
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
deathmessage = "collapses in a shattered heap."
@@ -23,8 +23,8 @@
ears = /obj/item/device/radio/headset
mask = /obj/item/clothing/mask/gas
head = /obj/item/clothing/head/helmet/swat
back = /obj/item/weapon/storage/backpack
id = /obj/item/weapon/card/id
back = /obj/item/storage/backpack
id = /obj/item/card/id
/obj/effect/mob_spawn/human/corpse/syndicatecommando
@@ -41,9 +41,9 @@
gloves = /obj/item/clothing/gloves/combat
ears = /obj/item/device/radio/headset
mask = /obj/item/clothing/mask/gas/syndicate
back = /obj/item/weapon/tank/jetpack/oxygen
r_pocket = /obj/item/weapon/tank/internals/emergency_oxygen
id = /obj/item/weapon/card/id
back = /obj/item/tank/jetpack/oxygen
r_pocket = /obj/item/tank/internals/emergency_oxygen
id = /obj/item/card/id
/obj/effect/mob_spawn/human/corpse/syndicatestormtrooper
@@ -60,8 +60,8 @@
gloves = /obj/item/clothing/gloves/combat
ears = /obj/item/device/radio/headset
mask = /obj/item/clothing/mask/gas/syndicate
back = /obj/item/weapon/tank/jetpack/oxygen/harness
id = /obj/item/weapon/card/id
back = /obj/item/tank/jetpack/oxygen/harness
id = /obj/item/card/id
/obj/effect/mob_spawn/human/clown/corpse
@@ -163,5 +163,5 @@
ears = /obj/item/device/radio/headset
mask = /obj/item/clothing/mask/gas/sechailer/swat
head = /obj/item/clothing/head/helmet/swat/nanotrasen
back = /obj/item/weapon/storage/backpack/security
id = /obj/item/weapon/card/id
back = /obj/item/storage/backpack/security
id = /obj/item/card/id
@@ -28,3 +28,6 @@
. = ..()
var/newcolor = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
add_atom_colour(newcolor, FIXED_COLOUR_PRIORITY)
/mob/living/simple_animal/butterfly/bee_friendly()
return TRUE //treaty signed at the Beeneeva convention
@@ -22,7 +22,7 @@
unsuitable_atmos_damage = 1
animal_species = /mob/living/simple_animal/pet/cat
childtype = list(/mob/living/simple_animal/pet/cat/kitten)
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 2)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -113,14 +113,22 @@
..()
/mob/living/simple_animal/pet/cat/Runtime/proc/Read_Memory()
var/savefile/S = new /savefile("data/npc_saves/Runtime.sav")
S["family"] >> family
if(fexists("data/npc_saves/Runtime.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Runtime.sav")
S["family"] >> family
fdel("data/npc_saves/Runtime.sav")
else
var/json_file = file("data/npc_saves/Runtime.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
family = json["family"]
if(isnull(family))
family = list()
/mob/living/simple_animal/pet/cat/Runtime/proc/Write_Memory(dead)
var/savefile/S = new /savefile("data/npc_saves/Runtime.sav")
var/json_file = file("data/npc_saves/Runtime.json")
family = list()
if(!dead)
for(var/mob/living/simple_animal/pet/cat/kitten/C in children)
@@ -130,7 +138,8 @@
family[C.type] += 1
else
family[C.type] = 1
WRITE_FILE(S["family"], family)
fdel(json_file)
WRITE_FILE(json_file, json_encode(family))
memory_saved = 1
/mob/living/simple_animal/pet/cat/Runtime/proc/Deploy_The_Cats()
@@ -232,8 +241,8 @@
maxHealth = 50
gender = FEMALE
harm_intent_damage = 10
butcher_results = list(/obj/item/organ/brain = 1, /obj/item/organ/heart = 1, /obj/item/weapon/reagent_containers/food/snacks/cakeslice/birthday = 3, \
/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 2)
butcher_results = list(/obj/item/organ/brain = 1, /obj/item/organ/heart = 1, /obj/item/reagent_containers/food/snacks/cakeslice/birthday = 3, \
/obj/item/reagent_containers/food/snacks/meat/slab = 2)
response_harm = "takes a bite out of"
attacked_sound = 'sound/items/eatfood.ogg'
deathmessage = "loses its false life and collapses!"
@@ -259,7 +268,7 @@
return
if(health < maxHealth)
adjustBruteLoss(-8) //Fast life regen
for(var/obj/item/weapon/reagent_containers/food/snacks/donut/D in range(1, src)) //Frosts nearby donuts!
for(var/obj/item/reagent_containers/food/snacks/donut/D in range(1, src)) //Frosts nearby donuts!
if(D.icon_state != "donut2")
D.name = "frosted donut"
D.icon_state = "donut2"
@@ -10,7 +10,7 @@
emote_see = list("clacks.")
speak_chance = 1
turns_per_move = 5
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "stomps"
@@ -23,7 +23,7 @@
icon_state = "corgi"
icon_living = "corgi"
icon_dead = "corgi_dead"
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/corgi = 3, /obj/item/stack/sheet/animalhide/corgi = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/corgi = 3, /obj/item/stack/sheet/animalhide/corgi = 1)
childtype = list(/mob/living/simple_animal/pet/dog/corgi/puppy = 95, /mob/living/simple_animal/pet/dog/corgi/puppy/void = 5)
animal_species = /mob/living/simple_animal/pet/dog
var/shaved = 0
@@ -41,7 +41,7 @@
icon_state = "pug"
icon_living = "pug"
icon_dead = "pug_dead"
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/pug = 3)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = 2
/mob/living/simple_animal/pet/dog/Initialize()
@@ -98,7 +98,7 @@
return armorval*0.5
/mob/living/simple_animal/pet/dog/corgi/attackby(obj/item/O, mob/user, params)
if (istype(O, /obj/item/weapon/razor))
if (istype(O, /obj/item/razor))
if (shaved)
to_chat(user, "<span class='warning'>You can't shave this corgi, it's already been shaved!</span>")
return
@@ -178,7 +178,7 @@
to_chat(usr, "<span class='warning'>\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s back!</span>")
return
if(istype(item_to_add, /obj/item/weapon/grenade/plastic)) // last thing he ever wears, I guess
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
item_to_add.afterattack(src,usr,1)
return
@@ -214,7 +214,7 @@
/mob/living/simple_animal/pet/dog/corgi/proc/place_on_head(obj/item/item_to_add, mob/user)
if(istype(item_to_add, /obj/item/weapon/grenade/plastic)) // last thing he ever wears, I guess
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
item_to_add.afterattack(src,user,1)
return
@@ -328,33 +328,44 @@
..()
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/Read_Memory()
var/savefile/S = new /savefile("data/npc_saves/Ian.sav")
S["age"] >> age
S["record_age"] >> record_age
S["saved_head"] >> saved_head
if(fexists("data/npc_saves/Ian.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Ian.sav")
S["age"] >> age
S["record_age"] >> record_age
S["saved_head"] >> saved_head
fdel("data/npc_saves/Ian.sav")
else
var/json_file = file("data/npc_saves/Ian.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
age = json["age"]
record_age = json["record_age"]
saved_head = json["saved_head"]
if(isnull(age))
age = 0
if(isnull(record_age))
record_age = 1
if(saved_head)
place_on_head(new saved_head)
/mob/living/simple_animal/pet/dog/corgi/Ian/proc/Write_Memory(dead)
var/savefile/S = new /savefile("data/npc_saves/Ian.sav")
var/json_file = file("data/npc_saves/Ian.json")
var/list/file_data = list()
if(!dead)
WRITE_FILE(S["age"], age + 1)
file_data["age"] = age + 1
if((age + 1) > record_age)
WRITE_FILE(S["record_age"], record_age + 1)
file_data["record_age"] = record_age + 1
if(inventory_head)
WRITE_FILE(S["saved_head"], inventory_head.type)
file_data["saved_head"] = inventory_head.type
else
WRITE_FILE(S["age"], 0)
WRITE_FILE(S["saved_head"], null)
file_data["age"] = 0
file_data["saved_head"] = null
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
memory_saved = 1
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
..()
@@ -369,7 +380,7 @@
if( !movement_target || !(movement_target.loc in oview(src, 3)) )
movement_target = null
stop_automated_movement = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3))
for(var/obj/item/reagent_containers/food/snacks/S in oview(src,3))
if(isturf(S.loc) || ishuman(S.loc))
movement_target = S
break
@@ -62,7 +62,7 @@
var/alarms = list("Atmosphere" = list(), "Fire" = list(), "Power" = list())
var/obj/item/internal_storage //Drones can store one item, of any size/type in their body
var/obj/item/head
var/obj/item/default_storage = /obj/item/weapon/storage/backpack/duffelbag/drone //If this exists, it will spawn in internal storage
var/obj/item/default_storage = /obj/item/storage/backpack/duffelbag/drone //If this exists, it will spawn in internal storage
var/obj/item/default_hatmask //If this exists, it will spawn in the hat/mask slot if it can fit
var/seeStatic = 1 //Whether we see static instead of mobs
var/visualAppearence = MAINTDRONE //What we appear as
@@ -81,7 +81,7 @@
/mob/living/simple_animal/drone/Initialize()
. = ..()
access_card = new /obj/item/weapon/card/id(src)
access_card = new /obj/item/card/id(src)
var/datum/job/captain/C = new /datum/job/captain
access_card.access = C.get_access()
@@ -92,7 +92,7 @@
var/obj/item/I = new default_hatmask(src)
equip_to_slot_or_del(I, slot_head)
access_card.flags |= NODROP
access_card.flags_1 |= NODROP_1
alert_drones(DRONE_NET_CONNECT)
@@ -175,21 +175,21 @@
//Hands
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(!(I.flags_1 & ABSTRACT_1))
if(I.blood_DNA)
msg += "<span class='warning'>It has [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!</span>\n"
else
msg += "It has [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
//Internal storage
if(internal_storage && !(internal_storage.flags&ABSTRACT))
if(internal_storage && !(internal_storage.flags_1&ABSTRACT_1))
if(internal_storage.blood_DNA)
msg += "<span class='warning'>It is holding [icon2html(internal_storage, user)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!</span>\n"
else
msg += "It is holding [icon2html(internal_storage, user)] \a [internal_storage] in its internal storage.\n"
//Cosmetic hat - provides no function other than looks
if(head && !(head.flags&ABSTRACT))
if(head && !(head.flags_1&ABSTRACT_1))
if(head.blood_DNA)
msg += "<span class='warning'>It is wearing [icon2html(head, user)] [head.gender==PLURAL?"some":"a"] blood-stained [head.name] on its head!</span>\n"
else
@@ -48,7 +48,7 @@
/mob/living/simple_animal/drone/syndrone/badass/Initialize()
..()
internal_storage.hidden_uplink.telecrystals = 30
var/obj/item/weapon/implant/weapons_auth/W = new/obj/item/weapon/implant/weapons_auth(src)
var/obj/item/implant/weapons_auth/W = new/obj/item/implant/weapons_auth(src)
W.implant(src)
/mob/living/simple_animal/drone/snowflake
@@ -125,7 +125,7 @@
light_color = "#E42742"
heavy_emp_damage = 0
laws = "0. Purge all untruths and honor Ratvar."
default_storage = /obj/item/weapon/storage/toolbox/brass/prefilled
default_storage = /obj/item/storage/toolbox/brass/prefilled
seeStatic = 0
hacked = TRUE
visualAppearence = CLOCKDRONE
@@ -135,10 +135,10 @@
temperatures and pressures. \nYour goal is to serve the Justiciar and his servants by repairing and defending all they create.</b>"
/mob/living/simple_animal/drone/cogscarab/ratvar //a subtype for spawning when ratvar is alive, has a slab that it can use and a normal fabricator
default_storage = /obj/item/weapon/storage/toolbox/brass/prefilled/ratvar
default_storage = /obj/item/storage/toolbox/brass/prefilled/ratvar
/mob/living/simple_animal/drone/cogscarab/admin //an admin-only subtype of cogscarab with a no-cost fabricator and slab in its box
default_storage = /obj/item/weapon/storage/toolbox/brass/prefilled/ratvar/admin
default_storage = /obj/item/storage/toolbox/brass/prefilled/ratvar/admin
/mob/living/simple_animal/drone/cogscarab/Initialize()
. = ..()
@@ -165,7 +165,7 @@
..()
/mob/living/simple_animal/drone/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/screwdriver) && stat == DEAD)
if(istype(I, /obj/item/screwdriver) && stat == DEAD)
try_reactivate(user)
else
..()
@@ -176,7 +176,7 @@
else
..()
/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/weapon/G)
/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/G)
return GLOB.ratvar_awakens
/mob/living/simple_animal/drone/cogscarab/get_armor_effectiveness()
@@ -81,7 +81,7 @@
/mob/living/simple_animal/drone/attackby(obj/item/I, mob/user)
if(istype(I, /obj/item/weapon/screwdriver) && stat != DEAD)
if(istype(I, /obj/item/screwdriver) && stat != DEAD)
if(health < maxHealth)
to_chat(user, "<span class='notice'>You start to tighten loose screws on [src]...</span>")
if(do_after(user,80*I.toolspeed,target=user))
@@ -92,7 +92,7 @@
else
to_chat(user, "<span class='warning'>[src]'s screws can't get any tighter!</span>")
return //This used to not exist and drones who repaired themselves also stabbed the shit out of themselves.
else if(istype(I, /obj/item/weapon/wrench) && user != src) //They aren't required to be hacked, because laws can change in other ways (i.e. admins)
else if(istype(I, /obj/item/wrench) && user != src) //They aren't required to be hacked, because laws can change in other ways (i.e. admins)
user.visible_message("<span class='notice'>[user] starts resetting [src]...</span>", \
"<span class='notice'>You press down on [src]'s factory reset control...</span>")
playsound(src, I.usesound, 50, 1)
@@ -12,7 +12,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 4)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 4)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -85,7 +85,7 @@
say("Nom")
/mob/living/simple_animal/hostile/retaliate/goat/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
udder.milkAnimal(O, user)
return 1
else
@@ -107,7 +107,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 6)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 6)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -130,7 +130,7 @@
return ..()
/mob/living/simple_animal/cow/attackby(obj/item/O, mob/user, params)
if(stat == CONSCIOUS && istype(O, /obj/item/weapon/reagent_containers/glass))
if(stat == CONSCIOUS && istype(O, /obj/item/reagent_containers/glass))
udder.milkAnimal(O, user)
return 1
else
@@ -182,7 +182,7 @@
density = FALSE
speak_chance = 2
turns_per_move = 2
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -229,9 +229,9 @@
density = FALSE
speak_chance = 2
turns_per_move = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 2)
var/egg_type = /obj/item/weapon/reagent_containers/food/snacks/egg
var/food_type = /obj/item/weapon/reagent_containers/food/snacks/grown/wheat
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2)
var/egg_type = /obj/item/reagent_containers/food/snacks/egg
var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -295,8 +295,8 @@
if(chicken_count < MAX_CHICKENS && prob(25))
START_PROCESSING(SSobj, E)
/obj/item/weapon/reagent_containers/food/snacks/egg/var/amount_grown = 0
/obj/item/weapon/reagent_containers/food/snacks/egg/process()
/obj/item/reagent_containers/food/snacks/egg/var/amount_grown = 0
/obj/item/reagent_containers/food/snacks/egg/process()
if(isturf(loc))
amount_grown += rand(1,2)
if(amount_grown >= 100)
@@ -321,7 +321,7 @@
reagents.add_reagent("milk", rand(5, 10))
/obj/item/udder/proc/milkAnimal(obj/O, mob/user)
var/obj/item/weapon/reagent_containers/glass/G = O
var/obj/item/reagent_containers/glass/G = O
if(G.reagents.total_volume >= G.volume)
to_chat(user, "<span class='danger'>[O] is full.</span>")
return
@@ -13,7 +13,7 @@
speak_chance = 1
turns_per_move = 5
see_in_dark = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 3)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -13,7 +13,7 @@
see_in_dark = 6
maxHealth = 5
health = 5
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "splats"
@@ -43,7 +43,7 @@
/mob/living/simple_animal/mouse/death(gibbed, toast)
if(!ckey)
..(1)
var/obj/item/trash/deadmouse/M = new(src.loc)
var/obj/item/reagent_containers/food/snacks/deadmouse/M = new(loc)
M.icon_state = icon_dead
M.name = name
if(toast)
@@ -101,8 +101,12 @@
response_harm = "splats"
gold_core_spawnable = 0
/obj/item/trash/deadmouse
/obj/item/reagent_containers/food/snacks/deadmouse
name = "dead mouse"
desc = "It looks like somebody dropped the bass on it."
desc = "It looks like somebody dropped the bass on it. A lizard's favorite meal."
icon = 'icons/mob/animal.dmi'
icon_state = "mouse_gray_dead"
bitesize = 3
eatverb = "devours"
list_reagents = list("nutriment" = 3, "vitamin" = 2)
foodtype = GROSS | MEAT | RAW
@@ -20,7 +20,7 @@
name = real_name
qdel(P)
return
if(istype(O, /obj/item/weapon/newspaper))
if(istype(O, /obj/item/newspaper))
if(!stat)
user.visible_message("[user] baps [name] on the nose with the rolled up [O].")
spawn(0)
@@ -10,7 +10,7 @@
emote_see = list("dozes off.", "looks around sleepily.")
speak_chance = 1
turns_per_move = 5
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab = 3)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -35,7 +35,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
obj_damage = 40
melee_damage_lower = 15
melee_damage_upper = 15
butcher_results = list(/obj/item/weapon/ectoplasm = 1)
butcher_results = list(/obj/item/ectoplasm = 1)
AIStatus = AI_OFF
dextrous_hud_type = /datum/hud/dextrous/guardian //if we're set to dextrous, account for it.
var/list/guardian_overlays[GUARDIAN_TOTAL_LAYERS]
@@ -455,7 +455,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
////////Creation
/obj/item/weapon/guardiancreator
/obj/item/guardiancreator
name = "deck of tarot cards"
desc = "An enchanted deck of tarot cards, rumored to be a source of unimaginable power. "
icon = 'icons/obj/toy.dmi'
@@ -474,7 +474,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
var/allowling = TRUE
var/allowguardian = FALSE
/obj/item/weapon/guardiancreator/attack_self(mob/living/user)
/obj/item/guardiancreator/attack_self(mob/living/user)
if(isguardian(user) && !allowguardian)
to_chat(user, "<span class='holoparasite'>[mob_name] chains are not allowed.</span>")
return
@@ -490,7 +490,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
return
used = TRUE
to_chat(user, "[use_message]")
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100)
var/list/mob/dead/observer/candidates = pollGhostCandidates("Do you want to play as the [mob_name] of [user.real_name]?", ROLE_PAI, null, FALSE, 100, POLL_IGNORE_HOLOPARASITE)
var/mob/dead/observer/theghost = null
if(candidates.len)
@@ -503,7 +503,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
used = FALSE
/obj/item/weapon/guardiancreator/proc/spawn_guardian(var/mob/living/user, var/key)
/obj/item/guardiancreator/proc/spawn_guardian(var/mob/living/user, var/key)
var/guardiantype = "Standard"
if(random)
guardiantype = pick(possible_guardians)
@@ -570,17 +570,17 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
user.verbs += /mob/living/proc/guardian_recall
user.verbs += /mob/living/proc/guardian_reset
/obj/item/weapon/guardiancreator/choose
/obj/item/guardiancreator/choose
random = FALSE
/obj/item/weapon/guardiancreator/choose/dextrous
/obj/item/guardiancreator/choose/dextrous
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
/obj/item/weapon/guardiancreator/choose/wizard
/obj/item/guardiancreator/choose/wizard
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard")
allowmultiple = TRUE
/obj/item/weapon/guardiancreator/tech
/obj/item/guardiancreator/tech
name = "holoparasite injector"
desc = "It contains an alien nanoswarm of unknown origin. Though capable of near sorcerous feats via use of hardlight holograms and nanomachines, it requires an organic host as a home base and source of fuel."
icon = 'icons/obj/syringe.dmi'
@@ -593,16 +593,16 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
ling_failure = "<span class='holoparasitebold'>The holoparasites recoil in horror. They want nothing to do with a creature like you.</span>"
activation_message = "<span class='holoparasite'>The injector self destructs after you inject yourself with it.</span>"
/obj/item/weapon/guardiancreator/tech/choose/traitor
/obj/item/guardiancreator/tech/choose/traitor
possible_guardians = list("Assassin", "Chaos", "Charger", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
/obj/item/weapon/guardiancreator/tech/choose
/obj/item/guardiancreator/tech/choose
random = FALSE
/obj/item/weapon/guardiancreator/tech/choose/dextrous
/obj/item/guardiancreator/tech/choose/dextrous
possible_guardians = list("Assassin", "Chaos", "Charger", "Dextrous", "Explosive", "Lightning", "Protector", "Ranged", "Standard", "Support")
/obj/item/weapon/paper/guides/antag/guardian
/obj/item/paper/guides/antag/guardian
name = "Holoparasite Guide"
icon_state = "alienpaper_words"
info = {"<b>A list of Holoparasite Types</b><br>
@@ -626,10 +626,10 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
<br>
"}
/obj/item/weapon/paper/guides/antag/guardian/update_icon()
/obj/item/paper/guides/antag/guardian/update_icon()
return
/obj/item/weapon/paper/guides/antag/guardian/wizard
/obj/item/paper/guides/antag/guardian/wizard
name = "Guardian Guide"
info = {"<b>A list of Guardian Types</b><br>
@@ -655,16 +655,16 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
"}
/obj/item/weapon/storage/box/syndie_kit/guardian
/obj/item/storage/box/syndie_kit/guardian
name = "holoparasite injector kit"
/obj/item/weapon/storage/box/syndie_kit/guardian/Initialize()
/obj/item/storage/box/syndie_kit/guardian/Initialize()
..()
new /obj/item/weapon/guardiancreator/tech/choose/traitor(src)
new /obj/item/weapon/paper/guides/antag/guardian(src)
new /obj/item/guardiancreator/tech/choose/traitor(src)
new /obj/item/paper/guides/antag/guardian(src)
return
/obj/item/weapon/guardiancreator/carp
/obj/item/guardiancreator/carp
name = "holocarp fishsticks"
desc = "Using the power of Carp'sie, you can catch a carp from byond the veil of Carpthulu, and bind it to your fleshy flesh form."
icon = 'icons/obj/food/food.dmi'
@@ -680,5 +680,5 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
allowling = TRUE
random = TRUE
/obj/item/weapon/guardiancreator/carp/choose
/obj/item/guardiancreator/carp/choose
random = FALSE
@@ -30,13 +30,13 @@
msg += "[desc]\n"
for(var/obj/item/I in held_items)
if(!(I.flags & ABSTRACT))
if(!(I.flags_1 & ABSTRACT_1))
if(I.blood_DNA)
msg += "<span class='warning'>It has [icon2html(I, user)] [I.gender==PLURAL?"some":"a"] blood-stained [I.name] in its [get_held_index_name(get_held_index_of_item(I))]!</span>\n"
else
msg += "It has [icon2html(I, user)] \a [I] in its [get_held_index_name(get_held_index_of_item(I))].\n"
if(internal_storage && !(internal_storage.flags&ABSTRACT))
if(internal_storage && !(internal_storage.flags_1&ABSTRACT_1))
if(internal_storage.blood_DNA)
msg += "<span class='warning'>It is holding [icon2html(internal_storage, user)] [internal_storage.gender==PLURAL?"some":"a"] blood-stained [internal_storage.name] in its internal storage!</span>\n"
else
@@ -11,7 +11,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 4,
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 4,
/obj/item/stack/sheet/animalhide/xeno = 1)
maxHealth = 125
health = 125
@@ -84,7 +84,7 @@
retreat_distance = 5
minimum_distance = 5
move_to_delay = 4
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 4,
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 4,
/obj/item/stack/sheet/animalhide/xeno = 1)
projectiletype = /obj/item/projectile/neurotox
projectilesound = 'sound/weapons/pierce.ogg'
@@ -134,7 +134,7 @@
move_to_delay = 4
maxHealth = 400
health = 400
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 10,
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/xeno = 10,
/obj/item/stack/sheet/animalhide/xeno = 2)
mob_size = MOB_SIZE_LARGE
gold_core_spawnable = 0
@@ -14,7 +14,7 @@
taunt_chance = 25
turns_per_move = 5
see_in_dark = 6
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
@@ -57,7 +57,7 @@
icon_living = "combatbear"
icon_dead = "combatbear_dead"
faction = list("russian")
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1, /obj/item/bear_armor = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1, /obj/item/bear_armor = 1)
melee_damage_lower = 25
melee_damage_upper = 35
armour_penetration = 20
@@ -77,7 +77,7 @@
name = "pile of bear armor"
desc = "A scattered pile of various shaped armor pieces fitted for a bear, some duct tape, and a nail filer. Crude instructions \
are written on the back of one of the plates in russian. This seems like an awful idea."
icon = 'icons/obj/items.dmi'
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "bear_armor_upgrade"
/obj/item/bear_armor/afterattack(atom/target, mob/user, proximity_flag)
@@ -32,7 +32,7 @@
move_to_delay = 0
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
mouse_opacity = 2
mouse_opacity = MOUSE_OPACITY_OPAQUE
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
movement_type = FLYING
@@ -249,8 +249,8 @@
/obj/item/queen_bee/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/reagent_containers/syringe))
var/obj/item/weapon/reagent_containers/syringe/S = I
if(istype(I, /obj/item/reagent_containers/syringe))
var/obj/item/reagent_containers/syringe/S = I
if(S.reagents.has_reagent("royal_bee_jelly")) //checked twice, because I really don't want royal bee jelly to be duped
if(S.reagents.has_reagent("royal_bee_jelly",5))
S.reagents.remove_reagent("royal_bee_jelly", 5)
@@ -7,7 +7,7 @@
icon_gib = "carp_gib"
speak_chance = 0
turns_per_move = 5
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/carpmeat = 2)
butcher_results = list(/obj/item/reagent_containers/food/snacks/carpmeat = 2)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
@@ -29,7 +29,7 @@
speak_chance = 5
turns_per_move = 5
see_in_dark = 10
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/spider = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/spider = 2, /obj/item/reagent_containers/food/snacks/spiderleg = 8)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
@@ -81,7 +81,7 @@
icon_living = "nurse"
icon_dead = "nurse_dead"
gender = FEMALE
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/spider = 2, /obj/item/weapon/reagent_containers/food/snacks/spiderleg = 8, /obj/item/weapon/reagent_containers/food/snacks/spidereggs = 4)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/spider = 2, /obj/item/reagent_containers/food/snacks/spiderleg = 8, /obj/item/reagent_containers/food/snacks/spidereggs = 4)
maxHealth = 40
health = 40
melee_damage_lower = 5
@@ -0,0 +1,11 @@
/datum/emote/sound/gorilla
mob_type_allowed_typecache = /mob/living/simple_animal/hostile/gorilla
mob_type_blacklist_typecache = list()
/datum/emote/sound/gorilla/ooga
key = "ooga"
key_third_person = "oogas"
message = "oogas."
message_param = "oogas at %t."
sound = "sound/creatures/gorilla.ogg"
@@ -0,0 +1,77 @@
#define GORILLA_HANDS_LAYER 1
#define GORILLA_TOTAL_LAYERS 1
/mob/living/simple_animal/hostile/gorilla
name = "Gorilla"
desc = "A ground-dwelling, predominantly herbivorous ape that inhabits the forests of central Africa."
icon = 'icons/mob/gorilla.dmi'
icon_state = "crawling"
icon_state = "crawling"
icon_living = "crawling"
icon_dead = "dead"
speak_chance = 80
maxHealth = 220
health = 220
loot = list(/obj/effect/gibspawner/generic)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/gorilla = 4)
response_help = "prods"
response_disarm = "challenges"
response_harm = "thumps"
speed = 1
melee_damage_lower = 15
melee_damage_upper = 18
damage_coeff = list(BRUTE = 1, BURN = 1.5, TOX = 1.5, CLONE = 0, STAMINA = 0, OXY = 1.5)
obj_damage = 20
environment_smash = 2
attacktext = "pummels"
attack_sound = 'sound/weapons/punch1.ogg'
dextrous = TRUE
possible_a_intents = list(INTENT_HELP, INTENT_GRAB, INTENT_DISARM, INTENT_HARM)
faction = list("jungle")
robust_searching = TRUE
stat_attack = UNCONSCIOUS
minbodytemp = 270
maxbodytemp = 350
var/list/gorilla_overlays[GORILLA_TOTAL_LAYERS]
// Gorillas like to dismember limbs from unconcious mobs.
// Returns null when the target is not an unconcious carbon mob; a list of limbs (possibly empty) otherwise.
/mob/living/simple_animal/hostile/gorilla/proc/target_bodyparts(atom/the_target)
var/list/parts = list()
if(iscarbon(the_target))
var/mob/living/carbon/C = the_target
if(C.stat >= UNCONSCIOUS)
for(var/X in C.bodyparts)
var/obj/item/bodypart/BP = X
if(BP.body_part != HEAD && BP.body_part != CHEST)
if(BP.dismemberable)
parts += BP
return parts
/mob/living/simple_animal/hostile/gorilla/AttackingTarget()
var/list/parts = target_bodyparts(target)
if(parts)
if(!parts.len)
return FALSE
var/obj/item/bodypart/BP = pick(parts)
BP.dismember()
return ..()
. = ..()
if(. && isliving(target))
var/mob/living/L = target
if(prob(80))
var/atom/throw_target = get_edge_target_turf(L, dir)
L.throw_at(throw_target, rand(1,2), 7, src)
else
L.Knockdown(20)
visible_message("<span class='danger'>[src] knocks [L] down!</span>")
/mob/living/simple_animal/hostile/gorilla/CanAttack(atom/the_target)
var/list/parts = target_bodyparts(target)
return ..() && !istype(the_target, /mob/living/carbon/monkey) && (!parts || parts.len > 3)
/mob/living/simple_animal/hostile/gorilla/handle_automated_speech(override)
if(speak_chance && (override || prob(speak_chance)))
playsound(src, "sound/creatures/gorilla.ogg", 200)
..()
@@ -0,0 +1,55 @@
/mob/living/simple_animal/hostile/gorilla/proc/apply_overlay(cache_index)
. = gorilla_overlays[cache_index]
if(.)
add_overlay(.)
/mob/living/simple_animal/hostile/gorilla/proc/remove_overlay(cache_index)
var/I = gorilla_overlays[cache_index]
if(I)
cut_overlay(I)
gorilla_overlays[cache_index] = null
/mob/living/simple_animal/hostile/gorilla/update_inv_hands()
cut_overlays("standing_overlay")
remove_overlay(GORILLA_HANDS_LAYER)
var/standing = FALSE
for(var/I in held_items)
if(I)
standing = TRUE
break
if(!standing)
if(stat != DEAD)
icon_state = "crawling"
speed = 1
return ..()
if(stat != DEAD)
icon_state = "standing"
speed = 3 // Gorillas are slow when standing up.
var/list/hands_overlays = list()
var/obj/item/l_hand = get_item_for_held_index(1)
var/obj/item/r_hand = get_item_for_held_index(2)
if(r_hand)
var/r_state = r_hand.item_state ? r_hand.item_state : r_hand.icon_state
var/mutable_appearance/r_hand_overlay = r_hand.build_worn_icon(state = r_state, default_layer = GORILLA_HANDS_LAYER, default_icon_file = r_hand.righthand_file, isinhands = TRUE)
r_hand_overlay.pixel_y -= 1
hands_overlays += r_hand_overlay
if(l_hand)
var/l_state = l_hand.item_state ? l_hand.item_state : l_hand.icon_state
var/mutable_appearance/l_hand_overlay = l_hand.build_worn_icon(state = l_state, default_layer = GORILLA_HANDS_LAYER, default_icon_file = l_hand.lefthand_file, isinhands = TRUE)
l_hand_overlay.pixel_y -= 1
hands_overlays += l_hand_overlay
if(hands_overlays.len)
gorilla_overlays[GORILLA_HANDS_LAYER] = hands_overlays
apply_overlay(GORILLA_HANDS_LAYER)
add_overlay("standing_overlay")
return ..()
/mob/living/simple_animal/hostile/gorilla/regenerate_icons()
update_inv_hands()
@@ -2,7 +2,7 @@
faction = list("hostile")
stop_automated_movement_when_pulled = 0
obj_damage = 40
environment_smash = ENVIRONMENT_SMASH_STRUCTURES //Set to 1 to break closets,tables,racks, etc; 2 for walls; 3 for rwalls
environment_smash = ENVIRONMENT_SMASH_STRUCTURES //Bitflags. Set to ENVIRONMENT_SMASH_STRUCTURES to break closets,tables,racks, etc; ENVIRONMENT_SMASH_WALLS for walls; ENVIRONMENT_SMASH_RWALLS for rwalls
var/atom/target
var/ranged = 0
var/rapid = 0
@@ -253,7 +253,7 @@
if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range) //We can't see our target, but he's in our vision range still
if(ranged_ignores_vision && ranged_cooldown <= world.time) //we can't see our target... but we can fire at them!
OpenFire(target)
if(environment_smash >= 2) //If we're capable of smashing through walls, forget about vision completely after finding our target
if((environment_smash & ENVIRONMENT_SMASH_WALLS) || (environment_smash & ENVIRONMENT_SMASH_RWALLS)) //If we're capable of smashing through walls, forget about vision completely after finding our target
Goto(target,move_to_delay,minimum_distance)
FindHidden()
return 1
@@ -0,0 +1,17 @@
/mob/living/simple_animal/hostile/jungle
vision_range = 5
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
faction = list("jungle")
weather_immunities = list("acid")
obj_damage = 30
environment_smash = ENVIRONMENT_SMASH_WALLS
minbodytemp = 0
maxbodytemp = 450
response_help = "pokes"
response_disarm = "shoves"
response_harm = "strikes"
status_flags = NONE
a_intent = INTENT_HARM
see_in_dark = 4
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
mob_size = MOB_SIZE_LARGE
@@ -0,0 +1,263 @@
#define PLAYER_HOP_DELAY 25
//Huge, carnivorous toads that spit an immobilizing toxin at its victims before leaping onto them.
//It has no melee attack, and its damage comes from the toxin in its bubbles and its crushing leap.
//Its eyes will turn red to signal an imminent attack!
/mob/living/simple_animal/hostile/jungle/leaper
name = "leaper"
desc = "Commonly referred to as 'leapers', the Geron Toad is a massive beast that spits out highly pressurized bubbles containing a unique toxin, knocking down its prey and then crushing it with its girth."
icon = 'icons/mob/jungle/leaper.dmi'
icon_state = "leaper"
icon_living = "leaper"
icon_dead = "leaper_dead"
maxHealth = 300
health = 300
ranged = TRUE
projectiletype = /obj/item/projectile/leaper
projectilesound = 'sound/weapons/pierce.ogg'
ranged_cooldown_time = 30
pixel_x = -16
layer = LARGE_MOB_LAYER
speed = 10
stat_attack = 1
robust_searching = 1
var/hopping = FALSE
var/hop_cooldown = 0 //Strictly for player controlled leapers
var/projectile_ready = FALSE //Stopping AI leapers from firing whenever they want, and only doing it after a hop has finished instead
/obj/item/projectile/leaper
name = "leaper bubble"
icon_state = "leaper"
knockdown = 50
damage = 0
range = 7
hitsound = 'sound/effects/snap.ogg'
nondirectional_sprite = TRUE
impact_effect_type = /obj/effect/temp_visual/leaper_projectile_impact
/obj/item/projectile/leaper/on_hit(atom/target, blocked = FALSE)
..()
if(iscarbon(target))
var/mob/living/carbon/C = target
C.reagents.add_reagent("leaper_venom", 5)
return
if(isanimal(target))
var/mob/living/simple_animal/L = target
L.adjustHealth(25)
/obj/item/projectile/leaper/on_range()
var/turf/T = get_turf(src)
..()
new /obj/structure/leaper_bubble(T)
/obj/effect/temp_visual/leaper_projectile_impact
name = "leaper bubble"
icon = 'icons/obj/projectiles.dmi'
icon_state = "leaper_bubble_pop"
layer = ABOVE_ALL_MOB_LAYER
duration = 3
/obj/effect/temp_visual/leaper_projectile_impact/Initialize()
. = ..()
new /obj/effect/decal/cleanable/leaper_sludge(get_turf(src))
/obj/effect/decal/cleanable/leaper_sludge
name = "leaper sludge"
desc = "A small pool of sludge, containing trace amounts of leaper venom."
icon = 'icons/effects/tomatodecal.dmi'
icon_state = "tomato_floor1"
/obj/structure/leaper_bubble
name = "leaper bubble"
desc = "A floating bubble containing leaper venom. The contents are under a surprising amount of pressure."
icon = 'icons/obj/projectiles.dmi'
icon_state = "leaper"
max_integrity = 10
density = FALSE
/obj/structure/leaper_bubble/Initialize()
. = ..()
float(on = TRUE)
QDEL_IN(src, 100)
/obj/structure/leaper_bubble/Destroy()
new /obj/effect/temp_visual/leaper_projectile_impact(get_turf(src))
playsound(src,'sound/effects/snap.ogg',50, 1, -1)
return ..()
/obj/structure/leaper_bubble/Crossed(atom/movable/AM)
if(isliving(AM))
var/mob/living/L = AM
if(!istype(L, /mob/living/simple_animal/hostile/jungle/leaper))
playsound(src,'sound/effects/snap.ogg',50, 1, -1)
L.Knockdown(50)
if(iscarbon(L))
var/mob/living/carbon/C = L
C.reagents.add_reagent("leaper_venom", 5)
if(isanimal(L))
var/mob/living/simple_animal/A = L
A.adjustHealth(25)
qdel(src)
return ..()
/datum/reagent/toxin/leaper_venom
name = "Leaper venom"
id = "leaper_venom"
description = "A toxin spat out by leapers that, while harmless in small doses, quickly creates a toxic reaction if too much is in the body."
color = "#801E28" // rgb: 128, 30, 40
toxpwr = 0
taste_description = "french cuisine"
taste_mult = 1.3
/datum/reagent/toxin/leaper_venom/on_mob_life(mob/living/M)
if(volume >= 10)
M.adjustToxLoss(5, 0)
..()
/obj/effect/temp_visual/leaper_crush
name = "grim tidings"
desc = "Incoming leaper!"
icon = 'icons/effects/96x96.dmi'
icon_state = "lily_pad"
layer = BELOW_MOB_LAYER
pixel_x = -32
pixel_y = -32
duration = 30
/mob/living/simple_animal/hostile/jungle/leaper/Initialize()
. = ..()
verbs -= /mob/living/verb/pulled
/mob/living/simple_animal/hostile/jungle/leaper/CtrlClickOn(atom/A)
face_atom(A)
target = A
if(!isturf(loc))
return
if(next_move > world.time)
return
if(hopping)
return
if(isliving(A))
var/mob/living/L = A
if(L.incapacitated())
BellyFlop()
return
if(hop_cooldown <= world.time)
Hop(player_hop = TRUE)
/mob/living/simple_animal/hostile/jungle/leaper/AttackingTarget()
if(isliving(target))
return
return ..()
/mob/living/simple_animal/hostile/jungle/leaper/handle_automated_action()
if(hopping || projectile_ready)
return
. = ..()
if(target)
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated())
BellyFlop()
return
if(!hopping)
Hop()
/mob/living/simple_animal/hostile/jungle/leaper/Life()
. = ..()
update_icons()
/mob/living/simple_animal/hostile/jungle/leaper/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(prob(33) && !ckey)
ranged_cooldown = 0 //Keeps em on their toes instead of a constant rotation
..()
/mob/living/simple_animal/hostile/jungle/leaper/OpenFire()
face_atom(target)
if(ranged_cooldown <= world.time)
if(ckey)
if(hopping)
return
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated())
return //No stunlocking. Hop on them after you stun them, you donk.
if(AIStatus == AI_ON && !projectile_ready && !ckey)
return
. = ..(target)
projectile_ready = FALSE
update_icons()
/mob/living/simple_animal/hostile/jungle/leaper/proc/Hop(player_hop = FALSE)
if(z != target.z)
return
hopping = TRUE
density = FALSE
pass_flags |= PASSMOB
notransform = TRUE
var/turf/new_turf = locate((target.x + rand(-3,3)),(target.y + rand(-3,3)),target.z)
if(player_hop)
new_turf = get_turf(target)
hop_cooldown = world.time + PLAYER_HOP_DELAY
if(AIStatus == AI_ON && ranged_cooldown <= world.time)
projectile_ready = TRUE
update_icons()
throw_at(new_turf, max(3,get_dist(src,new_turf)), 1, src, FALSE, callback = CALLBACK(src, .FinishHop))
/mob/living/simple_animal/hostile/jungle/leaper/proc/FinishHop()
density = TRUE
notransform = FALSE
pass_flags &= ~PASSMOB
hopping = FALSE
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 100, 1)
if(target && AIStatus == AI_ON && projectile_ready && !ckey)
face_atom(target)
addtimer(CALLBACK(src, .proc/OpenFire, target), 5)
/mob/living/simple_animal/hostile/jungle/leaper/proc/BellyFlop()
var/turf/new_turf = get_turf(target)
hopping = TRUE
notransform = TRUE
new /obj/effect/temp_visual/leaper_crush(new_turf)
addtimer(CALLBACK(src, .proc/BellyFlopHop, new_turf), 30)
/mob/living/simple_animal/hostile/jungle/leaper/proc/BellyFlopHop(turf/T)
density = FALSE
throw_at(T, get_dist(src,T),1,src, FALSE, callback = CALLBACK(src, .proc/Crush))
/mob/living/simple_animal/hostile/jungle/leaper/proc/Crush()
hopping = FALSE
density = TRUE
notransform = FALSE
playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1)
for(var/mob/living/L in orange(1, src))
L.adjustBruteLoss(35)
if(!QDELETED(L)) // Some mobs are deleted on death
var/throw_dir = get_dir(src, L)
if(L.loc == loc)
throw_dir = pick(GLOB.alldirs)
var/throwtarget = get_edge_target_turf(src, throw_dir)
L.throw_at(throwtarget, 3, 1)
visible_message("<span class='warning'>[L] is thrown clear of [src]!</span>")
if(ckey)//Lessens ability to chain stun as a player
ranged_cooldown = ranged_cooldown_time + world.time
update_icons()
/mob/living/simple_animal/hostile/jungle/leaper/Goto()
return
/mob/living/simple_animal/hostile/jungle/leaper/throw_impact()
return
/mob/living/simple_animal/hostile/jungle/leaper/update_icons()
. = ..()
if(stat)
icon_state = "leaper_dead"
return
if(ranged_cooldown <= world.time)
if(AIStatus == AI_ON && projectile_ready || ckey)
icon_state = "leaper_alert"
return
icon_state = "leaper"
#undef PLAYER_HOP_DELAY
@@ -0,0 +1,65 @@
//Large and powerful, but timid. It won't engage anything above 50 health, or anything without legcuffs.
//It can fire fleshy snares that legcuff anyone that it hits, making them look especially tasty to the arachnid.
/mob/living/simple_animal/hostile/jungle/mega_arachnid
name = "mega arachnid"
desc = "Though physically imposing, it prefers to ambush its prey, and it will only engage with an already crippled opponent."
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "arachnid"
icon_living = "arachnid"
icon_dead = "arachnid_dead"
melee_damage_lower = 30
melee_damage_upper = 30
maxHealth = 300
health = 300
speed = 1
ranged = 1
pixel_x = -16
move_to_delay = 10
aggro_vision_range = 9
speak_emote = list("chitters")
attack_sound = 'sound/weapons/bladeslice.ogg'
ranged_cooldown_time = 60
projectiletype = /obj/item/projectile/mega_arachnid
projectilesound = 'sound/weapons/pierce.ogg'
alpha = 50
/mob/living/simple_animal/hostile/jungle/mega_arachnid/Life()
..()
if(target && ranged_cooldown > world.time && iscarbon(target))
var/mob/living/carbon/C = target
if(!C.legcuffed && C.health < 50)
retreat_distance = 9
minimum_distance = 9
alpha = 125
return
retreat_distance = 0
minimum_distance = 0
alpha = 255
/mob/living/simple_animal/hostile/jungle/mega_arachnid/Aggro()
..()
alpha = 255
/mob/living/simple_animal/hostile/jungle/mega_arachnid/LoseAggro()
..()
alpha = 50
/obj/item/projectile/mega_arachnid
name = "flesh snare"
nodamage = 1
damage = 0
icon_state = "tentacle_end"
/obj/item/projectile/mega_arachnid/on_hit(atom/target, blocked = FALSE)
if(iscarbon(target) && blocked < 100)
var/obj/item/restraints/legcuffs/beartrap/mega_arachnid/B = new /obj/item/restraints/legcuffs/beartrap/mega_arachnid(get_turf(target))
B.Crossed(target)
..()
/obj/item/restraints/legcuffs/beartrap/mega_arachnid
name = "fleshy restraints"
desc = "Used by mega arachnids to immobilize their prey."
flags_1 = DROPDEL_1
icon_state = "tentacle_end"
icon = 'icons/obj/projectiles.dmi'
@@ -0,0 +1,224 @@
#define MOOK_ATTACK_NEUTRAL 0
#define MOOK_ATTACK_WARMUP 1
#define MOOK_ATTACK_ACTIVE 2
#define MOOK_ATTACK_RECOVERY 3
#define ATTACK_INTERMISSION_TIME 5
//Fragile but highly aggressive wanderers that pose a large threat in numbers.
//They'll attempt to leap at their target from afar using their hatchets.
/mob/living/simple_animal/hostile/jungle/mook
name = "wanderer"
desc = "This unhealthy looking primitive is wielding a rudimentary hatchet, swinging it with wild abandon. One isn't much of a threat, but in numbers they can quickly overwhelm a superior opponent."
icon = 'icons/mob/jungle/mook.dmi'
icon_state = "mook"
icon_living = "mook"
icon_dead = "mook_dead"
pixel_x = -16
maxHealth = 45
health = 45
melee_damage_lower = 30
melee_damage_upper = 30
pixel_y = -8
ranged = TRUE
ranged_cooldown_time = 10
pass_flags = LETPASSTHROW
robust_searching = TRUE
stat_attack = UNCONSCIOUS
attack_sound = 'sound/weapons/rapierhit.ogg'
death_sound = 'sound/voice/mook_death.ogg'
aggro_vision_range = 15 //A little more aggressive once in combat to balance out their really low HP
var/attack_state = MOOK_ATTACK_NEUTRAL
var/struck_target_leap = FALSE
/mob/living/simple_animal/hostile/jungle/mook/CanPass(atom/movable/O)
if(istype(O, /mob/living/simple_animal/hostile/jungle/mook))
var/mob/living/simple_animal/hostile/jungle/mook/M = O
if(M.attack_state == MOOK_ATTACK_ACTIVE && M.throwing)
return TRUE
return ..()
/mob/living/simple_animal/hostile/jungle/mook/death()
desc = "A deceased primitive. Upon closer inspection, it was suffering from severe cellular degeneration and its garments are machine made..."//Can you guess the twist
return ..()
/mob/living/simple_animal/hostile/jungle/mook/AttackingTarget()
if(isliving(target))
if(ranged_cooldown <= world.time && attack_state == MOOK_ATTACK_NEUTRAL)
var/mob/living/L = target
if(L.incapacitated())
WarmupAttack(forced_slash_combo = TRUE)
return
WarmupAttack()
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/Goto()
if(attack_state != MOOK_ATTACK_NEUTRAL)
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/Move()
if(attack_state == MOOK_ATTACK_WARMUP || attack_state == MOOK_ATTACK_RECOVERY)
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/proc/WarmupAttack(forced_slash_combo = FALSE)
if(attack_state == MOOK_ATTACK_NEUTRAL && target)
attack_state = MOOK_ATTACK_WARMUP
walk(src,0)
update_icons()
if(prob(50) && get_dist(src,target) <= 3 || forced_slash_combo)
addtimer(CALLBACK(src, .proc/SlashCombo), ATTACK_INTERMISSION_TIME)
return
addtimer(CALLBACK(src, .proc/LeapAttack), ATTACK_INTERMISSION_TIME + rand(0,3))
return
attack_state = MOOK_ATTACK_RECOVERY
ResetNeutral()
/mob/living/simple_animal/hostile/jungle/mook/proc/SlashCombo()
if(attack_state == MOOK_ATTACK_WARMUP && !stat)
attack_state = MOOK_ATTACK_ACTIVE
update_icons()
SlashAttack()
addtimer(CALLBACK(src, .proc/SlashAttack), 3)
addtimer(CALLBACK(src, .proc/SlashAttack), 6)
addtimer(CALLBACK(src, .proc/AttackRecovery), 9)
/mob/living/simple_animal/hostile/jungle/mook/proc/SlashAttack()
if(target && !stat && attack_state == MOOK_ATTACK_ACTIVE)
melee_damage_lower = 15
melee_damage_upper = 15
var/mob_direction = get_dir(src,target)
if(get_dist(src,target) > 1)
step(src,mob_direction)
if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from) && isliving(target))
var/mob/living/L = target
L.attack_animal(src)
return
var/swing_turf = get_step(src,mob_direction)
new /obj/effect/temp_visual/kinetic_blast(swing_turf)
playsound(src, 'sound/weapons/slashmiss.ogg', 50, 1)
/mob/living/simple_animal/hostile/jungle/mook/proc/LeapAttack()
if(target && !stat && attack_state == MOOK_ATTACK_WARMUP)
attack_state = MOOK_ATTACK_ACTIVE
density = FALSE
melee_damage_lower = 30
melee_damage_upper = 30
update_icons()
new /obj/effect/temp_visual/mook_dust(get_turf(src))
playsound(src, 'sound/weapons/thudswoosh.ogg', 25, 1)
playsound(src, 'sound/voice/mook_leap_yell.ogg', 100, 1)
var/target_turf = get_turf(target)
throw_at(target_turf, 7, 1, src, FALSE, callback = CALLBACK(src, .proc/AttackRecovery))
return
attack_state = MOOK_ATTACK_RECOVERY
ResetNeutral()
/mob/living/simple_animal/hostile/jungle/mook/proc/AttackRecovery()
if(attack_state == MOOK_ATTACK_ACTIVE && !stat)
attack_state = MOOK_ATTACK_RECOVERY
density = TRUE
face_atom(target)
if(!struck_target_leap)
update_icons()
struck_target_leap = FALSE
if(prob(40))
attack_state = MOOK_ATTACK_NEUTRAL
if(target)
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated() && L.stat != DEAD)
addtimer(CALLBACK(src, .proc/WarmupAttack, TRUE), ATTACK_INTERMISSION_TIME)
return
addtimer(CALLBACK(src, .proc/WarmupAttack), ATTACK_INTERMISSION_TIME)
return
addtimer(CALLBACK(src, .proc/ResetNeutral), ATTACK_INTERMISSION_TIME)
/mob/living/simple_animal/hostile/jungle/mook/proc/ResetNeutral()
if(attack_state == MOOK_ATTACK_RECOVERY)
attack_state = MOOK_ATTACK_NEUTRAL
ranged_cooldown = world.time + ranged_cooldown_time
update_icons()
if(target && !stat)
update_icons()
Goto(target, move_to_delay, minimum_distance)
/mob/living/simple_animal/hostile/jungle/mook/throw_impact(atom/hit_atom, throwingdatum)
. = ..()
if(isliving(hit_atom) && attack_state == MOOK_ATTACK_ACTIVE)
var/mob/living/L = hit_atom
if(CanAttack(L))
L.attack_animal(src)
struck_target_leap = TRUE
density = TRUE
update_icons()
var/mook_under_us = FALSE
for(var/A in get_turf(src))
if(struck_target_leap && mook_under_us)
break
if(A == src)
continue
if(isliving(A))
var/mob/living/ML = A
if(!struck_target_leap && CanAttack(ML))//Check if some joker is attempting to use rest to evade us
struck_target_leap = TRUE
ML.attack_animal(src)
density = TRUE
struck_target_leap = TRUE
update_icons()
continue
if(istype(ML, /mob/living/simple_animal/hostile/jungle/mook) && !mook_under_us)//If we land on the same tile as another mook, spread out so we don't stack our sprite on the same tile
var/mob/living/simple_animal/hostile/jungle/mook/M = ML
if(!M.stat)
mook_under_us = TRUE
var/anydir = pick(GLOB.cardinals)
Move(get_step(src, anydir), anydir)
continue
/mob/living/simple_animal/hostile/jungle/mook/handle_automated_action()
if(attack_state)
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/OpenFire()
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated())
return
WarmupAttack()
/mob/living/simple_animal/hostile/jungle/mook/update_icons()
. = ..()
if(!stat)
switch(attack_state)
if(MOOK_ATTACK_NEUTRAL)
icon_state = "mook"
if(MOOK_ATTACK_WARMUP)
icon_state = "mook_warmup"
if(MOOK_ATTACK_ACTIVE)
if(!density)
icon_state = "mook_leap"
return
if(struck_target_leap)
icon_state = "mook_strike"
return
icon_state = "mook_slash_combo"
if(MOOK_ATTACK_RECOVERY)
icon_state = "mook"
/obj/effect/temp_visual/mook_dust
name = "dust"
desc = "it's just a dust cloud!"
icon = 'icons/mob/jungle/mook.dmi'
icon_state = "mook_leap_cloud"
layer = BELOW_MOB_LAYER
pixel_x = -16
pixel_y = -16
duration = 10
#undef MOOK_ATTACK_NEUTRAL
#undef MOOK_ATTACK_WARMUP
#undef MOOK_ATTACK_ACTIVE
#undef MOOK_ATTACK_RECOVERY
#undef ATTACK_INTERMISSION_TIME
@@ -0,0 +1,244 @@
#define SEEDLING_STATE_NEUTRAL 0
#define SEEDLING_STATE_WARMUP 1
#define SEEDLING_STATE_ACTIVE 2
#define SEEDLING_STATE_RECOVERY 3
//A plant rooted in the ground that forfeits its melee attack in favor of ranged barrages.
//It will fire flurries of solar energy, and occasionally charge up a powerful blast that makes it vulnerable to attack.
/mob/living/simple_animal/hostile/jungle/seedling
name = "seedling"
desc = "This oversized, predatory flower conceals what can only be described as an organic energy cannon, and it will not die until its hidden vital organs are sliced out. \
The concentrated streams of energy it sometimes produces require its full attention, attacking it during this time will prevent it from finishing its attack."
icon = 'icons/mob/jungle/seedling.dmi'
icon_state = "seedling"
icon_living = "seedling"
icon_dead = "seedling_dead"
maxHealth = 100
health = 100
melee_damage_lower = 30
melee_damage_upper = 30
pixel_x = -16
pixel_y = -14
minimum_distance = 3
move_to_delay = 20
vision_range = 9
aggro_vision_range = 15
ranged = TRUE
ranged_cooldown_time = 10
projectiletype = /obj/item/projectile/seedling
projectilesound = 'sound/weapons/pierce.ogg'
robust_searching = TRUE
stat_attack = UNCONSCIOUS
anchored = TRUE
var/combatant_state = SEEDLING_STATE_NEUTRAL
var/obj/seedling_weakpoint/weak_point
var/mob/living/beam_debuff_target
var/solar_beam_identifier = 0
/obj/item/projectile/seedling
name = "solar energy"
icon_state = "seedling"
damage = 10
damage_type = BURN
light_range = 2
flag = "energy"
light_color = LIGHT_COLOR_YELLOW
hitsound = 'sound/weapons/sear.ogg'
hitsound_wall = 'sound/weapons/effects/searwall.ogg'
nondirectional_sprite = TRUE
/obj/item/projectile/seedling/Collide(atom/A)//Stops seedlings from destroying other jungle mobs through FF
if(isliving(A))
var/mob/living/L = A
if("jungle" in L.faction)
return FALSE
return ..()
/obj/effect/temp_visual/solarbeam_killsat
name = "beam of solar energy"
icon_state = "solar_beam"
icon = 'icons/effects/beam.dmi'
layer = LIGHTING_LAYER
duration = 5
randomdir = FALSE
/datum/status_effect/seedling_beam_indicator
id = "seedling beam indicator"
duration = 30
status_type = STATUS_EFFECT_MULTIPLE
alert_type = null
tick_interval = 1
var/obj/screen/seedling/seedling_screen_object
var/atom/target
/datum/status_effect/seedling_beam_indicator/on_creation(mob/living/new_owner, target_plant)
. = ..()
if(.)
target = target_plant
tick()
/datum/status_effect/seedling_beam_indicator/on_apply()
if(owner.client)
seedling_screen_object = new /obj/screen/seedling()
owner.client.screen += seedling_screen_object
tick()
return ..()
/datum/status_effect/seedling_beam_indicator/Destroy()
if(owner)
if(owner.client)
owner.client.screen -= seedling_screen_object
return ..()
/datum/status_effect/seedling_beam_indicator/tick()
var/target_angle = Get_Angle(owner, target)
var/matrix/final = matrix()
final.Turn(target_angle)
seedling_screen_object.transform = final
/obj/screen/seedling
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "seedling_beam_indicator"
screen_loc = "CENTER:-16,CENTER:-16"
/mob/living/simple_animal/hostile/jungle/seedling/Goto()
if(combatant_state != SEEDLING_STATE_NEUTRAL)
return
return ..()
/mob/living/simple_animal/hostile/jungle/seedling/AttackingTarget()
if(isliving(target))
if(ranged_cooldown <= world.time && combatant_state == SEEDLING_STATE_NEUTRAL)
OpenFire(target)
return
return ..()
/mob/living/simple_animal/hostile/jungle/seedling/OpenFire()
WarmupAttack()
/mob/living/simple_animal/hostile/jungle/seedling/proc/WarmupAttack()
if(combatant_state == SEEDLING_STATE_NEUTRAL)
combatant_state = SEEDLING_STATE_WARMUP
walk(src,0)
update_icons()
var/target_dist = get_dist(src,target)
var/living_target_check = isliving(target)
if(living_target_check)
if(target_dist > 7)//Offscreen check
SolarBeamStartup(target)
return
if(get_dist(src,target) >= 4 && prob(40))
SolarBeamStartup(target)
return
addtimer(CALLBACK(src, .proc/Volley), 5)
/mob/living/simple_animal/hostile/jungle/seedling/proc/SolarBeamStartup(mob/living/living_target)//It's more like requiem than final spark
if(combatant_state == SEEDLING_STATE_WARMUP && target)
combatant_state = SEEDLING_STATE_ACTIVE
living_target.apply_status_effect(/datum/status_effect/seedling_beam_indicator, src)
beam_debuff_target = living_target
playsound(src,'sound/effects/seedling_chargeup.ogg', 100, 0)
if(get_dist(src,living_target) > 7)
playsound(living_target,'sound/effects/seedling_chargeup.ogg', 100, 0)
solar_beam_identifier = world.time
addtimer(CALLBACK(src, .proc/Beamu, living_target, solar_beam_identifier), 35)
/mob/living/simple_animal/hostile/jungle/seedling/proc/Beamu(mob/living/living_target, beam_id = 0)
if(combatant_state == SEEDLING_STATE_ACTIVE && living_target && beam_id == solar_beam_identifier)
if(living_target.z == z)
update_icons()
var/obj/effect/temp_visual/solarbeam_killsat/S = new (get_turf(src))
var/matrix/starting = matrix()
starting.Scale(1,32)
starting.Translate(0,520)
S.transform = starting
var/obj/effect/temp_visual/solarbeam_killsat/K = new (get_turf(living_target))
var/matrix/final = matrix()
final.Scale(1,32)
final.Translate(0,512)
K.transform = final
living_target.adjustFireLoss(30)
living_target.adjust_fire_stacks(0.2)//Just here for the showmanship
living_target.IgniteMob()
playsound(living_target,'sound/weapons/sear.ogg', 50, 1)
addtimer(CALLBACK(src, .proc/AttackRecovery), 5)
return
AttackRecovery()
/mob/living/simple_animal/hostile/jungle/seedling/proc/Volley()
if(combatant_state == SEEDLING_STATE_WARMUP && target)
combatant_state = SEEDLING_STATE_ACTIVE
update_icons()
var/datum/callback/cb = CALLBACK(src, .proc/InaccurateShot)
for(var/i in 1 to 13)
addtimer(cb, i)
addtimer(CALLBACK(src, .proc/AttackRecovery), 14)
/mob/living/simple_animal/hostile/jungle/seedling/proc/InaccurateShot()
if(!QDELETED(target) && combatant_state == SEEDLING_STATE_ACTIVE && !stat)
if(get_dist(src,target) <= 3)//If they're close enough just aim straight at them so we don't miss at point blank ranges
Shoot(target)
return
var/turf/our_turf = get_turf(src)
var/obj/item/projectile/seedling/readied_shot = new /obj/item/projectile/seedling(our_turf)
readied_shot.current = our_turf
readied_shot.starting = our_turf
readied_shot.firer = src
readied_shot.original = target
readied_shot.yo = target.y - our_turf.y + rand(-1,1)
readied_shot.xo = target.x - our_turf.x + rand(-1,1)
readied_shot.fire()
playsound(src, projectilesound, 100, 1)
/mob/living/simple_animal/hostile/jungle/seedling/proc/AttackRecovery()
if(combatant_state == SEEDLING_STATE_ACTIVE)
combatant_state = SEEDLING_STATE_RECOVERY
update_icons()
ranged_cooldown = world.time + ranged_cooldown_time
if(target)
face_atom(target)
addtimer(CALLBACK(src, .proc/ResetNeutral), 10)
/mob/living/simple_animal/hostile/jungle/seedling/proc/ResetNeutral()
combatant_state = SEEDLING_STATE_NEUTRAL
if(target && !stat)
update_icons()
Goto(target, move_to_delay, minimum_distance)
/mob/living/simple_animal/hostile/jungle/seedling/adjustHealth()
. = ..()
if(combatant_state == SEEDLING_STATE_ACTIVE && beam_debuff_target)
beam_debuff_target.remove_status_effect(/datum/status_effect/seedling_beam_indicator)
beam_debuff_target = null
solar_beam_identifier = 0
AttackRecovery()
/mob/living/simple_animal/hostile/jungle/seedling/update_icons()
. = ..()
if(!stat)
switch(combatant_state)
if(SEEDLING_STATE_NEUTRAL)
icon_state = "seedling"
if(SEEDLING_STATE_WARMUP)
icon_state = "seedling_charging"
if(SEEDLING_STATE_ACTIVE)
icon_state = "seedling_fire"
if(SEEDLING_STATE_RECOVERY)
icon_state = "seedling"
/mob/living/simple_animal/hostile/jungle/seedling/GiveTarget()
if(target)
if(combatant_state == SEEDLING_STATE_WARMUP || combatant_state == SEEDLING_STATE_ACTIVE)//So it doesn't 180 and blast you in the face while it's firing at someone else
return
return ..()
/mob/living/simple_animal/hostile/jungle/seedling/LoseTarget()
if(combatant_state == SEEDLING_STATE_WARMUP || combatant_state == SEEDLING_STATE_ACTIVE)
return
return ..()
#undef SEEDLING_STATE_NEUTRAL
#undef SEEDLING_STATE_WARMUP
#undef SEEDLING_STATE_ACTIVE
#undef SEEDLING_STATE_RECOVERY
@@ -1,833 +0,0 @@
/mob/living/simple_animal/hostile/jungle
vision_range = 5
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
faction = list("jungle")
weather_immunities = list("acid")
obj_damage = 30
environment_smash = ENVIRONMENT_SMASH_WALLS
minbodytemp = 0
maxbodytemp = 450
response_help = "pokes"
response_disarm = "shoves"
response_harm = "strikes"
status_flags = 0
a_intent = INTENT_HARM
see_in_dark = 4
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
mob_size = MOB_SIZE_LARGE
//Mega arachnid
/mob/living/simple_animal/hostile/jungle/mega_arachnid
name = "mega arachnid"
desc = "Though physically imposing, it prefers to ambush its prey, and it will only engage with an already crippled opponent."
melee_damage_lower = 30
melee_damage_upper = 30
maxHealth = 300
health = 300
speed = 1
ranged = 1
pixel_x = -16
move_to_delay = 10
aggro_vision_range = 9
speak_emote = list("chitters")
attack_sound = 'sound/weapons/bladeslice.ogg'
ranged_cooldown_time = 60
projectiletype = /obj/item/projectile/mega_arachnid
projectilesound = 'sound/weapons/pierce.ogg'
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "arachnid"
icon_living = "arachnid"
icon_dead = "dead_purple"
alpha = 50
/mob/living/simple_animal/hostile/jungle/mega_arachnid/Life()
..()
if(target && ranged_cooldown > world.time && iscarbon(target))
var/mob/living/carbon/C = target
if(!C.legcuffed && C.health < 50)
retreat_distance = 9
minimum_distance = 9
alpha = 125
return
retreat_distance = 0
minimum_distance = 0
alpha = 255
/mob/living/simple_animal/hostile/jungle/mega_arachnid/Aggro()
..()
alpha = 255
/mob/living/simple_animal/hostile/jungle/mega_arachnid/LoseAggro()
..()
alpha = 50
/obj/item/projectile/mega_arachnid
name = "flesh snare"
nodamage = 1
damage = 0
icon_state = "tentacle_end"
/obj/item/projectile/mega_arachnid/on_hit(atom/target, blocked = FALSE)
if(iscarbon(target) && blocked < 100)
var/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid/B = new /obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid(get_turf(target))
B.Crossed(target)
..()
/obj/item/weapon/restraints/legcuffs/beartrap/mega_arachnid
name = "fleshy restraints"
desc = "Used by mega arachnids to immobilize their prey."
flags = DROPDEL
icon_state = "tentacle_end"
icon = 'icons/obj/projectiles.dmi'
////Leaper////
#define PLAYER_HOP_DELAY 25
/mob/living/simple_animal/hostile/jungle/leaper
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
faction = list("jungle")
weather_immunities = list("acid")
obj_damage = 30
environment_smash = ENVIRONMENT_SMASH_WALLS
maxHealth = 300
health = 300
minbodytemp = 0
maxbodytemp = 450
response_help = "pokes"
response_disarm = "shoves"
response_harm = "strikes"
status_flags = 0
a_intent = INTENT_HARM
see_in_dark = 4
ranged = TRUE
projectiletype = /obj/item/projectile/leaper
projectilesound = 'sound/weapons/pierce.ogg'
ranged_cooldown_time = 30
pixel_x = -16
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "leaper"
icon_living = "leaper"
icon_dead = "leaper_dead"
layer = LARGE_MOB_LAYER
name = "leaper"
desc = "Commonly referred to as 'leapers', the Geron Toad is a massive beast that spits out highly pressurized bubbles containing a unique toxin, knocking down its prey and then crushing it with its girth."
speed = 10
stat_attack = 1
robust_searching = 1
var/hopping = FALSE
var/hop_cooldown = 0 //Strictly for player controlled leapers
var/projectile_ready = FALSE //Stopping AI leapers from firing whenever they want, and only doing it after a hop has finished instead
/obj/item/projectile/leaper
name = "leaper bubble"
icon_state = "leaper"
knockdown = 50
damage = 0
range = 7
hitsound = 'sound/effects/snap.ogg'
nondirectional_sprite = TRUE
impact_effect_type = /obj/effect/temp_visual/leaper_projectile_impact
/obj/item/projectile/leaper/on_hit(atom/target, blocked = FALSE)
..()
if(iscarbon(target))
var/mob/living/carbon/C = target
C.reagents.add_reagent("leaper_venom", 5)
return
if(isanimal(target))
var/mob/living/simple_animal/L = target
L.adjustHealth(25)
/obj/item/projectile/leaper/on_range()
var/turf/T = get_turf(src)
..()
new /obj/structure/leaper_bubble(T)
/obj/effect/temp_visual/leaper_projectile_impact
name = "leaper bubble"
icon = 'icons/obj/projectiles.dmi'
icon_state = "leaper_bubble_pop"
layer = ABOVE_ALL_MOB_LAYER
duration = 3
/obj/effect/temp_visual/leaper_projectile_impact/Initialize()
. = ..()
new /obj/effect/decal/cleanable/leaper_sludge(get_turf(src))
/obj/effect/decal/cleanable/leaper_sludge
name = "leaper sludge"
desc = "A small pool of sludge, containing trace amounts of leaper venom"
icon = 'icons/effects/tomatodecal.dmi'
icon_state = "tomato_floor1"
/obj/structure/leaper_bubble
name = "leaper bubble"
desc = "A floating bubble containing leaper venom, the contents are under a surprising amount of pressure."
icon = 'icons/obj/projectiles.dmi'
icon_state = "leaper"
max_integrity = 10
density = FALSE
/obj/structure/leaper_bubble/Initialize()
. = ..()
float(on = TRUE)
QDEL_IN(src, 100)
/obj/structure/leaper_bubble/Destroy()
new /obj/effect/temp_visual/leaper_projectile_impact(get_turf(src))
playsound(src,'sound/effects/snap.ogg',50, 1, -1)
return ..()
/obj/structure/leaper_bubble/Crossed(atom/movable/AM)
if(isliving(AM))
var/mob/living/L = AM
if(!istype(L, /mob/living/simple_animal/hostile/jungle/leaper))
playsound(src,'sound/effects/snap.ogg',50, 1, -1)
L.Knockdown(50)
if(iscarbon(L))
var/mob/living/carbon/C = L
C.reagents.add_reagent("leaper_venom", 5)
if(isanimal(L))
var/mob/living/simple_animal/A = L
A.adjustHealth(25)
qdel(src)
return ..()
/datum/reagent/toxin/leaper_venom
name = "Leaper venom"
id = "leaper_venom"
description = "A toxin spat out by leapers that while harmless in small doses, quickly creates a toxic reaction if too much is in the body."
color = "#801E28" // rgb: 128, 30, 40
toxpwr = 0
taste_description = "french cuisine"
taste_mult = 1.3
/datum/reagent/toxin/leaper_venom/on_mob_life(mob/living/M)
if(volume >= 10)
M.adjustToxLoss(5, 0)
..()
/obj/effect/temp_visual/leaper_crush
name = "Grim tidings"
desc = "Incoming leaper!"
icon = 'icons/effects/96x96.dmi'
icon_state = "lily_pad"
layer = BELOW_MOB_LAYER
pixel_x = -32
pixel_y = -32
duration = 30
/mob/living/simple_animal/hostile/jungle/leaper/Initialize()
. = ..()
verbs -= /mob/living/verb/pulled
/mob/living/simple_animal/hostile/jungle/leaper/CtrlClickOn(atom/A)
face_atom(A)
target = A
if(!isturf(loc))
return
if(next_move > world.time)
return
if(hopping)
return
if(isliving(A))
var/mob/living/L = A
if(L.incapacitated())
BellyFlop()
return
if(hop_cooldown <= world.time)
Hop(player_hop = TRUE)
/mob/living/simple_animal/hostile/jungle/leaper/AttackingTarget()
if(isliving(target))
return
return ..()
/mob/living/simple_animal/hostile/jungle/leaper/handle_automated_action()
if(hopping || projectile_ready)
return
. = ..()
if(target)
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated())
BellyFlop()
return
if(!hopping)
Hop()
/mob/living/simple_animal/hostile/jungle/leaper/Life()
. = ..()
update_icons()
/mob/living/simple_animal/hostile/jungle/leaper/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
if(prob(33) && !ckey)
ranged_cooldown = 0 //Keeps em on their toes instead of a constant rotation
..()
/mob/living/simple_animal/hostile/jungle/leaper/OpenFire()
face_atom(target)
if(ranged_cooldown <= world.time)
if(ckey)
if(hopping)
return
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated())
return //No stunlocking. Hop on them after you stun them, you donk.
if(AIStatus == AI_ON && !projectile_ready && !ckey)
return
. = ..(target)
projectile_ready = FALSE
update_icons()
/mob/living/simple_animal/hostile/jungle/leaper/proc/Hop(player_hop = FALSE)
if(z != target.z)
return
hopping = TRUE
density = FALSE
pass_flags |= PASSMOB
notransform = TRUE
var/turf/new_turf = locate((target.x + rand(-3,3)),(target.y + rand(-3,3)),target.z)
if(player_hop)
new_turf = get_turf(target)
hop_cooldown = world.time + PLAYER_HOP_DELAY
if(AIStatus == AI_ON && ranged_cooldown <= world.time)
projectile_ready = TRUE
update_icons()
throw_at(new_turf, max(3,get_dist(src,new_turf)), 1, src, FALSE, callback = CALLBACK(src, .FinishHop))
/mob/living/simple_animal/hostile/jungle/leaper/proc/FinishHop()
density = TRUE
notransform = FALSE
pass_flags &= ~PASSMOB
hopping = FALSE
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 100, 1)
if(target && AIStatus == AI_ON && projectile_ready && !ckey)
face_atom(target)
addtimer(CALLBACK(src, .proc/OpenFire, target), 5)
/mob/living/simple_animal/hostile/jungle/leaper/proc/BellyFlop()
var/turf/new_turf = get_turf(target)
hopping = TRUE
notransform = TRUE
new /obj/effect/temp_visual/leaper_crush(new_turf)
addtimer(CALLBACK(src, .proc/BellyFlopHop, new_turf), 30)
/mob/living/simple_animal/hostile/jungle/leaper/proc/BellyFlopHop(turf/T)
density = FALSE
throw_at(T, get_dist(src,T),1,src, FALSE, callback = CALLBACK(src, .proc/Crush))
/mob/living/simple_animal/hostile/jungle/leaper/proc/Crush()
hopping = FALSE
density = TRUE
notransform = FALSE
playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1)
for(var/mob/living/L in orange(1, src))
L.adjustBruteLoss(35)
if(!QDELETED(L)) // Some mobs are deleted on death
var/throw_dir = get_dir(src, L)
if(L.loc == loc)
throw_dir = pick(GLOB.alldirs)
var/throwtarget = get_edge_target_turf(src, throw_dir)
L.throw_at(throwtarget, 3, 1)
visible_message("<span class='warning'>[L] is thrown clear of [src]!</span>")
if(ckey)//Lessens ability to chain stun as a player
ranged_cooldown = ranged_cooldown_time + world.time
update_icons()
/mob/living/simple_animal/hostile/jungle/leaper/Goto()
return
/mob/living/simple_animal/hostile/jungle/leaper/throw_impact()
return
/mob/living/simple_animal/hostile/jungle/leaper/update_icons()
. = ..()
if(stat)
icon_state = "leaper_dead"
return
if(ranged_cooldown <= world.time)
if(AIStatus == AI_ON && projectile_ready || ckey)
icon_state = "leaper_alert"
return
icon_state = "leaper"
#undef PLAYER_HOP_DELAY
////JUNGLE MOOK////
#define MOOK_ATTACK_NEUTRAL 0
#define MOOK_ATTACK_WARMUP 1
#define MOOK_ATTACK_ACTIVE 2
#define MOOK_ATTACK_RECOVERY 3
#define ATTACK_INTERMISSION_TIME 5
/mob/living/simple_animal/hostile/jungle/mook
name = "wanderer"
desc = "This unhealthy looking primitive is wielding a rudimentary hatchet, swinging it with wild abandon. One isn't much of a threat, but in numbers they can quickly overwhelm a superior opponent."
maxHealth = 45
health = 45
melee_damage_lower = 30
melee_damage_upper = 30
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "mook"
icon_living = "mook"
icon_dead = "mook_dead"
pixel_x = -16
pixel_y = -8
ranged = TRUE
ranged_cooldown_time = 10
pass_flags = LETPASSTHROW
robust_searching = TRUE
stat_attack = UNCONSCIOUS
attack_sound = 'sound/weapons/rapierhit.ogg'
death_sound = 'sound/voice/mook_death.ogg'
aggro_vision_range = 15 //A little more aggressive once in combat to balance out their really low HP
var/attack_state = MOOK_ATTACK_NEUTRAL
var/struck_target_leap = FALSE
/mob/living/simple_animal/hostile/jungle/mook/CanPass(atom/movable/O)
if(istype(O, /mob/living/simple_animal/hostile/jungle/mook))
var/mob/living/simple_animal/hostile/jungle/mook/M = O
if(M.attack_state == MOOK_ATTACK_ACTIVE && M.throwing)
return TRUE
return ..()
/mob/living/simple_animal/hostile/jungle/mook/death()
desc = "A deceased primitive. Upon closer inspection, it was suffering from severe cellular degeneration and its garments are machine made..."//Can you guess the twist
return ..()
/mob/living/simple_animal/hostile/jungle/mook/AttackingTarget()
if(isliving(target))
if(ranged_cooldown <= world.time && attack_state == MOOK_ATTACK_NEUTRAL)
var/mob/living/L = target
if(L.incapacitated())
WarmupAttack(forced_slash_combo = TRUE)
return
WarmupAttack()
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/Goto()
if(attack_state != MOOK_ATTACK_NEUTRAL)
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/Move()
if(attack_state == MOOK_ATTACK_WARMUP || attack_state == MOOK_ATTACK_RECOVERY)
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/proc/WarmupAttack(forced_slash_combo = FALSE)
if(attack_state == MOOK_ATTACK_NEUTRAL && target)
attack_state = MOOK_ATTACK_WARMUP
walk(src,0)
update_icons()
if(prob(50) && get_dist(src,target) <= 3 || forced_slash_combo)
addtimer(CALLBACK(src, .proc/SlashCombo), ATTACK_INTERMISSION_TIME)
return
addtimer(CALLBACK(src, .proc/LeapAttack), ATTACK_INTERMISSION_TIME + rand(0,3))
return
attack_state = MOOK_ATTACK_RECOVERY
ResetNeutral()
/mob/living/simple_animal/hostile/jungle/mook/proc/SlashCombo()
if(attack_state == MOOK_ATTACK_WARMUP && !stat)
attack_state = MOOK_ATTACK_ACTIVE
update_icons()
SlashAttack()
addtimer(CALLBACK(src, .proc/SlashAttack), 3)
addtimer(CALLBACK(src, .proc/SlashAttack), 6)
addtimer(CALLBACK(src, .proc/AttackRecovery), 9)
/mob/living/simple_animal/hostile/jungle/mook/proc/SlashAttack()
if(target && !stat && attack_state == MOOK_ATTACK_ACTIVE)
melee_damage_lower = 15
melee_damage_upper = 15
var/mob_direction = get_dir(src,target)
if(get_dist(src,target) > 1)
step(src,mob_direction)
if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from) && isliving(target))
var/mob/living/L = target
L.attack_animal(src)
return
var/swing_turf = get_step(src,mob_direction)
new /obj/effect/temp_visual/kinetic_blast(swing_turf)
playsound(src, 'sound/weapons/slashmiss.ogg', 50, 1)
/mob/living/simple_animal/hostile/jungle/mook/proc/LeapAttack()
if(target && !stat && attack_state == MOOK_ATTACK_WARMUP)
attack_state = MOOK_ATTACK_ACTIVE
density = FALSE
melee_damage_lower = 30
melee_damage_upper = 30
update_icons()
new /obj/effect/temp_visual/mook_dust(get_turf(src))
playsound(src, 'sound/weapons/thudswoosh.ogg', 25, 1)
playsound(src, 'sound/voice/mook_leap_yell.ogg', 100, 1)
var/target_turf = get_turf(target)
throw_at(target_turf, 7, 1, src, FALSE, callback = CALLBACK(src, .proc/AttackRecovery))
return
attack_state = MOOK_ATTACK_RECOVERY
ResetNeutral()
/mob/living/simple_animal/hostile/jungle/mook/proc/AttackRecovery()
if(attack_state == MOOK_ATTACK_ACTIVE && !stat)
attack_state = MOOK_ATTACK_RECOVERY
density = TRUE
face_atom(target)
if(!struck_target_leap)
update_icons()
struck_target_leap = FALSE
if(prob(40))
attack_state = MOOK_ATTACK_NEUTRAL
if(target)
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated() && L.stat != DEAD)
addtimer(CALLBACK(src, .proc/WarmupAttack, TRUE), ATTACK_INTERMISSION_TIME)
return
addtimer(CALLBACK(src, .proc/WarmupAttack), ATTACK_INTERMISSION_TIME)
return
addtimer(CALLBACK(src, .proc/ResetNeutral), ATTACK_INTERMISSION_TIME)
/mob/living/simple_animal/hostile/jungle/mook/proc/ResetNeutral()
if(attack_state == MOOK_ATTACK_RECOVERY)
attack_state = MOOK_ATTACK_NEUTRAL
ranged_cooldown = world.time + ranged_cooldown_time
update_icons()
if(target && !stat)
update_icons()
Goto(target, move_to_delay, minimum_distance)
/mob/living/simple_animal/hostile/jungle/mook/throw_impact(atom/hit_atom, throwingdatum)
. = ..()
if(isliving(hit_atom) && attack_state == MOOK_ATTACK_ACTIVE)
var/mob/living/L = hit_atom
if(CanAttack(L))
L.attack_animal(src)
struck_target_leap = TRUE
density = TRUE
update_icons()
var/mook_under_us = FALSE
for(var/A in get_turf(src))
if(struck_target_leap && mook_under_us)
break
if(A == src)
continue
if(isliving(A))
var/mob/living/ML = A
if(!struck_target_leap && CanAttack(ML))//Check if some joker is attempting to use rest to evade us
struck_target_leap = TRUE
ML.attack_animal(src)
density = TRUE
struck_target_leap = TRUE
update_icons()
continue
if(istype(ML, /mob/living/simple_animal/hostile/jungle/mook) && !mook_under_us)//If we land on the same tile as another mook, spread out so we don't stack our sprite on the same tile
var/mob/living/simple_animal/hostile/jungle/mook/M = ML
if(!M.stat)
mook_under_us = TRUE
var/anydir = pick(GLOB.cardinals)
Move(get_step(src, anydir), anydir)
continue
/mob/living/simple_animal/hostile/jungle/mook/handle_automated_action()
if(attack_state)
return
return ..()
/mob/living/simple_animal/hostile/jungle/mook/OpenFire()
if(isliving(target))
var/mob/living/L = target
if(L.incapacitated())
return
WarmupAttack()
/mob/living/simple_animal/hostile/jungle/mook/update_icons()
. = ..()
if(!stat)
switch(attack_state)
if(MOOK_ATTACK_NEUTRAL)
icon_state = "mook"
if(MOOK_ATTACK_WARMUP)
icon_state = "mook_warmup"
if(MOOK_ATTACK_ACTIVE)
if(!density)
icon_state = "mook_leap"
return
if(struck_target_leap)
icon_state = "mook_strike"
return
icon_state = "mook_slash_combo"
if(MOOK_ATTACK_RECOVERY)
icon_state = "mook"
/obj/effect/temp_visual/mook_dust
name = "dust"
desc = "it's just a dust cloud!"
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "mook_leap_cloud"
layer = BELOW_MOB_LAYER
pixel_x = -16
pixel_y = -16
duration = 10
#undef MOOK_ATTACK_NEUTRAL
#undef MOOK_ATTACK_WARMUP
#undef MOOK_ATTACK_ACTIVE
#undef MOOK_ATTACK_RECOVERY
#undef ATTACK_INTERMISSION_TIME
////Jungle Seedling////
#define SEEDLING_STATE_NEUTRAL 0
#define SEEDLING_STATE_WARMUP 1
#define SEEDLING_STATE_ACTIVE 2
#define SEEDLING_STATE_RECOVERY 3
/mob/living/simple_animal/hostile/jungle/seedling
name = "seedling"
desc = "This oversized, predatory flower conceals what can only be described as an organic energy cannon, and it will not die until its hidden vital organs are sliced out. \
The concentrated streams of energy it sometimes produces require its full attention, attacking it during this time will prevent it from finishing its attack."
maxHealth = 100
health = 100
melee_damage_lower = 30
melee_damage_upper = 30
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "seedling"
icon_living = "seedling"
icon_dead = "seedling_dead"
pixel_x = -16
pixel_y = -14
minimum_distance = 3
move_to_delay = 20
vision_range = 9
aggro_vision_range = 15
ranged = TRUE
ranged_cooldown_time = 10
projectiletype = /obj/item/projectile/seedling
projectilesound = 'sound/weapons/pierce.ogg'
robust_searching = TRUE
stat_attack = UNCONSCIOUS
anchored = TRUE
var/combatant_state = SEEDLING_STATE_NEUTRAL
var/obj/seedling_weakpoint/weak_point
var/mob/living/beam_debuff_target
var/solar_beam_identifier = 0
/obj/item/projectile/seedling
name = "solar energy"
icon_state = "seedling"
damage = 10
damage_type = BURN
light_range = 2
flag = "energy"
light_color = LIGHT_COLOR_YELLOW
hitsound = 'sound/weapons/sear.ogg'
hitsound_wall = 'sound/weapons/effects/searwall.ogg'
nondirectional_sprite = TRUE
/obj/item/projectile/seedling/Collide(atom/A)//Stops seedlings from destroying other jungle mobs through FF
if(isliving(A))
var/mob/living/L = A
if("jungle" in L.faction)
return FALSE
return ..()
/obj/effect/temp_visual/solarbeam_killsat
name = "beam of solar energy"
icon_state = "solar_beam"
icon = 'icons/effects/beam.dmi'
layer = LIGHTING_LAYER
duration = 5
randomdir = FALSE
/datum/status_effect/seedling_beam_indicator
id = "seedling beam indicator"
duration = 30
status_type = STATUS_EFFECT_MULTIPLE
alert_type = null
tick_interval = 1
var/obj/screen/seedling/seedling_screen_object
var/atom/target
/datum/status_effect/seedling_beam_indicator/on_creation(mob/living/new_owner, target_plant)
. = ..()
if(.)
target = target_plant
tick()
/datum/status_effect/seedling_beam_indicator/on_apply()
if(owner.client)
seedling_screen_object = new /obj/screen/seedling()
owner.client.screen += seedling_screen_object
tick()
return ..()
/datum/status_effect/seedling_beam_indicator/Destroy()
if(owner)
if(owner.client)
owner.client.screen -= seedling_screen_object
return ..()
/datum/status_effect/seedling_beam_indicator/tick()
var/target_angle = Get_Angle(owner, target)
var/matrix/final = matrix()
final.Turn(target_angle)
seedling_screen_object.transform = final
/obj/screen/seedling
icon = 'icons/mob/jungle/arachnid.dmi'
icon_state = "seedling_beam_indicator"
screen_loc = "CENTER:-16,CENTER:-16"
/mob/living/simple_animal/hostile/jungle/seedling/Goto()
if(combatant_state != SEEDLING_STATE_NEUTRAL)
return
return ..()
/mob/living/simple_animal/hostile/jungle/seedling/AttackingTarget()
if(isliving(target))
if(ranged_cooldown <= world.time && combatant_state == SEEDLING_STATE_NEUTRAL)
OpenFire(target)
return
return ..()
/mob/living/simple_animal/hostile/jungle/seedling/OpenFire()
WarmupAttack()
/mob/living/simple_animal/hostile/jungle/seedling/proc/WarmupAttack()
if(combatant_state == SEEDLING_STATE_NEUTRAL)
combatant_state = SEEDLING_STATE_WARMUP
walk(src,0)
update_icons()
var/target_dist = get_dist(src,target)
var/living_target_check = isliving(target)
if(living_target_check)
if(target_dist > 7)//Offscreen check
SolarBeamStartup(target)
return
if(get_dist(src,target) >= 4 && prob(40))
SolarBeamStartup(target)
return
addtimer(CALLBACK(src, .proc/Volley), 5)
/mob/living/simple_animal/hostile/jungle/seedling/proc/SolarBeamStartup(mob/living/living_target)//It's more like requiem than final spark
if(combatant_state == SEEDLING_STATE_WARMUP && target)
combatant_state = SEEDLING_STATE_ACTIVE
living_target.apply_status_effect(/datum/status_effect/seedling_beam_indicator, src)
beam_debuff_target = living_target
playsound(src,'sound/effects/seedling_chargeup.ogg', 100, 0)
if(get_dist(src,living_target) > 7)
playsound(living_target,'sound/effects/seedling_chargeup.ogg', 100, 0)
solar_beam_identifier = world.time
addtimer(CALLBACK(src, .proc/Beamu, living_target, solar_beam_identifier), 35)
/mob/living/simple_animal/hostile/jungle/seedling/proc/Beamu(mob/living/living_target, beam_id = 0)
if(combatant_state == SEEDLING_STATE_ACTIVE && living_target && beam_id == solar_beam_identifier)
if(living_target.z == z)
update_icons()
var/obj/effect/temp_visual/solarbeam_killsat/S = new (get_turf(src))
var/matrix/starting = matrix()
starting.Scale(1,32)
starting.Translate(0,520)
S.transform = starting
var/obj/effect/temp_visual/solarbeam_killsat/K = new (get_turf(living_target))
var/matrix/final = matrix()
final.Scale(1,32)
final.Translate(0,512)
K.transform = final
living_target.adjustFireLoss(30)
living_target.adjust_fire_stacks(0.2)//Just here for the showmanship
living_target.IgniteMob()
playsound(living_target,'sound/weapons/sear.ogg', 50, 1)
addtimer(CALLBACK(src, .proc/AttackRecovery), 5)
return
AttackRecovery()
/mob/living/simple_animal/hostile/jungle/seedling/proc/Volley()
if(combatant_state == SEEDLING_STATE_WARMUP && target)
combatant_state = SEEDLING_STATE_ACTIVE
update_icons()
var/datum/callback/cb = CALLBACK(src, .proc/InaccurateShot)
for(var/i in 1 to 13)
addtimer(cb, i)
addtimer(CALLBACK(src, .proc/AttackRecovery), 14)
/mob/living/simple_animal/hostile/jungle/seedling/proc/InaccurateShot()
if(!QDELETED(target) && combatant_state == SEEDLING_STATE_ACTIVE && !stat)
if(get_dist(src,target) <= 3)//If they're close enough just aim straight at them so we don't miss at point blank ranges
Shoot(target)
return
var/turf/our_turf = get_turf(src)
var/obj/item/projectile/seedling/readied_shot = new /obj/item/projectile/seedling(our_turf)
readied_shot.current = our_turf
readied_shot.starting = our_turf
readied_shot.firer = src
readied_shot.original = target
readied_shot.yo = target.y - our_turf.y + rand(-1,1)
readied_shot.xo = target.x - our_turf.x + rand(-1,1)
readied_shot.fire()
playsound(src, projectilesound, 100, 1)
/mob/living/simple_animal/hostile/jungle/seedling/proc/AttackRecovery()
if(combatant_state == SEEDLING_STATE_ACTIVE)
combatant_state = SEEDLING_STATE_RECOVERY
update_icons()
ranged_cooldown = world.time + ranged_cooldown_time
if(target)
face_atom(target)
addtimer(CALLBACK(src, .proc/ResetNeutral), 10)
/mob/living/simple_animal/hostile/jungle/seedling/proc/ResetNeutral()
combatant_state = SEEDLING_STATE_NEUTRAL
if(target && !stat)
update_icons()
Goto(target, move_to_delay, minimum_distance)
/mob/living/simple_animal/hostile/jungle/seedling/adjustHealth()
. = ..()
if(combatant_state == SEEDLING_STATE_ACTIVE && beam_debuff_target)
beam_debuff_target.remove_status_effect(/datum/status_effect/seedling_beam_indicator)
beam_debuff_target = null
solar_beam_identifier = 0
AttackRecovery()
/mob/living/simple_animal/hostile/jungle/seedling/update_icons()
. = ..()
if(!stat)
switch(combatant_state)
if(SEEDLING_STATE_NEUTRAL)
icon_state = "seedling"
if(SEEDLING_STATE_WARMUP)
icon_state = "seedling_charging"
if(SEEDLING_STATE_ACTIVE)
icon_state = "seedling_fire"
if(SEEDLING_STATE_RECOVERY)
icon_state = "seedling"
/mob/living/simple_animal/hostile/jungle/seedling/GiveTarget()
if(target)
if(combatant_state == SEEDLING_STATE_WARMUP || combatant_state == SEEDLING_STATE_ACTIVE)//So it doesn't 180 and blast you in the face while it's firing at someone else
return
return ..()
/mob/living/simple_animal/hostile/jungle/seedling/LoseTarget()
if(combatant_state == SEEDLING_STATE_WARMUP || combatant_state == SEEDLING_STATE_ACTIVE)
return
return ..()
#undef SEEDLING_STATE_NEUTRAL
#undef SEEDLING_STATE_WARMUP
#undef SEEDLING_STATE_ACTIVE
#undef SEEDLING_STATE_RECOVERY
@@ -10,7 +10,7 @@
maxHealth = 30
health = 30
see_in_dark = 3
butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/killertomato = 2)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/killertomato = 2)
response_help = "prods"
response_disarm = "pushes aside"
response_harm = "smacks"
@@ -38,13 +38,13 @@ Difficulty: Medium
ranged = 1
ranged_cooldown_time = 16
pixel_x = -16
crusher_loot = list(/obj/item/weapon/melee/transforming/cleaving_saw, /obj/item/weapon/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye)
loot = list(/obj/item/weapon/melee/transforming/cleaving_saw, /obj/item/weapon/gun/energy/kinetic_accelerator)
crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator, /obj/item/crusher_trophy/miner_eye)
loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator)
wander = FALSE
del_on_death = TRUE
blood_volume = BLOOD_VOLUME_NORMAL
medal_type = MEDAL_PREFIX
var/obj/item/weapon/melee/transforming/cleaving_saw/miner/miner_saw
var/obj/item/melee/transforming/cleaving_saw/miner/miner_saw
var/time_until_next_transform = 0
var/dashing = FALSE
var/dash_cooldown = 15
@@ -60,11 +60,11 @@ Difficulty: Medium
if(. && prob(12))
INVOKE_ASYNC(src, .proc/dash)
/obj/item/weapon/melee/transforming/cleaving_saw/miner //nerfed saw because it is very murdery
/obj/item/melee/transforming/cleaving_saw/miner //nerfed saw because it is very murdery
force = 6
force_on = 10
/obj/item/weapon/melee/transforming/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user)
/obj/item/melee/transforming/cleaving_saw/miner/attack(mob/living/target, mob/living/carbon/human/user)
target.add_stun_absorption("miner", 10, INFINITY)
..()
target.stun_absorption -= "miner"
@@ -251,9 +251,9 @@ Difficulty: Medium
animate(src, transform = M, pixel_y = -6, dir = final_dir, time = 2, easing = EASE_IN|EASE_OUT)
sleep(5)
animate(src, color = list("#A7A19E", "#A7A19E", "#A7A19E", list(0, 0, 0)), time = 10, easing = EASE_IN, flags = ANIMATION_PARALLEL)
animate(src, color = list("#A7A19E", "#A7A19E", "#A7A19E", list(0, 0, 0)), time = 10, easing = EASE_IN, flags_1 = ANIMATION_PARALLEL)
sleep(4)
animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags = ANIMATION_PARALLEL)
animate(src, alpha = 0, time = 6, easing = EASE_OUT, flags_1 = ANIMATION_PARALLEL)
/obj/item/device/gps/internal/miner
icon_state = null
@@ -48,7 +48,7 @@ Difficulty: Very Hard
score_type = COLOSSUS_SCORE
crusher_loot = list(/obj/structure/closet/crate/necropolis/colossus/crusher)
loot = list(/obj/structure/closet/crate/necropolis/colossus)
butcher_results = list(/obj/item/weapon/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
butcher_results = list(/obj/item/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
deathmessage = "disintegrates, leaving a glowing core in its wake."
death_sound = 'sound/magic/demon_dies.ogg'
@@ -250,7 +250,7 @@ Difficulty: Very Hard
use_power = NO_POWER_USE
var/memory_saved = FALSE
var/list/stored_items = list()
var/static/list/blacklist = typecacheof(list(/obj/item/weapon/spellbook))
var/static/list/blacklist = typecacheof(list(/obj/item/spellbook))
/obj/machinery/smartfridge/black_box/update_icon()
return
@@ -262,14 +262,14 @@ Difficulty: Very Hard
return FALSE
return TRUE
/obj/machinery/smartfridge/black_box/New()
/obj/machinery/smartfridge/black_box/Initialize()
. = ..()
var/static/obj/machinery/smartfridge/black_box/current
if(current && current != src)
qdel(src, force=TRUE)
return
current = src
ReadMemory()
. = ..()
/obj/machinery/smartfridge/black_box/process()
..()
@@ -277,19 +277,29 @@ Difficulty: Very Hard
WriteMemory()
/obj/machinery/smartfridge/black_box/proc/WriteMemory()
var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav")
var/json_file = file("data/npc_saves/Blackbox.json")
stored_items = list()
for(var/obj/O in (contents-component_parts))
stored_items += O.type
WRITE_FILE(S["stored_items"], stored_items)
var/list/file_data = list()
file_data["data"] = stored_items
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
memory_saved = TRUE
/obj/machinery/smartfridge/black_box/proc/ReadMemory()
var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav")
S["stored_items"] >> stored_items
if(fexists("data/npc_saves/Blackbox.sav")) //legacy compatability to convert old format to new
var/savefile/S = new /savefile("data/npc_saves/Blackbox.sav")
S["stored_items"] >> stored_items
fdel("data/npc_saves/Blackbox.sav")
else
var/json_file = file("data/npc_saves/Blackbox.json")
if(!fexists(json_file))
return
var/list/json = list()
json = json_decode(file2text(json_file))
stored_items = json["data"]
if(isnull(stored_items))
stored_items = list()
@@ -351,7 +361,7 @@ Difficulty: Very Hard
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
use_power = NO_POWER_USE
density = TRUE
flags = HEAR
flags_1 = HEAR_1
var/activation_method
var/list/possible_methods = list(ACTIVATE_TOUCH, ACTIVATE_SPEECH, ACTIVATE_HEAT, ACTIVATE_BULLET, ACTIVATE_ENERGY, ACTIVATE_BOMB, ACTIVATE_MOB_BUMP, ACTIVATE_WEAPON, ACTIVATE_MAGIC)
@@ -652,7 +662,7 @@ Difficulty: Very Hard
activation_method = ACTIVATE_TOUCH
cooldown_add = 50
activation_sound = 'sound/magic/timeparadox2.ogg'
var/list/banned_items_typecache = list(/obj/item/weapon/storage, /obj/item/weapon/implant, /obj/item/weapon/implanter, /obj/item/weapon/disk/nuclear, /obj/item/projectile, /obj/item/weapon/spellbook)
var/list/banned_items_typecache = list(/obj/item/storage, /obj/item/implant, /obj/item/implanter, /obj/item/disk/nuclear, /obj/item/projectile, /obj/item/spellbook)
/obj/machinery/anomalous_crystal/refresher/Initialize()
. = ..()
@@ -667,7 +677,7 @@ Difficulty: Very Hard
for(var/i in T)
if(isitem(i) && !is_type_in_typecache(i, banned_items_typecache))
var/obj/item/W = i
if(!W.admin_spawned && !HAS_SECONDARY_FLAG(W, HOLOGRAM) && !(W.flags & ABSTRACT))
if(!W.admin_spawned && !(W.flags_2 & HOLOGRAM_2) && !(W.flags_1 & ABSTRACT_1))
L += W
if(L.len)
var/obj/item/CHOSEN = pick(L)
@@ -53,7 +53,7 @@ Difficulty: Medium
pixel_x = -16
crusher_loot = list(/obj/structure/closet/crate/necropolis/dragon/crusher)
loot = list(/obj/structure/closet/crate/necropolis/dragon)
butcher_results = list(/obj/item/weapon/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
butcher_results = list(/obj/item/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30)
var/swooping = NONE
var/swoop_cooldown = 0
medal_type = MEDAL_PREFIX
@@ -193,11 +193,11 @@ Difficulty: Medium
qdel(F)
if(stat == DEAD)
swooping &= ~SWOOP_DAMAGEABLE
animate(src, alpha = 255, transform = oldtransform, time = 0, flags = ANIMATION_END_NOW) //reset immediately
animate(src, alpha = 255, transform = oldtransform, time = 0, flags_1 = ANIMATION_END_NOW) //reset immediately
return
animate(src, alpha = 100, transform = matrix()*0.7, time = 7)
swooping |= SWOOP_INVULNERABLE
mouse_opacity = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
sleep(7)
var/list/flame_hit = list()
while(swoop_duration > 0)
@@ -56,8 +56,8 @@ Difficulty: Hard
ranged = 1
ranged_cooldown_time = 40
aggro_vision_range = 21 //so it can see to one side of the arena to the other
loot = list(/obj/item/weapon/hierophant_club)
crusher_loot = list(/obj/item/weapon/hierophant_club)
loot = list(/obj/item/hierophant_club)
crusher_loot = list(/obj/item/hierophant_club)
wander = FALSE
var/burst_range = 3 //range on burst aoe
var/beam_range = 5 //range on cross blast beams
@@ -664,14 +664,14 @@ Difficulty: Hard
return
/obj/effect/hierophant/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/hierophant_club))
var/obj/item/weapon/hierophant_club/H = I
if(istype(I, /obj/item/hierophant_club))
var/obj/item/hierophant_club/H = I
if(H.timer > world.time)
return
if(H.beacon == src)
to_chat(user, "<span class='notice'>You start removing your hierophant beacon...</span>")
H.timer = world.time + 51
INVOKE_ASYNC(H, /obj/item/weapon/hierophant_club.proc/prepare_icon_update)
INVOKE_ASYNC(H, /obj/item/hierophant_club.proc/prepare_icon_update)
if(do_after(user, 50, target = src))
playsound(src,'sound/magic/blind.ogg', 200, 1, -4)
new /obj/effect/temp_visual/hierophant/telegraph/teleport(get_turf(src), user)
@@ -681,7 +681,7 @@ Difficulty: Hard
qdel(src)
else
H.timer = world.time
INVOKE_ASYNC(H, /obj/item/weapon/hierophant_club.proc/prepare_icon_update)
INVOKE_ASYNC(H, /obj/item/hierophant_club.proc/prepare_icon_update)
else
to_chat(user, "<span class='hierophant_warning'>You touch the beacon with the club, but nothing happens.</span>")
else

Some files were not shown because too many files have changed in this diff Show More