Merge remote-tracking branch 'upstream/master' into pull-move-rework

This commit is contained in:
joep van der velden
2020-08-17 21:35:35 +02:00
1231 changed files with 72306 additions and 379950 deletions
+5
View File
@@ -14,3 +14,8 @@
/mob/camera/experience_pressure_difference()
return
/mob/camera/forceMove(atom/destination)
var/oldloc = loc
loc = destination
Moved(oldloc, NONE)
+1 -1
View File
@@ -15,7 +15,7 @@
onTransitZ(old_turf?.z, new_turf?.z)
var/oldloc = loc
loc = destination
Moved(oldloc, NONE, TRUE)
Moved(oldloc, NONE)
/mob/dead/onTransitZ(old_z,new_z)
..()
+3 -11
View File
@@ -23,7 +23,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
//If you died in the game and are a ghsot - this will remain as null.
//Note that this is not a reliable way to determine if admins started as observers, since they change mobs a lot.
universal_speak = TRUE
var/atom/movable/following = null
var/image/ghostimage = null //this mobs ghost image, for deleting and stuff
var/ghostvision = TRUE //is the ghost able to see things humans can't?
var/seedarkness = TRUE
@@ -54,7 +53,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
if(ismob(body))
T = get_turf(body) //Where is the body located?
attack_log_old = body.attack_log_old //preserve our attack logs by copying them to our ghost
logs = body.logs.Copy()
var/mutable_appearance/MA = copy_appearance(body)
if(body.mind && body.mind.name)
@@ -230,7 +228,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Move(NewLoc, direct)
update_parallax_contents()
following = null
setDir(direct)
ghostimage.setDir(dir)
@@ -412,7 +409,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
forceMove(pick(L))
update_parallax_contents()
following = null
/mob/dead/observer/verb/follow()
set category = "Ghost"
@@ -424,7 +420,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
A.on_close(CALLBACK(src, .proc/ManualFollow))
// This is the ghost's follow verb with an argument
/mob/dead/observer/proc/ManualFollow(var/atom/movable/target)
/mob/dead/observer/proc/ManualFollow(atom/movable/target)
if(!target || !isobserver(usr))
return
@@ -432,7 +428,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return
if(target != src)
if(following && following == target)
if(orbiting && orbiting == target)
return
var/icon/I = icon(target.icon,target.icon_state,target.dir)
@@ -458,7 +454,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
else //Circular
rot_seg = 36 //360/10 bby, smooth enough aproximation of a circle
following = target
to_chat(src, "<span class='notice'>Now following [target]</span>")
orbit(target,orbitsize, FALSE, 20, rot_seg)
@@ -485,7 +480,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination.
A.forceMove(T)
M.update_parallax_contents()
following = null
return
to_chat(A, "This mob is not located in the game world.")
@@ -616,7 +610,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Topic(href, href_list)
if(usr != src)
return
..()
if(href_list["track"])
var/atom/target = locate(href_list["track"])
@@ -630,7 +623,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(href_list["jump"])
var/mob/target = locate(href_list["jump"])
var/mob/A = usr;
var/mob/A = usr
to_chat(A, "Teleporting to [target]...")
//var/mob/living/silicon/ai/A = locate(href_list["track2"]) in GLOB.mob_list
if(target && target != usr)
@@ -643,7 +636,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(!client)
return
forceMove(T)
following = null
if(href_list["reenter"])
reenter_corpse()
+1 -1
View File
@@ -135,7 +135,7 @@
if(message)
for(var/mob/M in GLOB.player_list)
if(istype(M, /mob/new_player))
if(isnewplayer(M))
continue
if(check_rights(R_ADMIN|R_MOD, 0, M) && M.get_preference(CHAT_DEAD)) // Show the emote to admins/mods
+4 -4
View File
@@ -47,7 +47,7 @@
. = trim(. + trim(msg))
. += "\""
/mob/proc/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
/mob/proc/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
if(!client)
return 0
@@ -74,7 +74,7 @@
return 0
var/speaker_name = speaker.name
if(ishuman(speaker))
if(use_voice && ishuman(speaker))
var/mob/living/carbon/human/H = speaker
speaker_name = H.GetVoice()
@@ -99,9 +99,9 @@
if(speaker == src)
to_chat(src, "<span class='warning'>You cannot hear yourself speak!</span>")
else
to_chat(src, "<span class='name'>[speaker_name]</span>[speaker.GetAltName()] talks but you cannot hear [speaker.p_them()].")
to_chat(src, "<span class='name'>[speaker.name]</span> talks but you cannot hear [speaker.p_them()].")
else
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[speaker.GetAltName()] [track][message]</span>")
to_chat(src, "<span class='game say'><span class='name'>[speaker_name]</span>[use_voice ? speaker.GetAltName() : ""] [track][message]</span>")
if(speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
playsound_local(source, speech_sound, sound_vol, 1, sound_frequency)
+1 -12
View File
@@ -33,7 +33,7 @@
for(var/i = 0;i<name_count;i++)
new_name = ""
for(var/x = rand(Floor(syllable_count/2),syllable_count);x>0;x--)
for(var/x = rand(FLOOR(syllable_count/2, 1),syllable_count);x>0;x--)
new_name += pick(syllables)
full_name += " [capitalize(lowertext(new_name))]"
@@ -767,17 +767,6 @@
desc = "Bark bark bark."
key = "vu"
/datum/language/zombie
name = "Zombie"
desc = "BRAAAAAAINS!"
speech_verb = "moans"
whisper_verb = "mutters"
exclaim_verb = "wails"
colour = "zombie"
key = "zom"
flags = RESTRICTED
syllables = list("BRAAAAAAAAAAAAAAAAINS", "BRAAINS", "BRAINS")
/mob/proc/grant_all_babel_languages()
for(var/la in GLOB.all_languages)
var/datum/language/new_language = GLOB.all_languages[la]
@@ -2,6 +2,7 @@
name = "alien"
voice_name = "alien"
speak_emote = list("hisses")
bubble_icon = "alien"
icon = 'icons/mob/alien.dmi'
gender = NEUTER
dna = null
@@ -226,7 +227,7 @@ Des: Removes all infected images from the alien.
/mob/living/carbon/alien/handle_footstep(turf/T)
if(..())
if(T.footstep_sounds["xeno"])
if(T.footstep_sounds && T.footstep_sounds["xeno"])
var/S = pick(T.footstep_sounds["xeno"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
@@ -136,14 +136,11 @@ Doesn't work on other aliens/AI.*/
set category = "Alien"
if(powerc())
if(stomach_contents.len)
if(LAZYLEN(stomach_contents))
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.forceMove(loc)
//Paralyse(10)
src.visible_message("<span class='alertalien'><B>[src] hurls out the contents of [p_their()] stomach!</span>")
return
LAZYREMOVE(stomach_contents, M)
M.forceMove(drop_location())
visible_message("<span class='alertalien'><B>[src] hurls out the contents of [p_their()] stomach!</span>")
/mob/living/carbon/proc/getPlasma()
var/obj/item/organ/internal/xenos/plasmavessel/vessel = get_int_organ(/obj/item/organ/internal/xenos/plasmavessel)
@@ -167,4 +164,4 @@ Doesn't work on other aliens/AI.*/
adjustPlasma(-amount)
return 1
return 0
return 0
@@ -6,6 +6,7 @@
icon_state = "alienq_s"
status_flags = CANPARALYSE
mob_size = MOB_SIZE_LARGE
bubble_icon = "alienroyal"
large = 1
ventcrawler = 0
@@ -55,7 +55,7 @@
playsound(loc, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
visible_message("<span class='danger'>[M] has attempted to disarm [src]!</span>")
/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
/mob/living/carbon/alien/humanoid/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_CLAW
..()
@@ -31,7 +31,7 @@
step_away(src, user, 15)
return TRUE
/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
/mob/living/carbon/alien/larva/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!no_effect && !visual_effect_icon)
visual_effect_icon = ATTACK_EFFECT_BITE
..()
@@ -16,7 +16,7 @@
death()
return
if(paralysis || sleeping || getOxyLoss() > 50 || (HEALTH_THRESHOLD_CRIT <= health && check_death_method()))
if(paralysis || sleeping || getOxyLoss() > 50 || (health <= HEALTH_THRESHOLD_CRIT && check_death_method()))
if(stat == CONSCIOUS)
KnockOut()
create_debug_log("fell unconscious, trigger reason: [reason]")
@@ -226,13 +226,6 @@
brainmob.emp_damage += rand(0,10)
..()
/obj/item/mmi/relaymove(var/mob/user, var/direction)
if(user.stat || user.stunned)
return
var/obj/item/rig/rig = src.get_rig()
if(rig)
rig.forced_move(direction, user)
/obj/item/mmi/Destroy()
if(isrobot(loc))
var/mob/living/silicon/robot/borg = loc
+66 -49
View File
@@ -2,6 +2,10 @@
var/canEnterVentWith = "/obj/item/implant=0&/obj/item/clothing/mask/facehugger=0&/obj/item/radio/borg=0&/obj/machinery/camera=0"
var/datum/middleClickOverride/middleClickOverride = null
/mob/living/carbon/Initialize(mapload)
. = ..()
GLOB.carbon_list += src
/mob/living/carbon/Destroy()
// This clause is here due to items falling off from limb deletion
for(var/obj/item in get_all_slots())
@@ -14,11 +18,11 @@
if(B)
B.leave_host()
qdel(B)
GLOB.carbon_list -= src
return ..()
/mob/living/carbon/handle_atom_del(atom/A)
if(A in processing_patches)
processing_patches -= A
LAZYREMOVE(processing_patches, A)
return ..()
/mob/living/carbon/blob_act(obj/structure/blob/B)
@@ -46,41 +50,40 @@
/mob/living/carbon/var/last_stomach_attack //defining this here because no one would look in carbon_defines for it
/mob/living/carbon/relaymove(var/mob/user, direction)
if(user in src.stomach_contents)
if(last_stomach_attack + STOMACH_ATTACK_DELAY > world.time) return
/mob/living/carbon/relaymove(mob/user, direction)
if(LAZYLEN(stomach_contents))
if(user in stomach_contents)
if(last_stomach_attack + STOMACH_ATTACK_DELAY > world.time)
return
last_stomach_attack = world.time
for(var/mob/M in hearers(4, src))
if(M.client)
M.show_message(text("<span class='warning'>You hear something rumbling inside [src]'s stomach...</span>"), 2)
var/obj/item/I = user.get_active_hand()
if(I && I.force)
var/d = rand(round(I.force / 4), I.force)
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/organ = H.get_organ("chest")
if(istype(organ))
if(organ.receive_damage(d, 0))
H.UpdateDamageIcon()
H.updatehealth("stomach attack")
else
src.take_organ_damage(d)
for(var/mob/M in viewers(user, null))
last_stomach_attack = world.time
for(var/mob/M in hearers(4, src))
if(M.client)
M.show_message(text("<span class='warning'><B>[user] attacks [src]'s stomach wall with the [I.name]!</span>"), 2)
playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
M.show_message(text("<span class='warning'>You hear something rumbling inside [src]'s stomach...</span>"), 2)
if(prob(src.getBruteLoss() - 50))
for(var/atom/movable/A in stomach_contents)
A.forceMove(drop_location())
stomach_contents.Remove(A)
src.gib()
var/obj/item/I = user.get_active_hand()
if(I && I.force)
var/d = rand(round(I.force / 4), I.force)
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
var/obj/item/organ/external/organ = H.get_organ("chest")
if(istype(organ))
if(organ.receive_damage(d, 0))
H.UpdateDamageIcon()
H.updatehealth("stomach attack")
else
take_organ_damage(d)
for(var/mob/M in viewers(user, null))
if(M.client)
M.show_message(text("<span class='warning'><B>[user] attacks [src]'s stomach wall with the [I.name]!</span>"), 2)
playsound(user.loc, 'sound/effects/attackblob.ogg', 50, 1)
if(prob(getBruteLoss() - 50))
gib()
#undef STOMACH_ATTACK_DELAY
@@ -135,9 +138,8 @@
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
for(var/mob/M in src)
if(M in src.stomach_contents)
src.stomach_contents.Remove(M)
M.forceMove(get_turf(src))
LAZYREMOVE(stomach_contents, M)
M.forceMove(drop_location())
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
/mob/living/carbon/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = FALSE, override = FALSE, tesla_shock = FALSE, illusion = FALSE, stun = TRUE)
@@ -870,7 +872,6 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
unEquip(I)
I.dropped()
return
return 1
else
to_chat(src, "<span class='warning'>You fail to remove [I]!</span>")
@@ -977,25 +978,30 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
/mob/living/carbon/proc/slip(description, stun, weaken, tilesSlipped, walkSafely, slipAny, slipVerb = "slip")
if(flying || buckled || (walkSafely && m_intent == MOVE_INTENT_WALK))
return 0
return FALSE
if((lying) && (!(tilesSlipped)))
return 0
return FALSE
if(!(slipAny))
if(istype(src, /mob/living/carbon/human))
var/mob/living/carbon/human/H = src
if(isobj(H.shoes) && H.shoes.flags & NOSLIP)
return 0
return FALSE
if(tilesSlipped)
for(var/t = 0, t<=tilesSlipped, t++)
spawn (t) step(src, src.dir)
for(var/i in 1 to tilesSlipped)
spawn(i)
step(src, dir)
stop_pulling()
to_chat(src, "<span class='notice'>You [slipVerb]ped on [description]!</span>")
playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3)
playsound(loc, 'sound/misc/slip.ogg', 50, 1, -3)
// Something something don't run with scissors
moving_diagonally = 0 //If this was part of diagonal move slipping will stop it.
Stun(stun)
Weaken(weaken)
return 1
return TRUE
/mob/living/carbon/proc/can_eat(flags = 255)
return 1
@@ -1060,10 +1066,6 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, list(/obj/machinery/atmospherics/unary/ven
/mob/living/carbon/proc/forceFedAttackLog(var/obj/item/reagent_containers/food/toEat, mob/user)
add_attack_logs(user, src, "Fed [toEat]. Reagents: [toEat.reagents.log_list(toEat)]", toEat.reagents.harmless_helper() ? ATKLOG_ALMOSTALL : null)
if(!iscarbon(user))
LAssailant = null
else
LAssailant = user
/*TO DO - If/when stomach organs are introduced, override this at the human level sending the item to the stomach
@@ -1196,3 +1198,18 @@ so that different stomachs can handle things in different ways VB*/
I.acid_level = 0 //washes off the acid on our clothes
I.extinguish() //extinguishes our clothes
..()
/mob/living/carbon/clean_blood(clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
if(head)
if(head.clean_blood())
update_inv_head()
if(head.flags_inv & HIDEMASK)
clean_mask = FALSE
if(wear_suit)
if(wear_suit.clean_blood())
update_inv_wear_suit()
if(wear_suit.flags_inv & HIDESHOES)
clean_feet = FALSE
if(wear_suit.flags_inv & HIDEGLOVES)
clean_hands = FALSE
..(clean_hands, clean_mask, clean_feet)
@@ -12,7 +12,7 @@
visible_message("<span class='warning'>[src] catches [AM]!</span>")
throw_mode_off()
return TRUE
..()
return ..()
/mob/living/carbon/water_act(volume, temperature, source, method = REAGENT_TOUCH)
. = ..()
@@ -1,11 +1,10 @@
/mob/living/carbon
gender = MALE
pressure_resistance = 15
var/list/stomach_contents = list()
var/list/processing_patches = list()
var/list/stomach_contents
var/list/processing_patches
var/list/internal_organs = list()
var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
var/antibodies = 0
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
@@ -1,17 +1,5 @@
GLOBAL_LIST_INIT(body_accessory_by_name, list("None" = null))
/hook/startup/proc/initalize_body_accessories()
__init_body_accessory(/datum/body_accessory/body)
__init_body_accessory(/datum/body_accessory/tail)
if(GLOB.body_accessory_by_name.len)
if(initialize_body_accessory_by_species())
return TRUE
return FALSE //fail if no bodies are found
GLOBAL_LIST_INIT(body_accessory_by_species, list("None" = null))
/proc/initialize_body_accessory_by_species()
+4 -13
View File
@@ -6,7 +6,7 @@
canmove = 0
icon = null
invisibility = 101
if(!isSynthetic())
if(!ismachineperson(src))
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
@@ -32,12 +32,11 @@
E.droplimb(DROPLIMB_SHARP)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.forceMove(get_turf(src))
LAZYREMOVE(stomach_contents, M)
M.forceMove(drop_location())
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
if(!isSynthetic())
if(!ismachineperson(src))
flick("gibbed-h", animation)
hgibs(loc, dna)
else
@@ -106,18 +105,10 @@
//Handle species-specific deaths.
dna.species.handle_death(gibbed, src)
if(ishuman(LAssailant))
var/mob/living/carbon/human/H=LAssailant
if(H.mind)
H.mind.kills += "[key_name(src)]"
if(SSticker && SSticker.mode)
// log_world("k")
sql_report_death(src)
if(wearing_rig)
wearing_rig.notify_ai("<span class='danger'>Warning: user death event. Mobility control passed to integrated intelligence system.</span>")
/mob/living/carbon/human/update_revive()
. = ..()
if(. && healthdoll)
+16 -8
View File
@@ -34,7 +34,7 @@
//Cooldown-inducing emotes
if("ping", "pings", "buzz", "buzzes", "beep", "beeps", "yes", "no", "buzz2")
var/found_machine_head = FALSE
if(ismachine(src)) //Only Machines can beep, ping, and buzz, yes, no, and make a silly sad trombone noise.
if(ismachineperson(src)) //Only Machines can beep, ping, and buzz, yes, no, and make a silly sad trombone noise.
on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm
found_machine_head = TRUE
else
@@ -139,10 +139,18 @@
//WHO THE FUCK THOUGHT THAT WAS A GOOD FUCKING IDEA!?!?
if("howl", "howls")
var/M = handle_emote_param(param) //Check to see if the param is valid (mob with the param name is in view).
message = "<B>[src]</B> howls[M ? " at [M]" : ""]!"
playsound(loc, 'sound/goonstation/voice/howl.ogg', 100, 1, 10, frequency = get_age_pitch())
m_type = 2
var/M = handle_emote_param(param)
if(miming)
message = "<B>[src]</B> acts out a howl[M ? " at [M]" : ""]!"
m_type = 1
else
if(!muzzled)
message = "<B>[src]</B> howls[M ? " at [M]" : ""]!"
playsound(loc, 'sound/goonstation/voice/howl.ogg', 100, 1, 10, frequency = get_age_pitch())
m_type = 2
else
message = "<B>[src]</B> makes a very loud noise[M ? " at [M]" : ""]."
m_type = 2
if("growl", "growls")
var/M = handle_emote_param(param)
@@ -300,14 +308,14 @@
m_type = 1
if("bow", "bows")
if(!buckled)
if(!restrained())
var/M = handle_emote_param(param)
message = "<B>[src]</B> bows[M ? " to [M]" : ""]."
m_type = 1
if("salute", "salutes")
if(!buckled)
if(!restrained())
var/M = handle_emote_param(param)
message = "<B>[src]</B> salutes[M ? " to [M]" : ""]."
@@ -939,7 +947,7 @@
if("Skrell")
emotelist += "\nSkrell specific emotes :- warble(s)"
if(ismachine(src))
if(ismachineperson(src))
emotelist += "\nMachine specific emotes :- beep(s)-(none)/mob, buzz(es)-none/mob, no-(none)/mob, ping(s)-(none)/mob, yes-(none)/mob, buzz2-(none)/mob"
else
var/obj/item/organ/external/head/H = get_organ("head") // If you have a robotic head, you can make beep-boop noises
@@ -208,7 +208,7 @@
if(!E)
wound_flavor_text["[organ_tag]"] = "<B>[p_they(TRUE)] [p_are()] missing [p_their()] [organ_descriptor].</B>\n"
else
if(!isSynthetic())
if(!ismachineperson(src))
if(E.is_robotic())
wound_flavor_text["[E.limb_name]"] = "[p_they(TRUE)] [p_have()] a robotic [E.name]!\n"
@@ -252,7 +252,7 @@
var/temp = getBruteLoss() //no need to calculate each of these twice
if(temp)
var/brute_message = !isSynthetic() ? "bruising" : "denting"
var/brute_message = !ismachineperson(src) ? "bruising" : "denting"
if(temp < 30)
msg += "[p_they(TRUE)] [p_have()] minor [brute_message ].\n"
else
@@ -301,13 +301,13 @@
else if(nutrition >= NUTRITION_LEVEL_FAT)
msg += "[p_they(TRUE)] [p_are()] quite chubby.\n"
if(!isSynthetic() && blood_volume < BLOOD_VOLUME_SAFE)
if(!ismachineperson(src) && blood_volume < BLOOD_VOLUME_SAFE)
msg += "[p_they(TRUE)] [p_have()] pale skin.\n"
if(bleedsuppress)
msg += "[p_they(TRUE)] [p_are()] bandaged with something.\n"
else if(bleed_rate)
var/bleed_message = !isSynthetic() ? "bleeding" : "leaking"
var/bleed_message = !ismachineperson(src) ? "bleeding" : "leaking"
msg += "<B>[p_they(TRUE)] [p_are()] [bleed_message]!</B>\n"
if(reagents.has_reagent("teslium"))
@@ -341,7 +341,7 @@
if(decaylevel == 3)
msg += "[p_they(TRUE)] [p_are()] rotting and blackened, the skin sloughing off. The smell is indescribably foul.\n"
if(decaylevel == 4)
msg += "[p_they(TRUE)] [p_are()] mostly dessicated now, with only bones remaining of what used to be a person.\n"
msg += "[p_they(TRUE)] [p_are()] mostly desiccated now, with only bones remaining of what used to be a person.\n"
if(hasHUD(user,"security"))
var/perpname = get_visible_name(TRUE)
+31 -59
View File
@@ -5,7 +5,6 @@
icon = 'icons/mob/human.dmi'
icon_state = "body_m_s"
deathgasp_on_death = TRUE
var/obj/item/rig/wearing_rig // This is very not good, but it's much much better than calling get_rig() every update_canmove() call.
/mob/living/carbon/human/New(loc)
icon = null // This is now handled by overlays -- we just keep an icon for the sake of the map editor.
@@ -18,7 +17,7 @@
dna = new /datum/dna(null)
// Species name is handled by set_species()
..()
. = ..()
set_species(new_species, 1, delay_icon_update = 1, skip_same_check = TRUE)
@@ -41,6 +40,7 @@
sync_organ_dna(1)
UpdateAppearance()
GLOB.human_list += src
/mob/living/carbon/human/OpenCraftingMenu()
handcrafting.ui_interact(src)
@@ -60,61 +60,62 @@
SSmobs.cubemonkeys -= src
QDEL_LIST(bodyparts)
splinted_limbs.Cut()
GLOB.human_list -= src
/mob/living/carbon/human/dummy
real_name = "Test Dummy"
status_flags = GODMODE|CANPUSH
/mob/living/carbon/human/skrell/Initialize(mapload)
..(mapload, /datum/species/skrell)
. = ..(mapload, /datum/species/skrell)
/mob/living/carbon/human/tajaran/Initialize(mapload)
..(mapload, /datum/species/tajaran)
. = ..(mapload, /datum/species/tajaran)
/mob/living/carbon/human/vulpkanin/Initialize(mapload)
..(mapload, /datum/species/vulpkanin)
. = ..(mapload, /datum/species/vulpkanin)
/mob/living/carbon/human/unathi/Initialize(mapload)
..(mapload, /datum/species/unathi)
. = ..(mapload, /datum/species/unathi)
/mob/living/carbon/human/vox/Initialize(mapload)
..(mapload, /datum/species/vox)
. = ..(mapload, /datum/species/vox)
/mob/living/carbon/human/voxarmalis/Initialize(mapload)
..(mapload, /datum/species/vox/armalis)
. = ..(mapload, /datum/species/vox/armalis)
/mob/living/carbon/human/skeleton/Initialize(mapload)
..(mapload, /datum/species/skeleton)
. = ..(mapload, /datum/species/skeleton)
/mob/living/carbon/human/kidan/Initialize(mapload)
..(mapload, /datum/species/kidan)
. = ..(mapload, /datum/species/kidan)
/mob/living/carbon/human/plasma/Initialize(mapload)
..(mapload, /datum/species/plasmaman)
. = ..(mapload, /datum/species/plasmaman)
/mob/living/carbon/human/slime/Initialize(mapload)
..(mapload, /datum/species/slime)
. = ..(mapload, /datum/species/slime)
/mob/living/carbon/human/grey/Initialize(mapload)
..(mapload, /datum/species/grey)
. = ..(mapload, /datum/species/grey)
/mob/living/carbon/human/abductor/Initialize(mapload)
..(mapload, /datum/species/abductor)
. = ..(mapload, /datum/species/abductor)
/mob/living/carbon/human/diona/Initialize(mapload)
..(mapload, /datum/species/diona)
. = ..(mapload, /datum/species/diona)
/mob/living/carbon/human/pod_diona/Initialize(mapload)
..(mapload, /datum/species/diona/pod)
. = ..(mapload, /datum/species/diona/pod)
/mob/living/carbon/human/machine/Initialize(mapload)
..(mapload, /datum/species/machine)
. = ..(mapload, /datum/species/machine)
/mob/living/carbon/human/machine/created
name = "Integrated Robotic Chassis"
/mob/living/carbon/human/machine/created/Initialize(mapload)
..()
. = ..()
rename_character(null, "Integrated Robotic Chassis ([rand(1, 9999)])")
update_dna()
for(var/obj/item/organ/external/E in bodyparts)
@@ -127,34 +128,34 @@
death()
/mob/living/carbon/human/shadow/Initialize(mapload)
..(mapload, /datum/species/shadow)
. = ..(mapload, /datum/species/shadow)
/mob/living/carbon/human/golem/Initialize(mapload)
..(mapload, /datum/species/golem)
. = ..(mapload, /datum/species/golem)
/mob/living/carbon/human/wryn/Initialize(mapload)
..(mapload, /datum/species/wryn)
. = ..(mapload, /datum/species/wryn)
/mob/living/carbon/human/nucleation/Initialize(mapload)
..(mapload, /datum/species/nucleation)
. = ..(mapload, /datum/species/nucleation)
/mob/living/carbon/human/drask/Initialize(mapload)
..(mapload, /datum/species/drask)
. = ..(mapload, /datum/species/drask)
/mob/living/carbon/human/monkey/Initialize(mapload)
..(mapload, /datum/species/monkey)
. = ..(mapload, /datum/species/monkey)
/mob/living/carbon/human/farwa/Initialize(mapload)
..(mapload, /datum/species/monkey/tajaran)
. = ..(mapload, /datum/species/monkey/tajaran)
/mob/living/carbon/human/wolpin/Initialize(mapload)
..(mapload, /datum/species/monkey/vulpkanin)
. = ..(mapload, /datum/species/monkey/vulpkanin)
/mob/living/carbon/human/neara/Initialize(mapload)
..(mapload, /datum/species/monkey/skrell)
. = ..(mapload, /datum/species/monkey/skrell)
/mob/living/carbon/human/stok/Initialize(mapload)
..(mapload, /datum/species/monkey/unathi)
. = ..(mapload, /datum/species/monkey/unathi)
/mob/living/carbon/human/Stat()
..()
@@ -180,13 +181,6 @@
stat("Tank Pressure", internal.air_contents.return_pressure())
stat("Distribution Pressure", internal.distribute_pressure)
if(istype(back, /obj/item/rig))
var/obj/item/rig/suit = back
var/cell_status = "ERROR"
if(suit.cell)
cell_status = "[suit.cell.charge]/[suit.cell.maxcharge]"
stat(null, "Suit charge: [cell_status]")
// I REALLY need to split up status panel things into datums
var/mob/living/simple_animal/borer/B = has_brain_worms()
if(B && B.controlling)
@@ -961,16 +955,6 @@
var/obj/item/clothing/mask/MT = src.wear_mask
tinted += MT.tint
//god help me
if(istype(back, /obj/item/rig))
var/obj/item/rig/O = back
if(O.helmet && O.helmet == head && (O.helmet.body_parts_covered & HEAD))
if((O.offline && O.offline_vision_restriction == 1) || (!O.offline && O.vision_restriction == 1))
tinted = 2
if((O.offline && O.offline_vision_restriction == 2) || (!O.offline && O.vision_restriction == 2))
tinted = 3
//im so sorry
return tinted
@@ -1160,18 +1144,6 @@
custom_pain("You feel a stabbing pain in your chest!")
L.damage = L.min_bruised_damage
//returns 1 if made bloody, returns 0 otherwise
/mob/living/carbon/human/clean_blood(var/clean_feet)
.=..()
if(clean_feet && !shoes && istype(feet_blood_DNA, /list) && feet_blood_DNA.len)
feet_blood_color = null
qdel(feet_blood_DNA)
bloody_feet = list(BLOOD_STATE_HUMAN = 0, BLOOD_STATE_XENO = 0, BLOOD_STATE_NOT_BLOODY = 0)
blood_state = BLOOD_STATE_NOT_BLOODY
update_inv_shoes()
return 1
/mob/living/carbon/human/cuff_resist(obj/item/I)
if(HULK in mutations)
say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ))
@@ -1699,14 +1671,14 @@ Eyes need to have significantly high darksight to shine unless the mob has the X
/mob/living/carbon/human/forceFed(var/obj/item/reagent_containers/food/toEat, mob/user, fullness)
if(!check_has_mouth())
if(!((istype(toEat, /obj/item/reagent_containers/food/drinks) && (ismachine(src)))))
if(!((istype(toEat, /obj/item/reagent_containers/food/drinks) && (ismachineperson(src)))))
to_chat(user, "Where do you intend to put \the [toEat]? \The [src] doesn't have a mouth!")
return 0
return ..()
/mob/living/carbon/human/selfDrink(var/obj/item/reagent_containers/food/drinks/toDrink)
if(!check_has_mouth())
if(!ismachine(src))
if(!ismachineperson(src))
to_chat(src, "Where do you intend to put \the [src]? You don't have a mouth!")
return 0
else
@@ -30,7 +30,7 @@
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
sponge.damage = Clamp(sponge.damage + amount, 0, 120)
sponge.damage = clamp(sponge.damage + amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
@@ -48,7 +48,7 @@
if(dna.species && amount > 0)
if(use_brain_mod)
amount = amount * dna.species.brain_mod
sponge.damage = Clamp(amount, 0, 120)
sponge.damage = clamp(amount, 0, 120)
if(sponge.damage >= 120)
visible_message("<span class='alert'><B>[src]</B> goes limp, [p_their()] facial expression utterly blank.</span>")
death()
@@ -129,13 +129,6 @@
O.heal_damage(0, -amount, internal = 0, robo_repair = O.is_robotic(), updating_health = updating_health)
return STATUS_UPDATE_HEALTH
/mob/living/carbon/human/Paralyse(amount)
// Notify our AI if they can now control the suit.
if(wearing_rig && !stat && paralysis < amount) //We are passing out right this second.
wearing_rig.notify_ai("<span class='danger'>Warning: user consciousness failure. Mobility control passed to integrated intelligence system.</span>")
return ..()
/mob/living/carbon/human/adjustCloneLoss(amount)
if(dna.species && amount > 0)
amount = amount * dna.species.clone_mod
@@ -342,7 +335,5 @@ This function restores all organs.
..(damage, damagetype, def_zone, blocked)
return 1
//Handle BRUTE and BURN damage
handle_suit_punctures(damagetype, damage)
//Handle species apply_damage procs
return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, sharp, used_weapon)
@@ -84,7 +84,7 @@ emp_act
E.heal_damage(rembrute,0,0,1)
rembrute = nrembrute
user.visible_message("<span class='alert'>[user] patches some dents on [src]'s [E.name] with [I].</span>")
if(bleed_rate && isSynthetic())
if(bleed_rate && ismachineperson(src))
bleed_rate = 0
user.visible_message("<span class='alert'>[user] patches some leaks on [src] with [I].</span>")
if(IgniteMob())
@@ -134,7 +134,7 @@ emp_act
if(bp && istype(bp ,/obj/item/clothing))
var/obj/item/clothing/C = bp
if(C.body_parts_covered & def_zone.body_part)
protection += C.armor[type]
protection += C.armor.getRating(type)
return protection
@@ -185,19 +185,19 @@ emp_act
var/block_chance_modifier = round(damage / -3)
if(l_hand && !istype(l_hand, /obj/item/clothing))
var/final_block_chance = l_hand.block_chance - (Clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
var/final_block_chance = l_hand.block_chance - (clamp((armour_penetration-l_hand.armour_penetration)/2,0,100)) + block_chance_modifier //So armour piercing blades can still be parried by other blades, for example
if(l_hand.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(r_hand && !istype(r_hand, /obj/item/clothing))
var/final_block_chance = r_hand.block_chance - (Clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
var/final_block_chance = r_hand.block_chance - (clamp((armour_penetration-r_hand.armour_penetration)/2,0,100)) + block_chance_modifier //Need to reset the var so it doesn't carry over modifications between attempts
if(r_hand.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(wear_suit)
var/final_block_chance = wear_suit.block_chance - (Clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
var/final_block_chance = wear_suit.block_chance - (clamp((armour_penetration-wear_suit.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_suit.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
if(w_uniform)
var/final_block_chance = w_uniform.block_chance - (Clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
var/final_block_chance = w_uniform.block_chance - (clamp((armour_penetration-w_uniform.armour_penetration)/2,0,100)) + block_chance_modifier
if(w_uniform.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return 1
return 0
@@ -387,11 +387,6 @@ emp_act
to_chat(user, "<span class='warning'>You hack off a chunk of meat from [name]</span>")
if(!meatleft)
add_attack_logs(user, src, "Chopped up into meat")
if(!iscarbon(user))
LAssailant = null
else
LAssailant = user
qdel(src)
var/obj/item/organ/external/affecting = get_organ(ran_zone(user.zone_selected))
@@ -536,17 +531,6 @@ emp_act
w_uniform.add_mob_blood(source)
update_inv_w_uniform()
/mob/living/carbon/human/proc/handle_suit_punctures(var/damtype, var/damage)
if(!wear_suit) return
if(!istype(wear_suit,/obj/item/clothing/suit/space)) return
if(damtype != BURN && damtype != BRUTE) return
var/obj/item/clothing/suit/space/SS = wear_suit
var/penetrated_dam = max(0,(damage - max(0,(SS.breach_threshold - SS.damage))))
if(penetrated_dam) SS.create_breaches(damtype, penetrated_dam)
/mob/living/carbon/human/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE)
if(user.a_intent == INTENT_HARM)
if(HAS_TRAIT(user, TRAIT_PACIFISM))
@@ -37,7 +37,6 @@ GLOBAL_DATUM_INIT(default_martial_art, /datum/martial_art, new())
var/obj/item/s_store = null
var/icon/stand_icon = null
var/icon/lying_icon = null
var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life()
@@ -16,12 +16,6 @@
else if(istype(wear_suit, /obj/item/clothing/suit/space/hardsuit))
var/obj/item/clothing/suit/space/hardsuit/C = wear_suit
thrust = C.jetpack
else if(istype(back,/obj/item/rig))
var/obj/item/rig/rig = back
for(var/obj/item/rig_module/maneuvering_jets/module in rig.installed_modules)
thrust = module.jets
break
if(thrust)
if((movement_dir || thrust.stabilizers) && thrust.allow_thrust(0.01, src))
return 1
@@ -81,7 +75,7 @@
/mob/living/carbon/human/handle_footstep(turf/T)
if(..())
if(T.footstep_sounds["human"])
if(T.footstep_sounds && T.footstep_sounds["human"])
var/S = pick(T.footstep_sounds["human"])
if(S)
if(m_intent == MOVE_INTENT_RUN)
+4 -12
View File
@@ -197,7 +197,7 @@
if(!(RADIMMUNE in dna.species.species_traits))
if(radiation)
radiation = Clamp(radiation, 0, 200)
radiation = clamp(radiation, 0, 200)
var/autopsy_damage = 0
switch(radiation)
@@ -302,14 +302,6 @@
if(!(head && head.flags & AIRTIGHT)) //if NOT (head AND head.flags CONTAIN AIRTIGHT)
null_internals = 1 //not wearing a mask or suitable helmet
if(istype(back, /obj/item/rig)) //wearing a rigsuit
var/obj/item/rig/rig = back //needs to be typecasted because this doesn't use get_rig() for some reason
if(rig.offline && (rig.air_supply && internal == rig.air_supply)) //if rig IS offline AND (rig HAS air_supply AND internal IS air_supply)
null_internals = 1 //offline suits do not breath
else if(rig.air_supply && internal == rig.air_supply) //if rig HAS air_supply AND internal IS rig air_supply
skip_contents_check = 1 //skip contents.Find() check, the oxygen is valid even being outside of the mob
if(!contents.Find(internal) && (!skip_contents_check)) //if internal NOT IN contents AND skip_contents_check IS false
null_internals = 1 //not a rigsuit and your oxygen is gone
@@ -635,7 +627,7 @@
else
overeatduration -= 2
if(!ismachine(src) && nutrition < NUTRITION_LEVEL_HYPOGLYCEMIA) //Gosh damn snowflakey IPCs
if(!ismachineperson(src) && nutrition < NUTRITION_LEVEL_HYPOGLYCEMIA) //Gosh damn snowflakey IPCs
var/datum/disease/D = new /datum/disease/critical/hypoglycemia
ForceContractDisease(D)
@@ -697,7 +689,7 @@
alcohol_strength /= sober_str
var/obj/item/organ/internal/liver/L
if(!isSynthetic())
if(!ismachineperson(src))
L = get_int_organ(/obj/item/organ/internal/liver)
if(L)
alcohol_strength *= L.alcohol_intensity
@@ -719,7 +711,7 @@
AdjustConfused(3 / sober_str)
if(alcohol_strength >= blur_start) //blurry eyes
EyeBlurry(10 / sober_str)
if(!isSynthetic()) //stuff only for non-synthetics
if(!ismachineperson(src)) //stuff only for non-synthetics
if(alcohol_strength >= vomit_start) //vomiting
if(prob(8))
fakevomit()
+1 -1
View File
@@ -7,7 +7,7 @@
species_exception = list(/datum/species/monkey)
/mob/living/carbon/human/monkey/punpun/Initialize(mapload)
..()
. = ..()
name = "Pun Pun"
real_name = name
equip_to_slot(new /obj/item/clothing/under/punpun(src), slot_w_uniform)
+1 -8
View File
@@ -62,11 +62,6 @@
return ..()
/mob/living/carbon/human/proc/HasVoiceChanger()
if(istype(back, /obj/item/rig))
var/obj/item/rig/rig = back
if(rig.speech && rig.speech.voice_holder && rig.speech.voice_holder.active && rig.speech.voice_holder.voice)
return rig.speech.voice_holder.voice
for(var/obj/item/gear in list(wear_mask, wear_suit, head))
if(!gear)
continue
@@ -134,11 +129,9 @@
S.message = "<span class='[span]'>[S.message]</span>"
verb = translator.speech_verb
return list("verb" = verb)
if(mind)
span = mind.speech_span
if((COMIC in mutations) \
|| (locate(/obj/item/organ/internal/cyberimp/brain/clown_voice) in internal_organs) \
|| GetComponent(/datum/component/jestosterone))
|| HAS_TRAIT(src, TRAIT_JESTER))
span = "sans"
if(WINGDINGS in mutations)
@@ -53,7 +53,6 @@
var/stun_mod = 1 // If a species is more/less impacated by stuns/weakens/paralysis
var/speed_mod = 0 // this affects the race's speed. positive numbers make it move slower, negative numbers make it move faster
var/blood_damage_type = OXY //What type of damage does this species take if it's low on blood?
var/obj/item/mutanthands
var/total_health = 100
var/punchdamagelow = 0 //lowest possible punch damage
var/punchdamagehigh = 9 //highest possible punch damage
@@ -346,30 +345,17 @@
switch(damagetype)
if(BRUTE)
H.damageoverlaytemp = 20
damage = damage * brute_mod
if(damage)
H.damageoverlaytemp = 20
if(organ.receive_damage(damage, 0, sharp, used_weapon))
H.UpdateDamageIcon()
if(H.LAssailant && ishuman(H.LAssailant)) //superheros still get the comical hit markers
var/mob/living/carbon/human/A = H.LAssailant
if(A.mind && (A.mind in (SSticker.mode.superheroes) || SSticker.mode.supervillains || SSticker.mode.greyshirts))
var/list/attack_bubble_recipients = list()
var/mob/living/user
for(var/mob/O in viewers(user, src))
if(O.client && O.has_vision(information_only=TRUE))
attack_bubble_recipients.Add(O.client)
spawn(0)
var/image/dmgIcon = image('icons/effects/hit_blips.dmi', src, "dmg[rand(1,2)]",MOB_LAYER+1)
dmgIcon.pixel_x = (!H.lying) ? rand(-3,3) : rand(-11,12)
dmgIcon.pixel_y = (!H.lying) ? rand(-11,9) : rand(-10,1)
flick_overlay(dmgIcon, attack_bubble_recipients, 9)
if(BURN)
H.damageoverlaytemp = 20
damage = damage * burn_mod
if(damage)
H.damageoverlaytemp = 20
if(organ.receive_damage(0, damage, sharp, used_weapon))
H.UpdateDamageIcon()
@@ -443,6 +429,9 @@
else
target.LAssailant = user
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
var/damage = rand(user.dna.species.punchdamagelow, user.dna.species.punchdamagehigh)
damage += attack.damage
if(!damage)
@@ -530,9 +519,6 @@
/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art) //Handles any species-specific attackhand events.
if(!istype(M))
return
if(H.frozen)
to_chat(M, "<span class='warning'>Do not touch Admin-Frozen people.</span>")
return
if(istype(M))
var/obj/item/organ/external/temp = M.bodyparts_by_name["r_hand"]
@@ -828,20 +814,6 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(!isnull(hat.lighting_alpha))
H.lighting_alpha = min(hat.lighting_alpha, H.lighting_alpha)
if(istype(H.back, /obj/item/rig)) ///aghhh so snowflakey
var/obj/item/rig/rig = H.back
if(rig.visor)
if(!rig.helmet || (H.head && rig.helmet == H.head))
if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
var/obj/item/clothing/glasses/G = rig.visor.vision.glasses
if(istype(G))
H.sight |= G.vision_flags
H.see_in_dark = max(G.see_in_dark, H.see_in_dark)
H.see_invisible = min(G.invis_view, H.see_invisible)
if(!isnull(G.lighting_alpha))
H.lighting_alpha = min(G.lighting_alpha, H.lighting_alpha)
if(H.vision_type)
H.sight |= H.vision_type.sight_flags
H.see_in_dark = max(H.see_in_dark, H.vision_type.see_in_dark)
@@ -636,12 +636,11 @@
H.mutations.Add(COMIC)
H.equip_to_slot_or_del(new /obj/item/reagent_containers/food/drinks/bottle/bottleofbanana(H), slot_r_store)
H.equip_to_slot_or_del(new /obj/item/bikehorn(H), slot_l_store)
H.AddComponent(/datum/component/waddling)
H.AddElement(/datum/element/waddling)
/datum/species/golem/bananium/on_species_loss(mob/living/carbon/C)
. = ..()
GET_COMPONENT_FROM(waddling, /datum/component/waddling, C)
waddling.Destroy()
C.RemoveElement(/datum/element/waddling)
/datum/species/golem/bananium/get_random_name()
var/clown_name = pick(GLOB.clown_names)
@@ -39,10 +39,10 @@
/datum/action/innate/shadow/darkvision/Activate()
var/mob/living/carbon/human/H = owner
if(!H.vision_type)
H.vision_type = new /datum/vision_override/nightvision
H.set_sight(/datum/vision_override/nightvision)
to_chat(H, "<span class='notice'>You adjust your vision to pierce the darkness.</span>")
else
H.vision_type = null
H.set_sight(null)
to_chat(H, "<span class='notice'>You adjust your vision to recognize the shadows.</span>")
/datum/species/shadow/on_species_gain(mob/living/carbon/human/H)
@@ -1,102 +0,0 @@
#define REGENERATION_DELAY 60 // After taking damage, how long it takes for automatic regeneration to begin
/datum/species/zombie
// 1spooky
name = "High-Functioning Zombie"
name_plural = "High-Functioning Zombies"
icobase = 'icons/mob/human_races/r_zombie.dmi'
deform = 'icons/mob/human_races/r_def_zombie.dmi'
dies_at_threshold = TRUE
language = "Zombie"
species_traits = list(NO_BLOOD, NOZOMBIE, NOTRANSSTING, NO_BREATHE, RADIMMUNE, NO_SCAN)
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')
warning_low_pressure = -1
hazard_low_pressure = -1
hazard_high_pressure = 999999999
warning_high_pressure = 999999999
cold_level_1 = -1
cold_level_2 = -1
cold_level_3 = -1
tox_mod = 0
flesh_color = "#00FF00" // for green examine text
bodyflags = HAS_SKIN_COLOR
dietflags = DIET_CARN
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"liver" = /obj/item/organ/internal/liver,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"ears" = /obj/item/organ/internal/ears)
/datum/species/zombie/infectious
name = "Infectious Zombie"
mutanthands = /obj/item/zombie_hand
icobase = 'icons/mob/human_races/r_zombie.dmi'
deform = 'icons/mob/human_races/r_def_zombie.dmi'
brute_mod = 0.8 // 120 damage to KO a zombie, which kills it
burn_mod = 0.8
clone_mod = 0.8
brain_mod = 0.8
stamina_mod = 0.8
speed_mod = 1.6
default_language = "Zombie"
var/heal_rate = 1
var/regen_cooldown = 0
/datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H, amount)
. = min(20, amount)
/datum/species/zombie/infectious/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, sharp = 0, obj/used_weapon = null)
. = ..()
if(damage)
regen_cooldown = world.time + REGENERATION_DELAY
/datum/species/zombie/infectious/handle_life(mob/living/carbon/human/H)
. = ..()
H.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW
//Zombies never actually die, they just fall down until they regenerate enough to rise back up.
//They must be restrained, beheaded or gibbed to stop being a threat.
if(regen_cooldown < world.time)
var/heal_amt = heal_rate
if(H.InCritical())
heal_amt *= 2
H.heal_overall_damage(heal_amt,heal_amt)
H.adjustToxLoss(-heal_amt)
if(!H.InCritical() && prob(4))
playsound(H, pick(spooks), 50, TRUE, 10)
//Congrats you somehow died so hard you stopped being a zombie
/datum/species/zombie/infectious/handle_death(gibbed, mob/living/carbon/C)
. = ..()
var/obj/item/organ/internal/zombie_infection/infection
infection = C.get_organ_slot("zombie_infection")
if(infection)
qdel(infection)
/datum/species/zombie/infectious/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
. = ..()
// Deal with the source of this zombie corruption
// Infection organ needs to be handled separately from mutant_organs
// because it persists through species transitions
if(mutanthands)
H.drop_l_hand()
H.drop_r_hand()
H.put_in_hands(new mutanthands())
H.put_in_hands(new mutanthands())
var/obj/item/organ/internal/zombie_infection/infection
infection = H.get_organ_slot("zombie_infection")
if(!infection)
infection = new()
infection.insert(H)
/datum/species/zombie/infectious/on_species_loss(mob/living/carbon/human/C, datum/species/old_species)
QDEL_NULL(C.r_hand)
QDEL_NULL(C.l_hand)
return ..()
#undef REGENERATION_DELAY
@@ -273,10 +273,10 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
overlays_standing[UNDERWEAR_LAYER] = mutable_appearance(underwear_standing, layer = -UNDERWEAR_LAYER)
apply_overlay(UNDERWEAR_LAYER)
if(lip_style && (LIPS in dna.species.species_traits))
var/icon/lips = icon("icon" = 'icons/mob/human_face.dmi', "icon_state" = "lips_[lip_style]_s")
lips.Blend(lip_color, ICON_ADD)
standing += mutable_appearance(lips, layer = -BODY_LAYER)
if(lip_style && (LIPS in dna.species.species_traits))
var/mutable_appearance/lips = mutable_appearance('icons/mob/human_face.dmi', "lips_[lip_style]_s")
lips.color = lip_color
standing += lips
overlays_standing[BODY_LAYER] = standing
apply_overlay(BODY_LAYER)
@@ -376,7 +376,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
//base icons
var/icon/hair_standing = new /icon('icons/mob/human_face.dmi',"bald_s")
if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(isSynthetic())))
if(head_organ.h_style && !(head && (head.flags & BLOCKHEADHAIR) && !(ismachineperson(src))))
var/datum/sprite_accessory/hair/hair_style = GLOB.hair_styles_full_list[head_organ.h_style]
if(hair_style && hair_style.species_allowed)
if((head_organ.dna.species.name in hair_style.species_allowed) || (head_organ.dna.species.bodyflags & ALL_RPARTS)) //If the head's species is in the list of allowed species for the hairstyle, or the head's species is one flagged to have bodies comprised wholly of cybernetics...
@@ -964,10 +964,6 @@ GLOBAL_LIST_EMPTY(damage_icon_parts)
var/mutable_appearance/standing
if(back.icon_override)
standing = mutable_appearance(back.icon_override, "[back.icon_state]", layer = -BACK_LAYER)
else if(istype(back, /obj/item/rig))
//If this is a rig and a mob_icon is set, it will take species into account in the rig update_icon() proc.
var/obj/item/rig/rig = back
standing = rig.mob_icon
else if(back.sprite_sheets && back.sprite_sheets[dna.species.name])
standing = mutable_appearance(back.sprite_sheets[dna.species.name], "[back.icon_state]", layer = -BACK_LAYER)
else
+21 -18
View File
@@ -11,6 +11,10 @@
if(stat != DEAD)
handle_organs()
//stuff in the stomach
if(LAZYLEN(stomach_contents))
handle_stomach(times_fired)
. = ..()
if(QDELETED(src))
@@ -122,7 +126,7 @@
var/O2_partialpressure = (breath.oxygen/breath.total_moles())*breath_pressure
var/Toxins_partialpressure = (breath.toxins/breath.total_moles())*breath_pressure
var/CO2_partialpressure = (breath.carbon_dioxide/breath.total_moles())*breath_pressure
var/SA_partialpressure = (breath.sleeping_agent/breath.total_moles())*breath_pressure
//OXYGEN
if(O2_partialpressure < safe_oxy_min) //Not enough oxygen
@@ -162,22 +166,20 @@
//TOXINS/PLASMA
if(Toxins_partialpressure > safe_tox_max)
var/ratio = (breath.toxins/safe_tox_max) * 10
adjustToxLoss(Clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
adjustToxLoss(clamp(ratio, MIN_TOXIC_GAS_DAMAGE, MAX_TOXIC_GAS_DAMAGE))
throw_alert("too_much_tox", /obj/screen/alert/too_much_tox)
else
clear_alert("too_much_tox")
//TRACE GASES
if(breath.trace_gases.len)
for(var/datum/gas/sleeping_agent/SA in breath.trace_gases)
var/SA_partialpressure = (SA.moles/breath.total_moles())*breath_pressure
if(SA_partialpressure > SA_para_min)
Paralyse(3)
if(SA_partialpressure > SA_sleep_min)
AdjustSleeping(2, bound_lower = 0, bound_upper = 10)
else if(SA_partialpressure > 0.01)
if(prob(20))
emote(pick("giggle","laugh"))
if(breath.sleeping_agent)
if(SA_partialpressure > SA_para_min)
Paralyse(3)
if(SA_partialpressure > SA_sleep_min)
AdjustSleeping(2, bound_lower = 0, bound_upper = 10)
else if(SA_partialpressure > 0.01)
if(prob(20))
emote(pick("giggle","laugh"))
//BREATH TEMPERATURE
handle_breath_temperature(breath)
@@ -245,7 +247,7 @@
adjustToxLoss(3)
updatehealth("handle mutations and radiation(75-100)")
radiation = Clamp(radiation, 0, 100)
radiation = clamp(radiation, 0, 100)
/mob/living/carbon/handle_chemicals_in_body()
@@ -256,14 +258,15 @@
if(times_fired % 20==2) //dry off a bit once every 20 ticks or so
wetlevel = max(wetlevel - 1,0)
/mob/living/carbon/handle_stomach(times_fired)
for(var/mob/living/M in stomach_contents)
/mob/living/carbon/proc/handle_stomach(times_fired)
for(var/thing in stomach_contents)
var/mob/living/M = thing
if(M.loc != src)
stomach_contents.Remove(M)
LAZYREMOVE(stomach_contents, M)
continue
if(stat != DEAD)
if(M.stat == DEAD)
stomach_contents.Remove(M)
LAZYREMOVE(stomach_contents, M)
qdel(M)
continue
if(times_fired % 3 == 1)
@@ -478,7 +481,7 @@
P.reagents.remove_any(applied_amount * 0.5)
else
if(!P.reagents || P.reagents.total_volume <= 0)
processing_patches -= P
LAZYREMOVE(processing_patches, P)
qdel(P)
/mob/living/carbon/proc/handle_germs()
-6
View File
@@ -58,9 +58,6 @@
handle_fire()
//stuff in the stomach
handle_stomach(times_fired)
update_gravity(mob_has_gravity())
if(pulling)
@@ -117,9 +114,6 @@
/mob/living/proc/handle_environment(datum/gas_mixture/environment)
return
/mob/living/proc/handle_stomach(times_fired)
return
/mob/living/proc/update_pulling()
if(incapacitated())
stop_pulling()
+19 -28
View File
@@ -80,8 +80,9 @@
//Even if we don't push/swap places, we "touched" them, so spread fire
spreadFire(M)
if(now_pushing)
return 1
// No pushing if we're already pushing past something, or if the mob we're pushing into is anchored.
if(now_pushing || M.anchored)
return TRUE
//Should stop you pushing a restrained person out of the way
if(isliving(M))
@@ -89,7 +90,7 @@
if(L.pulledby && L.pulledby != src && L.restrained())
if(!(world.time % 5))
to_chat(src, "<span class='warning'>[L] is restrained, you cannot push past.</span>")
return 1
return TRUE
if(L.pulling)
if(ismob(L.pulling))
@@ -97,28 +98,28 @@
if(P.restrained())
if(!(world.time % 5))
to_chat(src, "<span class='warning'>[L] is restrained, you cannot push past.</span>")
return 1
return TRUE
if(moving_diagonally) //no mob swap during diagonal moves.
return 1
return TRUE
if(a_intent == INTENT_HELP) // Help intent doesn't mob swap a mob pulling a structure
if(isstructure(M.pulling) || isstructure(pulling))
return 1
return TRUE
if(!M.buckled && !M.has_buckled_mobs())
var/mob_swap
//the puller can always swap with it's victim if on grab intent
if(M.pulledby == src && a_intent == INTENT_GRAB)
mob_swap = 1
mob_swap = TRUE
//restrained people act if they were on 'help' intent to prevent a person being pulled from being seperated from their puller
else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP))
mob_swap = 1
mob_swap = TRUE
if(mob_swap)
//switch our position with M
if(loc && !loc.Adjacent(M.loc))
return 1
now_pushing = 1
return TRUE
now_pushing = TRUE
var/oldloc = loc
var/oldMloc = M.loc
@@ -135,18 +136,18 @@
if(!M_passmob)
M.pass_flags &= ~PASSMOB
now_pushing = 0
return 1
now_pushing = FALSE
return TRUE
// okay, so we didn't switch. but should we push?
// not if he's not CANPUSH of course
if(!(M.status_flags & CANPUSH))
return 1
return TRUE
//anti-riot equipment is also anti-push
if(M.r_hand && (prob(M.r_hand.block_chance * 2)) && !istype(M.r_hand, /obj/item/clothing))
return 1
return TRUE
if(M.l_hand && (prob(M.l_hand.block_chance * 2)) && !istype(M.l_hand, /obj/item/clothing))
return 1
return TRUE
//Called when we bump into an obj
/mob/living/proc/ObjBump(obj/O)
@@ -196,13 +197,6 @@
AM.setDir(current_dir)
now_pushing = FALSE
/mob/living/Stat()
. = ..()
if(. && get_rig_stats)
var/obj/item/rig/rig = get_rig()
if(rig)
SetupStat(rig)
/mob/living/proc/can_track(mob/living/user)
//basic fast checks go first. When overriding this proc, I recommend calling ..() at the end.
var/turf/T = get_turf(src)
@@ -703,9 +697,6 @@
*/////////////////////
/mob/living/proc/resist_grab()
var/resisting = 0
for(var/obj/O in requests)
qdel(O)
resisting++
for(var/X in grabbed_by)
var/obj/item/grab/G = X
resisting++
@@ -761,7 +752,8 @@
clear_alert("weightless")
else
throw_alert("weightless", /obj/screen/alert/weightless)
float(!has_gravity)
if(!flying)
float(!has_gravity)
/mob/living/proc/float(on)
if(throwing)
@@ -846,8 +838,7 @@
spawn_dust()
gib()
/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect, end_pixel_y)
end_pixel_y = get_standard_pixel_y_offset(lying)
/mob/living/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
if(!used_item)
used_item = get_active_hand()
..()
+4 -6
View File
@@ -79,9 +79,9 @@
/obj/item/proc/get_volume_by_throwforce_and_or_w_class()
if(throwforce && w_class)
return Clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
return clamp((throwforce + w_class) * 5, 30, 100)// Add the item's throwforce to its weight class and multiply by 5, then clamp the value between 30 and 100
else if(w_class)
return Clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
return clamp(w_class * 8, 20, 100) // Multiply the item's weight class by 8, then clamp the value between 20 and 100
else
return 0
@@ -113,7 +113,7 @@
var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", I.armour_penetration)
apply_damage(I.throwforce, dtype, zone, armor, is_sharp(I), I)
if(I.thrownby)
add_attack_logs(I.thrownby, src, "Hit with thrown [I]")
add_attack_logs(I.thrownby, src, "Hit with thrown [I]", !I.throwforce ? ATKLOG_ALMOSTALL : null) // Only message if the person gets damages
else
return 1
else
@@ -175,7 +175,7 @@
return
/mob/living/proc/adjust_fire_stacks(add_fire_stacks) //Adjusting the amount of fire_stacks we have on person
fire_stacks = Clamp(fire_stacks + add_fire_stacks, -20, 20)
fire_stacks = clamp(fire_stacks + add_fire_stacks, -20, 20)
if(on_fire && fire_stacks <= 0)
ExtinguishMob()
@@ -260,8 +260,6 @@
add_attack_logs(user, src, "Grabbed passively", ATKLOG_ALL)
var/obj/item/grab/G = new /obj/item/grab(user, src)
if(buckled)
to_chat(user, "<span class='notice'>You cannot grab [src]; [p_they()] [p_are()] buckled in!</span>")
if(!G) //the grab will delete itself in New if src is anchored
return 0
user.put_in_active_hand(G)
+15 -17
View File
@@ -61,7 +61,7 @@ proc/get_radio_key_from_channel(var/channel)
return default_language
/mob/living/proc/handle_speech_problems(list/message_pieces, var/verb)
var/robot = isSynthetic()
var/robot = ismachineperson(src)
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
@@ -269,12 +269,12 @@ proc/get_radio_key_from_channel(var/channel)
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol, sound_frequency)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
if(loc && !isturf(loc))
var/atom/A = loc //Non-turf, let it handle the speech bubble
A.speech_bubble("hR[speech_bubble_test]", A, speech_bubble_recipients)
else //Turf, leave speech bubbles to the mob
speech_bubble("h[speech_bubble_test]", src, speech_bubble_recipients)
if(loc && !isturf(loc))
var/atom/A = loc //Non-turf, let it handle the speech bubble
A.speech_bubble("[A.bubble_icon][speech_bubble_test]", A, speech_bubble_recipients)
else //Turf, leave speech bubbles to the mob
speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients)
for(var/obj/O in listening_obj)
spawn(0)
@@ -336,7 +336,8 @@ proc/get_radio_key_from_channel(var/channel)
var/datum/multilingual_say_piece/S = message_pieces // Yay BYOND's hilarious typecasting
S.speaking.broadcast(src, S.message)
return 1
// Log it here since it skips the default way say handles it
create_log(SAY_LOG, "(whisper) '[message]'")
whisper_say(message_pieces)
// for weird circumstances where you're inside an atom that is also you, like pai's
@@ -450,21 +451,18 @@ proc/get_radio_key_from_channel(var/channel)
var/speech_bubble_test = say_test(message)
for(var/mob/M in listening)
M.hear_say(message_pieces, verb, italics, src)
M.hear_say(message_pieces, verb, italics, src, use_voice = FALSE)
if(M.client)
speech_bubble_recipients.Add(M.client)
if(eavesdropping.len)
stars_all(message_pieces) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
for(var/mob/M in eavesdropping)
M.hear_say(message_pieces, verb, italics, src)
M.hear_say(message_pieces, verb, italics, src, use_voice = FALSE)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
var/image/I = image('icons/mob/talk.dmi', src, "h[speech_bubble_test]", MOB_LAYER + 1)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, speech_bubble_recipients, 30)
speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients)
if(watching.len)
var/rendered = "<span class='game say'><span class='name'>[name]</span> [not_heard].</span>"
@@ -473,7 +471,7 @@ proc/get_radio_key_from_channel(var/channel)
return 1
/mob/living/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, MOB_LAYER + 1)
/mob/living/speech_bubble(bubble_state = "", bubble_loc = src, list/bubble_recipients = list())
var/image/I = image('icons/mob/talk.dmi', bubble_loc, bubble_state, FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
flick_overlay(I, bubble_recipients, 30)
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, bubble_recipients, 30)
+15 -29
View File
@@ -63,6 +63,7 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
//MALFUNCTION
var/datum/module_picker/malf_picker
var/datum/action/innate/ai/choose_modules/modules_action
var/list/datum/AI_Module/current_modules = list()
var/can_dominate_mechs = 0
var/shunted = 0 //1 if the AI is currently shunted. Used to differentiate between shunted and ghosted/braindead
@@ -243,7 +244,8 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
/mob/living/silicon/ai/proc/show_borg_info()
stat(null, text("Connected cyborgs: [connected_robots.len]"))
for(var/mob/living/silicon/robot/R in connected_robots)
for(var/thing in connected_robots)
var/mob/living/silicon/robot/R = thing
var/robot_status = "Nominal"
if(R.stat || !R.client)
robot_status = "OFFLINE"
@@ -251,8 +253,9 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
robot_status = "DEPOWERED"
// Name, Health, Battery, Module, Area, and Status! Everything an AI wants to know about its borgies!
var/area/A = get_area(R)
var/area_name = A ? sanitize(A.name) : "Unknown"
stat(null, text("[R.name] | S.Integrity: [R.health]% | Cell: [R.cell ? "[R.cell.charge] / [R.cell.maxcharge]" : "Empty"] | \
Module: [R.designation] | Loc: [sanitize(A.name)] | Status: [robot_status]"))
Module: [R.designation] | Loc: [area_name] | Status: [robot_status]"))
/mob/living/silicon/ai/rename_character(oldname, newname)
if(!..(oldname, newname))
@@ -849,13 +852,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
to_chat(src, "<span class='notice'>Switched to [network] camera network.</span>")
//End of code by Mord_Sith
/mob/living/silicon/ai/proc/choose_modules()
set category = "Malfunction"
set name = "Choose Module"
malf_picker.use(src)
/mob/living/silicon/ai/proc/ai_statuschange()
set category = "AI Commands"
set name = "AI Status"
@@ -1026,15 +1022,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
return
/mob/living/silicon/ai/proc/corereturn()
set category = "Malfunction"
set name = "Return to Main Core"
var/obj/machinery/power/apc/apc = loc
if(!istype(apc))
to_chat(src, "<span class='notice'>You are already in your Main Core.</span>")
return
apc.malfvacate()
//Toggles the luminosity and applies it by re-entereing the camera.
/mob/living/silicon/ai/proc/toggle_camera_light()
@@ -1179,16 +1166,6 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
/mob/living/silicon/ai/can_buckle()
return FALSE
// Pass lying down or getting up to our pet human, if we're in a rig.
/mob/living/silicon/ai/lay_down()
set name = "Rest"
set category = "IC"
resting = 0
var/obj/item/rig/rig = get_rig()
if(rig)
rig.force_rest(src)
/mob/living/silicon/ai/switch_to_camera(obj/machinery/camera/C)
if(!C.can_use() || !is_in_chassis())
return FALSE
@@ -1242,8 +1219,17 @@ GLOBAL_LIST_INIT(ai_verbs_default, list(
to_chat(src, "In the top right corner of the screen you will find the Malfunctions tab, where you can purchase various abilities, from upgraded surveillance to station ending doomsday devices.")
to_chat(src, "You are also capable of hacking APCs, which grants you more points to spend on your Malfunction powers. The drawback is that a hacked APC will give you away if spotted by the crew. Hacking an APC takes 60 seconds.")
view_core() //A BYOND bug requires you to be viewing your core before your verbs update
verbs += /mob/living/silicon/ai/proc/choose_modules
malf_picker = new /datum/module_picker
modules_action = new(malf_picker)
modules_action.Grant(src)
///Removes all malfunction-related /datum/action's from the target AI.
/mob/living/silicon/ai/proc/remove_malf_abilities()
QDEL_NULL(modules_action)
for(var/datum/AI_Module/AM in current_modules)
for(var/datum/action/A in actions)
if(istype(A, initial(AM.power_type)))
qdel(A)
/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target)
if(!istype(target))
+1 -1
View File
@@ -34,7 +34,7 @@
spawn(10)
explosion(src.loc, 3, 6, 12, 15)
for(var/obj/machinery/ai_status_display/O in world) //change status
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 2
if(istype(loc, /obj/item/aicard))
@@ -67,9 +67,6 @@
// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists.
/datum/camerachunk/proc/update()
set background = BACKGROUND_ENABLED
var/list/newVisibleTurfs = list()
for(var/camera in cameras)
@@ -142,7 +142,7 @@
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
/mob/camera/aiEye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
/mob/camera/aiEye/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
if(relay_speech)
if(istype(ai))
ai.relay_speech(speaker, message_pieces, verb)
@@ -1,15 +1,5 @@
GLOBAL_LIST_EMPTY(empty_playable_ai_cores)
/hook/roundstart/proc/spawn_empty_ai()
for(var/obj/effect/landmark/start/S in GLOB.landmarks_list)
if(S.name != "AI")
continue
if(locate(/mob/living) in S.loc)
continue
GLOB.empty_playable_ai_cores += new /obj/structure/AIcore/deactivated(get_turf(S))
return 1
/mob/living/silicon/ai/verb/wipe_core()
set name = "Wipe Core"
set category = "OOC"
+1 -1
View File
@@ -1,6 +1,6 @@
/mob/living/silicon/ai/Logout()
..()
for(var/obj/machinery/ai_status_display/O in world) //change status
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
O.mode = 0
src.view_core()
return
@@ -4,7 +4,7 @@
if(!.)
return FALSE
icon_state = "ai-crash"
for(var/obj/machinery/ai_status_display/O in world) //change status
for(var/obj/machinery/ai_status_display/O in GLOB.machines) //change status
if(atoms_share_level(O, src))
O.mode = 2
gib()
@@ -435,9 +435,6 @@
// Pass lying down or getting up to our pet human, if we're in a rig.
if(stat == CONSCIOUS && istype(loc,/obj/item/paicard))
resting = 0
var/obj/item/rig/rig = get_rig()
if(istype(rig))
rig.force_rest(src)
else
resting = !resting
to_chat(src, "<span class='notice'>You are now [resting ? "resting" : "getting up"]</span>")
@@ -1,6 +1,6 @@
// Recruiting observers to play as pAIs
GLOBAL_DATUM(paiController, /datum/paiController) // Global handler for pAI candidates
GLOBAL_DATUM_INIT(paiController, /datum/paiController, new) // Global handler for pAI candidates
/datum/paiCandidate
var/name
@@ -10,12 +10,6 @@ GLOBAL_DATUM(paiController, /datum/paiController) // Global handler for pAI cand
var/comments
var/ready = 0
/hook/startup/proc/paiControllerSetup()
GLOB.paiController = new /datum/paiController()
return 1
/datum/paiController
var/list/pai_candidates = list()
var/list/asked = list()
@@ -13,19 +13,6 @@ GLOBAL_LIST_INIT(pai_emotions, list(
GLOBAL_LIST_EMPTY(pai_software_by_key)
GLOBAL_LIST_EMPTY(default_pai_software)
/hook/startup/proc/populate_pai_software_list()
var/r = 1 // I would use ., but it'd sacrifice runtime detection
for(var/type in subtypesof(/datum/pai_software))
var/datum/pai_software/P = new type()
if(GLOB.pai_software_by_key[P.id])
var/datum/pai_software/O = GLOB.pai_software_by_key[P.id]
to_chat(world, "<span class='warning'>pAI software module [P.name] has the same key as [O.name]!</span>")
r = 0
continue
GLOB.pai_software_by_key[P.id] = P
if(P.default)
GLOB.default_pai_software[P.id] = P
return r
/mob/living/silicon/pai/New()
..()
@@ -227,7 +227,7 @@
throw_speed = 5
throw_range = 10
origin_tech = "magnets=1;biotech=1"
var/mode = 1;
var/mode = 1
/obj/item/robotanalyzer/attack(mob/living/M as mob, mob/living/user as mob)
if(( (CLUMSY in user.mutations) || user.getBrainLoss() >= 60) && prob(50))
@@ -253,7 +253,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
to_chat(user, "<span class='warning'>You can't analyze non-robotic things!</span>")
return
switch(scan_type)
if("robot")
var/BU = M.getFireLoss() > 50 ? "<b>[M.getFireLoss()]</b>" : M.getFireLoss()
@@ -269,7 +269,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
to_chat(user, "<span class='notice'>Localized Damage:</span>")
if(!LAZYLEN(damaged) && !LAZYLEN(missing))
to_chat(user, "<span class='notice'>\t Components are OK.</span>")
else
else
if(LAZYLEN(damaged))
for(var/datum/robot_component/org in damaged)
user.show_message(text("<span class='notice'>\t []: [][] - [] - [] - []</span>", \
@@ -282,7 +282,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
if(LAZYLEN(missing))
for(var/datum/robot_component/org in missing)
user.show_message("<span class='warning'>\t [capitalize(org.name)]: MISSING</span>")
if(H.emagged && prob(5))
to_chat(user, "<span class='warning'>\t ERROR: INTERNAL SYSTEMS COMPROMISED</span>")
@@ -313,7 +313,7 @@ proc/robot_healthscan(mob/user, mob/living/M)
if(!organ_found)
to_chat(user, "<span class='warning'>No prosthetics located.</span>")
if(H.isSynthetic())
if(ismachineperson(H))
to_chat(user, "<span class='notice'>Internal Fluid Level:[H.blood_volume]/[H.max_blood]</span>")
if(H.bleed_rate)
to_chat(user, "<span class='warning'>Warning:External component leak detected!</span>")
@@ -6,6 +6,7 @@
icon_state = "repairbot"
maxHealth = 35
health = 35
bubble_icon = "machine"
universal_speak = 0
universal_understand = 1
gender = NEUTER
@@ -13,6 +14,7 @@
braintype = "Robot"
lawupdate = 0
density = 0
has_camera = FALSE
req_one_access = list(ACCESS_ENGINE, ACCESS_ROBOTICS)
ventcrawler = 2
magpulse = 1
@@ -34,6 +36,14 @@
var/reboot_cooldown = 60 // one minute
var/last_reboot
var/emagged_time
var/list/pullable_drone_items = list(
/obj/item/pipe,
/obj/structure/disposalconstruct,
/obj/item/stack/cable_coil,
/obj/item/stack/rods,
/obj/item/stack/sheet,
/obj/item/stack/tile
)
holder_type = /obj/item/holder/drone
// var/sprite[0]
@@ -68,6 +78,10 @@
verbs -= /mob/living/silicon/robot/verb/Namepick
module = new /obj/item/robot_module/drone(src)
//Allows Drones to hear the Engineering channel.
module.channels = list("Engineering" = 1)
radio.recalculateChannels()
//Grab stacks.
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in src.module
stack_wood = locate(/obj/item/stack/sheet/wood) in src.module
@@ -82,7 +96,7 @@
scanner.Grant(src)
update_icons()
/mob/living/silicon/robot/drone/init()
/mob/living/silicon/robot/drone/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/drone()
connected_ai = null
@@ -145,7 +159,7 @@
user.visible_message("<span class='warning'>\the [user] swipes [user.p_their()] ID card through [src], attempting to reboot it.</span>", "<span class='warning'>You swipe your ID card through [src], attempting to reboot it.</span>")
last_reboot = world.time / 10
var/drones = 0
for(var/mob/living/silicon/robot/drone/D in world)
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.key && D.client)
drones++
if(drones < config.max_maint_drones)
@@ -153,15 +167,17 @@
return
else
user.visible_message("<span class='warning'>\the [user] swipes [user.p_their()] ID card through [src], attempting to shut it down.</span>", "<span class='warning'>You swipe your ID card through \the [src], attempting to shut it down.</span>")
var/confirm = alert("Using your ID on a Maintenance Drone will shut it down, are you sure you want to do this?", "Disable Drone", "Yes", "No")
if(confirm == ("Yes") && (user in range(3, src)))
user.visible_message("<span class='warning'>\the [user] swipes [user.p_their()] ID card through [src], attempting to shut it down.</span>", "<span class='warning'>You swipe your ID card through \the [src], attempting to shut it down.</span>")
if(emagged)
return
if(emagged)
return
if(allowed(W))
shut_down()
else
to_chat(user, "<span class='warning'>Access denied.</span>")
if(allowed(W))
shut_down()
else
to_chat(user, "<span class='warning'>Access denied.</span>")
return
@@ -322,8 +338,9 @@
/mob/living/silicon/robot/drone/start_pulling(atom/movable/AM, state, force = pull_force, show_message = FALSE)
if(istype(AM,/obj/item/pipe) || istype(AM,/obj/structure/disposalconstruct))
if(is_type_in_list(AM, pullable_drone_items))
..(AM, force = INFINITY) // Drone power! Makes them able to drag pipes and such
else if(istype(AM,/obj/item))
var/obj/item/O = AM
if(O.w_class > WEIGHT_CLASS_SMALL)
@@ -354,3 +371,20 @@
/mob/living/simple_animal/drone/flash_eyes(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0)
if(affect_silicon)
return ..()
/mob/living/silicon/robot/drone/decompile_act(obj/item/matter_decompiler/C, mob/user)
if(!client && istype(user, /mob/living/silicon/robot/drone))
to_chat(user, "<span class='warning'>You begin decompiling the other drone.</span>")
if(!do_after(user, 5 SECONDS, target = loc))
to_chat(user, "<span class='warning'>You need to remain still while decompiling such a large object.</span>")
return
if(QDELETED(src) || QDELETED(user))
return ..()
to_chat(user, "<span class='warning'>You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.</span>")
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
C.stored_comms["metal"] += 15
C.stored_comms["glass"] += 15
C.stored_comms["wood"] += 5
qdel(src)
return TRUE
return ..()
@@ -34,7 +34,7 @@
var/dat
dat += "<B>Maintenance Units</B><BR>"
for(var/mob/living/silicon/robot/drone/D in world)
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
dat += "<BR>[D.real_name] ([D.stat == 2 ? "<font color='red'>INACTIVE" : "<font color='green'>ACTIVE"]</FONT>)"
dat += "<font dize = 9><BR>Cell charge: [D.cell.charge]/[D.cell.maxcharge]."
dat += "<BR>Currently located in: [get_area(D)]."
@@ -74,7 +74,7 @@
else if(href_list["ping"])
to_chat(usr, "<span class='notice'>You issue a maintenance request for all active drones, highlighting [drone_call_area].</span>")
for(var/mob/living/silicon/robot/drone/D in world)
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.client && D.stat == 0)
to_chat(D, "-- Maintenance drone presence requested in: [drone_call_area].")
@@ -8,7 +8,6 @@
//Has a list of items that it can hold.
var/list/can_hold = list(
/obj/item/stock_parts/cell,
/obj/item/firealarm_electronics,
/obj/item/airalarm_electronics,
/obj/item/airlock_electronics,
@@ -24,6 +23,8 @@
/obj/item/mounted/frame/firealarm,
/obj/item/mounted/frame/newscaster_frame,
/obj/item/mounted/frame/intercom,
/obj/item/mounted/frame/extinguisher,
/obj/item/mounted/frame/light_switch,
/obj/item/rack_parts,
/obj/item/camera_assembly,
/obj/item/tank,
@@ -64,7 +65,7 @@
..()
can_hold = typecacheof(can_hold)
/obj/item/gripper/verb/drop_item()
/obj/item/gripper/verb/drop_item_gripped()
set name = "Drop Gripped Item"
set desc = "Release an item from your magnetic gripper."
set category = "Drone"
@@ -151,15 +152,13 @@
var/list/stored_comms = list(
"metal" = 0,
"glass" = 0,
"wood" = 0,
"plastic" = 0
"wood" = 0
)
/obj/item/matter_decompiler/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
/obj/item/matter_decompiler/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, proximity, params)
/obj/item/matter_decompiler/afterattack(atom/target, mob/living/user, proximity, params)
if(!proximity) return //Not adjacent.
//We only want to deal with using this on turfs. Specific items aren't important.
@@ -168,101 +167,11 @@
return
//Used to give the right message.
var/grabbed_something = 0
var/grabbed_something = FALSE
for(var/mob/M in T)
if(istype(M,/mob/living/simple_animal/lizard) || istype(M,/mob/living/simple_animal/mouse))
src.loc.visible_message("<span class='notice'>[src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.</span>","<span class='warning'>It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.</span>")
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
qdel(M)
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
return
else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
var/mob/living/silicon/robot/drone/D = src.loc
if(!istype(D))
return
to_chat(D, "<span class='warning'>You begin decompiling the other drone.</span>")
if(!do_after(D, 50, target = target))
to_chat(D, "<span class='warning'>You need to remain still while decompiling such a large object.</span>")
return
if(!M || !D) return
to_chat(D, "<span class='warning'>You carefully and thoroughly decompile your downed fellow, storing as much of its resources as you can within yourself.</span>")
qdel(M)
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
stored_comms["metal"] += 15
stored_comms["glass"] += 15
stored_comms["wood"] += 5
stored_comms["plastic"] += 5
return
else
continue
for(var/obj/W in T)
//Different classes of items give different commodities.
if(istype(W,/obj/item/cigbutt))
stored_comms["plastic"]++
else if(istype(W,/obj/structure/spider/spiderling))
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
else if(istype(W,/obj/item/light))
var/obj/item/light/L = W
if(L.status >= 2) //In before someone changes the inexplicably local defines. ~ Z
stored_comms["metal"]++
stored_comms["glass"]++
else
continue
else if(istype(W,/obj/effect/decal/remains/robot))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
stored_comms["glass"]++
else if(istype(W,/obj/item/trash))
stored_comms["metal"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
else if(istype(W,/obj/effect/decal/cleanable/blood/gibs/robot))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["glass"]++
stored_comms["glass"]++
else if(istype(W,/obj/item/ammo_casing))
stored_comms["metal"]++
else if(istype(W,/obj/item/shard))
stored_comms["glass"]++
stored_comms["glass"]++
stored_comms["glass"]++
else if(istype(W,/obj/item/reagent_containers/food/snacks/grown))
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["wood"]++
else if(istype(W,/obj/item/broken_bottle))
stored_comms["glass"]++
stored_comms["glass"]++
stored_comms["glass"]++
else if(istype(W,/obj/item/light/tube) || istype(W,/obj/item/light/bulb))
stored_comms["glass"]++
else
continue
qdel(W)
grabbed_something = 1
for(var/atom/movable/A in T)
if(A.decompile_act(src, user)) // Each decompileable mob or obj needs to have this defined
grabbed_something = TRUE
if(grabbed_something)
to_chat(user, "<span class='notice'>You deploy your decompiler and clear out the contents of \the [T].</span>")
@@ -353,11 +262,5 @@
stack_wood = new /obj/item/stack/sheet/wood(src.module)
stack_wood.amount = 1
stack = stack_wood
if("plastic")
if(!stack_plastic)
stack_plastic = new /obj/item/stack/sheet/plastic(src.module)
stack_plastic.amount = 1
stack = stack_plastic
stack.amount++
decompiler.stored_comms[type]--
@@ -52,7 +52,7 @@
/obj/machinery/drone_fabricator/proc/count_drones()
var/drones = 0
for(var/mob/living/silicon/robot/drone/D in world)
for(var/mob/living/silicon/robot/drone/D in GLOB.silicon_mob_list)
if(D.key && D.client)
drones++
return drones
@@ -142,7 +142,7 @@
if(alert("Are you sure you want to respawn as a drone?", "Are you sure?", "Yes", "No") != "Yes")
return
for(var/obj/machinery/drone_fabricator/DF in world)
for(var/obj/machinery/drone_fabricator/DF in GLOB.machines)
if(DF.stat & NOPOWER || !DF.produce_drones)
continue
@@ -36,7 +36,7 @@
if(is_component_functioning("power cell") && cell.charge)
if(cell.charge <= 100)
uneq_all()
var/amt = Clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
var/amt = clamp((lamp_intensity - 2) * 2,1,cell.charge) //Always try to use at least one charge per tick, but allow it to completely drain the cell.
cell.use(amt) //Usage table: 1/tick if off/lowest setting, 4 = 4/tick, 6 = 8/tick, 8 = 12/tick, 10 = 16/tick
else
uneq_all()
+131 -80
View File
@@ -9,6 +9,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
icon_state = "robot"
maxHealth = 100
health = 100
bubble_icon = "robot"
universal_understand = 1
deathgasp_on_death = TRUE
@@ -16,8 +17,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/custom_name = ""
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
//Hud stuff
//Hud stuff
var/obj/screen/inv1 = null
var/obj/screen/inv2 = null
var/obj/screen/inv3 = null
@@ -27,7 +27,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not
var/obj/screen/robot_modules_background
//3 Modules can be activated at any one time.
//3 Modules can be activated at any one time.
var/obj/item/robot_module/module = null
var/module_active = null
var/module_state_1 = null
@@ -57,6 +57,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/is_emaggable = TRUE
var/eye_protection = 0
var/ear_protection = 0
var/damage_protection = 0
var/emp_protection = FALSE
var/xeno_disarm_chance = 85
var/list/force_modules = list()
var/allow_rename = TRUE
@@ -82,11 +85,11 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/lockcharge //Used when locking down a borg to preserve cell charge
var/speed = 0 //Cause sec borgs gotta go fast //No they dont!
var/scrambledcodes = 0 // Used to determine if a borg shows up on the robotics console. Setting to one hides them.
var/has_camera = TRUE
var/pdahide = 0 //Used to hide the borg from the messenger list
var/tracking_entities = 0 //The number of known entities currently accessing the internal camera
var/braintype = "Cyborg"
var/base_icon = ""
var/crisis = 0
var/modules_break = TRUE
var/lamp_max = 10 //Maximum brightness of a borg lamp. Set as a var for easy adjusting.
@@ -97,6 +100,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
hud_possible = list(SPECIALROLE_HUD, DIAG_STAT_HUD, DIAG_HUD, DIAG_BATT_HUD)
var/default_cell_type = /obj/item/stock_parts/cell/high
var/magpulse = 0
var/ionpulse = 0 // Jetpack-like effect.
var/ionpulse_on = 0 // Jetpack-like effect.
@@ -108,7 +112,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/get_cell()
return cell
/mob/living/silicon/robot/New(loc,var/syndie = 0,var/unfinished = 0, var/alien = 0)
/mob/living/silicon/robot/New(loc, syndie = FALSE, unfinished = FALSE, alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
spark_system = new /datum/effect_system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
@@ -130,9 +134,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
radio = new /obj/item/radio/borg(src)
common_radio = radio
init()
init(ai_to_sync_to = ai_to_sync_to)
if(!scrambledcodes && !camera)
if(has_camera && !camera)
camera = new /obj/machinery/camera(src)
camera.c_tag = real_name
camera.network = list("SS13","Robots")
@@ -144,7 +148,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
mmi.icon_state = "boris"
if(!cell) // Make sure a new cell gets created *before* executing initialize_components(). The cell component needs an existing cell for it to get set up properly
cell = new /obj/item/stock_parts/cell/high(src)
cell = new default_cell_type(src)
initialize_components()
//if(!unfinished)
@@ -168,14 +172,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
scanner = new(src)
scanner.Grant(src)
/mob/living/silicon/robot/proc/init(var/alien=0)
/mob/living/silicon/robot/proc/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
make_laws()
additional_law_channels["Binary"] = ":b "
var/new_ai = select_active_ai_with_fewest_borgs()
if(new_ai)
var/found_ai = ai_to_sync_to
if(!found_ai)
found_ai = select_active_ai_with_fewest_borgs()
if(found_ai)
lawupdate = 1
connect_to_ai(new_ai)
connect_to_ai(found_ai)
else
lawupdate = 0
@@ -235,7 +241,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(custom_name)
return 0
if(!allow_rename)
to_chat(src, "<span class='warning'>Rename functionality is not enabled on this unit.</span>");
to_chat(src, "<span class='warning'>Rename functionality is not enabled on this unit.</span>")
return 0
rename_self(braintype, 1)
@@ -288,12 +294,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
/mob/living/silicon/robot/proc/pick_module()
if(module)
return
var/list/modules = list("Standard", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
var/list/modules = list("Generalist", "Engineering", "Medical", "Miner", "Janitor", "Service", "Security")
if(islist(force_modules) && force_modules.len)
modules = force_modules.Copy()
if(GLOB.security_level == (SEC_LEVEL_GAMMA || SEC_LEVEL_EPSILON) || crisis)
to_chat(src, "<span class='warning'>Crisis mode active. The combat module is now available.</span>")
modules += "Combat"
if(mmi != null && mmi.alien)
modules = list("Hunter")
modtype = input("Please, select a module!", "Robot", null, null) as null|anything in modules
@@ -306,9 +309,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return
switch(modtype)
if("Standard")
if("Generalist")
module = new /obj/item/robot_module/standard(src)
module.channels = list("Service" = 1)
module.channels = list("Engineering" = 1, "Medical" = 1, "Security" = 1, "Service" = 1)
module_sprites["Basic"] = "robot_old"
module_sprites["Android"] = "droid"
module_sprites["Default"] = "Standard"
@@ -337,6 +340,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
module_sprites["Standard"] = "Standard-Mine"
module_sprites["Noble-DIG"] = "Noble-DIG"
module_sprites["Cricket"] = "Cricket-MINE"
module_sprites["Lavaland"] = "lavaland"
if("Medical")
module = new /obj/item/robot_module/medical(src)
@@ -353,6 +357,17 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
status_flags &= ~CANPUSH
if("Security")
if(!weapons_unlock)
var/count_secborgs = 0
for(var/mob/living/silicon/robot/R in GLOB.alive_mob_list)
if(R && R.stat != DEAD && R.module && istype(R.module, /obj/item/robot_module/security))
count_secborgs++
var/max_secborgs = 2
if(GLOB.security_level == SEC_LEVEL_GREEN)
max_secborgs = 1
if(count_secborgs >= max_secborgs)
to_chat(src, "<span class='warning'>There are too many Security cyborgs active. Please choose another module.</span>")
return
module = new /obj/item/robot_module/security(src)
module.channels = list("Security" = 1)
module_sprites["Basic"] = "secborg"
@@ -387,10 +402,16 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
module_sprites["Noble-CLN"] = "Noble-CLN"
module_sprites["Cricket"] = "Cricket-JANI"
if("Combat")
module = new /obj/item/robot_module/combat(src)
if("Destroyer") // Rolling Borg
module = new /obj/item/robot_module/destroyer(src)
module.channels = list("Security" = 1)
icon_state = "droidcombat"
status_flags &= ~CANPUSH
if("Combat") // Gamma ERT
module = new /obj/item/robot_module/combat(src)
icon_state = "ertgamma"
status_flags &= ~CANPUSH
if("Hunter")
module = new /obj/item/robot_module/alien/hunter(src)
@@ -442,6 +463,8 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
ionpulse = FALSE
magpulse = FALSE
add_language("Robot Talk", 1)
if("lava" in weather_immunities) // Remove the lava-immunity effect given by a printable upgrade
weather_immunities -= "lava"
status_flags |= CANPUSH
@@ -916,7 +939,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
return 0
/mob/living/silicon/robot/update_icons()
overlays.Cut()
if(stat != DEAD && !(paralysis || stunned || IsWeakened() || low_power_mode)) //Not dead, not stunned.
if(custom_panel in custom_eye_names)
@@ -925,36 +947,24 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
overlays += "eyes-[icon_state]"
else
overlays -= "eyes"
if(opened)
var/panelprefix = "ov"
if(custom_sprite) //Custom borgs also have custom panels, heh
panelprefix = "[ckey]"
if(custom_panel in custom_panel_names) //For default borgs with different panels
panelprefix = custom_panel
if(wiresexposed)
overlays += "[panelprefix]-openpanel +w"
else if(cell)
overlays += "[panelprefix]-openpanel +c"
else
overlays += "[panelprefix]-openpanel -c"
var/combat = list("Combat")
if(modtype in combat)
if(base_icon == "")
base_icon = icon_state
if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
icon_state = "[base_icon]-roll"
else
icon_state = base_icon
if(module)
for(var/obj/item/borg/combat/shield/S in module.modules)
if(activated(S))
overlays += "[base_icon]-shield"
borg_icons()
update_fire()
/mob/living/silicon/robot/proc/borg_icons() // Exists so that robot/destroyer can override it
return
/mob/living/silicon/robot/proc/installed_modules()
if(weapon_lock)
to_chat(src, "<span class='warning'>Weapon lock active, unable to use modules! Count:[weaponlock_time]</span>")
@@ -1140,7 +1150,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
if(module)
if(module.type == /obj/item/robot_module/janitor)
var/turf/tile = loc
if(isturf(tile))
if(stat != DEAD && isturf(tile))
var/floor_only = TRUE
for(var/A in tile)
if(istype(A, /obj/effect))
@@ -1309,56 +1319,52 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
..()
update_module_icon()
/mob/living/silicon/robot/emp_act(severity)
if(emp_protection)
return
..()
switch(severity)
if(1)
disable_component("comms", 160)
if(2)
disable_component("comms", 60)
/mob/living/silicon/robot/deathsquad
base_icon = "nano_bloodhound"
icon_state = "nano_bloodhound"
designation = "SpecOps"
lawupdate = 0
scrambledcodes = 1
has_camera = FALSE
req_one_access = list(ACCESS_CENT_SPECOPS)
ionpulse = 1
magpulse = 1
pdahide = 1
eye_protection = 2 // Immunity to flashes and the visual part of flashbangs
ear_protection = 1 // Immunity to the audio part of flashbangs
damage_protection = 10 // Reduce all incoming damage by this number
xeno_disarm_chance = 20
allow_rename = FALSE
modtype = "Commando"
faction = list("nanotrasen")
is_emaggable = FALSE
default_cell_type = /obj/item/stock_parts/cell/bluespace
/mob/living/silicon/robot/deathsquad/New(loc)
..()
cell = new /obj/item/stock_parts/cell/hyper(src)
/mob/living/silicon/robot/deathsquad/init()
/mob/living/silicon/robot/deathsquad/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/deathsquad
module = new /obj/item/robot_module/deathsquad(src)
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
radio = new /obj/item/radio/borg/deathsquad(src)
radio.recalculateChannels()
playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
/mob/living/silicon/robot/combat
base_icon = "droidcombat"
icon_state = "droidcombat"
modtype = "Combat"
designation = "Combat"
/mob/living/silicon/robot/deathsquad/bullet_act(var/obj/item/projectile/P)
if(istype(P) && P.is_reflectable && P.starting)
visible_message("<span class='danger'>The [P.name] gets reflected by [src]!</span>", "<span class='userdanger'>The [P.name] gets reflected by [src]!</span>")
P.reflect_back(src)
return -1
return ..(P)
/mob/living/silicon/robot/combat/init()
..()
module = new /obj/item/robot_module/combat(src)
module.channels = list("Security" = 1)
//languages
module.add_languages(src)
//subsystems
module.add_subsystems_and_actions(src)
status_flags &= ~CANPUSH
radio.config(module.channels)
notify_ai(2)
/mob/living/silicon/robot/ert
designation = "ERT"
@@ -1366,24 +1372,24 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
scrambledcodes = 1
req_one_access = list(ACCESS_CENT_SPECOPS)
ionpulse = 1
force_modules = list("Engineering", "Medical", "Security")
static_radio_channels = 1
allow_rename = FALSE
weapons_unlock = TRUE
default_cell_type = /obj/item/stock_parts/cell/super
var/eprefix = "Amber"
/mob/living/silicon/robot/ert/init()
/mob/living/silicon/robot/ert/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/ert_override
radio = new /obj/item/radio/borg/ert(src)
radio.recalculateChannels()
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
/mob/living/silicon/robot/ert/New(loc, cyborg_unlock)
/mob/living/silicon/robot/ert/New(loc)
..(loc)
cell = new /obj/item/stock_parts/cell/hyper(src)
var/rnum = rand(1,1000)
var/borgname = "ERT [rnum]"
var/borgname = "[eprefix] ERT [rnum]"
name = borgname
custom_name = borgname
real_name = name
@@ -1392,22 +1398,67 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
mind.original = src
mind.assigned_role = SPECIAL_ROLE_ERT
mind.special_role = SPECIAL_ROLE_ERT
if(cyborg_unlock)
crisis = 1
if(!(mind in SSticker.minds))
SSticker.minds += mind
SSticker.mode.ert += mind
/mob/living/silicon/robot/ert/gamma
crisis = 1
/mob/living/silicon/robot/emp_act(severity)
..()
switch(severity)
if(1)
disable_component("comms", 160)
if(2)
disable_component("comms", 60)
/mob/living/silicon/robot/ert/red
eprefix = "Red"
default_cell_type = /obj/item/stock_parts/cell/hyper
/mob/living/silicon/robot/ert/gamma
default_cell_type = /obj/item/stock_parts/cell/bluespace
force_modules = list("Combat", "Engineering", "Medical")
damage_protection = 5 // Reduce all incoming damage by this number
eprefix = "Gamma"
magpulse = 1
xeno_disarm_chance = 40
/mob/living/silicon/robot/destroyer
// admin-only borg, the seraph / special ops officer of borgs
base_icon = "droidcombat"
icon_state = "droidcombat"
modtype = "Destroyer"
designation = "Destroyer"
lawupdate = 0
scrambledcodes = 1
has_camera = FALSE
req_one_access = list(ACCESS_CENT_SPECOPS)
ionpulse = 1
magpulse = 1
pdahide = 1
eye_protection = 2 // Immunity to flashes and the visual part of flashbangs
ear_protection = 1 // Immunity to the audio part of flashbangs
emp_protection = TRUE // Immunity to EMP, due to heavy shielding
damage_protection = 20 // Reduce all incoming damage by this number. Very high in the case of /destroyer borgs, since it is an admin-only borg.
xeno_disarm_chance = 10
default_cell_type = /obj/item/stock_parts/cell/bluespace
/mob/living/silicon/robot/destroyer/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
aiCamera = new/obj/item/camera/siliconcam/robot_camera(src)
additional_law_channels["Binary"] = ":b "
laws = new /datum/ai_laws/deathsquad
module = new /obj/item/robot_module/destroyer(src)
module.add_languages(src)
module.add_subsystems_and_actions(src)
status_flags &= ~CANPUSH
if(radio)
qdel(radio)
radio = new /obj/item/radio/borg/ert/specops(src)
radio.recalculateChannels()
playsound(loc, 'sound/mecha/nominalsyndi.ogg', 75, 0)
/mob/living/silicon/robot/destroyer/borg_icons()
if(base_icon == "")
base_icon = icon_state
if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility))
icon_state = "[base_icon]-roll"
else
icon_state = base_icon
overlays += "[base_icon]-shield"
/mob/living/silicon/robot/extinguish_light()
update_headlamp(1, 150)
@@ -76,29 +76,6 @@
if(!LAZYLEN(components))
return
//Combat shielding absorbs a percentage of damage directly into the cell.
var/obj/item/borg/combat/shield/shield
if(module_state_1 && istype(module_state_1, /obj/item/borg/combat/shield))
shield = module_state_1
else if(module_state_2 && istype(module_state_2, /obj/item/borg/combat/shield))
shield = module_state_2
else if(module_state_3 && istype(module_state_3, /obj/item/borg/combat/shield))
shield = module_state_3
if(shield)
//Shields absorb a certain percentage of damage based on their power setting.
var/absorb_brute = brute * shield.shield_level
var/absorb_burn = burn * shield.shield_level
var/cost = (absorb_brute+absorb_burn) * 100
cell.charge -= cost
if(cell.charge <= 0)
cell.charge = 0
to_chat(src, "<span class='warning'>Your shield has overloaded!</span>")
else
brute -= absorb_brute
burn -= absorb_burn
to_chat(src, "<span class='warning'>Your shield absorbs some of the impact!</span>")
var/datum/robot_component/armour/A = get_armour()
if(A)
A.take_damage(brute, burn, sharp, updating_health)
@@ -127,32 +104,15 @@
updatehealth("heal overall damage")
/mob/living/silicon/robot/take_overall_damage(brute = 0, burn = 0, updating_health = TRUE, used_weapon = null, sharp = 0)
if(status_flags & GODMODE) return //godmode
if(status_flags & GODMODE)
return
if(damage_protection)
brute = clamp(brute - damage_protection, 0, brute)
burn = clamp(burn - damage_protection, 0, burn)
var/list/datum/robot_component/parts = get_damageable_components()
//Combat shielding absorbs a percentage of damage directly into the cell.
var/obj/item/borg/combat/shield/shield
if(module_state_1 && istype(module_state_1, /obj/item/borg/combat/shield))
shield = module_state_1
else if(module_state_2 && istype(module_state_2, /obj/item/borg/combat/shield))
shield = module_state_2
else if(module_state_3 && istype(module_state_3, /obj/item/borg/combat/shield))
shield = module_state_3
if(shield)
//Shields absorb a certain percentage of damage based on their power setting.
var/absorb_brute = brute * shield.shield_level
var/absorb_burn = burn * shield.shield_level
var/cost = (absorb_brute+absorb_burn) * 100
cell.charge -= cost
if(cell.charge <= 0)
cell.charge = 0
to_chat(src, "<span class='warning'>Your shield has overloaded!</span>")
else
brute -= absorb_brute
burn -= absorb_burn
to_chat(src, "<span class='warning'>Your shield absorbs some of the impact!</span>")
var/datum/robot_component/armour/A = get_armour()
if(A)
A.take_damage(brute, burn, sharp)
@@ -2,7 +2,7 @@
if(M.a_intent == INTENT_DISARM)
if(!lying)
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
if(prob(85))
if(prob(xeno_disarm_chance))
Stun(7)
step(src, get_dir(M,src))
spawn(5)
@@ -73,24 +73,7 @@
/obj/item/borg
var/powerneeded // Percentage of power remaining required to run item
/obj/item/borg/combat/shield
name = "personal shielding"
desc = "A powerful experimental module that turns aside or absorbs incoming attacks at the cost of charge."
icon = 'icons/obj/decals.dmi'
icon_state = "shock"
powerneeded = 25
var/shield_level = 0.5 //Percentage of damage absorbed by the shield.
/obj/item/borg/combat/shield/verb/set_shield_level()
set name = "Set shield level"
set category = "Object"
set src in range(0)
var/N = input("How much damage should the shield absorb?") in list("5","10","25","50","75","100")
if(N)
shield_level = text2num(N)/100
/obj/item/borg/combat/mobility
/obj/item/borg/destroyer/mobility
name = "mobility module"
desc = "By retracting limbs and tucking in its head, a combat android can roll at high speeds."
icon = 'icons/obj/decals.dmi'
@@ -118,20 +118,48 @@
return
/obj/item/robot_module/standard
name = "standard robot module"
// if station is fine, assist with constructing station goal room, cleaning, and repairing cables chewed by rats
// if medical crisis, assist by providing basic healthcare, retrieving corpses, and monitoring crew lifesigns
// if eng crisis, assist by helping repair hull breaches
// if sec crisis, assist by opening doors for sec and providing backup zipties on patrols
name = "generalist robot module"
module_type = "Standard"
subsystems = list(/mob/living/silicon/proc/subsystem_power_monitor, /mob/living/silicon/proc/subsystem_crew_monitor)
stacktypes = list(
/obj/item/stack/sheet/metal/cyborg = 50,
/obj/item/stack/cable_coil/cyborg = 50,
/obj/item/stack/rods/cyborg = 60,
/obj/item/stack/tile/plasteel = 20
)
/obj/item/robot_module/standard/New()
..()
modules += new /obj/item/melee/baton/loaded(src)
modules += new /obj/item/extinguisher(src)
modules += new /obj/item/wrench/cyborg(src)
// sec
modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
// janitorial
modules += new /obj/item/soap/nanotrasen(src)
modules += new /obj/item/lightreplacer/cyborg(src)
// eng
modules += new /obj/item/crowbar/cyborg(src)
modules += new /obj/item/wrench/cyborg(src)
modules += new /obj/item/extinguisher(src) // for firefighting, and propulsion in space
modules += new /obj/item/weldingtool/largetank/cyborg(src)
// mining
modules += new /obj/item/pickaxe(src)
modules += new /obj/item/t_scanner/adv_mining_scanner(src)
modules += new /obj/item/storage/bag/ore/cyborg(src)
// med
modules += new /obj/item/healthanalyzer(src)
modules += new /obj/item/reagent_containers/borghypo/basic(src)
modules += new /obj/item/roller_holder(src) // for taking the injured to medbay without worsening their injuries or leaving a blood trail the whole way
emag = new /obj/item/melee/energy/sword/cyborg(src)
for(var/G in stacktypes)
var/obj/item/stack/sheet/M = new G(src)
M.amount = stacktypes[G]
modules += M
fix_modules()
/obj/item/robot_module/medical
name = "medical robot module"
module_type = "Medical"
@@ -259,6 +287,7 @@
modules += new /obj/item/mop/advanced/cyborg(src)
modules += new /obj/item/lightreplacer/cyborg(src)
modules += new /obj/item/holosign_creator(src)
modules += new /obj/item/extinguisher/mini(src)
emag = new /obj/item/reagent_containers/spray(src)
emag.reagents.add_reagent("lube", 250)
@@ -483,25 +512,44 @@
fix_modules()
/obj/item/robot_module/combat
name = "combat robot module"
/obj/item/robot_module/destroyer
name = "destroyer robot module"
module_type = "Malf"
module_actions = list(
/datum/action/innate/robot_sight/thermal,
)
/obj/item/robot_module/destroyer/New()
..()
modules += new /obj/item/gun/energy/immolator/multi/cyborg(src) // See comments on /robot_module/combat below
modules += new /obj/item/melee/baton/loaded(src) // secondary weapon, for things immune to burn, immune to ranged weapons, or for arresting low-grade threats
modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
modules += new /obj/item/pickaxe/drill/jackhammer(src) // for breaking walls to execute flanking moves
modules += new /obj/item/borg/destroyer/mobility(src)
emag = null
fix_modules()
/obj/item/robot_module/combat
name = "combat robot module"
module_type = "Malf"
module_actions = list()
/obj/item/robot_module/combat/New()
..()
modules += new /obj/item/gun/energy/immolator/multi/cyborg(src) // primary weapon, strong at close range (ie: against blob/terror/xeno), but consumes a lot of energy per shot.
// Borg gets 40 shots of this weapon. Gamma Sec ERT gets 10.
// So, borg has way more burst damage, but also takes way longer to recharge / get back in the fight once depleted. Has to find a borg recharger and sit in it for ages.
// Organic gamma sec ERT carries alternate weapons, including a box of flashbangs, and can load up on a huge number of guns from science. Borg cannot do either.
// Overall, gamma borg has higher skill floor but lower skill ceiling.
modules += new /obj/item/melee/baton/loaded(src) // secondary weapon, for things immune to burn, immune to ranged weapons, or for arresting low-grade threats
modules += new /obj/item/restraints/handcuffs/cable/zipties/cyborg(src)
modules += new /obj/item/gun/energy/gun/cyborg(src)
modules += new /obj/item/pickaxe/drill/jackhammer(src)
modules += new /obj/item/borg/combat/shield(src)
modules += new /obj/item/borg/combat/mobility(src)
modules += new /obj/item/wrench/cyborg(src)
emag = new /obj/item/gun/energy/lasercannon/cyborg(src)
modules += new /obj/item/pickaxe/drill/jackhammer(src) // for breaking walls to execute flanking moves
emag = null
fix_modules()
/obj/item/robot_module/alien/hunter
name = "alien hunter module"
module_type = "Standard"
@@ -9,7 +9,7 @@
/mob/living/silicon/robot/movement_delay()
. = ..()
. += speed
if(module_active && istype(module_active,/obj/item/borg/combat/mobility))
if(module_active && istype(module_active,/obj/item/borg/destroyer/mobility))
. -= 3
. += config.robot_delay
@@ -3,8 +3,10 @@
icon_state = "syndie_bloodhound"
lawupdate = 0
scrambledcodes = 1
has_camera = FALSE
pdahide = 1
faction = list("syndicate")
bubble_icon = "syndibot"
designation = "Syndicate Assault"
modtype = "Syndicate"
req_access = list(ACCESS_SYNDICATE)
@@ -19,7 +21,7 @@
..()
cell = new /obj/item/stock_parts/cell/hyper(src)
/mob/living/silicon/robot/syndicate/init()
/mob/living/silicon/robot/syndicate/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
laws = new /datum/ai_laws/syndicate_override
module = new /obj/item/robot_module/syndicate(src)
@@ -45,7 +47,7 @@
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>"
/mob/living/silicon/robot/syndicate/medical/init()
/mob/living/silicon/robot/syndicate/medical/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
..()
module = new /obj/item/robot_module/syndicate_medical(src)
@@ -65,7 +67,7 @@
Be aware that physical contact or taking damage will break your disguise. \
<i>Help the operatives secure the disk at all costs!</i></b>"
/mob/living/silicon/robot/syndicate/saboteur/init()
/mob/living/silicon/robot/syndicate/saboteur/init(alien = FALSE, mob/living/silicon/ai/ai_to_sync_to = null)
..()
module = new /obj/item/robot_module/syndicate_saboteur(src)
+3 -1
View File
@@ -2,7 +2,9 @@
gender = NEUTER
robot_talk_understand = 1
voice_name = "synthesized voice"
bubble_icon = "machine"
has_unlimited_silicon_privilege = 1
weather_immunities = list("ash")
var/syndicate = 0
var/const/MAIN_CHANNEL = "Main Frequency"
var/lawchannel = MAIN_CHANNEL // Default channel on which to state laws
@@ -283,7 +285,7 @@
/mob/living/silicon/proc/receive_alarm(var/datum/alarm_handler/alarm_handler, var/datum/alarm/alarm, was_raised)
if(!next_alarm_notice)
next_alarm_notice = world.time + SecondsToTicks(10)
next_alarm_notice = world.time + 10 SECONDS
var/list/alarms = queued_alarms[alarm_handler]
if(was_raised)
@@ -2,7 +2,7 @@
var/register_alarms = 1
var/datum/nano_module/alarm_monitor/all/alarm_monitor
var/datum/nano_module/atmos_control/atmos_control
var/datum/nano_module/crew_monitor/crew_monitor
var/datum/tgui_module/crew_monitor/crew_monitor
var/datum/nano_module/law_manager/law_manager
var/datum/nano_module/power_monitor/silicon/power_monitor
@@ -71,8 +71,7 @@
/mob/living/silicon/proc/subsystem_crew_monitor()
set category = "Subsystems"
set name = "Crew Monitor"
crew_monitor.ui_interact(usr, state = GLOB.self_state)
crew_monitor.tgui_interact(usr, state = GLOB.tgui_self_state)
/****************
* Law Manager *
@@ -118,7 +118,7 @@
/mob/living/simple_animal/blob_act(obj/structure/blob/B)
adjustBruteLoss(20)
/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
/mob/living/simple_animal/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
if(!no_effect && !visual_effect_icon && melee_damage_upper)
if(melee_damage_upper < 10)
visual_effect_icon = ATTACK_EFFECT_PUNCH
@@ -18,7 +18,7 @@
speak_emote = list("states")
friendly = "boops"
bubble_icon = "machine"
faction = list("neutral", "silicon")
var/obj/machinery/bot_core/bot_core = null
@@ -63,6 +63,7 @@
var/new_destination // pending new destination (waiting for beacon response)
var/destination // destination description tag
var/next_destination // the next destination in the patrol route
var/ignorelistcleanuptimer = 1 // This ticks up every automated action, at 300 we clean the ignore list
var/robot_arm = /obj/item/robot_parts/r_arm
var/blockcount = 0 //number of times retried a blocked path
@@ -254,6 +255,15 @@
/mob/living/simple_animal/bot/handle_automated_action()
diag_hud_set_botmode()
if(ignorelistcleanuptimer % 300 == 0) // Every 300 actions, clean up the ignore list from old junk
for(var/uid in ignore_list)
var/atom/referredatom = locateUID(uid)
if(!referredatom || QDELETED(referredatom))
ignore_list -= uid
ignorelistcleanuptimer = 1
else
ignorelistcleanuptimer++
if(!on)
return
@@ -439,14 +449,15 @@ Example usage: patient = scan(/mob/living/carbon/human, oldpatient, 1)
The proc would return a human next to the bot to be set to the patient var.
Pass the desired type path itself, declaring a temporary var beforehand is not required.
*/
/mob/living/simple_animal/bot/proc/scan(scan_type, old_target, scan_range = DEFAULT_SCAN_RANGE)
/mob/living/simple_animal/bot/proc/scan(atom/scan_type, atom/old_target, scan_range = DEFAULT_SCAN_RANGE)
var/final_result
for(var/scan in shuffle(view(scan_range, src))) //Search for something in range!
if(!istype(scan, scan_type)) //Check that the thing we found is the type we want!
var/atom/A = scan
if(!istype(A, scan_type)) //Check that the thing we found is the type we want!
continue //If not, keep searching!
if( (scan in ignore_list) || (scan == old_target) ) //Filter for blacklisted elements, usually unreachable or previously processed oness
if((A.UID() in ignore_list) || (A == old_target) ) //Filter for blacklisted elements, usually unreachable or previously processed oness
continue
var/scan_result = process_scan(scan) //Some bots may require additional processing when a result is selected.
var/scan_result = process_scan(A) //Some bots may require additional processing when a result is selected.
if(scan_result)
final_result = scan_result
else
@@ -454,17 +465,16 @@ Pass the desired type path itself, declaring a temporary var beforehand is not r
return final_result
//When the scan finds a target, run bot specific processing to select it for the next step. Empty by default.
/mob/living/simple_animal/bot/proc/process_scan(scan_target)
/mob/living/simple_animal/bot/proc/process_scan(atom/scan_target)
return scan_target
/mob/living/simple_animal/bot/proc/add_to_ignore(subject)
/mob/living/simple_animal/bot/proc/add_to_ignore(atom/A)
if(ignore_list.len < 50) //This will help keep track of them, so the bot is always trying to reach a blocked spot.
ignore_list |= subject
else if(ignore_list.len >= subject) //If the list is full, insert newest, delete oldest.
ignore_list -= ignore_list[1]
ignore_list |= subject
ignore_list |= A.UID()
else //If the list is full, insert newest, delete oldest.
ignore_list.Cut(1, 2)
ignore_list |= A.UID()
/*
Movement proc for stepping a bot through a path generated through A-star.
Pass a positive integer as an argument to override a bot's default speed.
@@ -746,7 +756,7 @@ Pass a positive integer as an argument to override a bot's default speed.
// send a radio signal with multiple data key/values
/mob/living/simple_animal/bot/proc/post_signal_multiple(var/freq, var/list/keyval)
if(z != 1) //Bot control will only work on station.
if(!is_station_level(z)) //Bot control will only work on station.
return
var/datum/radio_frequency/frequency = SSradio.return_frequency(freq)
if(!frequency)
@@ -50,7 +50,7 @@
/mob/living/simple_animal/bot/cleanbot/bot_reset()
..()
ignore_list = list() //Allows the bot to clean targets it previously ignored due to being unreachable.
ignore_list.Cut() //Allows the bot to clean targets it previously ignored due to being unreachable.
target = null
oldloc = null
@@ -106,7 +106,7 @@
audible_message("[src] makes an excited beeping booping sound!")
if(!target) //Search for cleanables it can see.
target = scan(/obj/effect/decal/cleanable/)
target = scan(/obj/effect/decal/cleanable)
if(!target && auto_patrol) //Search for cleanables it can see.
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
@@ -474,8 +474,7 @@
return
build_step++
to_chat(user, "<span class='notice'>You complete the Securitron! Beep boop.</span>")
var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot
S.forceMove(get_turf(src))
var/mob/living/simple_animal/bot/secbot/S = new /mob/living/simple_animal/bot/secbot(get_turf(src))
S.name = created_name
S.robot_arm = robot_arm
qdel(I)
@@ -512,7 +511,7 @@
//General Griefsky
else if((istype(I, /obj/item/wrench)) && (build_step == 3))
var/obj/item/griefsky_assembly/A = new /obj/item/griefsky_assembly
var/obj/item/griefsky_assembly/A = new /obj/item/griefsky_assembly(get_turf(src))
user.put_in_hands(A)
to_chat(user, "<span class='notice'>You adjust the arm slots for extra weapons!.</span>")
user.unEquip(src, 1)
@@ -540,8 +539,7 @@
if(!user.unEquip(I))
return
to_chat(user, "<span class='notice'>You complete General Griefsky!.</span>")
var/mob/living/simple_animal/bot/secbot/griefsky/S = new /mob/living/simple_animal/bot/secbot/griefsky
S.forceMove(get_turf(src))
new /mob/living/simple_animal/bot/secbot/griefsky(get_turf(src))
qdel(I)
qdel(src)
@@ -556,8 +554,7 @@
if(!user.unEquip(I))
return
to_chat(user, "<span class='notice'>You complete Genewul Giftskee!.</span>")
var/mob/living/simple_animal/bot/secbot/griefsky/toy/S = new /mob/living/simple_animal/bot/secbot/griefsky/toy
S.forceMove(get_turf(src))
new /mob/living/simple_animal/bot/secbot/griefsky/toy(get_turf(src))
qdel(I)
qdel(src)
@@ -56,7 +56,7 @@
..()
target = null
oldloc = null
ignore_list = list()
ignore_list.Cut()
nagged = 0
anchored = FALSE
update_icon()
@@ -270,7 +270,7 @@
return 1
//Floorbots, having several functions, need sort out special conditions here.
/mob/living/simple_animal/bot/floorbot/process_scan(scan_target)
/mob/living/simple_animal/bot/floorbot/process_scan(atom/scan_target)
var/result
var/turf/simulated/floor/F
switch(process_type)
@@ -33,7 +33,7 @@
/obj/machinery/bot_core/honkbot
req_one_access = list(ACCESS_CLOWN, ACCESS_ROBOTICS, ACCESS_MIME)
/mob/living/simple_animal/bot/honkbot/Initialize()
/mob/living/simple_animal/bot/honkbot/Initialize(mapload)
. = ..()
update_icon()
auto_patrol = TRUE
@@ -323,13 +323,13 @@
/mob/living/simple_animal/bot/mulebot/proc/buzz(type)
switch(type)
if(SIGH)
audible_message("[src] makes a sighing buzz.", "<span class='emote'>You hear an electronic buzzing sound.</span>")
audible_message("[src] makes a sighing buzz.")
playsound(loc, 'sound/machines/buzz-sigh.ogg', 50, 0)
if(ANNOYED)
audible_message("[src] makes an annoyed buzzing sound.", "<span class='emote'>You hear an electronic buzzing sound.</span>")
audible_message("[src] makes an annoyed buzzing sound.")
playsound(loc, 'sound/machines/buzz-two.ogg', 50, 0)
if(DELIGHT)
audible_message("[src] makes a delighted ping!", "<span class='emote'>You hear a ping.</span>")
audible_message("[src] makes a delighted ping!")
playsound(loc, 'sound/machines/ping.ogg', 50, 0)
@@ -601,7 +601,7 @@
/mob/living/simple_animal/bot/mulebot/proc/at_target()
if(!reached_target)
radio_channel = "Supply" //Supply channel
audible_message("[src] makes a chiming sound!", "<span class='emote'>You hear a chime.</span>")
audible_message("[src] makes a chiming sound!")
playsound(loc, 'sound/machines/chime.ogg', 50, 0)
reached_target = 1
@@ -103,9 +103,9 @@
name = "Space Wizard Corpse"
outfit = /datum/outfit/wizardcorpse
/obj/effect/mob_spawn/human/corpse/clownoff/Initialize()
/obj/effect/mob_spawn/human/corpse/clownoff/Initialize(mapload)
mob_name = "[pick(GLOB.wizard_first)], [pick(GLOB.wizard_second)]"
..()
. = ..()
/datum/outfit/wizardcorpse
name = "Space Wizard Corpse"
@@ -3,7 +3,7 @@
if(status_flags & GODMODE)
return FALSE
var/oldbruteloss = bruteloss
bruteloss = Clamp(bruteloss + amount, 0, maxHealth)
bruteloss = clamp(bruteloss + amount, 0, maxHealth)
if(oldbruteloss == bruteloss)
updating_health = FALSE
. = STATUS_UPDATE_NONE
@@ -123,6 +123,7 @@
for(var/mob/living/simple_animal/mouse/M in view(1, src))
if(!M.stat && Adjacent(M))
custom_emote(1, "splats \the [M]!")
M.death()
M.splat()
movement_target = null
stop_automated_movement = 0
@@ -153,16 +153,16 @@
if(def_zone)
if(def_zone == "head")
if(inventory_head)
armorval = inventory_head.armor[type]
armorval = inventory_head.armor.getRating(type)
else
if(inventory_back)
armorval = inventory_back.armor[type]
armorval = inventory_back.armor.getRating(type)
return armorval
else
if(inventory_head)
armorval += inventory_head.armor[type]
armorval += inventory_head.armor.getRating(type)
if(inventory_back)
armorval += inventory_back.armor[type]
armorval += inventory_back.armor.getRating(type)
return armorval * 0.5
/mob/living/simple_animal/pet/dog/corgi/attackby(obj/item/O, mob/user, params)
@@ -126,6 +126,7 @@
gold_core_spawnable = FRIENDLY_SPAWN
blood_volume = BLOOD_VOLUME_NORMAL
var/obj/item/udder/udder = null
gender = FEMALE
/mob/living/simple_animal/cow/Initialize()
udder = new()
@@ -23,3 +23,14 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat = 1)
can_collar = 1
gold_core_spawnable = FRIENDLY_SPAWN
/mob/living/simple_animal/lizard/decompile_act(obj/item/matter_decompiler/C, mob/user)
if(!istype(user, /mob/living/silicon/robot/drone))
user.visible_message("<span class='notice'>[user] sucks [src] into its decompiler. There's a horrible crunching noise.</span>", \
"<span class='warning'>It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.</span>")
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
C.stored_comms["wood"] += 2
C.stored_comms["glass"] += 2
qdel(src)
return TRUE
return ..()
@@ -80,15 +80,6 @@
icon_resting = "mouse_[mouse_color]_sleep"
desc = "It's a small [mouse_color] rodent, often seen hiding in maintenance areas and making a nuisance of itself."
/mob/living/simple_animal/mouse/proc/splat()
src.health = 0
src.stat = DEAD
src.icon_dead = "mouse_[mouse_color]_splat"
src.icon_state = "mouse_[mouse_color]_splat"
layer = MOB_LAYER
if(client)
client.time_died_as_mouse = world.time
/mob/living/simple_animal/mouse/attack_hand(mob/living/carbon/human/M as mob)
if(M.a_intent == INTENT_HELP)
get_scooped(M)
@@ -113,6 +104,10 @@
desc = "It's toast."
death()
/mob/living/simple_animal/mouse/proc/splat()
icon_dead = "mouse_[mouse_color]_splat"
icon_state = "mouse_[mouse_color]_splat"
/mob/living/simple_animal/mouse/death(gibbed)
// Only execute the below if we successfully died
playsound(src, squeak_sound, 40, 1)
@@ -237,3 +232,14 @@
gold_core_spawnable = NO_SPAWN
can_collar = 0
butcher_results = list(/obj/item/stack/sheet/metal = 1)
/mob/living/simple_animal/mouse/decompile_act(obj/item/matter_decompiler/C, mob/user)
if(!(istype(user, /mob/living/silicon/robot/drone)))
user.visible_message("<span class='notice'>[user] sucks [src] into its decompiler. There's a horrible crunching noise.</span>", \
"<span class='warning'>It's a bit of a struggle, but you manage to suck [src] into your decompiler. It makes a series of visceral crunching noises.</span>")
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
C.stored_comms["wood"] += 2
C.stored_comms["glass"] += 2
qdel(src)
return TRUE
return ..()
@@ -18,7 +18,7 @@
/mob/living/simple_animal/pet/penguin/Initialize(mapload)
. = ..()
AddComponent(/datum/component/waddling)
AddElement(/datum/element/waddling)
/mob/living/simple_animal/pet/penguin/emperor
name = "Emperor penguin"
@@ -123,8 +123,6 @@
if(health >= maxHealth)
to_chat(user, "<span class='warning'>[src] does not need repairing!</span>")
return
to_chat(user, "<span class='warning'>Unable to repair with the maintenance panel closed!</span>")
return
. = TRUE
if(!I.use_tool(src, user, volume = I.tool_volume))
return
@@ -20,6 +20,7 @@
melee_damage_upper = 25
attacktext = "slashes"
speak_emote = list("hisses")
bubble_icon = "alien"
a_intent = INTENT_HARM
attack_sound = 'sound/weapons/bladeslice.ogg'
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)
@@ -127,6 +128,7 @@
icon_state = "queen_s"
icon_living = "queen_s"
icon_dead = "queen_dead"
bubble_icon = "alienroyal"
move_to_delay = 4
maxHealth = 400
health = 400
@@ -153,7 +155,7 @@
icon_dead = "maid_dead"
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
if(ismovableatom(target))
if(ismovable(target))
if(istype(target, /obj/effect/decal/cleanable))
visible_message("<span class='notice'>\The [src] cleans up \the [target].</span>")
qdel(target)
@@ -60,6 +60,7 @@
/mob/living/simple_animal/hostile/poison/bees/New()
..()
generate_bee_visuals()
AddComponent(/datum/component/swarming)
/mob/living/simple_animal/hostile/poison/bees/Destroy()
beegent = null
@@ -94,6 +95,10 @@
for(var/mob/A in searched_for)
. += A
// All bee sprites are made up of overlays. They do not have any special sprite overlays for items placed on them, such as collars, so this proc is unneeded.
/mob/living/simple_animal/hostile/poison/bees/regenerate_icons()
return
/mob/living/simple_animal/hostile/poison/bees/proc/generate_bee_visuals()
overlays.Cut()
@@ -25,23 +25,20 @@
var/list/human_overlays = list()
/mob/living/simple_animal/hostile/headcrab/Life(seconds, times_fired)
if(..())
if(..() && !stat)
if(!is_zombie && isturf(src.loc))
for(var/mob/living/carbon/human/H in oview(src, 1)) //Only for corpse right next to/on same tile
if(H.stat == DEAD || (!H.check_death_method() && H.health <= HEALTH_THRESHOLD_DEAD))
Zombify(H)
break
var/cycles = 4
if(cycles >= 4)
if(times_fired % 4 == 0)
for(var/mob/living/simple_animal/K in oview(src, 1)) //Only for corpse right next to/on same tile
if(K.stat == DEAD || (!K.check_death_method() && K.health <= HEALTH_THRESHOLD_DEAD))
visible_message("<span class='danger'>[src] consumes [target] whole!</span>")
visible_message("<span class='danger'>[src] consumes [K] whole!</span>")
if(health < maxHealth)
health += 10
qdel(K)
break
cycles = 0
cycles++
/mob/living/simple_animal/hostile/headcrab/OpenFire(atom/A)
if(check_friendly_fire)
@@ -62,8 +59,8 @@
is_zombie = TRUE
if(H.wear_suit)
var/obj/item/clothing/suit/armor/A = H.wear_suit
if(A.armor && A.armor["melee"])
maxHealth += A.armor["melee"] //That zombie's got armor, I want armor!
if(A.armor && A.armor.getRating("melee"))
maxHealth += A.armor.getRating("melee") //That zombie's got armor, I want armor!
maxHealth += 200
health = maxHealth
name = "zombie"
@@ -93,7 +90,6 @@
if(is_zombie)
qdel(src)
/mob/living/simple_animal/hostile/headcrab/handle_automated_speech() // This way they have different screams when attacking, sometimes. Might be seen as sphagetthi code though.
if(speak_chance)
if(rand(0,200) < speak_chance)
@@ -106,7 +102,6 @@
M.loc = get_turf(src)
return ..()
/mob/living/simple_animal/hostile/headcrab/update_icons()
. = ..()
if(is_zombie)
@@ -72,7 +72,7 @@
/obj/item/organ/internal/body_egg/changeling_egg/proc/Pop()
var/mob/living/carbon/human/monkey/M = new(owner)
owner.stomach_contents += M
LAZYADD(owner.stomach_contents, M)
for(var/obj/item/organ/internal/I in src)
I.insert(M, 1)
@@ -25,6 +25,7 @@
gold_core_spawnable = HOSTILE_SPAWN
loot = list(/obj/effect/decal/cleanable/blood/gibs/robot)
deathmessage = "blows apart!"
bubble_icon = "machine"
del_on_death = 1
/mob/living/simple_animal/hostile/hivebot/range
@@ -116,8 +116,8 @@ Difficulty: Hard
if(charging)
return
anger_modifier = Clamp(((maxHealth - health)/60),0,20)
enrage_time = initial(enrage_time) * Clamp(anger_modifier / 20, 0.5, 1)
anger_modifier = clamp(((maxHealth - health)/60),0,20)
enrage_time = initial(enrage_time) * clamp(anger_modifier / 20, 0.5, 1)
ranged_cooldown = world.time + 50
if(client)
@@ -83,7 +83,7 @@ Difficulty: Very Hard
chosen_attack_num = 4
/mob/living/simple_animal/hostile/megafauna/colossus/OpenFire()
anger_modifier = Clamp(((maxHealth - health)/50),0,20)
anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + 120
if(client)
@@ -103,7 +103,7 @@ Difficulty: Medium
if(swooping)
return
anger_modifier = Clamp(((maxHealth - health)/50),0,20)
anger_modifier = clamp(((maxHealth - health)/50),0,20)
ranged_cooldown = world.time + ranged_cooldown_time
if(client)
@@ -254,7 +254,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/proc/line_target(var/offset, var/range, var/atom/at = target)
if(!at)
return
var/angle = Atan2(at.x - src.x, at.y - src.y) + offset
var/angle = ATAN2(at.x - src.x, at.y - src.y) + offset
var/turf/T = get_turf(src)
for(var/i in 1 to range)
var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z)
@@ -344,10 +344,10 @@ Difficulty: Medium
//ensure swoop direction continuity.
if(negative)
if(IsInRange(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
if(ISINRANGE(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
negative = FALSE
else
if(IsInRange(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
if(ISINRANGE(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
negative = TRUE
new /obj/effect/temp_visual/dragon_flight/end(loc, negative)
new /obj/effect/temp_visual/dragon_swoop(loc)
@@ -534,7 +534,7 @@ obj/effect/temp_visual/fireball
duration = 9
pixel_z = 270
/obj/effect/temp_visual/fireball/Initialize()
/obj/effect/temp_visual/fireball/Initialize(mapload)
. = ..()
animate(src, pixel_z = 0, time = duration)
@@ -452,6 +452,7 @@ Difficulty: Hard
else
burst_range = 3
INVOKE_ASYNC(src, .proc/burst, get_turf(src), 0.25) //melee attacks on living mobs cause it to release a fast burst if on cooldown
OpenFire()
else
devour(L)
else
@@ -481,7 +482,7 @@ Difficulty: Hard
/mob/living/simple_animal/hostile/megafauna/hierophant/proc/calculate_rage() //how angry we are overall
did_reset = FALSE //oh hey we're doing SOMETHING, clearly we might need to heal if we recall
anger_modifier = Clamp(((maxHealth - health) / 42),0,50)
anger_modifier = clamp(((maxHealth - health) / 42),0,50)
burst_range = initial(burst_range) + round(anger_modifier * 0.08)
beam_range = initial(beam_range) + round(anger_modifier * 0.12)
@@ -43,7 +43,6 @@
. = ..()
if(internal_type && true_spawn)
internal = new internal_type(src)
apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
for(var/action_type in attack_action_types)
var/datum/action/innate/megafauna_attack/attack_action = new action_type()
attack_action.Grant(src)
@@ -48,8 +48,8 @@
var/attempt_open = 0
// Pickup loot
/mob/living/simple_animal/hostile/mimic/crate/Initialize()
..()
/mob/living/simple_animal/hostile/mimic/crate/Initialize(mapload)
. = ..()
for(var/obj/item/I in loc)
I.loc = src
@@ -90,6 +90,7 @@
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/Initialize(mapload)
. = ..()
addtimer(CALLBACK(src, .proc/death), 100)
AddComponent(/datum/component/swarming)
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/blood
@@ -23,10 +23,6 @@
var/icon_aggro = null
var/crusher_drop_mod = 25
/mob/living/simple_animal/hostile/asteroid/Initialize(mapload)
. = ..()
apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
if(vision_range != aggro_vision_range)
@@ -31,7 +31,7 @@
deathmessage = "wails as its form turns into a pulpy mush."
death_sound = 'sound/voice/hiss6.ogg'
/mob/living/simple_animal/hostile/netherworld/migo/Initialize()
/mob/living/simple_animal/hostile/netherworld/migo/Initialize(mapload)
. = ..()
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/voice/bcreep.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/mpatchedup.ogg', 'sound/voice/mfeelbetter.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heartbeat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/goonstation/effects/screech.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/goonstation/misc/airraid_loop.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/chainsaw.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshots/gunshot_silenced.ogg', 'sound/weapons/gunshots/gunshot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlock_close.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlock_open.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/outbreak5.ogg', 'sound/ai/outbreak7.ogg', 'sound/ai/poweroff.ogg', 'sound/ai/radiation.ogg', 'sound/ai/shuttlecalled.ogg', 'sound/ai/shuttledock.ogg', 'sound/ai/shuttlerecalled.ogg', 'sound/ai/aimalf.ogg', 'sound/ambience/ambigen1.ogg', 'sound/ambience/ambigen3.ogg', 'sound/ambience/ambigen4.ogg', 'sound/ambience/ambigen5.ogg', 'sound/ambience/ambigen6.ogg', 'sound/ambience/ambigen10.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg') //hahahaha fuck you code divers
@@ -82,14 +82,14 @@
/obj/structure/spawner/nether/examine(mob/user)
. = ..()
if(isskeleton(user) || iszombie(user))
if(isskeleton(user))
. += "A direct link to another dimension full of creatures very happy to see you. <span class='nicegreen'>You can see your house from here!</span>"
else
. += "A direct link to another dimension full of creatures not very happy to see you. <span class='warning'>Entering the link would be a very bad idea.</span>"
/obj/structure/spawner/nether/attack_hand(mob/user)
. = ..()
if(isskeleton(user) || iszombie(user))
if(isskeleton(user))
to_chat(user, "<span class='notice'>You don't feel like going home yet...</span>")
else
user.visible_message("<span class='warning'>[user] is violently pulled into the link!</span>", \
@@ -335,7 +335,7 @@
//Jiggle the whole worm forwards towards the next segment
/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
/mob/living/simple_animal/hostile/spaceWorm/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
..()
if(previousWorm)
previousWorm.do_attack_animation(src)
@@ -260,7 +260,7 @@
alert_on_shield_breach = TRUE
/mob/living/simple_animal/hostile/syndicate/melee/autogib/depot/armory/Initialize(mapload)
..()
. = ..()
if(prob(50))
// 50% chance of switching to extremely dangerous ranged variant
melee_damage_lower = 10
@@ -349,7 +349,8 @@
icon = 'icons/mob/critter.dmi'
icon_state = "viscerator_attack"
icon_living = "viscerator_attack"
pass_flags = PASSTABLE
pass_flags = PASSTABLE | PASSMOB
a_intent = INTENT_HARM
health = 15
maxHealth = 15
obj_damage = 0
@@ -362,6 +363,11 @@
minbodytemp = 0
mob_size = MOB_SIZE_TINY
flying = 1
bubble_icon = "syndibot"
gold_core_spawnable = HOSTILE_SPAWN
del_on_death = 1
deathmessage = "is smashed into pieces!"
/mob/living/simple_animal/hostile/viscerator/Initialize(mapload)
. = ..()
AddComponent(/datum/component/swarming)
@@ -15,7 +15,7 @@
ai_target_method = TS_DAMAGE_SIMPLE
icon_state = "terror_princess1"
icon_living = "terror_princess1"
icon_dead = "terror_princess_dead1"
icon_dead = "terror_princess1_dead"
maxHealth = 150
health = 150
regen_points_per_hp = 1 // always regens very fast
@@ -51,7 +51,7 @@
if(fed == 0)
icon_state = "terror_princess1"
icon_living = "terror_princess1"
icon_dead = "terror_princess_dead1"
icon_dead = "terror_princess1_dead"
desc = "An enormous spider. It looks strangely cute and fluffy, with soft pink fur covering most of its body."
else if(fed == 1)
icon_state = "terror_princess2"
@@ -168,7 +168,7 @@
neststep = 4
else
spider_lastspawn = world.time
var/spiders_left_to_spawn = Clamp( (spider_max_per_nest - CountSpiders()), 1, 10)
var/spiders_left_to_spawn = clamp( (spider_max_per_nest - CountSpiders()), 1, 10)
DoLayTerrorEggs(pick(spider_types_standard), spiders_left_to_spawn)
if(4)
// Nest should be full. Otherwise, start replenishing nest (stage 5).
@@ -710,7 +710,7 @@
ears.talk_into(src, message_pieces, message_mode, verb)
used_radios += ears
/mob/living/simple_animal/parrot/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency)
/mob/living/simple_animal/parrot/hear_say(list/message_pieces, verb = "says", italics = 0, mob/speaker = null, sound/speech_sound, sound_vol, sound_frequency, use_voice = TRUE)
if(speaker != src && prob(50))
parrot_hear(html_decode(multilingual_to_message(message_pieces)))
..()
@@ -27,7 +27,7 @@
. += "<span class='warning'>[src] appears to be having trouble staying afloat!</span>"
/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect, end_pixel_y)
/mob/living/simple_animal/possessed_object/do_attack_animation(atom/A, visual_effect_icon, used_item, no_effect)
..()
animate_ghostly_presence(src, -1, 20, 1) // Restart the floating animation after the attack animation, as it will be cancelled.
@@ -144,7 +144,7 @@
/mob/living/simple_animal/updatehealth(reason = "none given")
..(reason)
health = Clamp(health, 0, maxHealth)
health = clamp(health, 0, maxHealth)
med_hud_set_health()
/mob/living/simple_animal/StartResting(updating = 1)
@@ -615,3 +615,8 @@
if(pcollar && collar_type)
add_overlay("[collar_type]collar")
add_overlay("[collar_type]tag")
/mob/living/simple_animal/Login()
..()
walk(src, 0) // if mob is moving under ai control, then stop AI movement

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