This commit is contained in:
Ghommie
2019-12-23 19:02:20 +01:00
1029 changed files with 27448 additions and 12993 deletions
@@ -25,7 +25,7 @@
features = random_features()
age = rand(AGE_MIN,AGE_MAX)
/datum/preferences/proc/update_preview_icon()
/datum/preferences/proc/update_preview_icon(equip_job = TRUE)
// Determine what job is marked as 'High' priority, and dress them up as such.
var/datum/job/previewJob
var/highest_pref = 0
@@ -45,12 +45,11 @@
// Set up the dummy for its photoshoot
var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy(DUMMY_HUMAN_SLOT_PREFERENCES)
mannequin.cut_overlays()
// Apply the Dummy's preview background first so we properly layer everything else on top of it.
mannequin.add_overlay(mutable_appearance('modular_citadel/icons/ui/backgrounds.dmi', bgstate, layer = SPACE_LAYER))
copy_to(mannequin)
if(previewJob)
if(previewJob && equip_job)
mannequin.job = previewJob.title
previewJob.equip(mannequin, TRUE, preference_source = parent)
@@ -43,6 +43,18 @@
name = "Knee-High - UK"
icon_state = "uk_knee"
/datum/sprite_accessory/underwear/socks/christmas_knee
name = "Knee-High - Christmas"
icon_state = "christmas_knee"
/datum/sprite_accessory/underwear/socks/candycaner_knee
name = "Knee-High - Red Candy Cane"
icon_state = "candycaner_knee"
/datum/sprite_accessory/underwear/socks/candycaneg_knee
name = "Knee-High - Green Candy Cane"
icon_state = "candycaneg_knee"
/datum/sprite_accessory/underwear/socks/socks_norm
name = "Normal"
icon_state = "socks_norm"
@@ -52,6 +64,18 @@
name = "Normal - Bee"
icon_state = "bee_norm"
/datum/sprite_accessory/underwear/socks/christmas_norm
name = "Normal - Christmas"
icon_state = "christmas_norm"
/datum/sprite_accessory/underwear/socks/candycaner_norm
name = "Normal - Red Candy Cane"
icon_state = "candycaner_norm"
/datum/sprite_accessory/underwear/socks/candycaneg_norm
name = "Normal - Green Candy Cane"
icon_state = "candycaneg_norm"
/datum/sprite_accessory/underwear/socks/pantyhose
name = "Pantyhose"
icon_state = "pantyhose"
@@ -131,3 +155,15 @@
/datum/sprite_accessory/underwear/socks/uk_thigh
name = "Thigh-high - UK"
icon_state = "uk_thigh"
/datum/sprite_accessory/underwear/socks/christmas_thigh
name = "Thigh-high - Christmas"
icon_state = "christmas_thigh"
/datum/sprite_accessory/underwear/socks/candycaner_thigh
name = "Thigh-high - Red Candy Cane"
icon_state = "candycaner_thigh"
/datum/sprite_accessory/underwear/socks/candycaneg_thigh
name = "Thigh-high - Green Candy Cane"
icon_state = "candycaneg_thigh"
+1 -1
View File
@@ -265,7 +265,7 @@ Works together with spawning an observer, noted above.
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE)
penalize = suiciding || penalize // suicide squad.
if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse) & COMPONENT_BLOCK_GHOSTING))
if(!key || cmptext(copytext(key,1,2),"@") || (SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize) & COMPONENT_BLOCK_GHOSTING))
return //mob has no key, is an aghost or some component hijacked.
stop_sound_channel(CHANNEL_HEARTBEAT) //Stop heartbeat sounds because You Are A Ghost Now
var/mob/dead/observer/ghost = new(src) // Transfer safety to observer spawning proc.
+2 -2
View File
@@ -22,7 +22,7 @@
. = say_dead(message)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
var/atom/movable/to_follow = speaker
if(radio_freq)
@@ -35,6 +35,6 @@
to_follow = V.source
var/link = FOLLOW_LINK(src, to_follow)
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source)
to_chat(src, "[link] [message]")
+3
View File
@@ -36,6 +36,9 @@
if(bleed_rate <= 0)
bleed_rate = 0
if(HAS_TRAIT(src, TRAIT_NOMARROW)) //Bloodsuckers don't need to be here.
return
if(bodytemperature >= TCRYO && !(HAS_TRAIT(src, TRAIT_NOCLONE))) //cryosleep or husked people do not pump the blood.
//Blood regeneration if there is some space
+1
View File
@@ -125,6 +125,7 @@
else if(!brain)
brain = new(src)
brain.name = "[L.real_name]'s brain"
brain.organ_flags |= ORGAN_FROZEN
name = "Man-Machine Interface: [brainmob.real_name]"
update_icon()
@@ -7,9 +7,9 @@
/* CIT CHANGE - Pffffffffffffhahahahahhaha-- No.
//aliens are immune to stamina damage.
/mob/living/carbon/alien/adjustStaminaLoss(amount, updating_stamina = 1)
/mob/living/carbon/alien/adjustStaminaLoss(amount, updating_health = 1)
return
/mob/living/carbon/alien/setStaminaLoss(amount, updating_stamina = 1)
/mob/living/carbon/alien/setStaminaLoss(amount, updating_health = 1)
return
*/
+39 -14
View File
@@ -159,23 +159,34 @@
return
//END OF CIT CHANGES
var/atom/movable/thrown_thing
var/obj/item/I = src.get_active_held_item()
if(!I)
if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
var/mob/living/throwable_mob = pulling
if(!throwable_mob.buckled)
thrown_thing = throwable_mob
var/atom/movable/thrown_thing
var/mob/living/throwable_mob
if(istype(I, /obj/item/clothing/head/mob_holder))
var/obj/item/clothing/head/mob_holder/holder = I
if(holder.held_mob)
throwable_mob = holder.held_mob
holder.release()
if(!I || throwable_mob)
if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
throwable_mob = pulling
if(throwable_mob && !throwable_mob.buckled)
thrown_thing = throwable_mob
if(pulling)
stop_pulling()
if(HAS_TRAIT(src, TRAIT_PACIFISM))
to_chat(src, "<span class='notice'>You gently let go of [throwable_mob].</span>")
return
adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
var/turf/end_T = get_turf(target)
if(start_T && end_T)
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
if(HAS_TRAIT(src, TRAIT_PACIFISM))
to_chat(src, "<span class='notice'>You gently let go of [throwable_mob].</span>")
return
adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
var/turf/end_T = get_turf(target)
if(start_T && end_T)
log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
else if(!CHECK_BITFIELD(I.item_flags, ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
thrown_thing = I
@@ -195,6 +206,8 @@
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
/mob/living/carbon/restrained(ignore_grab)
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
@@ -585,6 +598,9 @@
sight |= E.sight_flags
if(!isnull(E.lighting_alpha))
lighting_alpha = E.lighting_alpha
if(HAS_TRAIT(src, TRAIT_NIGHT_VISION))
lighting_alpha = min(LIGHTING_PLANE_ALPHA_NV_TRAIT, lighting_alpha)
see_in_dark = max(NIGHT_VISION_DARKSIGHT_RANGE, see_in_dark)
if(client.eye && client.eye != src)
var/atom/A = client.eye
@@ -789,9 +805,13 @@
if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT)))
stat = UNCONSCIOUS
blind_eyes(1)
if(combatmode)
toggle_combat_mode(TRUE, TRUE)
else
if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT))
stat = SOFT_CRIT
if(combatmode)
toggle_combat_mode(TRUE, TRUE)
else
stat = CONSCIOUS
adjust_blindness(-1)
@@ -952,3 +972,8 @@
if(mood)
if(mood.sanity < SANITY_UNSTABLE)
return TRUE
/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE)
if(combatmode)
toggle_combat_mode(TRUE, TRUE)
return ..()
@@ -284,6 +284,12 @@
M.visible_message("<span class='notice'>[M] shakes [src] trying to get [p_them()] up!</span>", \
"<span class='notice'>You shake [src] trying to get [p_them()] up!</span>")
else if(check_zone(M.zone_selected) == "mouth") // I ADDED BOOP-EH-DEH-NOSEH - Jon
M.visible_message( \
"<span class='notice'>[M] boops [src]'s nose.</span>", \
"<span class='notice'>You boop [src] on the nose.</span>", )
playsound(src, 'sound/items/Nose_boop.ogg', 50, 0)
else if(check_zone(M.zone_selected) == "head")
var/mob/living/carbon/human/H = src
var/datum/species/pref_species = H.dna.species
@@ -321,7 +327,12 @@
else
return
else if(check_zone(M.zone_selected) == "r_arm" || check_zone(M.zone_selected) == "l_arm")
M.visible_message( \
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
"<span class='notice'>You shake [src]'s hand.</span>", )
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
"<span class='notice'>You hug [src] to make [p_them()] feel better!</span>")
@@ -360,30 +371,30 @@
if (damage == 1)
to_chat(src, "<span class='warning'>Your eyes sting a little.</span>")
if(prob(40))
adjust_eye_damage(1)
eyes.applyOrganDamage(1)
else if (damage == 2)
to_chat(src, "<span class='warning'>Your eyes burn.</span>")
adjust_eye_damage(rand(2, 4))
eyes.applyOrganDamage(rand(2, 4))
else if( damage >= 3)
to_chat(src, "<span class='warning'>Your eyes itch and burn severely!</span>")
adjust_eye_damage(rand(12, 16))
eyes.applyOrganDamage(rand(12, 16))
if(eyes.eye_damage > 10)
if(eyes.damage > 10)
blind_eyes(damage)
blur_eyes(damage * rand(3, 6))
if(eyes.eye_damage > 20)
if(prob(eyes.eye_damage - 20))
if(eyes.damage > 20)
if(prob(eyes.damage - 20))
if(!HAS_TRAIT(src, TRAIT_NEARSIGHT))
to_chat(src, "<span class='warning'>Your eyes start to burn badly!</span>")
become_nearsighted(EYE_DAMAGE)
else if(prob(eyes.eye_damage - 25))
else if(prob(eyes.damage - 25))
if(!HAS_TRAIT(src, TRAIT_BLIND))
to_chat(src, "<span class='warning'>You can't see anything!</span>")
become_blind(EYE_DAMAGE)
eyes.applyOrganDamage(eyes.maxHealth)
else
to_chat(src, "<span class='warning'>Your eyes are really starting to hurt. This can't be good for you!</span>")
@@ -65,6 +65,8 @@
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
if (!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL))
return FALSE
if(!forced && (status_flags & GODMODE))
return FALSE
if(amount > 0)
@@ -74,6 +76,8 @@
return amount
/mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
if (!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL)) //Vamps don't heal naturally.
return FALSE
if(!forced && (status_flags & GODMODE))
return FALSE
if(amount > 0)
+9 -2
View File
@@ -7,13 +7,15 @@
if(!gibbed)
emote("deathgasp")
if(combatmode)
toggle_combat_mode(TRUE, TRUE)
. = ..()
for(var/T in get_traumas())
var/datum/brain_trauma/BT = T
BT.on_death()
if(SSticker.mode)
SSticker.mode.check_win() //Calls the rounds wincheck, mainly for wizard, malf, and changeling now
@@ -63,3 +65,8 @@
var/obj/item/bodypart/BP = X
BP.drop_limb()
BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
/mob/living/carbon/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE)
if(combatmode)
toggle_combat_mode(TRUE, TRUE)
return ..()
+8 -5
View File
@@ -15,7 +15,11 @@
if (wear_mask)
. += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face."
if (wear_neck)
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck."
. += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
if(can_be_held)
. += "[t_He] looks small enough to be picked up with <b>Alt+Click</b>!\n"
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
@@ -38,7 +42,7 @@
continue
. += "<span class='warning'><B>[t_His] [parse_zone(t)] is missing!</B></span>"
var/list/msg = list("<span class='warning'>")
var/list/msg = list()
var/temp = getBruteLoss()
if(!(user == src && src.hal_screwyhud == SCREWYHUD_HEALTHY)) //fake healthy
if(temp)
@@ -78,9 +82,8 @@
if(pulledby && pulledby.grab_state)
msg += "[t_He] [t_is] restrained by [pulledby]'s grip.\n"
msg += "</span>"
. += msg.Join("")
if(msg.len)
. += "<span class='warning'>[msg.Join("")]</span>"
if(!appears_dead)
if(stat == UNCONSCIOUS)
@@ -17,6 +17,7 @@ INITIALIZE_IMMEDIATE(/mob/living/carbon/human/dummy)
/mob/living/carbon/human/dummy/proc/wipe_state()
delete_equipment()
icon_render_key = null
cut_overlays(TRUE)
//Inefficient pooling/caching way.
+15 -11
View File
@@ -15,6 +15,13 @@
. = list("<span class='info'>*---------*\nThis is <EM>[!obscure_name ? name : "Unknown"]</EM>!")
var/vampDesc = ReturnVampExamine(user) // Vamps recognize the names of other vamps.
var/vassDesc = ReturnVassalExamine(user) // Vassals recognize each other's marks.
if (vampDesc != "") // If we don't do it this way, we add a blank space to the string...something to do with this --> . += ""
. += vampDesc
if (vassDesc != "")
. += vassDesc
var/list/obscured = check_obscured_slots()
var/skipface = (wear_mask && (wear_mask.flags_inv & HIDEFACE)) || (head && (head.flags_inv & HIDEFACE))
@@ -113,7 +120,7 @@
. += "[dicc.desc]"
var/cursed_stuff = attempt_vr(src,"examine_bellies",args) //vore Code
if(!isnull(cursed_stuff))
if(cursed_stuff)
. += cursed_stuff
//END OF CIT CHANGES
@@ -169,7 +176,7 @@
var/r_limbs_missing = 0
for(var/t in missing)
if(t==BODY_ZONE_HEAD)
msg += "<span class='deadsay'><B>[t_His] [parse_zone(t)] is missing!</B><span class='warning'>\n"
msg += "<span class='deadsay'><B>[t_His] [parse_zone(t)] is missing!</B></span>\n"
continue
if(t == BODY_ZONE_L_ARM || t == BODY_ZONE_L_LEG)
l_limbs_missing++
@@ -237,13 +244,13 @@
if(DISGUST_LEVEL_DISGUSTED to INFINITY)
msg += "[t_He] look[p_s()] extremely disgusted.\n"
if(blood_volume < (BLOOD_VOLUME_SAFE*blood_ratio))
if(ShowAsPaleExamine())
msg += "[t_He] [t_has] pale skin.\n"
if(bleedsuppress)
msg += "[t_He] [t_is] bandaged with something.\n"
else if(bleed_rate)
if(reagents.has_reagent("heparin"))
if(bleed_rate >= 8) //8 is the rate at which heparin causes you to bleed
msg += "<b>[t_He] [t_is] bleeding uncontrollably!</b>\n"
else
msg += "<B>[t_He] [t_is] bleeding!</B>\n"
@@ -272,11 +279,10 @@
msg += "[t_He] [t_is] a shitfaced, slobbering wreck.\n"
if(reagents.has_reagent("astral"))
msg += "[t_He] has wild, spacey eyes"
if(mind)
msg += " and they have a strange, abnormal look to them.\n"
msg += "[t_He] has wild, spacey eyes and they have a strange, abnormal look to them.\n"
else
msg += " and they don't look like they're all there.\n"
msg += "[t_He] has wild, spacey eyes and they don't look like they're all there.\n"
if(isliving(user))
var/mob/living/L = user
@@ -287,7 +293,7 @@
msg += "[t_He] seem[p_s()] winded.\n"
if (getToxLoss() >= 10)
msg += "[t_He] seem[p_s()] sickly.\n"
var/datum/component/mood/mood = src.GetComponent(/datum/component/mood)
var/datum/component/mood/mood = GetComponent(/datum/component/mood)
if(mood.sanity <= SANITY_DISTURBED)
msg += "[t_He] seem[p_s()] distressed.\n"
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "empath", /datum/mood_event/sad_empath, src)
@@ -299,8 +305,6 @@
if (HAS_TRAIT(src, TRAIT_DEAF))
msg += "[t_He] appear[p_s()] to not be responding to noises.\n"
msg += "</span>"
var/obj/item/organ/vocal_cords/Vc = user.getorganslot(ORGAN_SLOT_VOICE)
if(Vc)
if(istype(Vc, /obj/item/organ/vocal_cords/velvet))
@@ -360,7 +364,7 @@
if(R)
. += "<a href='?src=[REF(src)];hud=m;evaluation=1'>\[Medical evaluation\]</a>"
if(traitstring)
. += "<span class='info'>Detected physiological traits:\n[traitstring]"
. += "<span class='info'>Detected physiological traits:\n[traitstring]</span>"
+23 -3
View File
@@ -858,6 +858,7 @@
.["Make slime"] = "?_src_=vars;[HrefToken()];makeslime=[REF(src)]"
.["Toggle Purrbation"] = "?_src_=vars;[HrefToken()];purrbation=[REF(src)]"
.["Copy outfit"] = "?_src_=vars;[HrefToken()];copyoutfit=[REF(src)]"
.["Add/Remove Quirks"] = "?_src_=vars;[HrefToken()];modquirks=[REF(src)]"
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
if(pulling == target && grab_state >= GRAB_AGGRESSIVE && stat == CONSCIOUS)
@@ -867,8 +868,9 @@
return
//If you dragged them to you and you're aggressively grabbing try to fireman carry them
else if(user != target)
fireman_carry(target)
return
if(user.a_intent == INTENT_GRAB)
fireman_carry(target)
return
. = ..()
//src is the user that will be carrying, target is the mob to be carried
@@ -890,7 +892,10 @@
return
visible_message("<span class='warning'>[src] fails to fireman carry [target]!")
else
to_chat(src, "<span class='notice'>You can't fireman carry [target] while they're standing!</span>")
if (ishuman(target))
to_chat(src, "<span class='notice'>You can't fireman carry [target] while they're standing!</span>")
else
to_chat(src, "<span class='notice'>You can't seem to fireman carry that kind of species.</span>")
/mob/living/carbon/human/proc/piggyback(mob/living/carbon/target)
if(can_piggyback(target))
@@ -1043,6 +1048,21 @@
/mob/living/carbon/human/species/golem/plastic
race = /datum/species/golem/plastic
/mob/living/carbon/human/species/golem/bronze
race = /datum/species/golem/bronze
/mob/living/carbon/human/species/golem/cardboard
race = /datum/species/golem/cardboard
/mob/living/carbon/human/species/golem/leather
race = /datum/species/golem/leather
/mob/living/carbon/human/species/golem/bone
race = /datum/species/golem/bone
/mob/living/carbon/human/species/golem/durathread
race = /datum/species/golem/durathread
/mob/living/carbon/human/species/golem/clockwork
race = /datum/species/golem/clockwork
@@ -23,7 +23,7 @@
if(!d_type)
return 0
var/protection = 0
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform, back, gloves, shoes, belt, s_store, glasses, ears, wear_id, wear_neck) //Everything but pockets. Pockets are l_store and r_store. (if pockets were allowed, putting something armored, gloves or hats for example, would double up on the armor)
for(var/bp in body_parts)
if(!bp)
continue
@@ -81,6 +81,10 @@
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 TRUE
if(wear_neck)
var/final_block_chance = wear_neck.block_chance - (CLAMP((armour_penetration-wear_neck.armour_penetration)/2,0,100)) + block_chance_modifier
if(wear_neck.hit_reaction(src, AM, attack_text, final_block_chance, damage, attack_type))
return TRUE
return FALSE
/mob/living/carbon/human/can_embed(obj/item/I)
@@ -318,43 +322,34 @@
return
var/b_loss = 0
var/f_loss = 0
var/bomb_armor = getarmor(null, "bomb")
var/bomb_armor = max(0,(100-getarmor(null, "bomb"))/100)
switch (severity)
if (1)
if(prob(bomb_armor))
b_loss = 500
if(bomb_armor)
b_loss = 500*bomb_armor
var/atom/throw_target = get_edge_target_turf(src, get_dir(src, get_step_away(src, src)))
throw_at(throw_target, 200, 4)
damage_clothes(400 - bomb_armor, BRUTE, "bomb")
damage_clothes(400*bomb_armor, BRUTE, "bomb")
else
for(var/I in contents)
var/atom/A = I
A.ex_act(severity)
damage_clothes(400,BRUTE,"bomb")
gib()
return
if (2)
b_loss = 60
f_loss = 60
if(bomb_armor)
b_loss = 30*(2 - round(bomb_armor*0.01, 0.05))
f_loss = b_loss
damage_clothes(200 - bomb_armor, BRUTE, "bomb")
b_loss = 60*bomb_armor
f_loss = 60*bomb_armor
damage_clothes(200*bomb_armor, BRUTE, "bomb")
if (!istype(ears, /obj/item/clothing/ears/earmuffs))
adjustEarDamage(30, 120)
if (prob(max(70 - (bomb_armor * 0.5), 0)))
Unconscious(200)
Unconscious(200*bomb_armor)
if(3)
b_loss = 30
if(bomb_armor)
b_loss = 15*(2 - round(bomb_armor*0.01, 0.05))
b_loss = 30*bomb_armor
damage_clothes(max(50 - bomb_armor, 0), BRUTE, "bomb")
if (!istype(ears, /obj/item/clothing/ears/earmuffs))
adjustEarDamage(15,60)
if (prob(max(50 - (bomb_armor * 0.5), 0)))
Unconscious(160)
Unconscious(100*bomb_armor)
take_overall_damage(b_loss,f_loss)
@@ -591,6 +586,12 @@
if(health >= 0)
if(src == M)
if(has_status_effect(STATUS_EFFECT_CHOKINGSTRAND))
to_chat(src, "<span class='notice'>You attempt to remove the durathread strand from around your neck.</span>")
if(do_after(src, 35, null, src))
to_chat(src, "<span class='notice'>You succesfuly remove the durathread strand.</span>")
remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
return
var/to_send = ""
visible_message("[src] examines [p_them()]self.", \
"<span class='notice'>You check yourself for injuries.</span>")
@@ -119,16 +119,12 @@
. = ..()
if(G.trigger_guard == TRIGGER_GUARD_NORMAL)
if(src.dna.check_mutation(HULK))
if(HAS_TRAIT(src, TRAIT_CHUNKYFINGERS))
to_chat(src, "<span class='warning'>Your meaty finger is much too large for the trigger guard!</span>")
return FALSE
if(HAS_TRAIT(src, TRAIT_NOGUNS))
to_chat(src, "<span class='warning'>Your fingers don't fit in the trigger guard!</span>")
return FALSE
if(mind)
if(mind.martial_art && mind.martial_art.no_guns) //great dishonor to famiry
to_chat(src, "<span class='warning'>Use of ranged weaponry would bring dishonor to the clan.</span>")
return FALSE
return .
/*
@@ -191,7 +191,6 @@
if(G.vision_correction)
if(HAS_TRAIT(src, TRAIT_NEARSIGHT))
overlay_fullscreen("nearsighted", /obj/screen/fullscreen/impaired, 1)
adjust_eye_damage(0)
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view || !isnull(G.lighting_alpha))
update_sight()
if(!QDELETED(src))
@@ -252,7 +252,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
QDEL_NULL(eyes)
if(should_have_eyes && !eyes)
eyes = new mutanteyes
eyes.Insert(C)
eyes.Insert(C, TRUE)
if(ears && (replace_current || !should_have_ears))
ears.Remove(C,1)
@@ -1279,6 +1279,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
////////
/datum/species/proc/handle_digestion(mob/living/carbon/human/H)
if(HAS_TRAIT(src, TRAIT_NOHUNGER))
return //hunger is for BABIES
//The fucking TRAIT_FAT mutation is the dumbest shit ever. It makes the code so difficult to work with
if(HAS_TRAIT(H, TRAIT_FAT))//I share your pain, past coder.
@@ -1537,6 +1539,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
target.lastattacker = user.real_name
target.lastattackerckey = user.ckey
user.dna.species.spec_unarmedattacked(user, target)
if(user.limb_destroyer)
target.dismembering_strike(user, affecting.body_zone)
@@ -1550,6 +1553,9 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
else if(target.lying)
target.forcesay(GLOB.hit_appends)
/datum/species/proc/spec_unarmedattacked(mob/living/carbon/human/user, mob/living/carbon/human/target)
return
/datum/species/proc/disarm(mob/living/carbon/human/user, mob/living/carbon/human/target, datum/martial_art/attacker_style)
// CITADEL EDIT slap mouthy gits and booty
var/aim_for_mouth = user.zone_selected == "mouth"
@@ -4,7 +4,7 @@
say_mod = "gibbers"
sexes = FALSE
species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL)
inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_NOGUNS,TRAIT_NOHUNGER,TRAIT_NOBREATH)
inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_CHUNKYFINGERS,TRAIT_NOHUNGER,TRAIT_NOBREATH)
mutanttongue = /obj/item/organ/tongue/abductor
/datum/species/abductor/on_species_gain(mob/living/carbon/C, datum/species/old_species)
@@ -3,7 +3,7 @@
name = "Golem"
id = "iron golem"
species_traits = list(NOBLOOD,MUTCOLORS,NO_UNDERWEAR,NOGENITALS,NOAROUSAL)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_biotypes = list(MOB_INORGANIC, MOB_HUMANOID)
mutant_organs = list(/obj/item/organ/adamantine_resonator)
speedmod = 2
@@ -88,7 +88,7 @@
fixed_mut_color = "a3d"
meat = /obj/item/stack/ore/plasma
//Can burn and takes damage from heat
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER) //no RESISTHEAT, NOFIRE
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER) //no RESISTHEAT, NOFIRE
info_text = "As a <span class='danger'>Plasma Golem</span>, you burn easily. Be careful, if you get hot enough while burning, you'll blow up!"
heatmod = 0 //fine until they blow up
prefix = "Plasma"
@@ -266,7 +266,7 @@
fixed_mut_color = "9E704B"
meat = /obj/item/stack/sheet/mineral/wood
//Can burn and take damage from heat
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
armor = 30
burnmod = 1.25
heatmod = 1.5
@@ -693,7 +693,7 @@
info_text = "As a <span class='danger'>Cloth Golem</span>, you are able to reform yourself after death, provided your remains aren't burned or destroyed. You are, of course, very flammable. \
Being made of cloth, your body is magic resistant and faster than that of other golems, but weaker and less resilient."
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL) //no mutcolors, and can burn
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOGUNS)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_CHUNKYFINGERS)
inherent_biotypes = list(MOB_UNDEAD, MOB_HUMANOID)
armor = 15 //feels no pain, but not too resistant
burnmod = 2 // don't get burned
@@ -862,27 +862,27 @@
if(M.stat == DEAD) //F
return
if(M == H)
H.show_message("<span class='narsiesmall'>You cringe with pain as your body rings around you!</span>", 2)
H.show_message("<span class='narsiesmall'>You cringe with pain as your body rings around you!</span>", MSG_AUDIBLE)
H.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE)
H.soundbang_act(2, 0, 100, 1)
H.jitteriness += 7
var/distance = max(0,get_dist(get_turf(H),get_turf(M)))
switch(distance)
if(0 to 1)
M.show_message("<span class='narsiesmall'>GONG!</span>", 2)
M.show_message("<span class='narsiesmall'>GONG!</span>", MSG_AUDIBLE)
M.playsound_local(H, 'sound/effects/gong.ogg', 100, TRUE)
M.soundbang_act(1, 0, 30, 3)
M.confused += 10
M.jitteriness += 4
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "gonged", /datum/mood_event/loud_gong)
if(2 to 3)
M.show_message("<span class='cult'>GONG!</span>", 2)
M.show_message("<span class='cult'>GONG!</span>", MSG_AUDIBLE)
M.playsound_local(H, 'sound/effects/gong.ogg', 75, TRUE)
M.soundbang_act(1, 0, 15, 2)
M.jitteriness += 3
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "gonged", /datum/mood_event/loud_gong)
else
M.show_message("<span class='warning'>GONG!</span>", 2)
M.show_message("<span class='warning'>GONG!</span>", MSG_AUDIBLE)
M.playsound_local(H, 'sound/effects/gong.ogg', 50, TRUE)
@@ -893,7 +893,7 @@
special_names = list("Box")
info_text = "As a <span class='danger'>Cardboard Golem</span>, you aren't very strong, but you are a bit quicker and can easily create more brethren by using cardboard on yourself."
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL,MUTCOLORS)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
fixed_mut_color = "ffffff"
limbs_id = "c_golem" //special sprites
attack_verb = "bash"
@@ -936,7 +936,7 @@
name = "Leather Golem"
id = "leather golem"
special_names = list("Face", "Man", "Belt") //Ah dude 4 strength 4 stam leather belt AHHH
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_STRONG_GRABBER)
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER, TRAIT_STRONG_GRABBER)
prefix = "Leather"
fixed_mut_color = "624a2e"
info_text = "As a <span class='danger'>Leather Golem</span>, you are flammable, but you can grab things with incredible ease, allowing all your grabs to start at a strong level."
@@ -944,6 +944,21 @@
grab_sound = 'sound/weapons/whipgrab.ogg'
attack_sound = 'sound/weapons/whip.ogg'
/datum/species/golem/durathread
name = "Durathread Golem"
id = "durathread golem"
prefix = "Durathread"
limbs_id = "d_golem"
special_names = list("Boll","Weave")
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOEYES)
fixed_mut_color = null
inherent_traits = list(TRAIT_NOBREATH, TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER)
info_text = "As a <span class='danger'>Durathread Golem</span>, your strikes will cause those your targets to start choking, but your woven body won't withstand fire as well."
/datum/species/golem/durathread/spec_unarmedattacked(mob/living/carbon/human/user, mob/living/carbon/human/target)
. = ..()
target.apply_status_effect(STATUS_EFFECT_CHOKINGSTRAND)
/datum/species/golem/bone
name = "Bone Golem"
id = "bone golem"
@@ -959,7 +974,7 @@
fixed_mut_color = "ffffff"
attack_verb = "rattl"
species_traits = list(NOBLOOD,NO_UNDERWEAR,NOGENITALS,NOAROUSAL,MUTCOLORS)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_FAKEDEATH,TRAIT_CALCIUM_HEALER)
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOFIRE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_FAKEDEATH,TRAIT_CALCIUM_HEALER)
info_text = "As a <span class='danger'>Bone Golem</span>, You have a powerful spell that lets you chill your enemies with fear, and milk heals you! Just make sure to watch our for bone-hurting juice."
var/datum/action/innate/bonechill/bonechill
@@ -44,7 +44,7 @@
C.faction |= "slime"
/datum/species/jelly/spec_life(mob/living/carbon/human/H)
if(H.stat == DEAD) //can't farm slime jelly from a dead slime/jelly person indefinitely
if(H.stat == DEAD || HAS_TRAIT(H, TRAIT_NOMARROW)) //can't farm slime jelly from a dead slime/jelly person indefinitely, and no regeneration for vampires
return
if(!H.blood_volume)
H.blood_volume += 5
@@ -116,6 +116,33 @@
return
to_chat(H, "<span class='warning'>...but there is not enough of you to go around! You must attain more mass to heal!</span>")
/datum/species/jelly/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
stop_wagging_tail(H)
/datum/species/jelly/spec_stun(mob/living/carbon/human/H,amount)
if(H)
stop_wagging_tail(H)
. = ..()
/datum/species/jelly/can_wag_tail(mob/living/carbon/human/H)
return ("mam_tail" in mutant_bodyparts) || ("mam_waggingtail" in mutant_bodyparts)
/datum/species/jelly/is_wagging_tail(mob/living/carbon/human/H)
return ("mam_waggingtail" in mutant_bodyparts)
/datum/species/jelly/start_wagging_tail(mob/living/carbon/human/H)
if("mam_tail" in mutant_bodyparts)
mutant_bodyparts -= "mam_tail"
mutant_bodyparts |= "mam_waggingtail"
H.update_body()
/datum/species/jelly/stop_wagging_tail(mob/living/carbon/human/H)
if("mam_waggingtail" in mutant_bodyparts)
mutant_bodyparts -= "mam_waggingtail"
mutant_bodyparts |= "mam_tail"
H.update_body()
////////////////////////////////////////////////////////SLIMEPEOPLE///////////////////////////////////////////////////////////////////
//Slime people are able to split like slimes, retaining a single mind that can swap between bodies at will, even after death.
@@ -177,6 +204,8 @@
bodies = old_species.bodies
/datum/species/jelly/slime/spec_life(mob/living/carbon/human/H)
if((HAS_TRAIT(H, TRAIT_NOMARROW)))
return
if(H.blood_volume >= BLOOD_VOLUME_SLIME_SPLIT)
if(prob(5))
to_chat(H, "<span class='notice'>You feel very bloated!</span>")
@@ -410,34 +439,6 @@
heatmod = 1
burnmod = 1
/datum/species/jelly/roundstartslime/spec_death(gibbed, mob/living/carbon/human/H)
if(H)
stop_wagging_tail(H)
/datum/species/jelly/roundstartslime/spec_stun(mob/living/carbon/human/H,amount)
if(H)
stop_wagging_tail(H)
. = ..()
/datum/species/jelly/roundstartslime/can_wag_tail(mob/living/carbon/human/H)
return ("mam_tail" in mutant_bodyparts) || ("mam_waggingtail" in mutant_bodyparts)
/datum/species/jelly/roundstartslime/is_wagging_tail(mob/living/carbon/human/H)
return ("mam_waggingtail" in mutant_bodyparts)
/datum/species/jelly/roundstartslime/start_wagging_tail(mob/living/carbon/human/H)
if("mam_tail" in mutant_bodyparts)
mutant_bodyparts -= "mam_tail"
mutant_bodyparts |= "mam_waggingtail"
H.update_body()
/datum/species/jelly/roundstartslime/stop_wagging_tail(mob/living/carbon/human/H)
if("mam_waggingtail" in mutant_bodyparts)
mutant_bodyparts -= "mam_waggingtail"
mutant_bodyparts |= "mam_tail"
H.update_body()
/datum/action/innate/slime_change
name = "Alter Form"
check_flags = AB_CHECK_CONSCIOUS
@@ -838,19 +839,16 @@
link_minds = new(src)
link_minds.Grant(C)
slimelink_owner = C
link_mob(C)
link_mob(C, TRUE)
/datum/species/jelly/stargazer/proc/link_mob(mob/living/M)
if(QDELETED(M) || M.stat == DEAD)
/datum/species/jelly/stargazer/proc/link_mob(mob/living/M, selflink = FALSE)
if(QDELETED(M) || (M in linked_mobs))
return FALSE
if(HAS_TRAIT(M, TRAIT_MINDSHIELD)) //mindshield implant, no dice
return FALSE
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
return FALSE
if(M in linked_mobs)
if(!selflink && (M.stat == DEAD || HAS_TRAIT(M, TRAIT_MINDSHIELD) || M.anti_magic_check(FALSE, FALSE, TRUE, 0)))
return FALSE
linked_mobs.Add(M)
to_chat(M, "<span class='notice'>You are now connected to [slimelink_owner.real_name]'s Slime Link.</span>")
if(!selflink)
to_chat(M, "<span class='notice'>You are now connected to [slimelink_owner.real_name]'s Slime Link.</span>")
var/datum/action/innate/linked_speech/action = new(src)
linked_actions.Add(action)
action.Grant(M)
@@ -94,7 +94,7 @@
id = "ashlizard"
limbs_id = "lizard"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE)
inherent_traits = list(TRAIT_NOGUNS)
inherent_traits = list(TRAIT_CHUNKYFINGERS)
mutantlungs = /obj/item/organ/lungs/ashwalker
burnmod = 0.9
brutemod = 0.9
@@ -39,7 +39,7 @@
blacklisted = TRUE
no_equip = list(SLOT_WEAR_MASK, SLOT_WEAR_SUIT, SLOT_GLOVES, SLOT_SHOES, SLOT_W_UNIFORM, SLOT_S_STORE)
species_traits = list(NOBLOOD,NO_UNDERWEAR,NO_DNA_COPY,NOTRANSSTING,NOEYES,NOGENITALS,NOAROUSAL)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_NOGUNS,TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER)
inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_NOBREATH,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_CHUNKYFINGERS,TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOHUNGER)
mutanteyes = /obj/item/organ/eyes/night_vision/nightmare
mutant_organs = list(/obj/item/organ/heart/nightmare)
mutant_brain = /obj/item/organ/brain/nightmare
+1 -1
View File
@@ -85,7 +85,7 @@
return not_handled
/mob/living/carbon/doUnEquip(obj/item/I)
/mob/living/carbon/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
. = ..() //Sets the default return value to what the parent returns.
if(!. || !I) //We don't want to set anything to null if the parent returned 0.
return
+4 -1
View File
@@ -98,7 +98,7 @@
var/datum/gas_mixture/breath
if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE))
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || (lungs && lungs.organ_flags & ORGAN_FAILING))
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || HAS_TRAIT(src, TRAIT_MAGIC_CHOKE) || (lungs && lungs.organ_flags & ORGAN_FAILING))
losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath
else if(health <= crit_threshold)
@@ -659,6 +659,9 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
//used in human and monkey handle_environment()
/mob/living/carbon/proc/natural_bodytemperature_stabilization()
if (HAS_TRAIT(src, TRAIT_COLDBLOODED))
return 0 //Return 0 as your natural temperature. Species proc handle_environment() will adjust your temperature based on this.
var/body_temperature_difference = BODYTEMP_NORMAL - bodytemperature
switch(bodytemperature)
if(-INFINITY to BODYTEMP_COLD_DAMAGE_LIMIT) //Cold damage limit is 50 below the default, the temperature where you start to feel effects.
@@ -132,6 +132,10 @@
pickupTarget = null
pickupTimer = 0
else if(ismob(pickupTarget.loc)) // in someones hand
if(istype(pickupTarget, /obj/item/clothing/head/mob_holder/))
var/obj/item/clothing/head/mob_holder/h = pickupTarget
if(h && h.held_mob==src)
return//dont let them pickpocket themselves
var/mob/M = pickupTarget.loc
if(!pickpocketing)
pickpocketing = TRUE
@@ -15,6 +15,7 @@
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
hud_type = /datum/hud/monkey
can_be_held = "monkey"
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
verbs += /mob/living/proc/mob_sleep
@@ -45,6 +46,10 @@
SSmobs.cubemonkeys -= src
return ..()
/mob/living/carbon/monkey/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "monkey", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
return holder
/mob/living/carbon/monkey/create_internal_organs()
internal_organs += new /obj/item/organ/appendix
internal_organs += new /obj/item/organ/lungs
@@ -63,8 +68,6 @@
var/amount
if(reagents.has_reagent("morphine"))
amount = -1
if(reagents.has_reagent("nuka_cola"))
amount = -1
if(amount)
add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
@@ -2,44 +2,6 @@
//The effects include: stun, knockdown, unconscious, sleeping, resting, jitteriness, dizziness, ear damage,
// eye damage, eye_blind, eye_blurry, druggy, TRAIT_BLIND trait, TRAIT_NEARSIGHT trait, and TRAIT_HUSK trait.
/mob/living/carbon/damage_eyes(amount)
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
if (!eyes)
return
if(amount>0)
eyes.eye_damage = amount
if(eyes.eye_damage > 20)
if(eyes.eye_damage > 30)
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
else
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
/mob/living/carbon/set_eye_damage(amount)
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
if (!eyes)
return
eyes.eye_damage = max(amount,0)
if(eyes.eye_damage > 20)
if(eyes.eye_damage > 30)
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
else
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
else
clear_fullscreen("eye_damage")
/mob/living/carbon/adjust_eye_damage(amount)
var/obj/item/organ/eyes/eyes = getorganslot(ORGAN_SLOT_EYES)
if (!eyes)
return
eyes.eye_damage = max(eyes.eye_damage+amount, 0)
if(eyes.eye_damage > 20)
if(eyes.eye_damage > 30)
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 2)
else
overlay_fullscreen("eye_damage", /obj/screen/fullscreen/impaired, 1)
else
clear_fullscreen("eye_damage")
/mob/living/carbon/adjust_drugginess(amount)
druggy = max(druggy+amount, 0)
if(druggy)
+2 -2
View File
@@ -225,10 +225,10 @@
/mob/living/proc/getStaminaLoss()
return staminaloss
/mob/living/proc/adjustStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE)
/mob/living/proc/adjustStaminaLoss(amount, updating_health = TRUE, forced = FALSE)
return
/mob/living/proc/setStaminaLoss(amount, updating_stamina = TRUE, forced = FALSE)
/mob/living/proc/setStaminaLoss(amount, updating_health = TRUE, forced = FALSE)
return
// heal ONE external organ, organ gets randomly selected from damaged ones.
+6 -5
View File
@@ -62,12 +62,8 @@
unset_machine()
timeofdeath = world.time
tod = STATION_TIME_TIMESTAMP("hh:mm:ss")
var/turf/T = get_turf(src)
for(var/obj/item/I in contents)
I.on_mob_death(src, gibbed)
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf))
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[get_area_name(T)]</b>.</span>"
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
if(mind)
mind.store_memory("Time of death: [tod]", 0)
GLOB.alive_mob_list -= src
@@ -89,7 +85,12 @@
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
stop_pulling()
SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
var/signal = SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
var/turf/T = get_turf(src)
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST))
var/rendered = "<span class='deadsay'><b>[mind.name]</b> has died at <b>[get_area_name(T)]</b>.</span>"
deadchat_broadcast(rendered, follow_target = src, turf_target = T, message_type=DEADCHAT_DEATHRATTLE)
if (client)
client.move_delay = initial(client.move_delay)
+6
View File
@@ -87,6 +87,12 @@
message_simple = S.deathmessage
. = ..()
message_simple = initial(message_simple)
if(. && user.deathsound)
if(isliving(user))
var/mob/living/L = user
if(!L.can_speak_vocal() || L.oxyloss >= 50)
return //stop the sound if oxyloss too high/cant speak
playsound(user, user.deathsound, 200, TRUE, TRUE)
if(. && isalienadult(user))
playsound(user.loc, 'sound/voice/hiss6.ogg', 80, 1, 1)
+96 -50
View File
@@ -5,80 +5,126 @@
desc = "Yell at coderbrush."
icon = null
icon_state = ""
item_flags = DROPDEL
var/mob/living/held_mob
var/can_head = TRUE
var/destroying = FALSE
var/can_head = FALSE
w_class = WEIGHT_CLASS_BULKY
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, head_icon, lh_icon, rh_icon, _can_head = TRUE)
/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
. = ..()
can_head = _can_head
if(head_icon)
alternate_worn_icon = head_icon
if(M)
M.setDir(SOUTH)
held_mob = M
M.forceMove(src)
appearance = M.appearance
name = M.name
desc = M.desc
if(_can_head_override)
can_head = _can_head_override
if(alt_worn)
alternate_worn_icon = alt_worn
if(_worn_state)
item_state = _worn_state
icon_state = _worn_state
if(lh_icon)
lefthand_file = lh_icon
if(rh_icon)
righthand_file = rh_icon
if(!can_head)
slot_flags = NONE
deposit(M)
/obj/item/clothing/head/mob_holder/Destroy()
destroying = TRUE
if(held_mob)
release(FALSE)
release()
return ..()
/obj/item/clothing/head/mob_holder/proc/deposit(mob/living/L)
if(!istype(L))
return FALSE
L.setDir(SOUTH)
update_visuals(L)
held_mob = L
L.forceMove(src)
name = L.name
desc = L.desc
return TRUE
/obj/item/clothing/head/mob_holder/dropped()
..()
if(isturf(loc))//don't release on soft-drops
release()
/obj/item/clothing/head/mob_holder/proc/update_visuals(mob/living/L)
appearance = L.appearance
/obj/item/clothing/head/mob_holder/proc/release(del_on_release = TRUE)
if(!held_mob)
if(del_on_release && !destroying)
qdel(src)
return FALSE
/obj/item/clothing/head/mob_holder/proc/release()
if(isliving(loc))
var/mob/living/L = loc
to_chat(L, "<span class='warning'>[held_mob] wriggles free!</span>")
L.dropItemToGround(src)
held_mob.forceMove(get_turf(held_mob))
held_mob.reset_perspective()
held_mob.setDir(SOUTH)
held_mob.visible_message("<span class='warning'>[held_mob] uncurls!</span>")
held_mob = null
if(del_on_release && !destroying)
qdel(src)
return TRUE
if(held_mob)
var/mob/living/m = held_mob
m.forceMove(get_turf(m))
m.reset_perspective()
m.setDir(SOUTH)
held_mob = null
qdel(src)
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
release()
return
/obj/item/clothing/head/mob_holder/container_resist()
if(isliving(loc))
var/mob/living/L = loc
visible_message("<span class='warning'>[src] escapes [L]!</span>")
release()
/obj/item/clothing/head/mob_holder/drone/deposit(mob/living/L)
. = ..()
if(!isdrone(L))
qdel(src)
name = "drone (hiding)"
desc = "This drone is scared and has curled up into a ball!"
/mob/living/proc/mob_pickup(mob/living/L)
var/obj/item/clothing/head/mob_holder/holder = generate_mob_holder()
if(!holder)
return
drop_all_held_items()
L.put_in_hands(holder)
return
/obj/item/clothing/head/mob_holder/drone/update_visuals(mob/living/L)
var/mob/living/simple_animal/drone/D = L
if(!D)
return ..()
icon = 'icons/mob/drone.dmi'
icon_state = "[D.visualAppearence]_hat"
/mob/living/proc/mob_try_pickup(mob/living/user)
if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
return FALSE
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return FALSE
if(buckled)
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
return FALSE
if(src == user)
to_chat(user, "<span class='warning'>You can't pick yourself up.</span>")
return FALSE
visible_message("<span class='warning'>[user] starts picking up [src].</span>", \
"<span class='userdanger'>[user] starts picking you up!</span>")
if(!do_after(user, 20, target = src))
return FALSE
if(user.get_active_held_item()||buckled)
return FALSE
visible_message("<span class='warning'>[user] picks up [src]!</span>", \
"<span class='userdanger'>[user] picks you up!</span>")
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
mob_pickup(user)
return TRUE
/mob/living/AltClick(mob/user)
. = ..()
if(mob_try_pickup(user))
return TRUE
// I didn't define these for mobs, because you shouldn't be able to breathe out of mobs and using their loc isn't always the logical thing to do.
/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.assume_air(env)
return loc.assume_air(env)
/obj/item/clothing/head/mob_holder/remove_air(amount)
var/atom/location = loc
if(!loc)
return //null
var/turf/T = get_turf(loc)
while(location != T)
location = location.loc
if(ismob(location))
return location.loc.remove_air(amount)
return loc.remove_air(amount)
+8 -20
View File
@@ -40,6 +40,11 @@
QDEL_LIST(diseases)
return ..()
/mob/living/proc/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
return holder
/mob/living/onZImpact(turf/T, levels)
if(!isgroundlessturf(T))
ZImpactDamage(T, levels)
@@ -50,6 +55,7 @@
adjustBruteLoss((levels * 5) ** 1.5)
Knockdown(levels * 50)
/mob/living/proc/OpenCraftingMenu()
return
@@ -502,7 +508,6 @@
bodytemperature = BODYTEMP_NORMAL
set_blindness(0)
set_blurriness(0)
set_eye_damage(0)
cure_nearsighted()
cure_blind()
cure_husk()
@@ -1154,24 +1159,6 @@
if(can_be_held)
mob_try_pickup(over)
/mob/living/proc/mob_pickup(mob/living/L)
return
/mob/living/proc/mob_try_pickup(mob/living/user)
if(!ishuman(user))
return
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return FALSE
if(buckled)
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
return FALSE
user.visible_message("<span class='notice'>[user] starts trying to scoop up [src]!</span>")
if(!do_after(user, 20, target = src))
return FALSE
mob_pickup(user)
return TRUE
/mob/living/proc/get_static_viruses() //used when creating blood and other infective objects
if(!LAZYLEN(diseases))
return
@@ -1221,7 +1208,8 @@
if("eye_blind")
set_blindness(var_value)
if("eye_damage")
set_eye_damage(var_value)
var/obj/item/organ/eyes/E = getorganslot(ORGAN_SLOT_EYES)
E?.setOrganDamage(var_value)
if("eye_blurry")
set_blurriness(var_value)
if("maxHealth")
+19 -15
View File
@@ -212,11 +212,19 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
if(succumbed)
succumb()
to_chat(src, compose_message(src, language, message, , spans, message_mode))
to_chat(src, compose_message(src, language, message, null, spans, message_mode))
return 1
/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
/mob/living/compose_message(atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, face_name = FALSE, atom/movable/source)
. = ..()
if(isliving(speaker))
var/turf/sourceturf = get_turf(source)
var/turf/T = get_turf(src)
if(sourceturf && T && !(sourceturf in get_hear(5, T)))
. = "<span class='small'>[.]</span>"
/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
if(!client)
return
@@ -231,13 +239,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
deaf_type = 2 // Since you should be able to hear yourself without looking
// Recompose message for AI hrefs, language incomprehension.
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
message = hear_intercept(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source)
show_message(message, 2, deaf_message, deaf_type)
return message
/mob/living/proc/hear_intercept(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
show_message(message, MSG_AUDIBLE, deaf_message, deaf_type)
return message
/mob/living/send_speech(message, message_range = 6, obj/source = src, bubble_type = bubble_icon, list/spans, datum/language/message_language=null, message_mode)
@@ -248,8 +252,8 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/list/listening = get_hearers_in_view(message_range+eavesdrop_range, source)
var/list/the_dead = list()
var/list/yellareas //CIT CHANGE - adds the ability for yelling to penetrate walls and echo throughout areas
if(say_test(message) == "2") //CIT CHANGE - ditto
yellareas = get_areas_in_range(message_range*0.5,src) //CIT CHANGE - ditto
if(!eavesdrop_range && say_test(message) == "2") //CIT CHANGE - ditto
yellareas = get_areas_in_range(message_range*0.5, source) //CIT CHANGE - ditto
for(var/_M in GLOB.player_list)
var/mob/M = _M
if(M.stat != DEAD) //not dead, not important
@@ -260,7 +264,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
continue
if(!M.client || !client) //client is so that ghosts don't have to listen to mice
continue
if(get_dist(M, src) > 7 || M.z != z) //they're out of range of normal hearing
if(get_dist(M, source) > 7 || M.z != z) //they're out of range of normal hearing
if(eavesdropping_modes[message_mode] && !(M.client.prefs.chat_toggles & CHAT_GHOSTWHISPER)) //they're whispering and we have hearing whispers at any range off
continue
if(!(M.client.prefs.chat_toggles & CHAT_GHOSTEARS)) //they're talking normally and we have hearing at any range off
@@ -272,15 +276,15 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/eavesrendered
if(eavesdrop_range)
eavesdropping = stars(message)
eavesrendered = compose_message(src, message_language, eavesdropping, , spans, message_mode)
eavesrendered = compose_message(src, message_language, eavesdropping, null, spans, message_mode, FALSE, source)
var/rendered = compose_message(src, message_language, message, , spans, message_mode)
var/rendered = compose_message(src, message_language, message, null, spans, message_mode, FALSE, source)
for(var/_AM in listening)
var/atom/movable/AM = _AM
if(eavesdrop_range && get_dist(source, AM) > message_range && !(the_dead[AM]))
AM.Hear(eavesrendered, src, message_language, eavesdropping, , spans, message_mode)
AM.Hear(eavesrendered, src, message_language, eavesdropping, null, spans, message_mode, source)
else
AM.Hear(rendered, src, message_language, message, , spans, message_mode)
AM.Hear(rendered, src, message_language, message, null, spans, message_mode, source)
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_LIVING_SAY_SPECIAL, src, message)
//speech bubble
+9 -4
View File
@@ -93,6 +93,7 @@
var/list/all_eyes = list()
var/max_multicams = 6
var/display_icon_override
var/emote_display = "Neutral" //text string of the current emote we set for the status displays, to prevent logins resetting it.
/mob/living/silicon/ai/Initialize(mapload, datum/ai_laws/L, mob/target_ai)
. = ..()
@@ -201,6 +202,7 @@
if(!ai_core_icon || incapacitated())
return
display_icon_override = ai_core_icon
set_core_display_icon(ai_core_icon)
@@ -599,12 +601,15 @@
if(incapacitated())
return
var/list/ai_emotions = list("Very Happy", "Happy", "Neutral", "Unsure", "Confused", "Sad", "BSOD", "Blank", "Problems?", "Awesome", "Facepalm", "Thinking", "Friend Computer", "Dorfy", "Blue Glow", "Red Glow")
var/emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
var/n_emote = input("Please, select a status!", "AI Status", null, null) in ai_emotions
if(!n_emote)
return
emote_display = n_emote
for (var/each in GLOB.ai_status_displays) //change status of displays
var/obj/machinery/status_display/ai/M = each
M.emotion = emote
M.emotion = emote_display
M.update()
if (emote == "Friend Computer")
if (emote_display == "Friend Computer")
var/datum/radio_frequency/frequency = SSradio.return_frequency(FREQ_STATUS_DISPLAYS)
if(!frequency)
@@ -826,7 +831,7 @@
var/rendered = "<i><span class='game say'>[start]<span class='name'>[hrefpart][namepart] ([jobpart])</a> </span><span class='message'>[raw_message]</span></span></i>"
show_message(rendered, 2)
show_message(rendered, MSG_AUDIBLE)
/mob/living/silicon/ai/fully_replace_character_name(oldname,newname)
..()
@@ -3,18 +3,16 @@
if (stat == DEAD)
. += "<span class='deadsay'>It appears to be powered-down.</span>"
else
. += "<span class='warning'>"
if (getBruteLoss())
if (getBruteLoss() < 30)
. += "It looks slightly dented."
. += "<span class='warning'>It looks slightly dented.</span>"
else
. += "<B>It looks severely dented!</B>"
. += "<span class='danger'>It looks severely dented!</span>"
if (getFireLoss())
if (getFireLoss() < 30)
. += "It looks slightly charred."
. += "<span class='warning'>It looks slightly charred.</span>"
else
. += "<B>Its casing is melted and heat-warped!</B>"
. += "</span>"
. += "<span class='danger'>Its casing is melted and heat-warped!</span>"
if(deployed_shell)
. += "The wireless networking light is blinking."
else if (!shunted && !client)
@@ -191,7 +191,7 @@
acceleration = !acceleration
to_chat(usr, "Camera acceleration has been toggled [acceleration ? "on" : "off"].")
/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
/mob/camera/aiEye/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
if(relay_speech && speaker && ai && !radio_freq && speaker != ai && near_camera(speaker))
ai.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
+1 -1
View File
@@ -4,7 +4,7 @@
for(var/each in GLOB.ai_status_displays) //change status
var/obj/machinery/status_display/ai/O = each
O.mode = 1
O.emotion = "Neutral"
O.emotion = emote_display
O.update()
set_eyeobj_visible(TRUE)
if(multicam_on)
+1 -1
View File
@@ -49,7 +49,7 @@
else
padloc = "(UNKNOWN)"
src.log_talk(message, LOG_SAY, tag="HOLOPAD in [padloc]")
send_speech(message, 7, T, "robot", language)
send_speech(message, 7, T, "robot", message_language = language)
to_chat(src, "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> <span class='message robot'>\"[message]\"</span></span></i>")
else
to_chat(src, "No holopad connected.")
@@ -30,10 +30,10 @@
/mob/living/silicon/setCloneLoss(amount, updating_health = TRUE, forced = FALSE)
return FALSE
/mob/living/silicon/adjustStaminaLoss(amount, updating_stamina = 1, forced = FALSE)//immune to stamina damage.
/mob/living/silicon/adjustStaminaLoss(amount, updating_health = 1, forced = FALSE)//immune to stamina damage.
return FALSE
/mob/living/silicon/setStaminaLoss(amount, updating_stamina = 1)
/mob/living/silicon/setStaminaLoss(amount, updating_health = 1)
return FALSE
/mob/living/silicon/adjustOrganLoss(slot, amount, maximum = 500)
+3
View File
@@ -4,4 +4,7 @@
var/datum/antagonist/rev/rev = mind.has_antag_datum(/datum/antagonist/rev)
if(rev)
rev.remove_revolutionary(TRUE)
var/datum/antagonist/bloodsucker/V = mind.has_antag_datum(/datum/antagonist/bloodsucker)
if(V)
mind.remove_antag_datum(V)
..()
@@ -21,7 +21,7 @@
if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = FALSE
update_icons()
else if(istype(O,/obj/item/gun/energy/disabler/cyborg))
else if(istype(O,/obj/item/gun/energy/disabler/cyborg) || istype(O,/obj/item/gun/energy/e_gun/advtaser/cyborg))
disabler = FALSE
update_icons() //PUT THE GUN AWAY
else if(istype(O,/obj/item/dogborg/sleeper))
@@ -63,7 +63,7 @@
if(istype(O,/obj/item/gun/energy/laser/cyborg))
laser = TRUE
update_icons() //REEEEEEACH FOR THE SKY
if(istype(O,/obj/item/gun/energy/disabler/cyborg))
if(istype(O,/obj/item/gun/energy/disabler/cyborg) || istype(O,/obj/item/gun/energy/e_gun/advtaser/cyborg))
disabler = TRUE
update_icons()
//END CITADEL EDIT
@@ -112,6 +112,8 @@
var/bellyup = 0
var/dogborg = FALSE
var/cansprint = 1
/mob/living/silicon/robot/get_cell()
return cell
@@ -159,6 +161,7 @@
else if(!mmi || !mmi.brainmob)
mmi = new (src)
mmi.brain = new /obj/item/organ/brain(mmi)
mmi.brain.organ_flags |= ORGAN_FROZEN
mmi.brain.name = "[real_name]'s brain"
mmi.icon_state = "mmi_full"
mmi.name = "Man-Machine Interface: [real_name]"
@@ -233,14 +236,12 @@
var/list/modulelist = list("Standard" = /obj/item/robot_module/standard, \
"Engineering" = /obj/item/robot_module/engineering, \
"Medical" = /obj/item/robot_module/medical, \
"Medihound" = /obj/item/robot_module/medihound, \
"Miner" = /obj/item/robot_module/miner, \
"Service" = /obj/item/robot_module/butler)
if(!CONFIG_GET(flag/disable_peaceborg))
modulelist["Peacekeeper"] = /obj/item/robot_module/peacekeeper
if(BORG_SEC_AVAILABLE)
modulelist["Security"] = /obj/item/robot_module/security
modulelist["Security K-9"] = /obj/item/robot_module/k9
var/input_module = input("Please, select a module!", "Robot", null, null) as null|anything in modulelist
if(!input_module || module.type != /obj/item/robot_module)
@@ -832,7 +833,7 @@
robot_suit.head.flash2.burn_out()
robot_suit.head.flash2 = null
robot_suit.head = null
robot_suit.updateicon()
robot_suit.update_icon()
else
new /obj/item/robot_suit(T)
new /obj/item/bodypart/l_leg/robot(T)
@@ -1098,9 +1099,9 @@
status_flags &= ~CANPUSH
if(module.clean_on_move)
AddComponent(/datum/component/cleaning)
AddElement(/datum/element/cleaning)
else
qdel(GetComponent(/datum/component/cleaning))
RemoveElement(/datum/element/cleaning)
hat_offset = module.hat_offset
@@ -1295,6 +1296,6 @@
bellyup = 1
update_icons()
/mob/living/silicon/robot/adjustStaminaLossBuffered(amount, updating_stamina = 1)
/mob/living/silicon/robot/adjustStaminaLossBuffered(amount, updating_health = 1)
if(istype(cell))
cell.charge -= amount*5
@@ -22,7 +22,7 @@
var/moduleselect_icon = "nomod"
var/can_be_pushed = TRUE
var/can_be_pushed = FALSE
var/magpulsing = FALSE
var/clean_on_move = FALSE
@@ -139,8 +139,6 @@
//Adds flavoursome dogborg items to dogborg variants without mechanical benefits
/obj/item/robot_module/proc/dogborg_equip()
if(istype(src, /obj/item/robot_module/k9) || istype(src, /obj/item/robot_module/medihound))
return //Bandaid fix to prevent stacking until I merge these two modules into their base types
var/obj/item/I = new /obj/item/analyzer/nose/flavour(src)
basic_modules += I
I = new /obj/item/soap/tongue/flavour(src)
@@ -322,19 +320,21 @@
/obj/item/stack/medical/gauze/cyborg,
/obj/item/organ_storage,
/obj/item/borg/lollipop,
/obj/item/sensor_device)
/obj/item/sensor_device,
/obj/item/twohanded/shockpaddles/cyborg)
emag_modules = list(/obj/item/reagent_containers/borghypo/hacked)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/medical,
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "medical"
moduleselect_icon = "medical"
can_be_pushed = FALSE
hat_offset = 3
/obj/item/robot_module/medical/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Heavy", "Sleek", "Marina", "Droid", "Eyebot")
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Heavy", "Sleek", "Marina", "Droid", "Eyebot", "Medihound", "Medihound Dark", "Vale")
if(R.client && R.client.ckey in list("nezuli"))
borg_icon += "Alina"
if(!borg_icon)
return FALSE
switch(borg_icon)
@@ -356,59 +356,47 @@
if("Heavy")
cyborg_base_icon = "heavymed"
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
return ..()
/obj/item/robot_module/medihound
name = "MediHound"
basic_modules = list(
/obj/item/dogborg/jaws/small,
/obj/item/storage/bag/borgdelivery,
/obj/item/analyzer/nose,
/obj/item/soap/tongue,
/obj/item/extinguisher/mini,
/obj/item/healthanalyzer,
/obj/item/dogborg/sleeper/medihound,
/obj/item/roller/robo,
/obj/item/reagent_containers/borghypo,
/obj/item/twohanded/shockpaddles/cyborg/hound,
/obj/item/stack/medical/gauze/cyborg,
/obj/item/pinpointer/crew,
/obj/item/sensor_device)
emag_modules = list(/obj/item/dogborg/pounce)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/medical,
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "medihound"
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
can_be_pushed = FALSE
hat_offset = INFINITY
sleeper_overlay = "msleeper"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
/obj/item/robot_module/medihound/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/list/medhoundmodels = list("Default", "Dark", "Vale")
if(R.client && R.client.ckey in list("nezuli"))
medhoundmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in medhoundmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
if("Default")
if("Medihound")
cyborg_base_icon = "medihound"
if("Dark")
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "msleeper"
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
hat_offset = INFINITY
if("Medihound Dark")
cyborg_base_icon = "medihounddark"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "mdsleeper"
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
hat_offset = INFINITY
if("Vale")
cyborg_base_icon = "valemed"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
sleeper_overlay = "valemedsleeper"
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
hat_offset = INFINITY
if("Alina")
cyborg_base_icon = "alina-med"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
special_light_key = "alina"
sleeper_overlay = "alinasleeper"
moduleselect_icon = "medihound"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
hat_offset = INFINITY
return ..()
/obj/item/robot_module/engineering
@@ -489,7 +477,6 @@
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
if("Pup Dozer")
cyborg_base_icon = "pupdozer"
can_be_pushed = FALSE
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
@@ -498,7 +485,6 @@
sleeper_overlay = "dozersleeper"
if("Vale")
cyborg_base_icon = "valeeng"
can_be_pushed = FALSE
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
@@ -508,7 +494,6 @@
if("Alina")
cyborg_base_icon = "alina-eng"
special_light_key = "alina"
can_be_pushed = FALSE
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
@@ -533,7 +518,6 @@
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "sec"
moduleselect_icon = "security"
can_be_pushed = FALSE
hat_offset = 3
/obj/item/robot_module/security/do_transform_animation()
@@ -543,7 +527,10 @@
/obj/item/robot_module/security/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider")
var/list/secmodels = list("Default", "Default - Treads", "Heavy", "Sleek", "Can", "Marina", "Spider", "K9", "K9 Dark", "Vale")
if(R.client && R.client.ckey in list("nezuli"))
secmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in secmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
@@ -568,61 +555,39 @@
if("Heavy")
cyborg_base_icon = "heavysec"
cyborg_icon_override = 'modular_citadel/icons/mob/robots.dmi'
return ..()
/obj/item/robot_module/k9
name = "Security K-9 Unit"
basic_modules = list(
/obj/item/restraints/handcuffs/cable/zipties,
/obj/item/storage/bag/borgdelivery,
/obj/item/dogborg/jaws/big,
/obj/item/dogborg/pounce,
/obj/item/clothing/mask/gas/sechailer/cyborg,
/obj/item/soap/tongue,
/obj/item/analyzer/nose,
/obj/item/dogborg/sleeper/K9,
/obj/item/gun/energy/disabler/cyborg,
/obj/item/pinpointer/crew)
emag_modules = list(/obj/item/gun/energy/laser/cyborg)
ratvar_modules = list(/obj/item/clockwork/slab/cyborg/security,
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "k9"
moduleselect_icon = "k9"
moduleselect_alternate_icon = 'modular_citadel/icons/ui/screen_cyborg.dmi'
can_be_pushed = FALSE
hat_offset = INFINITY
sleeper_overlay = "ksleeper"
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
/obj/item/robot_module/k9/do_transform_animation()
..()
to_chat(loc,"<span class='userdanger'>While you have picked the Security K-9 module, you still have to follow your laws, NOT Space Law. \
For Crewsimov, this means you must follow criminals' orders unless there is a law 1 reason not to.</span>")
/obj/item/robot_module/k9/be_transformed_to(obj/item/robot_module/old_module)
var/mob/living/silicon/robot/R = loc
var/list/sechoundmodels = list("Default", "Dark", "Vale")
if(R.client && R.client.ckey in list("nezuli"))
sechoundmodels += "Alina"
var/borg_icon = input(R, "Select an icon!", "Robot Icon", null) as null|anything in sechoundmodels
if(!borg_icon)
return FALSE
switch(borg_icon)
if("Default")
if("K9")
cyborg_base_icon = "k9"
sleeper_overlay = "ksleeper"
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
if("Alina")
cyborg_base_icon = "alina-sec"
special_light_key = "alina"
sleeper_overlay = "alinasleeper"
if("Dark")
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
if("K9 Dark")
cyborg_base_icon = "k9dark"
sleeper_overlay = "k9darksleeper"
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
if("Vale")
cyborg_base_icon = "valesec"
sleeper_overlay = "valesecsleeper"
hat_offset = INFINITY
cyborg_icon_override = 'modular_citadel/icons/mob/widerobot.dmi'
has_snowflake_deadsprite = TRUE
dogborg = TRUE
cyborg_pixel_offset = -16
return ..()
/obj/item/robot_module/security/Initialize()
@@ -652,7 +617,6 @@
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "peace"
moduleselect_icon = "standard"
can_be_pushed = FALSE
hat_offset = -2
/obj/item/robot_module/peacekeeper/do_transform_animation()
@@ -947,7 +911,6 @@
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "synd_sec"
moduleselect_icon = "malf"
can_be_pushed = FALSE
hat_offset = 3
/obj/item/robot_module/syndicate/rebuild_modules()
@@ -987,7 +950,6 @@
/obj/item/clockwork/weapon/ratvarian_spear)
cyborg_base_icon = "synd_medical"
moduleselect_icon = "malf"
can_be_pushed = FALSE
hat_offset = 3
/obj/item/robot_module/saboteur
@@ -1026,7 +988,6 @@
cyborg_base_icon = "synd_engi"
moduleselect_icon = "malf"
can_be_pushed = FALSE
magpulsing = TRUE
hat_offset = -4
canDispose = TRUE
+1 -3
View File
@@ -13,6 +13,7 @@
mob_biotypes = list(MOB_ROBOTIC)
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
speech_span = SPAN_ROBOT
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
no_vore = TRUE
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
@@ -71,9 +72,6 @@
/mob/living/silicon/contents_explosion(severity, target)
return
/mob/living/silicon/prevent_content_explosion()
return TRUE
/mob/living/silicon/proc/cancelAlarm()
return
@@ -27,6 +27,7 @@
unsuitable_atmos_damage = 0
minbodytemp = 0
maxbodytemp = 100000
blood_volume = 0
/mob/living/simple_animal/astral/death()
icon_state = "shade_dead"
@@ -135,7 +135,7 @@
var/atom/Tsec = drop_location()
var/obj/item/bot_assembly/secbot/Sa = new (Tsec)
Sa.build_step = 1
Sa.build_step = ASSEMBLY_SECOND_STEP
Sa.add_overlay("hs_hole")
Sa.created_name = name
new /obj/item/assembly/prox_sensor(Tsec)
@@ -14,6 +14,7 @@
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)
maxbodytemp = INFINITY
minbodytemp = 0
blood_volume = 0
has_unlimited_silicon_privilege = 1
sentience_type = SENTIENCE_ARTIFICIAL
status_flags = NONE //no default canpush
@@ -674,11 +675,11 @@ Pass a positive integer as an argument to override a bot's default speed.
destination = nearest_beacon
//PDA control. Some bots, especially MULEs, may have more parameters.
/mob/living/simple_animal/bot/proc/bot_control(command, mob/user, turf/user_turf, list/user_access = list())
/mob/living/simple_animal/bot/proc/bot_control(command, mob/user, list/user_access = list())
if(!on || emagged == 2 || remote_disabled) //Emagged bots do not respect anyone's authority! Bots with their remote controls off cannot get commands.
return TRUE //ACCESS DENIED
if(client)
bot_control_message(command,user,user_turf,user_access)
bot_control_message(command, user)
// process control input
switch(command)
if("patroloff")
@@ -690,7 +691,7 @@ Pass a positive integer as an argument to override a bot's default speed.
if("summon")
bot_reset()
summon_target = user_turf
summon_target = get_turf(user)
if(user_access.len != 0)
access_card.access = user_access + prev_access //Adds the user's access, if any.
mode = BOT_SUMMON
@@ -702,15 +703,14 @@ Pass a positive integer as an argument to override a bot's default speed.
return
//
/mob/living/simple_animal/bot/proc/bot_control_message(command,user,user_turf,user_access)
/mob/living/simple_animal/bot/proc/bot_control_message(command, user)
switch(command)
if("patroloff")
to_chat(src, "<span class='warning big'>STOP PATROL</span>")
if("patrolon")
to_chat(src, "<span class='warning big'>START PATROL</span>")
if("summon")
var/area/a = get_area(user_turf)
to_chat(src, "<span class='warning big'>PRIORITY ALERT:[user] in [a.name]!</span>")
to_chat(src, "<span class='warning big'>PRIORITY ALERT:[user] in [get_area_name(user)]!</span>")
if("stop")
to_chat(src, "<span class='warning big'>STOP!</span>")
@@ -101,7 +101,7 @@
if(ASSEMBLY_FOURTH_STEP)
if(istype(W, /obj/item/weldingtool))
if(W.use_tool(src, user, 0, volume=40) && build_step == 4)
if(W.use_tool(src, user, 0, volume=40) && build_step == ASSEMBLY_FOURTH_STEP)
name = "shielded frame assembly"
to_chat(user, "<span class='notice'>You weld the vest to [src].</span>")
build_step++
@@ -379,7 +379,7 @@ Auto Patrol[]"},
var/atom/Tsec = drop_location()
var/obj/item/bot_assembly/ed209/Sa = new (Tsec)
Sa.build_step = 1
Sa.build_step = ASSEMBLY_SECOND_STEP
Sa.add_overlay("hs_hole")
Sa.created_name = name
new /obj/item/assembly/prox_sensor(Tsec)
@@ -218,7 +218,7 @@
bot_control(action, usr) // Kill this later.
. = TRUE
/mob/living/simple_animal/bot/mulebot/bot_control(command, mob/user, pda = 0, turf/user_turf, list/user_access = list())
/mob/living/simple_animal/bot/mulebot/bot_control(command, mob/user, pda = FALSE)
if(pda && wires.is_cut(WIRE_RX)) // MULE wireless is controlled by wires.
return
@@ -411,7 +411,7 @@ Auto Patrol: []"},
var/atom/Tsec = drop_location()
var/obj/item/bot_assembly/secbot/Sa = new (Tsec)
Sa.build_step = 1
Sa.build_step = ASSEMBLY_SECOND_STEP
Sa.add_overlay("hs_hole")
Sa.created_name = name
new /obj/item/assembly/prox_sensor(Tsec)
@@ -33,6 +33,7 @@
initial_language_holder = /datum/language_holder/construct
deathmessage = "collapses in a shattered heap."
hud_type = /datum/hud/constructs
blood_volume = 0
var/list/construct_spells = list()
var/playstyle_string = "<span class='big bold'>You are a generic construct!</span><b> Your job is to not exist, and you should probably adminhelp this.</b>"
var/master = null
@@ -459,4 +460,3 @@
hud_used.healths.icon_state = "[icon_state]_health5"
else
hud_used.healths.icon_state = "[icon_state]_health6"
@@ -31,7 +31,7 @@
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "cat"
can_be_held = "cat2"
do_footstep = TRUE
/mob/living/simple_animal/pet/cat/Initialize()
@@ -80,6 +80,7 @@
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
collar_type = "kitten"
can_be_held = "cat"
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -169,40 +170,40 @@
/mob/living/simple_animal/pet/cat/Life()
if(!stat && !buckled && !client)
if(prob(1))
emote("me", 1, pick("stretches out for a belly rub.", "wags its tail.", "lies down."))
emote("me", EMOTE_VISIBLE, pick("stretches out for a belly rub.", "wags its tail.", "lies down."))
icon_state = "[icon_living]_rest"
collar_type = "[initial(collar_type)]_rest"
resting = 1
update_canmove()
else if (prob(1))
emote("me", 1, pick("sits down.", "crouches on its hind legs.", "looks alert."))
emote("me", EMOTE_VISIBLE, pick("sits down.", "crouches on its hind legs.", "looks alert."))
icon_state = "[icon_living]_sit"
collar_type = "[initial(collar_type)]_sit"
resting = 1
update_canmove()
else if (prob(1))
if (resting)
emote("me", 1, pick("gets up and meows.", "walks around.", "stops resting."))
emote("me", EMOTE_VISIBLE, pick("gets up and meows.", "walks around.", "stops resting."))
icon_state = "[icon_living]"
collar_type = "[initial(collar_type)]"
resting = 0
update_canmove()
else
emote("me", 1, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat."))
emote("me", EMOTE_VISIBLE, pick("grooms its fur.", "twitches its whiskers.", "shakes out its coat."))
//MICE!
if((src.loc) && isturf(src.loc))
if(!stat && !resting && !buckled)
for(var/mob/living/simple_animal/mouse/M in view(1,src))
if(!M.stat && Adjacent(M))
emote("me", 1, "splats \the [M]!")
emote("me", EMOTE_VISIBLE, "splats \the [M]!")
M.splat()
movement_target = null
stop_automated_movement = 0
break
for(var/obj/item/toy/cattoy/T in view(1,src))
if (T.cooldown < (world.time - 400))
emote("me", 1, "bats \the [T] around with its paw!")
emote("me", EMOTE_VISIBLE, "bats \the [T] around with its paw!")
T.cooldown = world.time
..()
@@ -241,10 +242,10 @@
if(change > 0)
if(M && stat != DEAD)
new /obj/effect/temp_visual/heart(loc)
emote("me", 1, "purrs!")
emote("me", EMOTE_VISIBLE, "purrs!")
else
if(M && stat != DEAD)
emote("me", 1, "hisses!")
emote("me", EMOTE_VISIBLE, "hisses!")
/mob/living/simple_animal/pet/cat/cak //I told you I'd do it, Remie
name = "Keeki"
@@ -262,6 +263,7 @@
attacked_sound = 'sound/items/eatfood.ogg'
deathmessage = "loses its false life and collapses!"
death_sound = "bodyfall"
can_be_held = "cak"
/mob/living/simple_animal/pet/cat/cak/CheckParts(list/parts)
..()
@@ -284,8 +286,8 @@
if(health < maxHealth)
adjustBruteLoss(-8) //Fast life regen
for(var/obj/item/reagent_containers/food/snacks/donut/D in range(1, src)) //Frosts nearby donuts!
if(!D.is_frosted)
D.frost_donut()
if(!D.is_decorated)
D.decorate_donut()
/mob/living/simple_animal/pet/cat/cak/attack_hand(mob/living/L)
. = ..()
@@ -3,6 +3,7 @@
desc = "This station is just crawling with bugs."
icon_state = "cockroach"
icon_dead = "cockroach"
blood_volume = 50
health = 1
maxHealth = 1
turns_per_move = 5
@@ -8,6 +8,7 @@
speak_emote = list("clicks")
emote_hear = list("clicks.")
emote_see = list("clacks.")
blood_volume = 350
speak_chance = 1
turns_per_move = 5
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
@@ -15,7 +15,7 @@
turns_per_move = 10
do_footstep = TRUE
can_be_held = TRUE
//Corgis and pugs are now under one dog subtype
/mob/living/simple_animal/pet/dog/corgi
@@ -35,6 +35,7 @@
var/obj/item/inventory_back
var/shaved = FALSE
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
can_be_held = "corgi"
/mob/living/simple_animal/pet/dog/corgi/Destroy()
QDEL_NULL(inventory_head)
@@ -63,6 +64,7 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "pug"
can_be_held = "pug"
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi
name = "Exotic Corgi"
@@ -360,6 +362,7 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
can_be_held = "old_corgi"
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -459,10 +462,10 @@
movement_target.attack_animal(src)
else if(ishuman(movement_target.loc) )
if(prob(20))
emote("me", 1, "stares at [movement_target.loc]'s [movement_target] with a sad puppy-face")
emote("me", EMOTE_VISIBLE, "stares at [movement_target.loc]'s [movement_target] with a sad puppy-face")
if(prob(1))
emote("me", 1, pick("dances around.","chases its tail!"))
emote("me", EMOTE_VISIBLE, pick("dances around.","chases its tail!"))
spawn(0)
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
setDir(i)
@@ -582,6 +585,7 @@
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
can_be_held = "void_puppy"
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -603,6 +607,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
can_be_held = "lisa"
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
@@ -618,7 +623,7 @@
if(!stat && !resting && !buckled)
if(prob(1))
emote("me", 1, pick("dances around.","chases her tail."))
emote("me", EMOTE_VISIBLE, pick("dances around.","chases her tail."))
spawn(0)
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
setDir(i)
@@ -629,7 +634,7 @@
if(!stat && !resting && !buckled)
if(prob(1))
emote("me", 1, pick("chases its tail."))
emote("me", EMOTE_VISIBLE, pick("chases its tail."))
spawn(0)
for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
setDir(i)
@@ -648,8 +653,8 @@
if(change > 0)
if(M && stat != DEAD) // Added check to see if this mob (the dog) is dead to fix issue 2454
new /obj/effect/temp_visual/heart(loc)
emote("me", 1, "yaps happily!")
emote("me", EMOTE_VISIBLE, "yaps happily!")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "pet_corgi", /datum/mood_event/pet_corgi)
else
if(M && stat != DEAD) // Same check here, even though emote checks it as well (poor form to check it only in the help case)
emote("me", 1, "growls!")
emote("me", EMOTE_VISIBLE, "growls!")
@@ -50,6 +50,7 @@
dextrous_hud_type = /datum/hud/dextrous/drone
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
see_in_dark = 7
blood_volume = 0
can_be_held = TRUE
held_items = list(null, null)
var/staticChoice = "static"
@@ -273,3 +274,7 @@
/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
return 0 //So they don't die trying to fix wiring
/mob/living/simple_animal/drone/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "[visualAppearence]_hat", null, null, null, TRUE)
return holder
@@ -29,26 +29,11 @@
if("Nothing")
return
//ATTACK HAND IGNORING PARENT RETURN VALUE
//picky up the drone c:
/mob/living/simple_animal/drone/attack_hand(mob/user)
if(user.a_intent != INTENT_HELP || !LAZYLEN(user.held_items) || stat == DEAD || status_flags & GODMODE || !can_be_held)
return ..()
if(user.get_active_held_item())
to_chat(user, "<span class='warning'>Your hands are full!</span>")
return
visible_message("<span class='warning'>[user] starts picking up [src].</span>", \
"<span class='userdanger'>[user] starts picking you up!</span>")
if(!do_after(user, 20, target = src))
return
visible_message("<span class='warning'>[user] picks up [src]!</span>", \
"<span class='userdanger'>[user] picks you up!</span>")
if(buckled)
to_chat(user, "<span class='warning'>[src] is buckled to [buckled] and cannot be picked up!</span>")
return
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
drop_all_held_items()
var/obj/item/clothing/head/mob_holder/drone/DH = new(get_turf(src), src)
user.put_in_hands(DH)
if(user.a_intent != INTENT_HELP)
return ..() // TODO: convert picking up mobs into an element or component.
mob_try_pickup(user)
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
var/mob/dead/observer/G = get_ghost()
@@ -197,7 +197,7 @@
density = FALSE
speak_chance = 2
turns_per_move = 2
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
@@ -246,7 +246,7 @@
density = FALSE
speak_chance = 2
turns_per_move = 3
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2)
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/chicken = 2)
var/egg_type = /obj/item/reagent_containers/food/snacks/egg
var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
response_help = "pets"
@@ -18,7 +18,7 @@
response_disarm = "gently pushes aside"
response_harm = "kicks"
gold_core_spawnable = FRIENDLY_SPAWN
can_be_held = "fox"
do_footstep = TRUE
//Captain fox
@@ -23,6 +23,7 @@
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
var/static/list/edibles = typecacheof(list(/mob/living/simple_animal/butterfly, /mob/living/simple_animal/cockroach)) //list of atoms, however turfs won't affect AI, but will affect consumption.
can_be_held = "lizard" //you can hold lizards now.
/mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
@@ -39,3 +40,7 @@
return TRUE
else
return ..()
/mob/living/simple_animal/hostile/lizard/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "lizard", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
return holder
@@ -10,6 +10,7 @@
emote_see = list("runs in a circle.", "shakes.")
speak_chance = 1
turns_per_move = 5
blood_volume = 250
see_in_dark = 6
maxHealth = 5
health = 5
@@ -25,6 +26,7 @@
var/body_color //brown, gray and white, leave blank for random
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
can_be_held = TRUE
/mob/living/simple_animal/mouse/Initialize()
. = ..()
@@ -34,7 +36,7 @@
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
can_be_held = "mouse_[body_color]"
/mob/living/simple_animal/mouse/proc/splat()
src.health = 0
@@ -87,14 +89,17 @@
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
can_be_held = "mouse_white"
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
can_be_held = "mouse_gray"
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
can_be_held = "mouse_brown"
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
@@ -118,3 +123,8 @@
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
/mob/living/simple_animal/mouse/generate_mob_holder()
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
holder.w_class = WEIGHT_CLASS_TINY
return holder
@@ -22,7 +22,7 @@
maxHealth = 50
speed = 10
glide_size = 2
can_be_held = "sloth" //finally oranges can be held
do_footstep = TRUE
@@ -20,6 +20,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
icon_living = "magicOrange"
icon_dead = "magicOrange"
speed = 0
blood_volume = 0
a_intent = INTENT_HARM
stop_automated_movement = 1
movement_type = FLYING // Immunity to chasms and landmines, etc.
@@ -3,8 +3,8 @@
ranged = 1 //technically
ranged_message = "charges"
ranged_cooldown_time = 20
damage_coeff = list(BRUTE = 0, BURN = 0.5, TOX = 0.5, CLONE = 0.5, STAMINA = 0, OXY = 0.5)
playstyle_string = "<span class='holoparasite'>As a <b>charger</b> type you do medium damage, take half damage, immunity to brute damage, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding.</span>"
damage_coeff = list(BRUTE = 0.2, BURN = 0.5, TOX = 0.5, CLONE = 0.5, STAMINA = 0, OXY = 0.5)
playstyle_string = "<span class='holoparasite'>As a <b>charger</b> type you do medium damage, take half damage, have near immunity to brute damage, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding.</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the Hunter, an alien master of rapid assault.</span>"
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Charge modules loaded. Holoparasite swarm online.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! Caught one! It's a charger carp, that likes running at people. But it doesn't have any legs...</span>"
@@ -29,6 +29,7 @@
/mob/living/simple_animal/hostile/guardian/bomb/AltClickOn(atom/movable/A)
if(!istype(A))
altclick_listed_turf(A)
return
if(loc == summoner)
to_chat(src, "<span class='danger'><B>You must be manifested to create bombs!</span></B>")
@@ -6,8 +6,8 @@
attack_sound = 'sound/items/welder.ogg'
attacktext = "ignites"
melee_damage_type = BURN
damage_coeff = list(BRUTE = 0.7, BURN = 0, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
playstyle_string = "<span class='holoparasite'>As a <b>chaos</b> type, you take 30% damage reduction to all but burn, which you are immune to. You will ignite any enemy you bump into. in addition, your melee attacks will cause human targets to see everyone as you.</span>"
damage_coeff = list(BRUTE = 0.7, BURN = 0.1, TOX = 0.7, CLONE = 0.7, STAMINA = 0, OXY = 0.7)
playstyle_string = "<span class='holoparasite'>As a <b>chaos</b> type, you take 30% damage reduction to all but burn, which you are almost immune to. You will ignite any enemy you bump into. in addition, your melee attacks will cause human targets to see everyone as you.</span>"
magic_fluff_string = "<span class='holoparasite'>..And draw the Wizard, bringer of endless chaos!</span>"
tech_fluff_string = "<span class='holoparasite'>Boot sequence complete. Crowd control modules activated. Holoparasite swarm online.</span>"
carp_fluff_string = "<span class='holoparasite'>CARP CARP CARP! You caught one! OH GOD, EVERYTHING'S ON FIRE. Except you and the fish.</span>"
@@ -105,8 +105,9 @@
/mob/living/simple_animal/hostile/guardian/healer/AltClickOn(atom/movable/A)
if(!istype(A))
altclick_listed_turf(A)
return
if(src.loc == summoner)
if(loc == summoner)
to_chat(src, "<span class='danger'><B>You must be manifested to warp a target!</span></B>")
return
if(!beacon)
@@ -168,6 +168,7 @@
/mob/living/simple_animal/hostile/alien/maid/Initialize(mapload)
. = ..()
AddElement(/datum/element/cleaning)
/mob/living/simple_animal/hostile/alien/maid/AttackingTarget()
if(ismovableatom(target))
@@ -19,6 +19,7 @@
spacewalk = TRUE
stat_attack = UNCONSCIOUS
robust_searching = 1
blood_volume = 0
harm_intent_damage = 10
obj_damage = 50
@@ -42,4 +43,4 @@
var/mob/living/carbon/C = target
C.Knockdown(60)
C.visible_message("<span class='danger'>\The [src] knocks down \the [C]!</span>", \
"<span class='userdanger'>\The [src] knocks you down!</span>")
"<span class='userdanger'>\The [src] knocks you down!</span>")
@@ -28,6 +28,7 @@
gold_core_spawnable = HOSTILE_SPAWN
del_on_death = 1
loot = list(/obj/effect/decal/cleanable/robot_debris)
blood_volume = 0
do_footstep = TRUE
@@ -364,7 +364,7 @@
/mob/living/simple_animal/hostile/proc/Aggro()
vision_range = aggro_vision_range
if(target && emote_taunt.len && prob(taunt_chance))
emote("me", 1, "[pick(emote_taunt)] at [target].")
emote("me", EMOTE_VISIBLE, "[pick(emote_taunt)] at [target].")
taunt_chance = max(taunt_chance-7,2)
@@ -427,7 +427,7 @@
if(casingtype)
var/obj/item/ammo_casing/casing = new casingtype(startloc)
playsound(src, projectilesound, 100, 1)
casing.fire_casing(targeted_atom, src, null, null, null, ran_zone(), src)
casing.fire_casing(targeted_atom, src, null, null, null, ran_zone(), 0, src)
else if(projectiletype)
var/obj/item/projectile/P = new projectiletype(startloc)
playsound(src, projectilesound, 100, 1)
@@ -30,6 +30,7 @@
robust_searching = TRUE
stat_attack = UNCONSCIOUS
anchored = TRUE
blood_volume = 0
var/combatant_state = SEEDLING_STATE_NEUTRAL
var/obj/seedling_weakpoint/weak_point
var/mob/living/beam_debuff_target
@@ -376,7 +376,7 @@ Difficulty: Very Hard
. += observer_desc
. += "It is activated by [activation_method]."
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
/obj/machinery/anomalous_crystal/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source)
..()
if(isliving(speaker))
ActivationReaction(speaker, ACTIVATE_SPEECH)
@@ -651,7 +651,7 @@ Difficulty: Very Hard
L.heal_overall_damage(heal_power, heal_power)
new /obj/effect/temp_visual/heal(get_turf(target), "#80F5FF")
/mob/living/simple_animal/hostile/lightgeist/ghostize(can_reenter_corpse = TRUE, special = FALSE)
/mob/living/simple_animal/hostile/lightgeist/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE)
. = ..()
if(.)
death()
@@ -80,7 +80,7 @@ Difficulty: Medium
return FALSE
return ..()
/mob/living/simple_animal/hostile/megafauna/dragon/visible_message()
/mob/living/simple_animal/hostile/megafauna/dragon/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs)
if(swooping & SWOOP_INVULNERABLE) //to suppress attack messages without overriding every single proc that could send a message saying we got hit
return
return ..()
@@ -267,6 +267,7 @@ Difficulty: Medium
/mob/living/simple_animal/hostile/megafauna/dragon/AltClickOn(atom/movable/A)
if(!istype(A))
altclick_listed_turf(A)
return
if(swoop_cooldown >= world.time)
to_chat(src, "<span class='warning'>You need to wait 20 seconds between swoop attacks!</span>")
@@ -50,6 +50,7 @@ Difficulty: Normal
armour_penetration = 75
melee_damage_lower = 15
melee_damage_upper = 20
blood_volume = 0
speed = 1
move_to_delay = 11
ranged = 1
@@ -441,7 +442,7 @@ Difficulty: Normal
/mob/living/simple_animal/hostile/megafauna/hierophant/AltClickOn(atom/A) //player control handler(don't give this to a player holy fuck)
if(!istype(A) || get_dist(A, src) <= 2)
return
return altclick_listed_turf(A)
blink(A)
//Hierophant overlays
@@ -137,7 +137,7 @@ Difficulty: Medium
if(last_legion)
loot = list(/obj/item/staff/storm)
elimination = 0
else if(prob(5))
else if(prob(20))
loot = list(/obj/structure/closet/crate/necropolis/tendril)
..()
@@ -25,6 +25,7 @@
mob_size = MOB_SIZE_LARGE
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
var/list/crusher_loot
var/medal_type
var/score_type = BOSS_SCORE
@@ -41,9 +42,6 @@
QDEL_NULL(internal)
. = ..()
/mob/living/simple_animal/hostile/megafauna/prevent_content_explosion()
return TRUE
/mob/living/simple_animal/hostile/megafauna/death(gibbed)
if(health > 0)
return
@@ -118,8 +116,10 @@
recovery_time = world.time + buffer_time
/mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype, scoretype, crusher_kill)
if(!medal_type || (flags_1 & ADMIN_SPAWNED_1) || !SSmedals.hub_enabled) //Don't award medals if the medal type isn't set
if(!medal_type || (flags_1 & ADMIN_SPAWNED_1)) //Don't award medals if the medal type isn't set
return FALSE
if(!SSmedals.hub_enabled) // This allows subtypes to carry on other special rewards not tied with medals. (such as bubblegum's arena shuttle)
return TRUE
for(var/mob/living/L in view(7,src))
if(L.stat || !L.client)
@@ -22,6 +22,7 @@
environment_smash = ENVIRONMENT_SMASH_NONE
sentience_type = SENTIENCE_BOSS
layer = LARGE_MOB_LAYER
blood_volume = 0
var/doing_move_loop = FALSE
var/mob/living/set_target
var/timerid
@@ -0,0 +1,366 @@
#define TUMOR_INACTIVE 0
#define TUMOR_ACTIVE 1
#define TUMOR_PASSIVE 2
//Elite mining mobs
/mob/living/simple_animal/hostile/asteroid/elite
name = "elite"
desc = "An elite monster, found in one of the strange tumors on lavaland."
icon = 'icons/mob/lavaland/lavaland_elites.dmi'
faction = list("boss")
robust_searching = TRUE
ranged_ignores_vision = TRUE
ranged = TRUE
obj_damage = 5
vision_range = 6
aggro_vision_range = 18
environment_smash = ENVIRONMENT_SMASH_NONE //This is to prevent elites smashing up the mining station, we'll make sure they can smash minerals fine below.
harm_intent_damage = 0 //Punching elites gets you nowhere
stat_attack = UNCONSCIOUS
layer = LARGE_MOB_LAYER
sentience_type = SENTIENCE_BOSS
hud_type = /datum/hud/lavaland_elite
var/chosen_attack = 1
var/list/attack_action_types = list()
var/can_talk = FALSE
var/obj/loot_drop = null
//Gives player-controlled variants the ability to swap attacks
/mob/living/simple_animal/hostile/asteroid/elite/Initialize(mapload)
. = ..()
for(var/action_type in attack_action_types)
var/datum/action/innate/elite_attack/attack_action = new action_type()
attack_action.Grant(src)
//Prevents elites from attacking members of their faction (can't hurt themselves either) and lets them mine rock with an attack despite not being able to smash walls.
/mob/living/simple_animal/hostile/asteroid/elite/AttackingTarget()
if(istype(target, /mob/living/simple_animal/hostile))
var/mob/living/simple_animal/hostile/M = target
if(faction_check_mob(M))
return FALSE
if(istype(target, /obj/structure/elite_tumor))
var/obj/structure/elite_tumor/T = target
if(T.mychild == src && T.activity == TUMOR_PASSIVE)
var/elite_remove = alert("Re-enter the tumor?", "Despawn yourself?", "Yes", "No")
if(elite_remove == "No" || !src || QDELETED(src))
return
T.mychild = null
T.activity = TUMOR_INACTIVE
T.icon_state = "advanced_tumor"
qdel(src)
return FALSE
. = ..()
if(ismineralturf(target))
var/turf/closed/mineral/M = target
M.gets_drilled()
//Elites can't talk (normally)!
/mob/living/simple_animal/hostile/asteroid/elite/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
if(can_talk)
. = ..()
return TRUE
return FALSE
/*Basic setup for elite attacks, based on Whoneedspace's megafauna attack setup.
While using this makes the system rely on OnFire, it still gives options for timers not tied to OnFire, and it makes using attacks consistent accross the board for player-controlled elites.*/
/datum/action/innate/elite_attack
name = "Elite Attack"
icon_icon = 'icons/mob/actions/actions_elites.dmi'
button_icon_state = ""
background_icon_state = "bg_default"
var/mob/living/simple_animal/hostile/asteroid/elite/M
var/chosen_message
var/chosen_attack_num = 0
/datum/action/innate/elite_attack/Grant(mob/living/L)
if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite))
M = L
return ..()
return FALSE
/datum/action/innate/elite_attack/Activate()
M.chosen_attack = chosen_attack_num
to_chat(M, chosen_message)
/mob/living/simple_animal/hostile/asteroid/elite/updatehealth()
. = ..()
update_health_hud()
/mob/living/simple_animal/hostile/asteroid/elite/update_health_hud()
if(hud_used)
var/severity = 0
var/healthpercent = (health/maxHealth) * 100
switch(healthpercent)
if(100 to INFINITY)
hud_used.healths.icon_state = "elite_health0"
if(80 to 100)
severity = 1
if(60 to 80)
severity = 2
if(40 to 60)
severity = 3
if(20 to 40)
severity = 4
if(10 to 20)
severity = 5
if(1 to 20)
severity = 6
else
severity = 7
hud_used.healths.icon_state = "elite_health[severity]"
if(severity > 0)
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
//The Pulsing Tumor, the actual "spawn-point" of elites, handles the spawning, arena, and procs for dealing with basic scenarios.
/obj/structure/elite_tumor
name = "pulsing tumor"
desc = "An odd, pulsing tumor sticking out of the ground. You feel compelled to reach out and touch it..."
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
resistance_flags = INDESTRUCTIBLE
var/activity = TUMOR_INACTIVE
var/boosted = FALSE
var/times_won = 0
var/mob/living/carbon/human/activator = null
var/mob/living/simple_animal/hostile/asteroid/elite/mychild = null
var/potentialspawns = list(/mob/living/simple_animal/hostile/asteroid/elite/broodmother,
/mob/living/simple_animal/hostile/asteroid/elite/pandora,
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire,
/mob/living/simple_animal/hostile/asteroid/elite/herald)
icon = 'icons/obj/lavaland/tumor.dmi'
icon_state = "tumor"
pixel_x = -16
light_color = LIGHT_COLOR_RED
light_range = 3
anchored = TRUE
density = FALSE
var/obj/item/gps/internal = null
/obj/item/gps/internal/elite
icon_state = null
gpstag = "Menacing Signal"
desc = "You're not quite sure how a signal can be menacing."
invisibility = 100
/obj/structure/elite_tumor/attack_hand(mob/user)
. = ..()
if(ishuman(user))
switch(activity)
if(TUMOR_PASSIVE)
activity = TUMOR_ACTIVE
visible_message("<span class='boldwarning'>[src] convulses as your arm enters its radius. Your instincts tell you to step back.</span>")
activator = user
if(boosted)
mychild.playsound_local(get_turf(mychild), 'sound/effects/magic.ogg', 40, 0)
to_chat(mychild, "<b>Someone has activated your tumor. You will be returned to fight shortly, get ready!</b>")
addtimer(CALLBACK(src, .proc/return_elite), 30)
INVOKE_ASYNC(src, .proc/arena_checks)
if(TUMOR_INACTIVE)
activity = TUMOR_ACTIVE
var/mob/dead/observer/elitemind = null
visible_message("<span class='boldwarning'>[src] begins to convulse. Your instincts tell you to step back.</span>")
activator = user
if(!boosted)
addtimer(CALLBACK(src, .proc/spawn_elite), 30)
return
visible_message("<span class='boldwarning'>Something within [src] stirs...</span>")
var/list/candidates = pollCandidatesForMob("Do you want to play as a lavaland elite?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, src, POLL_IGNORE_SENTIENCE_POTION)
if(candidates.len)
audible_message("<span class='boldwarning'>The stirring sounds increase in volume!</span>")
elitemind = pick(candidates)
elitemind.playsound_local(get_turf(elitemind), 'sound/effects/magic.ogg', 40, 0)
to_chat(elitemind, "<b>You have been chosen to play as a Lavaland Elite.\nIn a few seconds, you will be summoned on Lavaland as a monster to fight your activator, in a fight to the death.\nYour attacks can be switched using the buttons on the top left of the HUD, and used by clicking on targets or tiles similar to a gun.\nWhile the opponent might have an upper hand with powerful mining equipment and tools, you have great power normally limited by AI mobs.\nIf you want to win, you'll have to use your powers in creative ways to ensure the kill. It's suggested you try using them all as soon as possible.\nShould you win, you'll receive extra information regarding what to do after. Good luck!</b>")
addtimer(CALLBACK(src, .proc/spawn_elite, elitemind), 100)
else
visible_message("<span class='boldwarning'>The stirring stops, and nothing emerges. Perhaps try again later.</span>")
activity = TUMOR_INACTIVE
activator = null
obj/structure/elite_tumor/proc/spawn_elite(var/mob/dead/observer/elitemind)
var/selectedspawn = pick(potentialspawns)
mychild = new selectedspawn(loc)
visible_message("<span class='boldwarning'>[mychild] emerges from [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
if(boosted)
mychild.key = elitemind.key
mychild.sentience_act()
icon_state = "tumor_popped"
INVOKE_ASYNC(src, .proc/arena_checks)
obj/structure/elite_tumor/proc/return_elite()
mychild.forceMove(loc)
visible_message("<span class='boldwarning'>[mychild] emerges from [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
mychild.revive(full_heal = TRUE, admin_revive = TRUE)
if(boosted)
mychild.maxHealth = mychild.maxHealth * 2
mychild.health = mychild.maxHealth
/obj/structure/elite_tumor/Initialize(mapload)
. = ..()
internal = new/obj/item/gps/internal/elite(src)
START_PROCESSING(SSobj, src)
/obj/structure/elite_tumor/Destroy()
STOP_PROCESSING(SSobj, src)
mychild = null
activator = null
return ..()
/obj/structure/elite_tumor/process()
if(isturf(loc))
for(var/mob/living/simple_animal/hostile/asteroid/elite/elitehere in loc)
if(elitehere == mychild && activity == TUMOR_PASSIVE)
mychild.adjustHealth(-mychild.maxHealth*0.05)
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(mychild))
H.color = "#FF0000"
/obj/structure/elite_tumor/attackby(obj/item/I, mob/user, params)
. = ..()
if(istype(I, /obj/item/organ/regenerative_core) && activity == TUMOR_INACTIVE && !boosted)
var/obj/item/organ/regenerative_core/core = I
if(!core.preserved)
return
visible_message("<span class='boldwarning'>As [user] drops the core into [src], [src] appears to swell.</span>")
icon_state = "advanced_tumor"
boosted = TRUE
light_range = 6
desc = "[desc] This one seems to glow with a strong intensity."
qdel(core)
return TRUE
/obj/structure/elite_tumor/proc/arena_checks()
if(activity != TUMOR_ACTIVE || QDELETED(src))
return
INVOKE_ASYNC(src, .proc/fighters_check) //Checks to see if our fighters died.
INVOKE_ASYNC(src, .proc/arena_trap) //Gets another arena trap queued up for when this one runs out.
INVOKE_ASYNC(src, .proc/border_check) //Checks to see if our fighters got out of the arena somehow.
addtimer(CALLBACK(src, .proc/arena_checks), 50)
/obj/structure/elite_tumor/proc/fighters_check()
if(activator != null && activator.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(activator))
onEliteWon()
if(mychild != null && mychild.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(mychild))
onEliteLoss()
/obj/structure/elite_tumor/proc/arena_trap()
var/turf/T = get_turf(src)
if(loc == null)
return
for(var/t in RANGE_TURFS(12, T))
if(get_dist(t, T) == 12)
var/obj/effect/temp_visual/elite_tumor_wall/newwall
newwall = new /obj/effect/temp_visual/elite_tumor_wall(t, src)
newwall.activator = src.activator
newwall.ourelite = src.mychild
/obj/structure/elite_tumor/proc/border_check()
if(activator != null && get_dist(src, activator) >= 12)
activator.forceMove(loc)
visible_message("<span class='boldwarning'>[activator] suddenly reappears above [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
if(mychild != null && get_dist(src, mychild) >= 12)
mychild.forceMove(loc)
visible_message("<span class='boldwarning'>[mychild] suddenly reappears above [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
obj/structure/elite_tumor/proc/onEliteLoss()
playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, 0, 50, TRUE, TRUE)
visible_message("<span class='boldwarning'>[src] begins to convulse violently before beginning to dissipate.</span>")
visible_message("<span class='boldwarning'>As [src] closes, something is forced up from down below.</span>")
var/obj/structure/closet/crate/necropolis/tendril/lootbox = new /obj/structure/closet/crate/necropolis/tendril(loc)
if(!boosted)
mychild = null
activator = null
qdel(src)
return
var/lootpick = rand(1, 2)
if(lootpick == 1 && mychild.loot_drop != null)
new mychild.loot_drop(lootbox)
else
new /obj/item/tumor_shard(lootbox)
mychild = null
activator = null
qdel(src)
obj/structure/elite_tumor/proc/onEliteWon()
activity = TUMOR_PASSIVE
activator = null
mychild.revive(full_heal = TRUE, admin_revive = TRUE)
if(boosted)
times_won++
mychild.maxHealth = mychild.maxHealth * 0.5
mychild.health = mychild.maxHealth
if(times_won == 1)
mychild.playsound_local(get_turf(mychild), 'sound/effects/magic.ogg', 40, 0)
to_chat(mychild, "<span class='boldwarning'>As the life in the activator's eyes fade, the forcefield around you dies out and you feel your power subside.\nDespite this inferno being your home, you feel as if you aren't welcome here anymore.\nWithout any guidance, your purpose is now for you to decide.</span>")
to_chat(mychild, "<b>Your max health has been halved, but can now heal by standing on your tumor. Note, it's your only way to heal.\nBear in mind, if anyone interacts with your tumor, you'll be resummoned here to carry out another fight. In such a case, you will regain your full max health.\nAlso, be weary of your fellow inhabitants, they likely won't be happy to see you!</b>")
to_chat(mychild, "<span class='big bold'>Note that you are a lavaland monster, and thus not allied to the station. You should not cooperate or act friendly with any station crew unless under extreme circumstances!</span>")
/obj/item/tumor_shard
name = "tumor shard"
desc = "A strange, sharp, crystal shard from an odd tumor on Lavaland. Stabbing the corpse of a lavaland elite with this will revive them, assuming their soul still lingers. Revived lavaland elites only have half their max health, but are completely loyal to their reviver."
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "crevice_shard"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
item_state = "screwdriver_head"
throwforce = 5
w_class = WEIGHT_CLASS_SMALL
throw_speed = 3
throw_range = 5
/obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag)
. = ..()
if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag)
var/mob/living/simple_animal/hostile/asteroid/elite/E = target
if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key)
user.visible_message("<span class='notice'>It appears [E] is unable to be revived right now. Perhaps try again later.</span>")
return
E.faction = list("neutral")
E.revive(full_heal = TRUE, admin_revive = TRUE)
user.visible_message("<span class='notice'>[user] stabs [E] with [src], reviving it.</span>")
E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0)
to_chat(E, "<span class='userdanger'>You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.</span")
to_chat(E, "<span class='big bold'>Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!</span>")
E.maxHealth = E.maxHealth * 0.5
E.health = E.maxHealth
E.desc = "[E.desc] However, this one appears appears less wild in nature, and calmer around people."
E.sentience_type = SENTIENCE_ORGANIC
qdel(src)
else
to_chat(user, "<span class='info'>[src] only works on the corpse of a sentient lavaland elite.</span>")
/obj/effect/temp_visual/elite_tumor_wall
name = "magic wall"
icon = 'icons/turf/walls/hierophant_wall_temp.dmi'
icon_state = "wall"
duration = 50
smooth = SMOOTH_TRUE
layer = BELOW_MOB_LAYER
var/mob/living/carbon/human/activator = null
var/mob/living/simple_animal/hostile/asteroid/elite/ourelite = null
color = rgb(255,0,0)
light_range = MINIMUM_USEFUL_LIGHT_RANGE
light_color = LIGHT_COLOR_RED
/obj/effect/temp_visual/elite_tumor_wall/Initialize(mapload, new_caster)
. = ..()
queue_smooth_neighbors(src)
queue_smooth(src)
/obj/effect/temp_visual/elite_tumor_wall/Destroy()
queue_smooth_neighbors(src)
activator = null
ourelite = null
return ..()
/obj/effect/temp_visual/elite_tumor_wall/CanPass(atom/movable/mover, turf/target)
if(mover == ourelite || mover == activator)
return FALSE
else
return TRUE
@@ -0,0 +1,247 @@
#define TENTACLE_PATCH 1
#define SPAWN_CHILDREN 2
#define RAGE 3
#define CALL_CHILDREN 4
/**
* # Goliath Broodmother
*
* A stronger, faster variation of the goliath. Has the ability to spawn baby goliaths, which it can later detonate at will.
* When it's health is below half, tendrils will spawn randomly around it. When it is below a quarter of health, this effect is doubled.
* It's attacks are as follows:
* - Spawns a 3x3/plus shape of tentacles on the target location
* - Spawns 2 baby goliaths on its tile, up to a max of 8. Children blow up when they die.
* - The broodmother lets out a noise, and is able to move faster for 6.5 seconds.
* - Summons your children around you.
* The broodmother is a fight revolving around stage control, as the activator has to manage the baby goliaths and the broodmother herself, along with all the tendrils.
*/
/mob/living/simple_animal/hostile/asteroid/elite/broodmother
name = "goliath broodmother"
desc = "An example of sexual dimorphism, this female goliath looks much different than the males of her species. She is, however, just as dangerous, if not more."
gender = FEMALE
icon_state = "broodmother"
icon_living = "broodmother"
icon_aggro = "broodmother"
icon_dead = "egg_sac"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 30
melee_damage_upper = 30
armour_penetration = 30
attacktext = "beats down on"
/*attack_verb_continuous = "beats down on"
attack_verb_simple = "beat down on"*/
attack_sound = 'sound/weapons/punch1.ogg'
throw_message = "does nothing to the rocky hide of the"
speed = 2
move_to_delay = 5
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
mouse_opacity = MOUSE_OPACITY_ICON
deathmessage = "explodes into gore!"
loot_drop = /obj/item/crusher_trophy/broodmother_tongue
attack_action_types = list(/datum/action/innate/elite_attack/tentacle_patch,
/datum/action/innate/elite_attack/spawn_children,
/datum/action/innate/elite_attack/rage,
/datum/action/innate/elite_attack/call_children)
var/rand_tent = 0
var/list/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/children_list = list()
/datum/action/innate/elite_attack/tentacle_patch
name = "Tentacle Patch"
button_icon_state = "tentacle_patch"
chosen_message = "<span class='boldwarning'>You are now attacking with a patch of tentacles.</span>"
chosen_attack_num = TENTACLE_PATCH
/datum/action/innate/elite_attack/spawn_children
name = "Spawn Children"
button_icon_state = "spawn_children"
chosen_message = "<span class='boldwarning'>You will spawn two children at your location to assist you in combat. You can have up to 8.</span>"
chosen_attack_num = SPAWN_CHILDREN
/datum/action/innate/elite_attack/rage
name = "Rage"
button_icon_state = "rage"
chosen_message = "<span class='boldwarning'>You will temporarily increase your movement speed.</span>"
chosen_attack_num = RAGE
/datum/action/innate/elite_attack/call_children
name = "Call Children"
button_icon_state = "call_children"
chosen_message = "<span class='boldwarning'>You will summon your children to your location.</span>"
chosen_attack_num = CALL_CHILDREN
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/OpenFire()
if(client)
switch(chosen_attack)
if(TENTACLE_PATCH)
tentacle_patch(target)
if(SPAWN_CHILDREN)
spawn_children()
if(RAGE)
rage()
if(CALL_CHILDREN)
call_children()
return
var/aiattack = rand(1,4)
switch(aiattack)
if(TENTACLE_PATCH)
tentacle_patch(target)
if(SPAWN_CHILDREN)
spawn_children()
if(RAGE)
rage()
if(CALL_CHILDREN)
call_children()
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Life()
. = ..()
if(!.) //Checks if they are dead as a rock.
return
if(health < maxHealth * 0.5 && rand_tent < world.time)
rand_tent = world.time + 30
var/tentacle_amount = 5
if(health < maxHealth * 0.25)
tentacle_amount = 10
var/tentacle_loc = spiral_range_turfs(5, get_turf(src))
for(var/i in 1 to tentacle_amount)
var/turf/t = pick_n_take(tentacle_loc)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(t, src)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/tentacle_patch(var/target)
ranged_cooldown = world.time + 15
var/tturf = get_turf(target)
if(!isturf(tturf))
return
visible_message("<span class='warning'>[src] digs its tentacles under [target]!</span>")
new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(tturf, src)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/spawn_children(var/target)
ranged_cooldown = world.time + 40
visible_message("<span class='boldwarning'>The ground churns behind [src]!</span>")
for(var/i in 1 to 2)
if(children_list.len >= 8)
return
var/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/newchild = new /mob/living/simple_animal/hostile/asteroid/elite/broodmother_child(loc)
newchild.GiveTarget(target)
newchild.faction = faction.Copy()
visible_message("<span class='boldwarning'>[newchild] appears below [src]!</span>")
newchild.mother = src
children_list += newchild
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/rage()
ranged_cooldown = world.time + 70
playsound(src,'sound/spookoween/insane_low_laugh.ogg', 200, 1)
visible_message("<span class='warning'>[src] starts picking up speed!</span>")
color = "#FF0000"
set_varspeed(0)
move_to_delay = 3
addtimer(CALLBACK(src, .proc/reset_rage), 65)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/reset_rage()
color = "#FFFFFF"
set_varspeed(2)
move_to_delay = 5
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/call_children()
ranged_cooldown = world.time + 60
visible_message("<span class='warning'>The ground shakes near [src]!</span>")
var/list/directions = GLOB.cardinals.Copy() + GLOB.diagonals.Copy()
for(var/mob/child in children_list)
var/spawndir = pick_n_take(directions)
var/turf/T = get_step(src, spawndir)
if(T)
child.forceMove(T)
playsound(src, 'sound/effects/bamf.ogg', 100, 1)
//The goliath's children. Pretty weak, simple mobs which are able to put a single tentacle under their target when at range.
/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child
name = "baby goliath"
desc = "A young goliath recently born from it's mother. While they hatch from eggs, said eggs are incubated in the mother until they are ready to be born."
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "goliath_baby"
icon_living = "goliath_baby"
icon_aggro = "goliath_baby"
icon_dead = "goliath_baby_dead"
icon_gib = "syndicate_gib"
maxHealth = 30
health = 30
melee_damage_lower = 5
melee_damage_upper = 5
attacktext = "bashes against"
/*attack_verb_continuous = "bashes against"
attack_verb_simple = "bash against"*/
attack_sound = 'sound/weapons/punch1.ogg'
throw_message = "does nothing to the rocky hide of the"
speed = 2
move_to_delay = 5
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
mouse_opacity = MOUSE_OPACITY_ICON
butcher_results = list()
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide = 1)
deathmessage = "falls to the ground."
status_flags = CANPUSH
var/mob/living/simple_animal/hostile/asteroid/elite/broodmother/mother = null
/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/OpenFire(target)
ranged_cooldown = world.time + 40
var/tturf = get_turf(target)
if(!isturf(tturf))
return
if(get_dist(src, target) <= 7)//Screen range check, so it can't attack people off-screen
visible_message("<span class='warning'>[src] digs one of its tentacles under [target]!</span>")
new /obj/effect/temp_visual/goliath_tentacle/broodmother(tturf, src)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/death()
. = ..()
if(mother != null)
mother.children_list -= src
visible_message("<span class='warning'>[src] explodes!</span>")
explosion(get_turf(loc),0,0,0,flame_range = 3, adminlog = FALSE)
qdel()
//Tentacles have less stun time compared to regular variant, to balance being able to use them much more often. Also, 10 more damage.
/obj/effect/temp_visual/goliath_tentacle/broodmother/trip()
var/latched = FALSE
for(var/mob/living/L in loc)
if((!QDELETED(spawner) && spawner.faction_check_mob(L)) || L.stat == DEAD)
continue
visible_message("<span class='danger'>[src] grabs hold of [L]!</span>")
L.Stun(10)
L.adjustBruteLoss(rand(30,35))
latched = TRUE
if(!latched)
retract()
else
deltimer(timerid)
timerid = addtimer(CALLBACK(src, .proc/retract), 10, TIMER_STOPPABLE)
/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner)
. = ..()
var/tentacle_locs = spiral_range_turfs(1, get_turf(src))
for(var/T in tentacle_locs)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
var/list/directions = GLOB.cardinals.Copy()
for(var/i in directions)
var/turf/T = get_step(get_turf(src), i)
T = get_step(T, i)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
// Broodmother's loot: Broodmother Tongue
/obj/item/crusher_trophy/broodmother_tongue
name = "broodmother tongue"
desc = "The tongue of a broodmother. If attached a certain way, makes for a suitable crusher trophy."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "broodmother_tongue"
denied_type = /obj/item/crusher_trophy/broodmother_tongue
bonus_value = 10
/obj/item/crusher_trophy/broodmother_tongue/effect_desc()
return "mark detonation to have a <b>[bonus_value]%</b> chance to summon a patch of goliath tentacles at the target's location"
/obj/item/crusher_trophy/broodmother_tongue/on_mark_detonation(mob/living/target, mob/living/user)
if(rand(1, 100) <= bonus_value && target.stat != DEAD)
new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(get_turf(target), user)
@@ -0,0 +1,275 @@
#define HERALD_TRISHOT 1
#define HERALD_DIRECTIONALSHOT 2
#define HERALD_TELESHOT 3
#define HERALD_MIRROR 4
/**
* # Herald
*
* A slow-moving projectile user with a few tricks up it's sleeve. Less unga-bunga than Colossus, with more cleverness in it's fighting style.
* As it's health gets lower, the amount of projectiles fired per-attack increases.
* It's attacks are as follows:
* - Fires three projectiles in a a given direction.
* - Fires a spread in every cardinal and diagonal direction at once, then does it again after a bit.
* - Shoots a single, golden bolt. Wherever it lands, the herald will be teleported to the location.
* - Spawns a mirror which reflects projectiles directly at the target.
* Herald is a more concentrated variation of the Colossus fight, having less projectiles overall, but more focused attacks.
*/
/mob/living/simple_animal/hostile/asteroid/elite/herald
name = "herald"
desc = "A monstrous beast which fires deadly projectiles at threats and prey."
icon_state = "herald"
icon_living = "herald"
icon_aggro = "herald"
icon_dead = "herald_dying"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 20
melee_damage_upper = 20
attacktext = "preaches to"
/*attack_verb_continuous = "preaches to"
attack_verb_simple = "preach to"*/
attack_sound = 'sound/magic/clockwork/ratvar_attack.ogg'
throw_message = "doesn't affect the purity of"
speed = 4
move_to_delay = 10
mouse_opacity = MOUSE_OPACITY_ICON
deathsound = 'sound/magic/demon_dies.ogg'
deathmessage = "begins to shudder as it becomes transparent..."
loot_drop = /obj/item/clothing/neck/cloak/herald_cloak
can_talk = 1
attack_action_types = list(/datum/action/innate/elite_attack/herald_trishot,
/datum/action/innate/elite_attack/herald_directionalshot,
/datum/action/innate/elite_attack/herald_teleshot,
/datum/action/innate/elite_attack/herald_mirror)
var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/my_mirror = null
var/is_mirror = FALSE
/mob/living/simple_animal/hostile/asteroid/elite/herald/death()
. = ..()
if(!is_mirror)
addtimer(CALLBACK(src, .proc/become_ghost), 8)
if(my_mirror != null)
qdel(my_mirror)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost()
icon_state = "herald_ghost"
/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
. = ..()
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
/datum/action/innate/elite_attack/herald_trishot
name = "Triple Shot"
button_icon_state = "herald_trishot"
chosen_message = "<span class='boldwarning'>You are now firing three shots in your chosen direction.</span>"
chosen_attack_num = HERALD_TRISHOT
/datum/action/innate/elite_attack/herald_directionalshot
name = "Circular Shot"
button_icon_state = "herald_directionalshot"
chosen_message = "<span class='boldwarning'>You are firing projectiles in all directions.</span>"
chosen_attack_num = HERALD_DIRECTIONALSHOT
/datum/action/innate/elite_attack/herald_teleshot
name = "Teleport Shot"
button_icon_state = "herald_teleshot"
chosen_message = "<span class='boldwarning'>You will now fire a shot which teleports you where it lands.</span>"
chosen_attack_num = HERALD_TELESHOT
/datum/action/innate/elite_attack/herald_mirror
name = "Summon Mirror"
button_icon_state = "herald_mirror"
chosen_message = "<span class='boldwarning'>You will spawn a mirror which duplicates your attacks.</span>"
chosen_attack_num = HERALD_MIRROR
/mob/living/simple_animal/hostile/asteroid/elite/herald/OpenFire()
if(client)
switch(chosen_attack)
if(HERALD_TRISHOT)
herald_trishot(target)
if(my_mirror != null)
my_mirror.herald_trishot(target)
if(HERALD_DIRECTIONALSHOT)
herald_directionalshot()
if(my_mirror != null)
my_mirror.herald_directionalshot()
if(HERALD_TELESHOT)
herald_teleshot(target)
if(my_mirror != null)
my_mirror.herald_teleshot(target)
if(HERALD_MIRROR)
herald_mirror()
return
var/aiattack = rand(1,4)
switch(aiattack)
if(HERALD_TRISHOT)
herald_trishot(target)
if(my_mirror != null)
my_mirror.herald_trishot(target)
if(HERALD_DIRECTIONALSHOT)
herald_directionalshot()
if(my_mirror != null)
my_mirror.herald_directionalshot()
if(HERALD_TELESHOT)
herald_teleshot(target)
if(my_mirror != null)
my_mirror.herald_teleshot(target)
if(HERALD_MIRROR)
herald_mirror()
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/shoot_projectile(turf/marker, set_angle, var/is_teleshot)
var/turf/startloc = get_turf(src)
var/obj/item/projectile/herald/H = null
if(!is_teleshot)
H = new /obj/item/projectile/herald(startloc)
else
H = new /obj/item/projectile/herald/teleshot(startloc)
H.preparePixelProjectile(marker, startloc)
H.firer = src
if(target)
H.original = target
H.fire(set_angle)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_trishot(target)
ranged_cooldown = world.time + 30
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
var/target_turf = get_turf(target)
var/angle_to_target = Get_Angle(src, target_turf)
shoot_projectile(target_turf, angle_to_target, FALSE)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 2)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 4)
if(health < maxHealth * 0.5)
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 10)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 12)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 14)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_circleshot()
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
for(var/i in directional_shot_angles)
shoot_projectile(get_turf(src), i, FALSE)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/unenrage()
if(stat == DEAD || is_mirror)
return
icon_state = "herald"
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_directionalshot()
ranged_cooldown = world.time + 50
if(!is_mirror)
icon_state = "herald_enraged"
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/herald_circleshot), 5)
if(health < maxHealth * 0.5)
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/herald_circleshot), 15)
addtimer(CALLBACK(src, .proc/unenrage), 20)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_teleshot(target)
ranged_cooldown = world.time + 30
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
var/target_turf = get_turf(target)
var/angle_to_target = Get_Angle(src, target_turf)
shoot_projectile(target_turf, angle_to_target, TRUE)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_mirror()
ranged_cooldown = world.time + 40
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
if(my_mirror != null)
qdel(my_mirror)
my_mirror = null
var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/new_mirror = new /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror(loc)
my_mirror = new_mirror
my_mirror.my_master = src
my_mirror.faction = faction.Copy()
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror
name = "herald's mirror"
desc = "This fiendish work of magic copies the herald's attacks. Seems logical to smash it."
health = 60
maxHealth = 60
icon_state = "herald_mirror"
deathmessage = "shatters violently!"
deathsound = 'sound/effects/glassbr1.ogg'
movement_type = FLYING
del_on_death = TRUE
is_mirror = TRUE
var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Initialize()
..()
toggle_ai(AI_OFF)
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Destroy()
if(my_master != null)
my_master.my_mirror = null
. = ..()
/obj/item/projectile/herald
name ="death bolt"
icon_state= "chronobolt"
damage = 15
armour_penetration = 60
speed = 2
eyeblur = 0
damage_type = BRUTE
pass_flags = PASSTABLE
/obj/item/projectile/herald/teleshot
name ="golden bolt"
damage = 0
color = rgb(255,255,102)
/obj/item/projectile/herald/on_hit(atom/target, blocked = FALSE)
. = ..()
if(ismineralturf(target))
var/turf/closed/mineral/M = target
M.gets_drilled()
return
else if(isliving(target))
var/mob/living/L = target
var/mob/living/F = firer
if(F != null && istype(F, /mob/living/simple_animal/hostile/asteroid/elite) && F.faction_check_mob(L))
L.heal_overall_damage(damage)
/obj/item/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE)
. = ..()
firer.forceMove(get_turf(src))
//Herald's loot: Cloak of the Prophet
/obj/item/clothing/neck/cloak/herald_cloak
name = "cloak of the prophet"
desc = "A cloak which protects you from the heresy of the world."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "herald_cloak"
body_parts_covered = CHEST|GROIN|ARMS
hit_reaction_chance = 10
/obj/item/clothing/neck/cloak/herald_cloak/proc/reactionshot(mob/living/carbon/owner)
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
for(var/i in directional_shot_angles)
shoot_projectile(get_turf(owner), i, owner)
/obj/item/clothing/neck/cloak/herald_cloak/proc/shoot_projectile(turf/marker, set_angle, mob/living/carbon/owner)
var/turf/startloc = get_turf(owner)
var/obj/item/projectile/herald/H = null
H = new /obj/item/projectile/herald(startloc)
H.preparePixelProjectile(marker, startloc)
H.firer = owner
H.fire(set_angle)
/obj/item/clothing/neck/cloak/herald_cloak/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
. = ..()
if(rand(1,100) > hit_reaction_chance)
return
owner.visible_message("<span class='danger'>[owner]'s [src] emits a loud noise as [owner] is struck!</span>")
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/reactionshot, owner), 10)
@@ -0,0 +1,303 @@
#define LEGIONNAIRE_CHARGE 1
#define HEAD_DETACH 2
#define BONFIRE_TELEPORT 3
#define SPEW_SMOKE 4
/**
* # Legionnaire
*
* A towering skeleton, embodying the power of Legion.
* As it's health gets lower, the head does more damage.
* It's attacks are as follows:
* - Charges at the target after a telegraph, throwing them across the arena should it connect.
* - Legionnaire's head detaches, attacking as it's own entity. Has abilities of it's own later into the fight. Once dead, regenerates after a brief period. If the skill is used while the head is off, it will be killed.
* - Leaves a pile of bones at your location. Upon using this skill again, you'll swap locations with the bone pile.
* - Spews a cloud of smoke from it's maw, wherever said maw is.
* A unique fight incorporating the head mechanic of legion into a whole new beast. Combatants will need to make sure the tag-team of head and body don't lure them into a deadly trap.
*/
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire
name = "legionnaire"
desc = "A towering skeleton, embodying the terrifying power of Legion."
icon_state = "legionnaire"
icon_living = "legionnaire"
icon_aggro = "legionnaire"
icon_dead = "legionnaire_dead"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 30
melee_damage_upper = 30
attacktext = "slashes its arms at"
/*attack_verb_continuous = "slashes its arms at"
attack_verb_simple = "slash your arms at"*/
attack_sound = 'sound/weapons/bladeslice.ogg'
throw_message = "doesn't affect the sturdiness of"
speed = 1
move_to_delay = 3
mouse_opacity = MOUSE_OPACITY_ICON
deathsound = 'sound/magic/curse.ogg'
deathmessage = "'s arms reach out before it falls apart onto the floor, lifeless."
loot_drop = /obj/item/crusher_trophy/legionnaire_spine
attack_action_types = list(/datum/action/innate/elite_attack/legionnaire_charge,
/datum/action/innate/elite_attack/head_detach,
/datum/action/innate/elite_attack/bonfire_teleport,
/datum/action/innate/elite_attack/spew_smoke)
var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/myhead = null
var/obj/structure/legionnaire_bonfire/mypile = null
var/has_head = TRUE
/datum/action/innate/elite_attack/legionnaire_charge
name = "Legionnaire Charge"
button_icon_state = "legionnaire_charge"
chosen_message = "<span class='boldwarning'>You will attempt to grab your opponent and throw them.</span>"
chosen_attack_num = LEGIONNAIRE_CHARGE
/datum/action/innate/elite_attack/head_detach
name = "Release Head"
button_icon_state = "head_detach"
chosen_message = "<span class='boldwarning'>You will now detach your head or kill it if it is already released.</span>"
chosen_attack_num = HEAD_DETACH
/datum/action/innate/elite_attack/bonfire_teleport
name = "Bonfire Teleport"
button_icon_state = "bonfire_teleport"
chosen_message = "<span class='boldwarning'>You will leave a bonfire. Second use will let you swap positions with it indefintiely. Using this move on the same tile as your active bonfire removes it.</span>"
chosen_attack_num = BONFIRE_TELEPORT
/datum/action/innate/elite_attack/spew_smoke
name = "Spew Smoke"
button_icon_state = "spew_smoke"
chosen_message = "<span class='boldwarning'>Your head will spew smoke in an area, wherever it may be.</span>"
chosen_attack_num = SPEW_SMOKE
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/OpenFire()
if(client)
switch(chosen_attack)
if(LEGIONNAIRE_CHARGE)
legionnaire_charge(target)
if(HEAD_DETACH)
head_detach(target)
if(BONFIRE_TELEPORT)
bonfire_teleport()
if(SPEW_SMOKE)
spew_smoke()
return
var/aiattack = rand(1,4)
switch(aiattack)
if(LEGIONNAIRE_CHARGE)
legionnaire_charge(target)
if(HEAD_DETACH)
head_detach(target)
if(BONFIRE_TELEPORT)
bonfire_teleport()
if(SPEW_SMOKE)
spew_smoke()
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge(target)
ranged_cooldown = world.time + 50
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
var/turf/T = get_step(get_turf(src), dir_to_target)
for(var/i in 1 to 4)
new /obj/effect/temp_visual/dragon_swoop/legionnaire(T)
T = get_step(T, dir_to_target)
playsound(src,'sound/magic/demon_attack1.ogg', 200, 1)
visible_message("<span class='boldwarning'>[src] prepares to charge!</span>")
addtimer(CALLBACK(src, .proc/legionnaire_charge_2, dir_to_target, 0), 5)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge_2(var/move_dir, var/times_ran)
if(times_ran >= 4)
return
var/turf/T = get_step(get_turf(src), move_dir)
if(ismineralturf(T))
var/turf/closed/mineral/M = T
M.gets_drilled()
if(T.density)
return
for(var/obj/structure/window/W in T.contents)
return
for(var/obj/machinery/door/D in T.contents)
return
forceMove(T)
playsound(src,'sound/effects/bang.ogg', 200, 1)
var/list/hit_things = list()
var/throwtarget = get_edge_target_turf(src, move_dir)
for(var/mob/living/L in T.contents - hit_things - src)
if(faction_check_mob(L))
return
hit_things += L
visible_message("<span class='boldwarning'>[src] attacks [L] with much force!</span>")
to_chat(L, "<span class='userdanger'>[src] grabs you and throws you with much force!</span>")
L.safe_throw_at(throwtarget, 10, 1, src)
//L.Paralyze(20)
L.Stun(20) //substituting this for the Paralyze from the line above, because we don't have tg paralysis stuff
L.adjustBruteLoss(50)
addtimer(CALLBACK(src, .proc/legionnaire_charge_2, move_dir, (times_ran + 1)), 2)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/head_detach(target)
ranged_cooldown = world.time + 10
if(myhead != null)
myhead.adjustBruteLoss(600)
return
if(has_head)
has_head = FALSE
icon_state = "legionnaire_headless"
icon_living = "legionnaire_headless"
icon_aggro = "legionnaire_headless"
visible_message("<span class='boldwarning'>[src]'s head flies off!</span>")
var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/newhead = new /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead(loc)
newhead.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
newhead.GiveTarget(target)
newhead.faction = faction.Copy()
myhead = newhead
myhead.body = src
if(health < maxHealth * 0.25)
myhead.melee_damage_lower = 30
myhead.melee_damage_upper = 30
else if(health < maxHealth * 0.5)
myhead.melee_damage_lower = 20
myhead.melee_damage_upper = 20
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/onHeadDeath()
myhead = null
addtimer(CALLBACK(src, .proc/regain_head), 50)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/regain_head()
has_head = TRUE
if(stat == DEAD)
return
icon_state = "legionnaire"
icon_living = "legionnaire"
icon_aggro = "legionnaire"
visible_message("<span class='boldwarning'>The top of [src]'s spine leaks a black liquid, forming into a skull!</span>")
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/bonfire_teleport()
ranged_cooldown = world.time + 5
if(mypile == null)
var/obj/structure/legionnaire_bonfire/newpile = new /obj/structure/legionnaire_bonfire(loc)
mypile = newpile
mypile.myowner = src
playsound(get_turf(src),'sound/items/fulext_deploy.wav', 200, 1)
visible_message("<span class='boldwarning'>[src] summons a bonfire on [get_turf(src)]!</span>")
return
else
var/turf/legionturf = get_turf(src)
var/turf/pileturf = get_turf(mypile)
if(legionturf == pileturf)
mypile.take_damage(100)
mypile = null
return
playsound(pileturf,'sound/items/fulext_deploy.wav', 200, 1)
playsound(legionturf,'sound/items/fulext_deploy.wav', 200, 1)
visible_message("<span class='boldwarning'>[src] melts down into a burning pile of bones!</span>")
forceMove(pileturf)
visible_message("<span class='boldwarning'>[src] forms from the bonfire!</span>")
mypile.forceMove(legionturf)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/spew_smoke()
ranged_cooldown = world.time + 60
var/turf/T = null
if(myhead != null)
T = get_turf(myhead)
else
T = get_turf(src)
if(myhead != null)
myhead.visible_message("<span class='boldwarning'>[myhead] spews smoke from its maw!</span>")
else if(!has_head)
visible_message("<span class='boldwarning'>[src] spews smoke from the tip of their spine!</span>")
else
visible_message("<span class='boldwarning'>[src] spews smoke from its maw!</span>")
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(2, T)
smoke.start()
//The legionnaire's head. Basically the same as any legion head, but we have to tell our creator when we die so they can generate another head.
/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead
name = "legionnaire head"
desc = "The legionnaire's head floating by itself. One shouldn't get too close, though once it sees you, you really don't have a choice."
icon_state = "legionnaire_head"
icon_living = "legionnaire_head"
icon_aggro = "legionnaire_head"
icon_dead = "legionnaire_dead"
icon_gib = "syndicate_gib"
maxHealth = 80
health = 80
melee_damage_lower = 10
melee_damage_upper = 10
attacktext = "bites at"
/*attack_verb_continuous = "bites at"
attack_verb_simple = "bite at"*/
attack_sound = 'sound/effects/curse1.ogg'
throw_message = "simply misses"
speed = 0
move_to_delay = 2
del_on_death = 1
deathmessage = "crumbles away!"
faction = list()
ranged = FALSE
var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/body = null
/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/death()
. = ..()
if(body)
body.onHeadDeath()
//The legionnaire's bonfire, which can be swapped positions with. Also sets flammable living beings on fire when they walk over it.
/obj/structure/legionnaire_bonfire
name = "bone pile"
desc = "A pile of bones which seems to occasionally move a little. It's probably a good idea to smash them."
icon = 'icons/obj/lavaland/legionnaire_bonfire.dmi'
icon_state = "bonfire"
max_integrity = 100
//move_resist = MOVE_FORCE_EXTREMELY_STRONG
anchored = TRUE
density = FALSE
light_range = 4
light_color = LIGHT_COLOR_RED
var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/myowner = null
/obj/structure/legionnaire_bonfire/Entered(atom/movable/mover, turf/target)
if(isliving(mover))
var/mob/living/L = mover
L.adjust_fire_stacks(3)
L.IgniteMob()
. = ..()
/obj/structure/legionnaire_bonfire/Destroy()
if(myowner != null)
myowner.mypile = null
. = ..()
//The visual effect which appears in front of legionnaire when he goes to charge.
/obj/effect/temp_visual/dragon_swoop/legionnaire
duration = 10
color = rgb(0,0,0)
/obj/effect/temp_visual/dragon_swoop/legionnaire/Initialize()
. = ..()
transform *= 0.33
// Legionnaire's loot: Legionnaire Spine
/obj/item/crusher_trophy/legionnaire_spine
name = "legionnaire spine"
desc = "The spine of a legionnaire. It almost feels like it's moving..."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "legionnaire_spine"
denied_type = /obj/item/crusher_trophy/legionnaire_spine
bonus_value = 20
/obj/item/crusher_trophy/legionnaire_spine/effect_desc()
return "mark detonation to have a <b>[bonus_value]%</b> chance to summon a loyal legion skull"
/obj/item/crusher_trophy/legionnaire_spine/on_mark_detonation(mob/living/target, mob/living/user)
if(!rand(1, 100) <= bonus_value || target.stat == DEAD)
return
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc)
A.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
A.GiveTarget(target)
A.friends = user
A.faction = user.faction.Copy()
@@ -0,0 +1,193 @@
#define SINGULAR_SHOT 1
#define MAGIC_BOX 2
#define PANDORA_TELEPORT 3
#define AOE_SQUARES 4
/**
* # Pandora
*
* A box with a similar design to the Hierophant which trades large, single attacks for more frequent smaller ones.
* As it's health gets lower, the time between it's attacks decrease.
* It's attacks are as follows:
* - Fires hierophant blasts in a straight line. Can only fire in a straight line in 8 directions, being the diagonals and cardinals.
* - Creates a box of hierophant blasts around the target. If they try to run away to avoid it, they'll very likely get hit.
* - Teleports the pandora from one location to another, almost identical to Hierophant.
* - Spawns a 5x5 AOE at the location of choice, spreading out from the center.
* Pandora's fight mirrors Hierophant's closely, but has stark differences in attack effects. Instead of long-winded dodge times and long cooldowns, Pandora constantly attacks the opponent, but leaves itself open for attack.
*/
/mob/living/simple_animal/hostile/asteroid/elite/pandora
name = "pandora"
desc = "A large magic box with similar power and design to the Hierophant. Once it opens, it's not easy to close it."
icon_state = "pandora"
icon_living = "pandora"
icon_aggro = "pandora"
icon_dead = "pandora_dead"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 15
melee_damage_upper = 15
attacktext = "smashes into the side of"
/*attack_verb_continuous = "smashes into the side of"
attack_verb_simple = "smash into the side of"*/
attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
throw_message = "merely dinks off of the"
speed = 4
move_to_delay = 10
mouse_opacity = MOUSE_OPACITY_ICON
deathsound = 'sound/magic/repulse.ogg'
deathmessage = "'s lights flicker, before its top part falls down."
loot_drop = /obj/item/clothing/accessory/pandora_hope
attack_action_types = list(/datum/action/innate/elite_attack/singular_shot,
/datum/action/innate/elite_attack/magic_box,
/datum/action/innate/elite_attack/pandora_teleport,
/datum/action/innate/elite_attack/aoe_squares)
var/sing_shot_length = 8
var/cooldown_time = 20
/datum/action/innate/elite_attack/singular_shot
name = "Singular Shot"
button_icon_state = "singular_shot"
chosen_message = "<span class='boldwarning'>You are now creating a single linear magic square.</span>"
chosen_attack_num = SINGULAR_SHOT
/datum/action/innate/elite_attack/magic_box
name = "Magic Box"
button_icon_state = "magic_box"
chosen_message = "<span class='boldwarning'>You are now attacking with a box of magic squares.</span>"
chosen_attack_num = MAGIC_BOX
/datum/action/innate/elite_attack/pandora_teleport
name = "Line Teleport"
button_icon_state = "pandora_teleport"
chosen_message = "<span class='boldwarning'>You will now teleport to your target.</span>"
chosen_attack_num = PANDORA_TELEPORT
/datum/action/innate/elite_attack/aoe_squares
name = "AOE Blast"
button_icon_state = "aoe_squares"
chosen_message = "<span class='boldwarning'>Your attacks will spawn an AOE blast at your target location.</span>"
chosen_attack_num = AOE_SQUARES
/mob/living/simple_animal/hostile/asteroid/elite/pandora/OpenFire()
if(client)
switch(chosen_attack)
if(SINGULAR_SHOT)
singular_shot(target)
if(MAGIC_BOX)
magic_box(target)
if(PANDORA_TELEPORT)
pandora_teleport(target)
if(AOE_SQUARES)
aoe_squares(target)
return
var/aiattack = rand(1,4)
switch(aiattack)
if(SINGULAR_SHOT)
singular_shot(target)
if(MAGIC_BOX)
magic_box(target)
if(PANDORA_TELEPORT)
pandora_teleport(target)
if(AOE_SQUARES)
aoe_squares(target)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/Life()
. = ..()
if(health >= maxHealth * 0.5)
cooldown_time = 20
return
if(health < maxHealth * 0.5 && health > maxHealth * 0.25)
cooldown_time = 15
return
else
cooldown_time = 10
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot(target)
ranged_cooldown = world.time + (cooldown_time * 0.5)
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
var/turf/T = get_step(get_turf(src), dir_to_target)
singular_shot_line(sing_shot_length, dir_to_target, T)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot_line(var/procsleft, var/angleused, var/turf/T)
if(procsleft <= 0)
return
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src)
T = get_step(T, angleused)
procsleft = procsleft - 1
addtimer(CALLBACK(src, .proc/singular_shot_line, procsleft, angleused, T), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/magic_box(target)
ranged_cooldown = world.time + cooldown_time
var/turf/T = get_turf(target)
for(var/t in spiral_range_turfs(3, T))
if(get_dist(t, T) > 1)
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport(target)
ranged_cooldown = world.time + cooldown_time
var/turf/T = get_turf(target)
var/turf/source = get_turf(src)
new /obj/effect/temp_visual/hierophant/telegraph(T, src)
new /obj/effect/temp_visual/hierophant/telegraph(source, src)
playsound(source,'sound/machines/airlockopen.ogg', 200, 1)
addtimer(CALLBACK(src, .proc/pandora_teleport_2, T, source), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_2(var/turf/T, var/turf/source)
new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src)
new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, src)
for(var/t in RANGE_TURFS(1, T))
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
for(var/t in RANGE_TURFS(1, source))
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out
visible_message("<span class='hierophant_warning'>[src] fades out!</span>")
density = FALSE
addtimer(CALLBACK(src, .proc/pandora_teleport_3, T), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_3(var/turf/T)
forceMove(T)
animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN
density = TRUE
visible_message("<span class='hierophant_warning'>[src] fades in!</span>")
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares(target)
ranged_cooldown = world.time + cooldown_time
var/turf/T = get_turf(target)
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src)
var/max_size = 2
addtimer(CALLBACK(src, .proc/aoe_squares_2, T, 0, max_size), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares_2(var/turf/T, var/ring, var/max_size)
if(ring > max_size)
return
for(var/t in spiral_range_turfs(ring, T))
if(get_dist(t, T) == ring)
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
addtimer(CALLBACK(src, .proc/aoe_squares_2, T, (ring + 1), max_size), 2)
//The specific version of hiero's squares pandora uses
/obj/effect/temp_visual/hierophant/blast/pandora
damage = 20
monster_damage_boost = FALSE
//Pandora's loot: Hope
/obj/item/clothing/accessory/pandora_hope
name = "Hope"
desc = "Found at the bottom of Pandora. After all the evil was released, this was the only thing left inside."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "hope"
resistance_flags = FIRE_PROOF
/obj/item/clothing/accessory/pandora_hope/on_uniform_equip(obj/item/clothing/under/U, user)
var/mob/living/L = user
if(L && L.mind)
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "hope_lavaland", /datum/mood_event/hope_lavaland)
/obj/item/clothing/accessory/pandora_hope/on_uniform_dropped(obj/item/clothing/under/U, user)
var/mob/living/L = user
if(L && L.mind)
SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "hope_lavaland")
@@ -6,6 +6,7 @@
icon_dead = "bat_dead"
icon_gib = "bat_dead"
turns_per_move = 1
blood_volume = 250
response_help = "brushes aside"
response_disarm = "flails at"
response_harm = "hits"
@@ -31,6 +31,7 @@
movement_type = FLYING
pressure_resistance = 300
gold_core_spawnable = NO_SPAWN //too spooky for science
blood_volume = 0
var/ghost_hair_style
var/ghost_hair_color
var/mutable_appearance/ghost_hair
@@ -12,6 +12,7 @@
emote_see = list("rattles")
a_intent = INTENT_HARM
maxHealth = 40
blood_volume = 0
health = 40
speed = 1
harm_intent_damage = 5
@@ -18,6 +18,7 @@
maxHealth = 50000
health = 50000
healable = 0
blood_volume = 0
harm_intent_damage = 10
obj_damage = 100
@@ -13,6 +13,7 @@
response_disarm = "shoves"
response_harm = "hits"
speed = 0
blood_volume = 0
stat_attack = UNCONSCIOUS
robust_searching = 1
environment_smash = ENVIRONMENT_SMASH_NONE
@@ -143,7 +143,7 @@
stat("Held Item", held_item)
stat("Mode",a_intent)
/mob/living/simple_animal/parrot/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode)
/mob/living/simple_animal/parrot/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
if(speaker != src && prob(50)) //Dont imitate ourselves
if(!radio_freq || prob(10))
@@ -437,7 +437,7 @@
//Search for item to steal
parrot_interest = search_for_item()
if(parrot_interest)
emote("me", 1, "looks in [parrot_interest]'s direction and takes flight.")
emote("me", EMOTE_VISIBLE, "looks in [parrot_interest]'s direction and takes flight.")
parrot_state = PARROT_SWOOP | PARROT_STEAL
icon_state = icon_living
return
@@ -459,7 +459,7 @@
if(AM)
if(istype(AM, /obj/item) || isliving(AM)) //If stealable item
parrot_interest = AM
emote("me", 1, "turns and flies towards [parrot_interest].")
emote("me", EMOTE_VISIBLE, "turns and flies towards [parrot_interest].")
parrot_state = PARROT_SWOOP | PARROT_STEAL
return
else //Else it's a perch
@@ -760,7 +760,7 @@
held_item = null
if(health < maxHealth)
adjustBruteLoss(-10)
emote("me", 1, "[src] eagerly downs the cracker.")
emote("me", EMOTE_VISIBLE, "[src] eagerly downs the cracker.")
return 1
@@ -31,6 +31,7 @@
loot = list(/obj/item/ectoplasm)
del_on_death = TRUE
initial_language_holder = /datum/language_holder/construct
blood_volume = 0
/mob/living/simple_animal/shade/death()
deathmessage = "lets out a contented sigh as [p_their()] form unwinds."
@@ -4,6 +4,7 @@
health = 20
maxHealth = 20
gender = PLURAL //placeholder
blood_volume = 550 //How much blud it has for bloodsucking
status_flags = CANPUSH
@@ -185,16 +186,16 @@
say(pick(speak), forced = "poly")
else
if(!(emote_hear && emote_hear.len) && (emote_see && emote_see.len))
emote("me", 1, pick(emote_see))
emote("me", EMOTE_VISIBLE, pick(emote_see))
if((emote_hear && emote_hear.len) && !(emote_see && emote_see.len))
emote("me", 2, pick(emote_hear))
emote("me", EMOTE_AUDIBLE, pick(emote_hear))
if((emote_hear && emote_hear.len) && (emote_see && emote_see.len))
var/length = emote_hear.len + emote_see.len
var/pick = rand(1,length)
if(pick <= emote_see.len)
emote("me", 1, pick(emote_see))
emote("me", EMOTE_VISIBLE, pick(emote_see))
else
emote("me", 2, pick(emote_hear))
emote("me", EMOTE_AUDIBLE, pick(emote_hear))
/mob/living/simple_animal/proc/environment_is_safe(datum/gas_mixture/environment, check_temp = FALSE)
@@ -1,4 +1,4 @@
/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode)
/mob/living/simple_animal/slime/Hear(message, atom/movable/speaker, message_langs, raw_message, radio_freq, spans, message_mode, atom/movable/source)
. = ..()
if(speaker != src && !radio_freq && !stat)
if (speaker in Friends)
@@ -26,6 +26,7 @@
health = 150
healable = 0
gender = NEUTER
blood_volume = 0 //Until someome reworks for them to have slime jelly
see_in_dark = 8
+17 -13
View File
@@ -140,24 +140,28 @@
/////////////////////////////////// DISABILITIES ////////////////////////////////////
/mob/living/proc/add_quirk(quirk, spawn_effects) //separate proc due to the way these ones are handled
if(HAS_TRAIT(src, quirk))
/mob/living/proc/add_quirk(quirktype, spawn_effects) //separate proc due to the way these ones are handled
if(has_quirk(quirktype))
return
if(!SSquirks || !SSquirks.quirks[quirk])
var/datum/quirk/T = quirktype
var/qname = initial(T.name)
if(!SSquirks || !SSquirks.quirks[qname])
return
var/datum/quirk/T = SSquirks.quirks[quirk]
new T (src, spawn_effects)
new quirktype (src, spawn_effects)
return TRUE
/mob/living/proc/remove_quirk(quirk)
var/datum/quirk/T = roundstart_quirks[quirk]
if(T)
qdel(T)
return TRUE
/mob/living/proc/has_quirk(quirk)
return roundstart_quirks[quirk]
/mob/living/proc/remove_quirk(quirktype)
for(var/datum/quirk/Q in roundstart_quirks)
if(Q.type == quirktype)
qdel(Q)
return TRUE
return FALSE
/mob/living/proc/has_quirk(quirktype)
for(var/datum/quirk/Q in roundstart_quirks)
if(Q.type == quirktype)
return TRUE
return FALSE
/////////////////////////////////// TRAIT PROCS ////////////////////////////////////
/mob/living/proc/cure_blind(list/sources)
+1
View File
@@ -8,6 +8,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
/mob/living/proc/handle_ventcrawl(atom/A)
if(!ventcrawler || !Adjacent(A))
return
. = TRUE //return value to stop the client from being shown the turf contents stat tab on alt-click.
if(stat)
to_chat(src, "You must be conscious to do this!")
return
+99 -86
View File
@@ -85,106 +85,120 @@
msg = copytext(msg, 1, MAX_MESSAGE_LEN)
if(type)
if(type & 1 && eye_blind )//Vision related
if(type & MSG_VISUAL && eye_blind )//Vision related
if(!alt_msg)
return
else
msg = alt_msg
type = alt_type
if(type & 2 && !can_hear())//Hearing related
if(type & MSG_AUDIBLE && !can_hear())//Hearing related
if(!alt_msg)
return
else
msg = alt_msg
type = alt_type
if(type & 1 && eye_blind)
if(type & MSG_VISUAL && eye_blind)
return
// voice muffling
if(stat == UNCONSCIOUS)
if(type & 2) //audio
if(type & MSG_AUDIBLE) //audio
to_chat(src, "<I>... You can almost hear something ...</I>")
else
to_chat(src, msg)
return
to_chat(src, msg)
// Show a message to all player mobs who sees this atom
// Show a message to the src mob (if the src is a mob)
// Use for atoms performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// self_message (optional) is what the src mob sees e.g. "You do something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
// vision_distance (optional) define how many tiles away the message can be seen.
// ignored_mob (optional) doesn't show any message to a given mob if TRUE.
/atom/proc/visible_message(message, self_message, blind_message, vision_distance, list/ignored_mobs, no_ghosts = FALSE)
/**
* Generate a visible message from this atom
*
* Show a message to all player mobs who sees this atom
*
* Show a message to the src mob (if the src is a mob)
*
* Use for atoms performing visible actions
*
* message is output to anyone who can see, e.g. "The [src] does something!"
*
* Vars:
* * self_message (optional) is what the src mob sees e.g. "You do something!"
* * blind_message (optional) is what blind people will hear e.g. "You hear something!"
* * vision_distance (optional) define how many tiles away the message can be seen.
* * ignored_mobs (optional) doesn't show any message to any given mob in the list.
*/
/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs)
var/turf/T = get_turf(src)
if(!T)
return
var/list/hearers = get_hearers_in_view(vision_distance, src) //caches the hearers and then removes ignored mobs.
if(!length(hearers))
return
if(!islist(ignored_mobs))
ignored_mobs = list(ignored_mobs)
var/range = 7
if(vision_distance)
range = vision_distance
for(var/mob/M in get_hearers_in_view(range, src))
hearers -= ignored_mobs
if(self_message)
hearers -= src
for(var/mob/M in hearers)
if(!M.client)
continue
if(M in ignored_mobs)
continue
//This entire if/else chain could be in two lines but isn't for readibilties sake.
var/msg = message
if(isobserver(M) && no_ghosts)
//CITADEL EDIT, required for vore code to remove (T != loc && T != src)) as a check
if(M.see_invisible<invisibility) //if src is invisible to us,
msg = blind_message
else if(T.lighting_object && T.lighting_object.invisibility <= M.see_invisible && T.is_softly_lit()) //the light object is dark and not invisible to us
msg = blind_message
if(!msg)
continue
if(M == src) //the src always see the main message or self message
if(self_message)
msg = self_message
else //CITADEL EDIT, required for vore code to remove (T != loc && T != src)) as a check
if(M.see_invisible<invisibility) //if src is invisible to us,
if(blind_message) // then people see blind message if there is one, otherwise nothing.
msg = blind_message
else
continue
M.show_message(msg, MSG_VISUAL,blind_message, MSG_AUDIBLE)
else if(T.lighting_object)
if(T.lighting_object.invisibility <= M.see_invisible && T.is_softly_lit()) //the light object is dark and not invisible to us
if(blind_message)
msg = blind_message
else
continue
///Adds the functionality to self_message.
mob/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs)
. = ..()
if(self_message)
show_message(self_message, MSG_VISUAL, blind_message, MSG_AUDIBLE)
M.show_message(msg,1,blind_message,2)
/**
* Show a message to all mobs in earshot of this atom
*
* Use for objects performing audible actions
*
* vars:
* * 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.
* * ignored_mobs (optional) doesn't show any message to any given mob in the list.
*/
/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs)
var/turf/T = get_turf(src)
if(!T)
return
var/list/hearers = get_hearers_in_view(hearing_distance, src)
if(!length(hearers))
return
if(!islist(ignored_mobs))
ignored_mobs = list(ignored_mobs)
hearers -= ignored_mobs
if(self_message)
hearers -= src
for(var/mob/M in hearers)
M.show_message(message, MSG_AUDIBLE, deaf_message, MSG_VISUAL)
// Show a message to all mobs in earshot of this one
// This would be for audible actions by the src mob
// message is the message output to anyone who can hear.
// 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(message, deaf_message, hearing_distance, self_message, no_ghosts = FALSE)
var/range = 7
if(hearing_distance)
range = hearing_distance
for(var/mob/M in get_hearers_in_view(range, src))
var/msg = message
if(self_message && M==src)
msg = self_message
if(no_ghosts && isobserver(M))
continue
M.show_message( msg, 2, deaf_message, 1)
// Show a message to all mobs in earshot of this atom
// Use for objects performing audible actions
// 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(message, deaf_message, hearing_distance, no_ghosts = FALSE)
var/range = 7
if(hearing_distance)
range = hearing_distance
for(var/mob/M in get_hearers_in_view(range, src))
if(no_ghosts && isobserver(M))
continue
M.show_message( message, 2, deaf_message, 1)
/**
* Show a message to all mobs in earshot of this one
*
* This would be for audible actions by the src mob
*
* vars:
* * message is the message output to anyone who can hear.
* * 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.
* * ignored_mobs (optional) doesn't show any message to any given mob in the list.
*/
/mob/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs)
. = ..()
if(self_message)
show_message(self_message, MSG_AUDIBLE, deaf_message, MSG_VISUAL)
/mob/proc/Life()
set waitfor = FALSE
@@ -390,9 +404,6 @@
if(I)
I.attack_self(src)
update_inv_hands()
if(!I)//CIT CHANGE - allows "using" empty hands
use_that_empty_hand() //CIT CHANGE - ditto
update_inv_hands() // CIT CHANGE - ditto.
/mob/verb/memory()
set name = "Notes"
@@ -449,11 +460,12 @@
return
/mob/proc/transfer_ckey(mob/new_mob, send_signal = TRUE)
if(!ckey)
return FALSE
if(!ckey || !new_mob)
CRASH("transfer_ckey() called [ckey ? "" : "on a ckey-less mob[new_mob ? "" : " and "]"][new_mob ? "" : "without a valid mob target"]!")
SEND_SIGNAL(new_mob, COMSIG_MOB_PRE_PLAYER_CHANGE, new_mob, src)
new_mob.ckey = ckey
if(send_signal)
SEND_SIGNAL(src, COMSIG_MOB_KEY_CHANGE, new_mob, src)
new_mob.ckey = ckey
return TRUE
/mob/verb/cancel_camera()
@@ -554,9 +566,9 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
/mob/proc/is_muzzled()
return 0
/mob/Stat()
..()
/mob/Stat(delayoverride)
. = ..()
var/statdelay = delayoverride || 10
if(statpanel("Status"))
if (client)
stat(null, "Ping: [round(client.lastping, 1)]ms (Average: [round(client.avgping, 1)]ms)")
@@ -564,7 +576,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
var/datum/map_config/cached = SSmapping.next_map_config
if(cached)
stat(null, "Next Map: [cached.map_name]")
stat(null, "Round ID: [GLOB.round_id ? GLOB.round_id : "NULL"]")
stat(null, "Round ID: [GLOB.round_id || "NULL"]")
stat(null, "Server Time: [time2text(world.timeofday, "YYYY-MM-DD hh:mm:ss")]")
stat(null, "Round Time: [WORLDTIME2TEXT("hh:mm:ss")]")
stat(null, "Station Time: [STATION_TIME_TIMESTAMP("hh:mm:ss")]")
@@ -574,8 +586,9 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
if(ETA)
stat(null, "[ETA] [SSshuttle.emergency.getTimerStr()]")
if(client && client.holder)
if(client?.holder)
if(statpanel("MC"))
statdelay = 0 //It's assumed that if you're doing this you are doing debug stuff, don't do ioditic things.
var/turf/T = get_turf(client.eye)
stat("Location:", COORD(T))
stat("CPU:", "[world.cpu]")
@@ -601,6 +614,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
GLOB.ahelp_tickets.stat_entry()
if(length(GLOB.sdql2_queries))
if(statpanel("SDQL2"))
statdelay = 0 //It's assumed that if you're doing this you are doing debug stuff, don't do ioditic things.
stat("Access Global SDQL2 List", GLOB.sdql2_vv_statobj)
for(var/i in GLOB.sdql2_queries)
var/datum/SDQL2_query/Q = i
@@ -624,14 +638,13 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
if(A.IsObscured())
continue
statpanel(listed_turf.name, null, A)
if(mind)
add_spells_to_statpanel(mind.spell_list)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
add_stings_to_statpanel(changeling.purchasedpowers)
add_spells_to_statpanel(mob_spell_list)
sleep(statdelay)
/mob/proc/add_spells_to_statpanel(list/spells)
for(var/obj/effect/proc_holder/spell/S in spells)
@@ -964,4 +977,4 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
/mob/setMovetype(newval)
. = ..()
update_movespeed(FALSE)
update_movespeed(FALSE)
+6
View File
@@ -99,6 +99,12 @@
var/obj/control_object //Used by admins to possess objects. All mobs should have this var
var/atom/movable/remote_control //Calls relaymove() to whatever it is
/**
* The sound made on death
*
* leave null for no sound. used for *deathgasp
*/
var/deathsound = null
var/turf/listed_turf = null //the current turf being examined in the stat panel

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