Merge branch 'master' into hook-kill-v10-final-ultimate-final

This commit is contained in:
AffectedArc07
2020-07-02 11:17:30 +01:00
committed by GitHub
414 changed files with 23025 additions and 3199 deletions
@@ -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
@@ -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)
@@ -6,6 +6,7 @@
icon_state = "alienq_s"
status_flags = CANPARALYSE
mob_size = MOB_SIZE_LARGE
bubble_icon = "alienroyal"
large = 1
ventcrawler = 0
+49 -41
View File
@@ -22,8 +22,7 @@
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)
@@ -51,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
@@ -140,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)
@@ -1069,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
@@ -1205,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)
@@ -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.
+4 -10
View File
@@ -6,7 +6,7 @@
canmove = 0
icon = null
invisibility = 101
if(!isSynthetic())
if(!ismachineperson(src))
animation = new(loc)
animation.icon_state = "blank"
animation.icon = 'icons/mob/mob.dmi'
@@ -32,12 +32,11 @@
E.droplimb(DROPLIMB_SHARP)
for(var/mob/M in src)
if(M in stomach_contents)
stomach_contents.Remove(M)
M.forceMove(get_turf(src))
LAZYREMOVE(stomach_contents, M)
M.forceMove(drop_location())
visible_message("<span class='danger'>[M] bursts out of [src]!</span>")
if(!isSynthetic())
if(!ismachineperson(src))
flick("gibbed-h", animation)
hgibs(loc, dna)
else
@@ -106,11 +105,6 @@
//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)
@@ -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
@@ -947,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"))
+2 -14
View File
@@ -1162,18 +1162,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!" ))
@@ -1701,14 +1689,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
@@ -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())
@@ -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))
@@ -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()
+3 -3
View File
@@ -635,7 +635,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 +697,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 +719,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()
@@ -352,21 +352,6 @@
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
@@ -443,6 +428,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)
@@ -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...
+10 -5
View File
@@ -11,6 +11,10 @@
if(stat != DEAD)
handle_organs()
//stuff in the stomach
if(LAZYLEN(stomach_contents))
handle_stomach(times_fired)
. = ..()
if(QDELETED(src))
@@ -254,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)
@@ -476,7 +481,7 @@
P.reagents.remove_any(applied_amount * 0.5)
else
if(!P.reagents || P.reagents.total_volume <= 0)
processing_patches -= P
LAZYREMOVE(processing_patches, P)
qdel(P)
/mob/living/carbon/proc/handle_germs()
-6
View File
@@ -58,9 +58,6 @@
handle_fire()
//stuff in the stomach
handle_stomach(times_fired)
update_gravity(mob_has_gravity())
if(pulling)
@@ -117,9 +114,6 @@
/mob/living/proc/handle_environment(datum/gas_mixture/environment)
return
/mob/living/proc/handle_stomach(times_fired)
return
/mob/living/proc/update_pulling()
if(incapacitated())
stop_pulling()
-3
View File
@@ -682,9 +682,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++
+11 -14
View File
@@ -61,7 +61,7 @@ proc/get_radio_key_from_channel(var/channel)
return default_language
/mob/living/proc/handle_speech_problems(list/message_pieces, var/verb)
var/robot = isSynthetic()
var/robot = ismachineperson(src)
for(var/datum/multilingual_say_piece/S in message_pieces)
if(S.speaking && S.speaking.flags & NO_STUTTER)
continue
@@ -269,12 +269,12 @@ proc/get_radio_key_from_channel(var/channel)
M.hear_say(message_pieces, verb, italics, src, speech_sound, sound_vol, sound_frequency)
if(M.client)
speech_bubble_recipients.Add(M.client)
spawn(0)
if(loc && !isturf(loc))
var/atom/A = loc //Non-turf, let it handle the speech bubble
A.speech_bubble("hR[speech_bubble_test]", A, speech_bubble_recipients)
else //Turf, leave speech bubbles to the mob
speech_bubble("h[speech_bubble_test]", src, speech_bubble_recipients)
if(loc && !isturf(loc))
var/atom/A = loc //Non-turf, let it handle the speech bubble
A.speech_bubble("[A.bubble_icon][speech_bubble_test]", A, speech_bubble_recipients)
else //Turf, leave speech bubbles to the mob
speech_bubble("[bubble_icon][speech_bubble_test]", src, speech_bubble_recipients)
for(var/obj/O in listening_obj)
spawn(0)
@@ -462,10 +462,7 @@ proc/get_radio_key_from_channel(var/channel)
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>"
@@ -474,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)
@@ -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
+112 -69
View File
@@ -9,6 +9,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
icon_state = "robot"
maxHealth = 100
health = 100
bubble_icon = "robot"
universal_understand = 1
deathgasp_on_death = TRUE
@@ -16,8 +17,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/custom_name = ""
var/custom_sprite = 0 //Due to all the sprites involved, a var for our custom borgs may be best
//Hud stuff
//Hud stuff
var/obj/screen/inv1 = null
var/obj/screen/inv2 = null
var/obj/screen/inv3 = null
@@ -27,7 +27,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/shown_robot_modules = 0 //Used to determine whether they have the module menu shown or not
var/obj/screen/robot_modules_background
//3 Modules can be activated at any one time.
//3 Modules can be activated at any one time.
var/obj/item/robot_module/module = null
var/module_active = null
var/module_state_1 = null
@@ -57,6 +57,9 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
var/is_emaggable = TRUE
var/eye_protection = 0
var/ear_protection = 0
var/damage_protection = 0
var/emp_protection = FALSE
var/xeno_disarm_chance = 85
var/list/force_modules = list()
var/allow_rename = TRUE
@@ -86,7 +89,6 @@ GLOBAL_LIST_INIT(robot_verbs_default, 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 +99,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.
@@ -132,7 +135,7 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
init()
if(!scrambledcodes && !camera)
if(!camera && (!scrambledcodes || designation == "ERT"))
camera = new /obj/machinery/camera(src)
camera.c_tag = real_name
camera.network = list("SS13","Robots")
@@ -144,7 +147,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)
@@ -288,12 +291,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 +306,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 +337,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 +354,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 +399,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 +460,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 +936,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 +944,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>")
@@ -1309,6 +1316,16 @@ 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"
@@ -1321,44 +1338,29 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
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
/mob/living/silicon/robot/deathsquad/New(loc)
..()
cell = new /obj/item/stock_parts/cell/hyper(src)
default_cell_type = /obj/item/stock_parts/cell/bluespace
/mob/living/silicon/robot/deathsquad/init()
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,11 +1368,12 @@ 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()
@@ -1379,11 +1382,10 @@ GLOBAL_LIST_INIT(robot_verbs_default, list(
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 +1394,63 @@ 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)
/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
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()
..()
switch(severity)
if(1)
disable_component("comms", 160)
if(2)
disable_component("comms", 60)
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()
/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
@@ -5,6 +5,7 @@
scrambledcodes = 1
pdahide = 1
faction = list("syndicate")
bubble_icon = "syndibot"
designation = "Syndicate Assault"
modtype = "Syndicate"
req_access = list(ACCESS_SYNDICATE)
@@ -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
@@ -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 *
@@ -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.
@@ -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)
@@ -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)
@@ -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
@@ -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
@@ -25,7 +25,7 @@
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))
@@ -35,7 +35,7 @@
if(cycles >= 4)
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)
@@ -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
@@ -363,6 +363,7 @@
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!"
@@ -17,6 +17,7 @@
response_harm = "stomps on"
emote_see = list("jiggles", "bounces in place")
speak_emote = list("blorbles")
bubble_icon = "slime"
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)
+1
View File
@@ -1,5 +1,6 @@
/mob/Logout()
SSnanoui.user_logout(src) // this is used to clean up (remove) this user's Nano UIs
SStgui.on_logout(src) // Cleanup any TGUIs the user has open
unset_machine()
GLOB.player_list -= src
log_access_out(src)
+31 -7
View File
@@ -20,8 +20,8 @@
AA.viewers -= src
viewing_alternate_appearances = null
logs.Cut()
..()
return QDEL_HINT_HARDDEL
LAssailant = null
return ..()
/mob/Initialize()
GLOB.mob_list += src
@@ -127,14 +127,12 @@
// self_message (optional) is what the src mob hears.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
/mob/audible_message(var/message, var/deaf_message, var/hearing_distance, var/self_message)
/mob/audible_message(message, deaf_message, hearing_distance)
var/range = 7
if(hearing_distance)
range = hearing_distance
var/msg = message
for(var/mob/M in get_mobs_in_view(range, src))
if(self_message && M == src)
msg = self_message
M.show_message(msg, 2, deaf_message, 1)
// based on say code
@@ -156,12 +154,12 @@
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance)
/atom/proc/audible_message(message, deaf_message, hearing_distance)
var/range = 7
if(hearing_distance)
range = hearing_distance
for(var/mob/M in get_mobs_in_view(range, src))
M.show_message( message, 2, deaf_message, 1)
M.show_message(message, 2, deaf_message, 1)
/mob/proc/findname(msg)
for(var/mob/M in GLOB.mob_list)
@@ -1390,3 +1388,29 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
///Force set the mob nutrition
/mob/proc/set_nutrition(change)
nutrition = max(0, change)
/mob/clean_blood(clean_hands = TRUE, clean_mask = TRUE, clean_feet = TRUE)
. = ..()
if(bloody_hands && clean_hands)
bloody_hands = 0
update_inv_gloves()
if(l_hand)
if(l_hand.clean_blood())
update_inv_l_hand()
if(r_hand)
if(r_hand.clean_blood())
update_inv_r_hand()
if(back)
if(back.clean_blood())
update_inv_back()
if(wear_mask && clean_mask)
if(wear_mask.clean_blood())
update_inv_wear_mask()
if(clean_feet)
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()
update_icons() //apply the now updated overlays to the mob
+15 -20
View File
@@ -31,8 +31,8 @@
var/use_me = 1 //Allows all mobs to use the me verb by default, will have to manually specify they cannot
var/damageoverlaytemp = 0
var/computer_id = null
var/lastattacker = null
var/lastattacked = null
var/lastattacker = null // real name of the person doing the attacking
var/lastattackerckey = null // their ckey
var/list/attack_log_old = list( )
var/list/debug_log = null
@@ -50,7 +50,6 @@
var/med_record = ""
var/sec_record = ""
var/gen_record = ""
var/bhunger = 0 //Carbon
var/lying = 0
var/lying_prev = 0
var/lastpuke = 0
@@ -61,8 +60,7 @@
var/emote_type = 1 // Define emote default type, 1 for seen emotes, 2 for heard emotes
var/name_archive //For admin things like possession
var/timeofdeath = 0.0//Living
var/timeofdeath = 0 //Living
var/bodytemperature = 310.055 //98.7 F
var/flying = 0
@@ -71,22 +69,22 @@
var/hunger_drain = HUNGER_FACTOR // how quickly the mob gets hungry; largely utilized by species.
var/overeatduration = 0 // How long this guy is overeating //Carbon
var/intent = null//Living
var/intent = null //Living
var/shakecamera = 0
var/a_intent = INTENT_HELP//Living
var/m_intent = MOVE_INTENT_RUN//Living
var/a_intent = INTENT_HELP //Living
var/m_intent = MOVE_INTENT_RUN //Living
var/lastKnownIP = null
/// movable atoms buckled to this mob
var/atom/movable/buckled = null//Living
var/atom/movable/buckled = null //Living
/// movable atom we are buckled to
var/atom/movable/buckling
var/obj/item/l_hand = null//Living
var/obj/item/r_hand = null//Living
var/obj/item/back = null//Human/Monkey
var/obj/item/tank/internal = null//Human/Monkey
var/obj/item/storage/s_active = null//Carbon
var/obj/item/clothing/mask/wear_mask = null//Carbon
var/obj/item/l_hand = null //Living
var/obj/item/r_hand = null //Living
var/obj/item/back = null //Human
var/obj/item/tank/internal = null //Human
var/obj/item/storage/s_active = null //Carbon
var/obj/item/clothing/mask/wear_mask = null //Carbon
var/datum/hud/hud_used = null
@@ -95,7 +93,6 @@
var/research_scanner = 0 //For research scanner equipped mobs. Enable to show research data when examining.
var/list/grabbed_by = list()
var/list/requests = list()
var/lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
var/list/mapobjs = list()
@@ -103,9 +100,9 @@
var/emote_cd = 0 // Used to supress emote spamming. 1 if on CD, 2 if disabled by admin (manually set), else 0
var/job = null//Living
var/job = null //Living
var/datum/dna/dna = null//Carbon
var/datum/dna/dna = null //Carbon
var/radiation = 0 //Carbon
var/list/mutations = list() //Carbon -- Doohl
@@ -179,8 +176,6 @@
var/turf/listed_turf = null //the current turf being examined in the stat panel
var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
var/kills = 0
var/stance_damage = 0 //Whether this mob's ability to stand has been affected
var/list/active_genes = list()
+1 -1
View File
@@ -408,7 +408,7 @@
add_attack_logs(attacker, affecting, "Devoured")
affecting.forceMove(user)
attacker.stomach_contents.Add(affecting)
LAZYADD(attacker.stomach_contents, affecting)
qdel(src)
/obj/item/grab/proc/checkvalid(var/mob/attacker, var/mob/prey) //does all the checking for the attack proc to see if a mob can eat another with the grab
-8
View File
@@ -12,14 +12,6 @@
return 1
return 0
/mob/proc/isSynthetic()
return 0
/mob/living/carbon/human/isSynthetic()
if(ismachine(src))
return TRUE
return FALSE
/mob/proc/get_screen_colour()
/mob/proc/update_client_colour(var/time = 10) //Update the mob's client.color with an animation the specified time in length.
+1 -1
View File
@@ -114,7 +114,7 @@
return get_turf(src)
/mob/proc/say_test(var/text)
/proc/say_test(text)
var/ending = copytext(text, length(text))
if(ending == "?")
return "1"
+10 -9
View File
@@ -5,31 +5,32 @@ mob/var/typing
mob/var/last_typed
mob/var/last_typed_time
GLOBAL_DATUM(typing_indicator, /image)
GLOBAL_LIST_EMPTY(typing_indicator)
/mob/proc/set_typing_indicator(var/state)
/mob/proc/set_typing_indicator(state)
if(!GLOB.typing_indicator)
GLOB.typing_indicator = image('icons/mob/talk.dmi', null, "typing", MOB_LAYER + 1)
GLOB.typing_indicator.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
if(!GLOB.typing_indicator[bubble_icon])
GLOB.typing_indicator[bubble_icon] = image('icons/mob/talk.dmi', null, "[bubble_icon]typing", FLY_LAYER)
var/image/I = GLOB.typing_indicator[bubble_icon]
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
if(ishuman(src))
var/mob/living/carbon/human/H = src
if((MUTE in H.mutations) || H.silent)
overlays -= GLOB.typing_indicator
overlays -= GLOB.typing_indicator[bubble_icon]
return
if(client)
if((client.prefs.toggles & SHOW_TYPING) || stat != CONSCIOUS || is_muzzled())
overlays -= GLOB.typing_indicator
overlays -= GLOB.typing_indicator[bubble_icon]
else
if(state)
if(!typing)
overlays += GLOB.typing_indicator
overlays += GLOB.typing_indicator[bubble_icon]
typing = 1
else
if(typing)
overlays -= GLOB.typing_indicator
overlays -= GLOB.typing_indicator[bubble_icon]
typing = 0
return state