mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-25 21:19:00 +01:00
Merge remote-tracking branch 'upstream/master' into pull-move-rework
This commit is contained in:
@@ -14,3 +14,8 @@
|
||||
|
||||
/mob/camera/experience_pressure_difference()
|
||||
return
|
||||
|
||||
/mob/camera/forceMove(atom/destination)
|
||||
var/oldloc = loc
|
||||
loc = destination
|
||||
Moved(oldloc, NONE)
|
||||
|
||||
@@ -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)
|
||||
..()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user