Merge branch 'master' into HeadCorgi

This commit is contained in:
lolman360
2019-11-17 12:24:04 +11:00
committed by GitHub
1884 changed files with 45460 additions and 148028 deletions
+1 -1
View File
@@ -310,7 +310,7 @@
});
$( "#sortable" ).disableSelection();
$('form').submit(function(){
$('#IRVdata').val($( "#sortable" ).sortable("toArray", { attribute: "voteid" }));
$('#IRVdata').val($( "#sortable" ).sortable("toArray", { attribute: "voteid" }));
});
});
@@ -130,10 +130,10 @@
color_src = MATRIXED
/datum/sprite_accessory/ears/human/rabbit
name = "Rabbit"
icon_state = "rabbit"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
name = "Rabbit"
icon_state = "rabbit"
color_src = MATRIXED
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
/datum/sprite_accessory/ears/human/sergal
name = "Sergal"
@@ -287,8 +287,8 @@
icon_state = "pede"
/datum/sprite_accessory/mam_ears/rabbit
name = "Rabbit"
icon_state = "rabbit"
name = "Rabbit"
icon_state = "rabbit"
/datum/sprite_accessory/mam_ears/sergal
name = "Sergal"
+51 -23
View File
@@ -3,6 +3,8 @@ GLOBAL_LIST_EMPTY(ghost_images_simple) //this is a list of all ghost images as t
GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
#define CANT_REENTER_ROUND -1
/mob/dead/observer
name = "ghost"
desc = "It's a g-g-g-g-ghooooost!" //jinkies!
@@ -17,8 +19,9 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
see_in_dark = 100
invisibility = INVISIBILITY_OBSERVER
hud_type = /datum/hud/ghost
movement_type = GROUND | FLYING
var/can_reenter_corpse
var/can_reenter_round = TRUE
var/reenter_round_timeout = 0 // used to prevent people from coming back through ghost roles/midround antags as they suicide/cryo for a duration set by CONFIG_GET(number/suicide_reenter_round_timer) and CONFIG_GET(number/roundstart_suicide_time_limit)
var/datum/hud/living/carbon/hud = null // hud
var/bootime = 0
var/started_as_observer //This variable is set to 1 when you enter the game as an observer.
@@ -231,7 +234,7 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
var/r_val
var/b_val
var/g_val
var/color_format = lentext(input_color)
var/color_format = length(input_color)
if(color_format == 3)
r_val = hex2num(copytext(input_color, 1, 2))*16
g_val = hex2num(copytext(input_color, 2, 3))*16
@@ -260,14 +263,22 @@ Transfer_mind is there to check if mob is being deleted/not going to have a body
Works together with spawning an observer, noted above.
*/
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE)
if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special) & COMPONENT_BLOCK_GHOSTING))
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE)
if(!key || cmptext(copytext(key,1,2),"@") || (!special && SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse) & 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.
SStgui.on_transfer(src, ghost) // Transfer NanoUIs.
ghost.can_reenter_corpse = can_reenter_corpse
ghost.can_reenter_round = (can_reenter_corpse && !suiciding)
if(penalize) //penalizing them from making a ghost role / midround antag comeback right away.
var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES
var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES
if(world.time < roundstart_quit_limit) //add up the time difference to their antag rolling penalty if they quit before half a (ingame) hour even passed.
penalty += roundstart_quit_limit - world.time
if(penalty)
ghost.reenter_round_timeout = world.realtime + penalty
if(ghost.reenter_round_timeout - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
ghost.reenter_round_timeout = CANT_REENTER_ROUND
transfer_ckey(ghost, FALSE)
return ghost
@@ -283,26 +294,27 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, (stat == DEAD) ? TRUE : FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING)
return
// CITADEL EDIT
if(istype(loc, /obj/machinery/cryopod))
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
if(response != "Ghost")//darn copypaste
return
var/obj/machinery/cryopod/C = loc
C.despawn_occupant()
return
// END EDIT
var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES
var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES
if(world.time < roundstart_quit_limit)
penalty += roundstart_quit_limit - world.time
if(penalty + world.realtime - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
penalty = CANT_REENTER_ROUND
if(stat != DEAD)
succumb()
if(stat == DEAD)
ghostize(1)
else
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles [penalty != CANT_REENTER_ROUND ? "until the round is over" : "for the next [DisplayTimeText(penalty)]"]" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
if(response != "Ghost")
return //didn't want to ghost after-all
ghostize(0) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
suicide_log(TRUE)
if(istype(loc, /obj/machinery/cryopod))
var/obj/machinery/cryopod/C = loc
C.despawn_occupant()
else
ghostize(0, penalize = TRUE) //0 parameter is so we can never re-enter our body, "Charlie, you can never come baaaack~" :3
suicide_log(TRUE)
/mob/camera/verb/ghost()
set category = "OOC"
@@ -312,10 +324,24 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, FALSE, FALSE) & COMPONENT_BLOCK_GHOSTING)
return
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst still alive you won't be able to re-enter this round! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
var/penalty = CONFIG_GET(number/suicide_reenter_round_timer) MINUTES
var/roundstart_quit_limit = CONFIG_GET(number/roundstart_suicide_time_limit) MINUTES
if(world.time < roundstart_quit_limit)
penalty += roundstart_quit_limit - world.time
if(penalty + world.realtime - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
penalty = CANT_REENTER_ROUND
var/response = alert(src, "Are you -sure- you want to ghost?\n(You are alive. If you ghost whilst alive you won't be able to re-enter this round [penalty ? "or play ghost roles [penalty != CANT_REENTER_ROUND ? "until the round is over" : "for the next [DisplayTimeText(penalty)]"]" : ""]! You can't change your mind so choose wisely!!)","Are you sure you want to ghost?","Ghost","Stay in body")
if(response != "Ghost")
return
ghostize(0)
ghostize(0, penalize = TRUE)
/mob/dead/observer/proc/can_reenter_round(silent = FALSE)
if(reenter_round_timeout != CANT_REENTER_ROUND && reenter_round_timeout <= world.realtime)
return TRUE
if(!silent)
to_chat(src, "<span class='warning'>You are unable to reenter the round[reenter_round_timeout != CANT_REENTER_ROUND ? " yet. Your ghost role blacklist will expire in [DisplayTimeText(reenter_round_timeout - world.realtime)]" : ""].</span>")
return FALSE
/mob/dead/observer/Move(NewLoc, direct)
if(updatedir)
@@ -603,6 +629,10 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
set name = "Possess!"
set desc= "Take over the body of a mindless creature!"
if(reenter_round_timeout > world.realtime)
to_chat(src, "<span class='warning'>You are unable to re-enter the round yet. Your ghost role blacklist will expire in [DisplayTimeText(reenter_round_timeout - world.realtime)].</span>")
return FALSE
var/list/possessible = list()
for(var/mob/living/L in GLOB.alive_mob_list)
if(istype(L,/mob/living/carbon/human/dummy) || !get_turf(L)) //Haha no.
@@ -623,10 +653,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(src, "<span class='warning'>This isn't really a creature, now is it!</span>")
return 0
if(!can_reenter_round)
to_chat(src, "<span class='warning'>You are unable to re-enter the round.</span>")
return FALSE
if(can_reenter_corpse && mind && mind.current)
if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go forward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No")
return 0
@@ -871,3 +897,5 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
spawners_menu = new(src)
spawners_menu.ui_interact(src)
#undef CANT_REENTER_ROUND
@@ -0,0 +1,2 @@
/mob/dead/observer/canZMove(direction, turf/target)
return TRUE
+1 -2
View File
@@ -152,8 +152,7 @@
newcolor = BLOOD_COLOR_XENO
add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY)
// but only for a few seconds
spawn(30)
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, newcolor)
addtimer(CALLBACK(src, /atom/.proc/remove_atom_colour, TEMPORARY_COLOUR_PRIORITY, newcolor), 6 SECONDS)
/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
if(src.notransform)
+1 -1
View File
@@ -24,7 +24,7 @@
var/list/datum/brain_trauma/traumas = list()
/obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0,no_id_transfer = FALSE)
/obj/item/organ/brain/Insert(mob/living/carbon/C, special = 0,no_id_transfer = FALSE, drop_if_replaced = TRUE)
..()
name = "brain"
+7 -4
View File
@@ -36,7 +36,7 @@ GLOBAL_VAR(posibrain_notify_cooldown)
/obj/item/mmi/posibrain/proc/ping_ghosts(msg, newlymade)
if(newlymade || GLOB.posibrain_notify_cooldown <= world.time)
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/misc/server-ready.ogg':null, enter_link = "<a href=?src=[REF(src)];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_POSIBRAIN)
notify_ghosts("[name] [msg] in [get_area(src)]!", ghost_sound = !newlymade ? 'sound/misc/server-ready.ogg':null, enter_link = "<a href=?src=[REF(src)];activate=1>(Click to enter)</a>", source = src, action = NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_POSIBRAIN, ignore_dnr_observers = TRUE)
if(!newlymade)
GLOB.posibrain_notify_cooldown = world.time + askDelay
@@ -83,11 +83,14 @@ GLOBAL_VAR(posibrain_notify_cooldown)
//Two ways to activate a positronic brain. A clickable link in the ghost notif, or simply clicking the object itself.
/obj/item/mmi/posibrain/proc/activate(mob/user)
if(QDELETED(brainmob))
return
if(is_occupied() || jobban_isbanned(user,"posibrain") || QDELETED(brainmob) || QDELETED(src) || QDELETED(user))
if(QDELETED(brainmob) || is_occupied() || jobban_isbanned(user,"posibrain") || QDELETED(src) || QDELETED(user))
return
if(isobserver(user))
var/mob/dead/observer/O = user
if(!O.can_reenter_round())
return FALSE
var/posi_ask = alert("Become a [name]? (Warning, You can no longer be cloned, and all past lives will be forgotten!)","Are you positive?","Yes","No")
if(posi_ask == "No" || QDELETED(src))
return
@@ -1,8 +1,9 @@
/mob/living/carbon/alien/spawn_gibs(with_bodyparts)
/mob/living/carbon/alien/spawn_gibs(with_bodyparts, atom/loc_override)
var/location = loc_override ? loc_override.drop_location() : drop_location()
if(with_bodyparts)
new /obj/effect/gibspawner/xeno(drop_location())
new /obj/effect/gibspawner/xeno(location, src)
else
new /obj/effect/gibspawner/xeno/bodypartless(drop_location())
new /obj/effect/gibspawner/xeno/bodypartless(location, src)
/mob/living/carbon/alien/gib_animation()
new /obj/effect/temp_visual/gib_animation(loc, "gibbed-a")
@@ -95,8 +95,14 @@ Doesn't work on other aliens/AI.*/
var/mob/living/M = input("Select who to whisper to:","Whisper to?",null) as null|mob in options
if(!M)
return 0
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='noticealien'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return FALSE
var/msg = sanitize(input("Message:", "Alien Whisper") as text|null)
if(msg)
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(user, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
log_directed_talk(user, M, msg, LOG_SAY, tag="alien whisper")
to_chat(M, "<span class='noticealien'>You hear a strange, alien voice in your head...</span>[msg]")
to_chat(user, "<span class='noticealien'>You said: \"[msg]\" to [M]</span>")
@@ -6,11 +6,12 @@
update_icons()
/mob/living/carbon/alien/larva/spawn_gibs(with_bodyparts)
/mob/living/carbon/alien/larva/spawn_gibs(with_bodyparts, atom/loc_override)
var/location = loc_override ? loc_override.drop_location() : drop_location()
if(with_bodyparts)
new /obj/effect/gibspawner/larva(drop_location())
new /obj/effect/gibspawner/larva(location, src)
else
new /obj/effect/gibspawner/larva/bodypartless(drop_location())
new /obj/effect/gibspawner/larva/bodypartless(location, src)
/mob/living/carbon/alien/larva/gib_animation()
new /obj/effect/temp_visual/gib_animation(loc, "gibbed-l")
@@ -14,7 +14,7 @@
QDEL_LIST(alien_powers)
return ..()
/obj/item/organ/alien/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/alien/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
for(var/obj/effect/proc_holder/alien/P in alien_powers)
M.AddAbility(P)
@@ -94,7 +94,7 @@
else
owner.adjustPlasma(plasma_rate * 0.1)
/obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/alien/plasmavessel/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
if(isalien(M))
var/mob/living/carbon/alien/A = M
@@ -117,7 +117,7 @@
var/recent_queen_death = 0 //Indicates if the queen died recently, aliens are heavily weakened while this is active.
alien_powers = list(/obj/effect/proc_holder/alien/whisper)
/obj/item/organ/alien/hivenode/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/alien/hivenode/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
M.faction |= ROLE_ALIEN
+2 -2
View File
@@ -266,7 +266,7 @@
/mob/living/carbon/fall(forced)
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
loc.handle_fall(src, forced)//it's loc so it doesn't call the mob's handle_fall which does nothing
/mob/living/carbon/is_muzzled()
return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
@@ -595,7 +595,7 @@
if(!isnull(E.lighting_alpha))
lighting_alpha = E.lighting_alpha
if(client.eye != src)
if(client.eye && client.eye != src)
var/atom/A = client.eye
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
@@ -36,7 +36,7 @@
/mob/living/carbon/Move(NewLoc, direct)
. = ..()
if(. && mob_has_gravity()) //floating is easy
if(. && (movement_type & FLOATING)) //floating is easy
if(HAS_TRAIT(src, TRAIT_NOHUNGER))
nutrition = NUTRITION_LEVEL_FED - 1 //just less than feeling vigorous
else if(nutrition && stat != DEAD)
+3 -3
View File
@@ -31,9 +31,9 @@
if (!user.get_bodypart(BODY_ZONE_L_ARM) || !user.get_bodypart(BODY_ZONE_R_ARM))
return
var/clap = pick('sound/misc/clap1.ogg',
'sound/misc/clap2.ogg',
'sound/misc/clap3.ogg',
'sound/misc/clap4.ogg')
'sound/misc/clap2.ogg',
'sound/misc/clap3.ogg',
'sound/misc/clap4.ogg')
playsound(user, clap, 50, 1, -1)
/datum/emote/living/carbon/gnarl
+18 -28
View File
@@ -4,36 +4,21 @@
/mob/living/carbon/human/dust_animation()
new /obj/effect/temp_visual/dust_animation(loc, "dust-h")
/mob/living/carbon/human/spawn_gibs(with_bodyparts)
if(isjellyperson(src))
if(with_bodyparts)
new /obj/effect/gibspawner/slime(drop_location(), dna, get_static_viruses())
/mob/living/carbon/human/spawn_gibs(with_bodyparts, atom/loc_override)
var/location = loc_override ? loc_override.drop_location() : drop_location()
if(dna?.species?.gib_types)
var/datum/species/S = dna.species
var/length = length(S.gib_types)
if(length)
var/path = (with_bodyparts && length > 1) ? S.gib_types[2] : S.gib_types[1]
new path(location, src, get_static_viruses())
else
new /obj/effect/gibspawner/slime/bodypartless(drop_location(), dna, get_static_viruses())
if(isipcperson(src))
if(with_bodyparts)
new /obj/effect/gibspawner/ipc(drop_location(), dna, get_static_viruses())
else
new /obj/effect/gibspawner/ipc/bodypartless(drop_location(), dna, get_static_viruses())
if(isxenoperson(src))
if(with_bodyparts)
new /obj/effect/gibspawner/xeno/xenoperson(drop_location(), dna, get_static_viruses())
else
new /obj/effect/gibspawner/xeno/xenoperson/bodypartless(drop_location(), dna, get_static_viruses())
if(islizard(src))
if(with_bodyparts)
new /obj/effect/gibspawner/lizard(drop_location(), dna, get_static_viruses())
else
new /obj/effect/gibspawner/lizard/bodypartless(drop_location(), dna, get_static_viruses())
new S.gib_types(location, src, get_static_viruses())
else
if(with_bodyparts)
new /obj/effect/gibspawner/human(drop_location(), dna, get_static_viruses())
new /obj/effect/gibspawner/human(location, src, get_static_viruses())
else
new /obj/effect/gibspawner/human/bodypartless(drop_location(), dna, get_static_viruses())
new /obj/effect/gibspawner/human/bodypartless(location, src, get_static_viruses())
/mob/living/carbon/human/spawn_dust(just_ash = FALSE)
if(just_ash)
@@ -69,11 +54,16 @@
/mob/living/carbon/human/proc/makeSkeleton()
ADD_TRAIT(src, TRAIT_DISFIGURED, TRAIT_GENERIC)
set_species(/datum/species/skeleton)
return 1
return TRUE
/mob/living/carbon/proc/Drain()
become_husk(CHANGELING_DRAIN)
ADD_TRAIT(src, TRAIT_NOCLONE, CHANGELING_DRAIN)
blood_volume = 0
return 1
return TRUE
/mob/living/carbon/proc/makeUncloneable()
ADD_TRAIT(src, TRAIT_NOCLONE, MADE_UNCLONEABLE)
blood_volume = 0
return TRUE
@@ -488,7 +488,7 @@
var/counter = 1
while(R.fields[text("com_[]", counter)])
counter++
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer+540, t1)
R.fields[text("com_[]", counter)] = text("Made by [] on [] [], []<BR>[]", allowed_access, STATION_TIME_TIMESTAMP("hh:mm:ss"), time2text(world.realtime, "MMM DD"), GLOB.year_integer, t1)
to_chat(usr, "<span class='notice'>Successfully added comment.</span>")
return
to_chat(usr, "<span class='warning'>Unable to locate a data core entry for this person.</span>")
@@ -574,7 +574,7 @@
return threatcount
//Check for ID
var/obj/item/card/id/idcard = get_idcard()
var/obj/item/card/id/idcard = get_idcard(FALSE)
if( (judgement_criteria & JUDGE_IDCHECK) && !idcard && name=="Unknown")
threatcount += 4
@@ -946,7 +946,7 @@
return FALSE
/mob/living/carbon/human/proc/clear_shove_slowdown()
remove_movespeed_modifier(SHOVE_SLOWDOWN_ID)
remove_movespeed_modifier(MOVESPEED_ID_SHOVE)
var/active_item = get_active_held_item()
if(is_type_in_typecache(active_item, GLOB.shove_disarming_types))
visible_message("<span class='warning'>[src.name] regains their grip on \the [active_item]!</span>", "<span class='warning'>You regain your grip on \the [active_item]</span>", null, COMBAT_MESSAGE_RANGE)
@@ -778,7 +778,7 @@
broken_plural = TRUE
else
var/holder = broken[1] //our one and only element
if(holder[lentext(holder)] == "s")
if(holder[length(holder)] == "s")
broken_plural = TRUE
//Put the items in that list into a string of text
for(var/B in broken)
@@ -790,7 +790,7 @@
damaged_plural = TRUE
else
var/holder = damaged[1]
if(holder[lentext(holder)] == "s")
if(holder[length(holder)] == "s")
damaged_plural = TRUE
for(var/D in damaged)
damaged_message += D
@@ -11,8 +11,8 @@
//gets assignment from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job")
var/obj/item/card/id/id = get_idcard()
/mob/living/carbon/human/proc/get_assignment(if_no_id = "No id", if_no_job = "No job", hand_first = TRUE)
var/obj/item/card/id/id = get_idcard(hand_first)
if(id)
. = id.assignment
else
@@ -27,7 +27,7 @@
//gets name from ID or ID inside PDA or PDA itself
//Useful when player do something with computers
/mob/living/carbon/human/proc/get_authentification_name(if_no_id = "Unknown")
var/obj/item/card/id/id = get_idcard()
var/obj/item/card/id/id = get_idcard(FALSE)
if(id)
return id.registered_name
var/obj/item/pda/pda = wear_id
@@ -86,10 +86,15 @@
return
//gets ID card object from special clothes slot or null.
/mob/living/carbon/human/get_idcard()
if(wear_id)
return wear_id.GetID()
/mob/living/carbon/human/get_idcard(hand_first = TRUE)
. = ..()
if(. && hand_first)
return
//Check inventory slots
var/obj/item/card/id/id_card = wear_id?.GetID()
if(!id_card)
id_card = belt?.GetID()
return id_card || .
/mob/living/carbon/human/IsAdvancedToolUser()
if(HAS_TRAIT(src, TRAIT_MONKEYLIKE))
@@ -100,7 +105,6 @@
return dna.species.handle_chemicals(R,src)
// if it returns 0, it will run the usual on_mob_life for that reagent. otherwise, it will stop after running handle_chemicals for the species.
/mob/living/carbon/human/can_track(mob/living/user)
if(wear_id && istype(wear_id.GetID(), /obj/item/card/id/syndicate))
return 0
@@ -79,7 +79,8 @@
//This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible()
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot)
if(!..()) //a check failed or the item has already found its slot
. = ..()
if(!.) //a check failed or the item has already found its slot
return
var/not_handled = FALSE //Added in case we make this type path deeper one day
@@ -136,6 +137,7 @@
update_inv_s_store()
else
to_chat(src, "<span class='danger'>You are trying to equip this item to an unsupported inventory slot. Report this to a coder!</span>")
not_handled = TRUE
//Item is handled and in slot, valid to call callback, for this proc should always be true
if(!not_handled)
+45 -51
View File
@@ -3,7 +3,7 @@
//NOTE: Breathing happens once per FOUR TICKS, unless the last breath fails. In which case it happens once per ONE TICK! So oxyloss healing is done once per 4 ticks while oxyloss damage is applied once per tick!
// bitflags for the percentual amount of protection a piece of clothing which covers the body part offers.
// Used with human/proc/get_heat_protection() and human/proc/get_cold_protection()
// Used with human/proc/get_thermal_protection()
// The values here should add up to 1.
// Hands and feet have 2.5%, arms and legs 7.5%, each of the torso parts has 15% and the head has 30%
#define THERMAL_PROTECTION_HEAD 0.3
@@ -18,7 +18,7 @@
#define THERMAL_PROTECTION_HAND_LEFT 0.025
#define THERMAL_PROTECTION_HAND_RIGHT 0.025
/mob/living/carbon/human/Life()
/mob/living/carbon/human/Life(seconds, times_fired)
set invisibility = 0
if (notransform)
return
@@ -41,7 +41,7 @@
if(stat != DEAD)
//process your dick energy
handle_arousal()
handle_arousal(times_fired)
//Update our name based on whether our face is obscured/disfigured
name = get_visible_name()
@@ -53,16 +53,17 @@
/mob/living/carbon/human/calculate_affecting_pressure(pressure)
if (wear_suit && head && istype(wear_suit, /obj/item/clothing) && istype(head, /obj/item/clothing))
var/headless = !get_bodypart(BODY_ZONE_HEAD) //should the mob be perennially headless (see dullahans), we only take the suit into account, so they can into space.
if (wear_suit && istype(wear_suit, /obj/item/clothing) && (headless || (head && istype(head, /obj/item/clothing))))
var/obj/item/clothing/CS = wear_suit
var/obj/item/clothing/CH = head
if (CS.clothing_flags & CH.clothing_flags & STOPSPRESSUREDAMAGE)
if (CS.clothing_flags & STOPSPRESSUREDAMAGE && (headless || (CH.clothing_flags & STOPSPRESSUREDAMAGE)))
return ONE_ATMOSPHERE
if(isbelly(loc)) //START OF CIT CHANGES - Makes it so you don't suffocate while inside vore organs. Remind me to modularize this some time - Bhijn
return ONE_ATMOSPHERE
if(istype(loc, /obj/item/dogborg/sleeper))
return ONE_ATMOSPHERE //END OF CIT CHANGES
return pressure
return ..()
/mob/living/carbon/human/handle_traits()
@@ -136,7 +137,7 @@
if(dna)
dna.species.handle_fire(src)
/mob/living/carbon/human/proc/get_thermal_protection()
/mob/living/carbon/human/proc/easy_thermal_protection()
var/thermal_protection = 0 //Simple check to estimate how protected we are against multiple temperatures
//CITADEL EDIT Vore code required overrides
if(istype(loc, /obj/item/dogborg/sleeper))
@@ -168,7 +169,6 @@
..()
//END FIRE CODE
//This proc returns a number made up of the flags for body parts which you are protected on. (such as HEAD, CHEST, GROIN, etc. See setup.dm for the full list)
/mob/living/carbon/human/proc/get_heat_protection_flags(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = 0
@@ -194,37 +194,6 @@
return thermal_protection_flags
/mob/living/carbon/human/proc/get_heat_protection(temperature) //Temperature is the temperature you're being exposed to.
var/thermal_protection_flags = get_heat_protection_flags(temperature)
var/thermal_protection = 0
if(thermal_protection_flags)
if(thermal_protection_flags & HEAD)
thermal_protection += THERMAL_PROTECTION_HEAD
if(thermal_protection_flags & CHEST)
thermal_protection += THERMAL_PROTECTION_CHEST
if(thermal_protection_flags & GROIN)
thermal_protection += THERMAL_PROTECTION_GROIN
if(thermal_protection_flags & LEG_LEFT)
thermal_protection += THERMAL_PROTECTION_LEG_LEFT
if(thermal_protection_flags & LEG_RIGHT)
thermal_protection += THERMAL_PROTECTION_LEG_RIGHT
if(thermal_protection_flags & FOOT_LEFT)
thermal_protection += THERMAL_PROTECTION_FOOT_LEFT
if(thermal_protection_flags & FOOT_RIGHT)
thermal_protection += THERMAL_PROTECTION_FOOT_RIGHT
if(thermal_protection_flags & ARM_LEFT)
thermal_protection += THERMAL_PROTECTION_ARM_LEFT
if(thermal_protection_flags & ARM_RIGHT)
thermal_protection += THERMAL_PROTECTION_ARM_RIGHT
if(thermal_protection_flags & HAND_LEFT)
thermal_protection += THERMAL_PROTECTION_HAND_LEFT
if(thermal_protection_flags & HAND_RIGHT)
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
return min(1,thermal_protection)
//See proc/get_heat_protection_flags(temperature) for the description of this proc.
/mob/living/carbon/human/proc/get_cold_protection_flags(temperature)
var/thermal_protection_flags = 0
@@ -251,17 +220,42 @@
return thermal_protection_flags
/mob/living/carbon/human/proc/get_cold_protection(temperature)
//CITADEL EDIT Mandatory for vore code.
if(istype(loc, /obj/item/dogborg/sleeper))
return TRUE //freezing to death in sleepers ruins fun.
if(isbelly(loc))
return TRUE
if(ismob(loc))
return TRUE //because lazy and being inside somemone insulates you from space
//END EDIT
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = get_cold_protection_flags(temperature)
/mob/living/carbon/human/proc/get_thermal_protection(temperature, cold = FALSE)
if(cold)
//CITADEL EDIT Mandatory for vore code.
if(istype(loc, /obj/item/dogborg/sleeper) || isbelly(loc) || ismob(loc))
return 1 //freezing to death in sleepers ruins fun.
//END EDIT
temperature = max(temperature, 2.7) //There is an occasional bug where the temperature is miscalculated in ares with a small amount of gas on them, so this is necessary to ensure that that bug does not affect this calculation. Space's temperature is 2.7K and most suits that are intended to protect against any cold, protect down to 2.0K.
var/thermal_protection_flags = cold ? get_cold_protection_flags(temperature) : get_heat_protection_flags(temperature)
var/missing_body_parts_flags = ~get_body_parts_flags()
var/max_protection = 1
if(missing_body_parts_flags) //I don't like copypasta as much as proc overhead. Do you want me to make these into a macro?
DISABLE_BITFIELD(thermal_protection_flags, missing_body_parts_flags)
if(missing_body_parts_flags & HEAD)
max_protection -= THERMAL_PROTECTION_HEAD
if(missing_body_parts_flags & CHEST)
max_protection -= THERMAL_PROTECTION_CHEST
if(missing_body_parts_flags & GROIN)
max_protection -= THERMAL_PROTECTION_GROIN
if(missing_body_parts_flags & LEG_LEFT)
max_protection -= THERMAL_PROTECTION_LEG_LEFT
if(missing_body_parts_flags & LEG_RIGHT)
max_protection -= THERMAL_PROTECTION_LEG_RIGHT
if(missing_body_parts_flags & FOOT_LEFT)
max_protection -= THERMAL_PROTECTION_FOOT_LEFT
if(missing_body_parts_flags & FOOT_RIGHT)
max_protection -= THERMAL_PROTECTION_FOOT_RIGHT
if(missing_body_parts_flags & ARM_LEFT)
max_protection -= THERMAL_PROTECTION_ARM_LEFT
if(missing_body_parts_flags & ARM_RIGHT)
max_protection -= THERMAL_PROTECTION_ARM_RIGHT
if(missing_body_parts_flags & HAND_LEFT)
max_protection -= THERMAL_PROTECTION_HAND_LEFT
if(missing_body_parts_flags & HAND_RIGHT)
max_protection -= THERMAL_PROTECTION_HAND_RIGHT
if(max_protection == 0) //Is it even a man if it doesn't have a body at all? Early return to avoid division by zero.
return 1
var/thermal_protection = 0
if(thermal_protection_flags)
@@ -288,7 +282,7 @@
if(thermal_protection_flags & HAND_RIGHT)
thermal_protection += THERMAL_PROTECTION_HAND_RIGHT
return min(1,thermal_protection)
return round(thermal_protection/max_protection, 0.001)
/mob/living/carbon/human/handle_random_events()
//Puke if toxloss is too high
@@ -21,8 +21,6 @@
var/bleed_mod = 1 // % bleeding modifier
var/datum/armor/armor // internal armor datum
var/speed_mod = 0 //tick modifier for each step. Positive is slower, negative is faster.
var/hunger_mod = 1 //% of hunger rate taken per tick.
var/do_after_speed = 1 //Speed mod for do_after. Lower is better. If temporarily adjusting, please only modify using *= and /=, so you don't interrupt other calculations.
+17 -45
View File
@@ -43,6 +43,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/exotic_blood = "" // If your race wants to bleed something other than bog standard blood, change this to reagent id.
var/exotic_bloodtype = "" //If your race uses a non standard bloodtype (A+, O-, AB-, etc)
var/meat = /obj/item/reagent_containers/food/snacks/meat/slab/human //What the species drops on gibbing
var/list/gib_types = list(/obj/effect/gibspawner/human, /obj/effect/gibspawner/human/bodypartless)
var/skinned_type
var/liked_food = NONE
var/disliked_food = GROSS
@@ -81,7 +82,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/sound/attack_sound = 'sound/weapons/punch1.ogg'
var/sound/miss_sound = 'sound/weapons/punchmiss.ogg'
var/mob/living/list/ignored_by = list() // list of mobs that will ignore this species
var/list/mob/living/ignored_by = list() // list of mobs that will ignore this species
//Breathing!
var/obj/item/organ/lungs/mutantlungs = null
var/breathid = "o2"
@@ -332,6 +333,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if("meat_type" in default_features) //I can't believe it's come to the meat
H.type_of_meat = GLOB.meat_types[H.dna.features["meat_type"]]
C.add_movespeed_modifier(MOVESPEED_ID_SPECIES, TRUE, 100, override=TRUE, multiplicative_slowdown=speedmod, movetypes=(~FLYING))
SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species)
@@ -348,6 +351,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
for(var/X in inherent_traits)
REMOVE_TRAIT(C, X, SPECIES_TRAIT)
C.remove_movespeed_modifier(MOVESPEED_ID_SPECIES)
if("meat_type" in default_features)
C.type_of_meat = GLOB.meat_types[C.dna.features["meat_type"]]
else
@@ -541,7 +546,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.hidden_underwear)
H.underwear = "Nude"
else
H.saved_underwear = H.underwear
H.underwear = H.saved_underwear
var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear]
if(B)
var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER)
@@ -553,7 +558,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.hidden_undershirt)
H.undershirt = "Nude"
else
H.saved_undershirt = H.undershirt
H.undershirt = H.saved_undershirt
var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt]
if(T)
var/mutable_appearance/MA
@@ -569,7 +574,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(H.hidden_socks)
H.socks = "Nude"
else
H.saved_socks = H.socks
H.socks = H.saved_socks
var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks]
if(S)
var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : ""
@@ -1389,39 +1394,16 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
/datum/species/proc/movement_delay(mob/living/carbon/human/H)
. = 0 //We start at 0.
var/flight = 0 //Check for flight and flying items
var/ignoreslow = 0
var/gravity = 0
if(H.movement_type & FLYING)
flight = 1
gravity = H.has_gravity()
if(gravity && !flight) //Check for chemicals and innate speedups and slowdowns if we're on the ground
if(HAS_TRAIT(H, TRAIT_GOTTAGOFAST))
. -= 1
if(HAS_TRAIT(H, TRAIT_GOTTAGOREALLYFAST))
. -= 2
. += speedmod
. += H.physiology.speed_mod
if (H.m_intent == MOVE_INTENT_WALK && HAS_TRAIT(H, TRAIT_SPEEDY_STEP))
. -= 1.5
if(HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN))
ignoreslow = 1
if(!gravity)
var/obj/item/tank/jetpack/J = H.back
var/obj/item/clothing/suit/space/hardsuit/C = H.wear_suit
var/obj/item/organ/cyberimp/chest/thrusters/T = H.getorganslot(ORGAN_SLOT_THRUSTERS)
if(!istype(J) && istype(C))
J = C.jetpack
if(istype(J) && J.full_speed && J.allow_thrust(0.01, H)) //Prevents stacking
. -= 0.4
else if(istype(T) && T.allow_thrust(0.01, H))
. -= 0.4
if(!ignoreslow && gravity)
if(!HAS_TRAIT(H, TRAIT_IGNORESLOWDOWN) && gravity)
if(H.wear_suit)
. += H.wear_suit.slowdown
if(H.shoes)
@@ -1448,16 +1430,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/grav_force = min(gravity - STANDARD_GRAVITY,3)
. += 1 + grav_force
var/datum/component/mood/mood = H.GetComponent(/datum/component/mood)
if(mood && !flight) //How can depression slow you down if you can just fly away from your problems?
switch(mood.sanity)
if(SANITY_INSANE to SANITY_CRAZY)
. += 1.5
if(SANITY_CRAZY to SANITY_UNSTABLE)
. += 1
if(SANITY_UNSTABLE to SANITY_DISTURBED)
. += 0.5
if(HAS_TRAIT(H, TRAIT_FAT))
. += (1.5 - flight)
if(H.bodytemperature < BODYTEMP_COLD_DAMAGE_LIMIT && !HAS_TRAIT(H, TRAIT_RESISTCOLD))
@@ -1784,7 +1756,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
switch(hit_area)
if(BODY_ZONE_HEAD)
if(!I.is_sharp() && armor_block < 50)
if(!I.get_sharpness() && armor_block < 50)
if(prob(I.force))
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20)
if(H.stat == CONSCIOUS)
@@ -1817,7 +1789,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
H.update_inv_glasses()
if(BODY_ZONE_CHEST)
if(H.stat == CONSCIOUS && !I.is_sharp() && armor_block < 50)
if(H.stat == CONSCIOUS && !I.get_sharpness() && armor_block < 50)
if(prob(I.force))
H.visible_message("<span class='danger'>[H] has been knocked down!</span>", \
"<span class='userdanger'>[H] has been knocked down!</span>")
@@ -1940,8 +1912,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
var/knocked_item = FALSE
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
target_held_item = null
if(!target.has_movespeed_modifier(SHOVE_SLOWDOWN_ID))
target.add_movespeed_modifier(SHOVE_SLOWDOWN_ID, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
if(target_held_item)
target.visible_message("<span class='danger'>[target.name]'s grip on \the [target_held_item] loosens!</span>",
"<span class='danger'>Your grip on \the [target_held_item] loosens!</span>", null, COMBAT_MESSAGE_RANGE)
@@ -2063,13 +2035,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
natural = H.natural_bodytemperature_stabilization()
var/thermal_protection = 1
if(loc_temp < H.bodytemperature) //Place is colder than we are
thermal_protection -= H.get_cold_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
thermal_protection -= H.get_thermal_protection(loc_temp, TRUE) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(H.bodytemperature < BODYTEMP_NORMAL) //we're cold, insulation helps us retain body heat and will reduce the heat we lose to the environment
H.adjust_bodytemperature((thermal_protection+1)*natural + max(thermal_protection * (loc_temp - H.bodytemperature) / BODYTEMP_COLD_DIVISOR, BODYTEMP_COOLING_MAX))
else //we're sweating, insulation hinders our ability to reduce heat - and it will reduce the amount of cooling you get from the environment
H.adjust_bodytemperature(natural*(1/(thermal_protection+1)) + max((thermal_protection * (loc_temp - H.bodytemperature) + BODYTEMP_NORMAL - H.bodytemperature) / BODYTEMP_COLD_DIVISOR , BODYTEMP_COOLING_MAX)) //Extra calculation for hardsuits to bleed off heat
else //Place is hotter than we are
thermal_protection -= H.get_heat_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
thermal_protection -= H.get_thermal_protection(loc_temp) //This returns a 0 - 1 value, which corresponds to the percentage of protection based on what you're wearing and what you're exposed to.
if(H.bodytemperature < BODYTEMP_NORMAL) //and we're cold, insulation enhances our ability to retain body heat but reduces the heat we get from the environment
H.adjust_bodytemperature((thermal_protection+1)*natural + min(thermal_protection * (loc_temp - H.bodytemperature) / BODYTEMP_HEAT_DIVISOR, BODYTEMP_HEATING_MAX))
else //we're sweating, insulation hinders out ability to reduce heat - but will reduce the amount of heat we get from the environment
@@ -2208,7 +2180,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
if(!(I.resistance_flags & FIRE_PROOF))
I.take_damage(H.fire_stacks, BURN, "fire", 0)
var/thermal_protection = H.get_thermal_protection()
var/thermal_protection = H.easy_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT && !no_protection)
return
@@ -6,6 +6,7 @@
inherent_traits = list(TRAIT_RESISTHEAT,TRAIT_NOBREATH,TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_NOFIRE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_LIMBATTACHMENT)
inherent_biotypes = list(MOB_ROBOTIC, MOB_HUMANOID)
meat = null
gib_types = /obj/effect/gibspawner/robot
damage_overlay_type = "synth"
mutanttongue = /obj/item/organ/tongue/robot
limbs_id = "synth"
@@ -29,7 +29,7 @@
if(fly)
fly.Remove(H)
if(H.movement_type & FLYING)
H.movement_type &= ~FLYING
H.setMovetype(H.movement_type & ~FLYING)
ToggleFlight(H,0)
if(H.dna && H.dna.species && (H.dna.features["wings"] == "Angel"))
if("wings" in H.dna.species.mutant_bodyparts)
@@ -132,14 +132,14 @@
if(flight && CanFly(H))
stunmod = 2
speedmod = -0.35
H.movement_type |= FLYING
H.setMovetype(H.movement_type | FLYING)
override_float = TRUE
H.pass_flags |= PASSTABLE
H.OpenWings()
else
stunmod = 1
speedmod = 0
H.movement_type &= ~FLYING
H.setMovetype(H.movement_type & ~FLYING)
override_float = FALSE
H.pass_flags &= ~PASSTABLE
H.CloseWings()
@@ -17,4 +17,5 @@
use_skintones = 0
species_traits = list(NOBLOOD,EYECOLOR,NOGENITALS)
inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NODISMEMBER,TRAIT_NOLIMBDISABLE,TRAIT_NOHUNGER)
sexes = 0
sexes = 0
gib_types = /obj/effect/gibspawner/robot
@@ -18,6 +18,8 @@
var/obj/item/dullahan_relay/myhead
/datum/species/dullahan/pumpkin
name = "Pumpkin Head Dullahan"
id = "pumpkindullahan"
pumpkin = TRUE
/datum/species/dullahan/check_roundstart_eligible()
@@ -27,7 +29,7 @@
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
. = ..()
H.flags_1 &= ~HEAR_1
DISABLE_BITFIELD(H.flags_1, HEAR_1)
var/obj/item/bodypart/head/head = H.get_bodypart(BODY_ZONE_HEAD)
if(head)
if(pumpkin)//Pumpkinhead!
@@ -36,16 +38,16 @@
head.icon_state = "hardhat1_pumpkin_j"
head.custom_head = TRUE
head.drop_limb()
head.flags_1 = HEAR_1
head.throwforce = 25
myhead = new /obj/item/dullahan_relay (head, H)
H.put_in_hands(head)
var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES)
for(var/datum/action/item_action/organ_action/OA in E.actions)
OA.Trigger()
if(!QDELETED(head)) //drop_limb() deletes the limb if it's no drop location and dummy humans used for rendering icons are located in nullspace. Do the math.
head.throwforce = 25
myhead = new /obj/item/dullahan_relay (head, H)
H.put_in_hands(head)
var/obj/item/organ/eyes/E = H.getorganslot(ORGAN_SLOT_EYES)
for(var/datum/action/item_action/organ_action/OA in E.actions)
OA.Trigger()
/datum/species/dullahan/on_species_loss(mob/living/carbon/human/H)
H.flags_1 |= ~HEAR_1
ENABLE_BITFIELD(H.flags_1, HEAR_1)
H.reset_perspective(H)
if(myhead)
var/obj/item/dullahan_relay/DR = myhead
@@ -84,7 +86,7 @@
/obj/item/organ/tongue/dullahan/handle_speech(datum/source, list/speech_args)
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.dna.species.id == "dullahan")
if(isdullahan(H))
var/datum/species/dullahan/D = H.dna.species
if(isobj(D.myhead.loc))
var/obj/O = D.myhead.loc
@@ -99,6 +101,7 @@
desc = "An abstraction."
actions_types = list(/datum/action/item_action/organ_action/dullahan)
zone = "abstract"
tint = INFINITY // used to switch the vision perspective to the head on species_gain().
/datum/action/item_action/organ_action/dullahan
name = "Toggle Perspective"
@@ -114,37 +117,53 @@
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(H.dna.species.id == "dullahan")
if(isdullahan(H))
var/datum/species/dullahan/D = H.dna.species
D.update_vision_perspective(H)
/obj/item/dullahan_relay
name = "dullahan relay"
var/mob/living/owner
flags_1 = HEAR_1
/obj/item/dullahan_relay/Initialize(mapload,new_owner)
/obj/item/dullahan_relay/Initialize(mapload, mob/living/carbon/human/new_owner)
. = ..()
if(!new_owner)
return INITIALIZE_HINT_QDEL
owner = new_owner
START_PROCESSING(SSobj, src)
RegisterSignal(owner, COMSIG_MOB_EXAMINATE, .proc/examinate_check)
RegisterSignal(src, COMSIG_ATOM_HEARER_IN_VIEW, .proc/include_owner)
RegisterSignal(owner, COMSIG_LIVING_REGENERATE_LIMBS, .proc/unlist_head)
RegisterSignal(owner, COMSIG_LIVING_FULLY_HEAL, .proc/retrieve_head)
/obj/item/dullahan_relay/proc/examinate_check(mob/source, atom/A)
if(source.client.eye == src && ((A in view(source.client.view, src)) || (isturf(A) && source.sight & SEE_TURFS) || (ismob(A) && source.sight & SEE_MOBS) || (isobj(A) && source.sight & SEE_OBJS)))
return COMPONENT_ALLOW_EXAMINE
/obj/item/dullahan_relay/proc/include_owner(datum/source, list/processing_list, list/hearers)
if(!QDELETED(owner))
hearers += owner
/obj/item/dullahan_relay/proc/unlist_head(datum/source, noheal = FALSE, list/excluded_limbs)
excluded_limbs |= BODY_ZONE_HEAD // So we don't gib when regenerating limbs.
/obj/item/dullahan_relay/proc/retrieve_head(datum/source, admin_revive = FALSE)
if(admin_revive) //retrieving the owner's head for ahealing purposes.
var/obj/item/bodypart/head/H = loc
var/turf/T = get_turf(owner)
if(H && istype(H) && T && !(H in owner.GetAllContents()))
H.forceMove(T)
/obj/item/dullahan_relay/process()
if(!istype(loc, /obj/item/bodypart/head) || QDELETED(owner))
. = PROCESS_KILL
qdel(src)
/obj/item/dullahan_relay/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
. = ..()
if(!QDELETED(owner))
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode)
to_chat(owner,message)
else
qdel(src)
/obj/item/dullahan_relay/Destroy()
if(!QDELETED(owner))
var/mob/living/carbon/human/H = owner
if(H.dna.species.id == "dullahan")
if(isdullahan(H))
var/datum/species/dullahan/D = H.dna.species
D.myhead = null
owner.gib()
@@ -64,6 +64,7 @@
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/reagent_containers/food/snacks/meat/slab/xeno
gib_types = list(/obj/effect/gibspawner/xeno/xenoperson, /obj/effect/gibspawner/xeno/xenoperson/bodypartless)
skinned_type = /obj/item/stack/sheet/animalhide/xeno
exotic_bloodtype = "X*"
damage_overlay_type = "xeno"
@@ -796,7 +796,7 @@
if(resistance_flags & ON_FIRE)
return
if(P.is_hot())
if(P.get_temperature())
visible_message("<span class='danger'>[src] bursts into flames!</span>")
fire_act()
@@ -11,6 +11,7 @@
mutant_bodyparts = list("ipc_screen", "ipc_antenna")
default_features = list("ipc_screen" = "Blank", "ipc_antenna" = "None")
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
mutanttongue = /obj/item/organ/tongue/robot/ipc
mutant_heart = /obj/item/organ/heart/ipc
exotic_bloodtype = "HF"
@@ -11,6 +11,7 @@
default_features = list("mcolor" = "FFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None") //CIT CHANGE
inherent_traits = list(TRAIT_TOXINLOVER)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
gib_types = list(/obj/effect/gibspawner/slime, /obj/effect/gibspawner/slime/bodypartless)
exotic_blood = "jellyblood"
exotic_bloodtype = "GEL"
damage_overlay_type = ""
@@ -472,37 +473,25 @@
H.hair_style = new_style
H.update_hair()
else if (select_alteration == "Genitals")
var/list/organs = list()
var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add sexual organ", "remove sexual organ", "cancel")
switch(operation)
if("add sexual organ")
var/new_organ = input("Select sexual organ:", "Organ Manipulation") in list("Penis", "Testicles", "Breasts", "Vagina", "Womb", "Cancel")
if(new_organ == "Penis")
H.give_penis()
else if(new_organ == "Testicles")
H.give_balls()
else if(new_organ == "Breasts")
H.give_breasts()
else if(new_organ == "Vagina")
H.give_vagina()
else if(new_organ == "Womb")
H.give_womb()
else
var/new_organ = input("Select sexual organ:", "Organ Manipulation") as null|anything in GLOB.genitals_list
if(!new_organ)
return
H.give_genital(GLOB.genitals_list[new_organ])
if("remove sexual organ")
var/list/organs = list()
for(var/obj/item/organ/genital/X in H.internal_organs)
var/obj/item/organ/I = X
organs["[I.name] ([I.type])"] = I
var/obj/item/organ = input("Select sexual organ:", "Organ Manipulation", null) in organs
organ = organs[organ]
if(!organ)
var/obj/item/O = input("Select sexual organ:", "Organ Manipulation", null) as null|anything in organs
var/obj/item/organ/genital/G = organs[O]
if(!G)
return
var/obj/item/organ/genital/O
if(isorgan(organ))
O = organ
O.Remove(H)
organ.forceMove(get_turf(H))
qdel(organ)
G.forceMove(get_turf(H))
qdel(G)
H.update_genitals()
else if (select_alteration == "Ears")
@@ -592,8 +581,8 @@
if(new_shape)
H.dna.features["cock_shape"] = new_shape
H.update_genitals()
H.give_balls()
H.give_penis()
H.give_genital(/obj/item/organ/genital/testicles)
H.give_genital(/obj/item/organ/genital/penis)
H.apply_overlay()
@@ -605,8 +594,8 @@
if(new_shape)
H.dna.features["vag_shape"] = new_shape
H.update_genitals()
H.give_womb()
H.give_vagina()
H.give_genital(/obj/item/organ/genital/womb)
H.give_genital(/obj/item/organ/genital/vagina)
H.apply_overlay()
else if (select_alteration == "Penis Length")
@@ -618,8 +607,8 @@
H.dna.features["cock_length"] = max(min( round(text2num(new_length)), COCK_SIZE_MAX),COCK_SIZE_MIN)
H.update_genitals()
H.apply_overlay()
H.give_balls()
H.give_penis()
H.give_genital(/obj/item/organ/genital/testicles)
H.give_genital(/obj/item/organ/genital/penis)
else if (select_alteration == "Breast Size")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
@@ -630,7 +619,7 @@
H.dna.features["breasts_size"] = new_size
H.update_genitals()
H.apply_overlay()
H.give_breasts()
H.give_genital(/obj/item/organ/genital/breasts)
else if (select_alteration == "Breast Shape")
for(var/obj/item/organ/genital/breasts/X in H.internal_organs)
@@ -641,7 +630,7 @@
H.dna.features["breasts_shape"] = new_shape
H.update_genitals()
H.apply_overlay()
H.give_breasts()
H.give_genital(/obj/item/organ/genital/breasts)
else
return
@@ -856,6 +845,8 @@
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)
return FALSE
linked_mobs.Add(M)
@@ -941,9 +932,14 @@
var/mob/living/M = input("Select who to send your message to:","Send thought to?",null) as null|mob in options
if(!M)
return
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(H, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
var/msg = sanitize(input("Message:", "Telepathy") as text|null)
if(msg)
if(M.anti_magic_check(FALSE, FALSE, TRUE, 0))
to_chat(H, "<span class='notice'>As you try to communicate with [M], you're suddenly stopped by a vision of a massive tinfoil wall that streches beyond visible range. It seems you've been foiled.</span>")
return
log_directed_talk(H, M, msg, LOG_SAY, "slime telepathy")
to_chat(M, "<span class='notice'>You hear an alien voice in your head... </span><font color=#008CA2>[msg]</font>")
to_chat(H, "<span class='notice'>You telepathically said: \"[msg]\" to [M]</span>")
@@ -18,6 +18,7 @@
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/lizard
gib_types = list(/obj/effect/gibspawner/lizard, /obj/effect/gibspawner/lizard/bodypartless)
skinned_type = /obj/item/stack/sheet/animalhide/lizard
exotic_bloodtype = "L"
disliked_food = GRAIN | DAIRY
@@ -78,7 +78,7 @@
icon_state = "brain-x-d"
var/obj/effect/proc_holder/spell/targeted/shadowwalk/shadowwalk
/obj/item/organ/brain/nightmare/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/brain/nightmare/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
if(M.dna.species.id != "nightmare")
M.set_species(/datum/species/shadow/nightmare)
@@ -118,7 +118,7 @@
user.temporarilyRemoveItemFromInventory(src, TRUE)
Insert(user)
/obj/item/organ/heart/nightmare/Insert(mob/living/carbon/M, special = 0)
/obj/item/organ/heart/nightmare/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
..()
if(special != HEART_SPECIAL_SHADOWIFY)
blade = new/obj/item/light_eater
@@ -9,6 +9,7 @@
dangerous_existence = 1
blacklisted = 1
meat = null
gib_types = /obj/effect/gibspawner/robot
damage_overlay_type = "synth"
limbs_id = "synth"
var/list/initial_species_traits = list(NOTRANSSTING) //for getting these values back for assume_disguise()
@@ -45,14 +45,14 @@
C.adjustOxyLoss(-4)
C.adjustCloneLoss(-4)
return
C.blood_volume -= 0.75
C.blood_volume -= 0.75 //Will take roughly 19.5 minutes to die from standard blood volume, roughly 83 minutes to die from max blood volume.
if(C.blood_volume <= (BLOOD_VOLUME_SURVIVE*C.blood_ratio))
to_chat(C, "<span class='danger'>You ran out of blood!</span>")
C.dust()
var/area/A = get_area(C)
if(istype(A, /area/chapel))
to_chat(C, "<span class='danger'>You don't belong here!</span>")
C.adjustFireLoss(20)
C.adjustFireLoss(5)
C.adjust_fire_stacks(6)
C.IgniteMob()
@@ -88,7 +88,7 @@
to_chat(H, "<span class='notice'>[victim] doesn't have blood!</span>")
return
V.drain_cooldown = world.time + 30
if(victim.anti_magic_check(FALSE, TRUE))
if(victim.anti_magic_check(FALSE, TRUE, FALSE, 0))
to_chat(victim, "<span class='warning'>[H] tries to bite you, but stops before touching you!</span>")
to_chat(H, "<span class='warning'>[victim] is blessed! You stop just in time to avoid catching fire.</span>")
return
@@ -141,7 +141,7 @@
H = new(shape,src,caster)
if(istype(H, /mob/living/simple_animal))
var/mob/living/simple_animal/SA = H
if(ventcrawl_nude_only && length(caster.get_equipped_items(include_pockets = TRUE)))
if((caster.blood_volume >= (BLOOD_VOLUME_BAD*caster.blood_ratio)) || (ventcrawl_nude_only && length(caster.get_equipped_items(include_pockets = TRUE))))
SA.ventcrawler = FALSE
if(transfer_name)
H.name = caster.name
@@ -66,7 +66,7 @@
playsound(C, pick(spooks), 50, TRUE, 10)
//Congrats you somehow died so hard you stopped being a zombie
/datum/species/zombie/infectious/spec_death(mob/living/carbon/C)
/datum/species/zombie/infectious/spec_death(gibbed, mob/living/carbon/C)
. = ..()
var/obj/item/organ/zombie_infection/infection
infection = C.getorganslot(ORGAN_SLOT_ZOMBIE)
@@ -400,17 +400,17 @@ There are several things that need to be remembered:
if(wear_suit)
var/obj/item/clothing/suit/S = wear_suit
var/no_taur_thanks = FALSE
var/item_level_support = FALSE // LISTEN! If you must degrade the code with further snowflake checks, at least keep it compatible with worn non-clothing items!
if(!istype(S))
no_taur_thanks = TRUE
item_level_support = TRUE
wear_suit.screen_loc = ui_oclothing
if(client && hud_used && hud_used.hud_shown)
if(hud_used.inventory_shown)
client.screen += wear_suit
update_observer_view(wear_suit,1)
if(!S.force_alternate_icon)
if(!no_taur_thanks && S.mutantrace_variation) //Just make sure we've got this checked too
if(!item_level_support && !S.force_alternate_icon)
if(S.mutantrace_variation) //Just make sure we've got this checked too
if(S.taurmode == NOT_TAURIC && S.adjusted == ALT_STYLE) //are we not a taur, but we have Digitigrade legs? Run this check first, then.
S.alternate_worn_icon = 'modular_citadel/icons/mob/suit_digi.dmi'
else
@@ -431,7 +431,7 @@ There are several things that need to be remembered:
if(OFFSET_SUIT in dna.species.offset_features)
suit_overlay.pixel_x += dna.species.offset_features[OFFSET_SUIT][1]
suit_overlay.pixel_y += dna.species.offset_features[OFFSET_SUIT][2]
if(!no_taur_thanks && S.center)
if(!item_level_support && S.center)
suit_overlay = center_image(suit_overlay, S.dimension_x, S.dimension_y)
overlays_standing[SUIT_LAYER] = suit_overlay
update_hair()
+1 -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.organ_flags & ORGAN_FAILING)
if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || !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)
@@ -23,7 +23,7 @@
if(changed)
animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
/mob/living/carbon
+6 -2
View File
@@ -23,8 +23,12 @@
/mob/living/proc/gib_animation()
return
/mob/living/proc/spawn_gibs()
new /obj/effect/gibspawner/generic(drop_location(), null, get_static_viruses())
/mob/living/proc/spawn_gibs(with_bodyparts, atom/loc_override)
var/location = loc_override ? loc_override.drop_location() : drop_location()
if(MOB_ROBOTIC in mob_biotypes)
new /obj/effect/gibspawner/robot(location, src, get_static_viruses())
else
new /obj/effect/gibspawner/generic(location, src, get_static_viruses())
/mob/living/proc/spill_organs()
return
+1 -1
View File
@@ -4,7 +4,7 @@
if(digitalinvis)
handle_diginvis() //AI becomes unable to see mob
if((movement_type & FLYING) && !floating) //TODO: Better floating
if((movement_type & FLYING) && !(movement_type & FLOATING)) //TODO: Better floating
float(on = TRUE)
if (client)
+19 -6
View File
@@ -40,11 +40,23 @@
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)
return ..()
/mob/living/proc/ZImpactDamage(turf/T, levels)
visible_message("<span class='danger'>[src] crashes into [T] with a sickening noise!</span>")
adjustBruteLoss((levels * 5) ** 1.5)
Knockdown(levels * 50)
/mob/living/proc/OpenCraftingMenu()
return
@@ -519,6 +531,7 @@
for(var/organ in C.internal_organs)
var/obj/item/organ/O = organ
O.setOrganDamage(0)
SEND_SIGNAL(src, COMSIG_LIVING_FULLY_HEAL, admin_revive)
//proc called by revive(), to check if we can actually ressuscitate the mob (we don't want to revive him and have him instantly die again)
@@ -721,14 +734,14 @@
var/fixed = 0
if(anchored || (buckled && buckled.anchored))
fixed = 1
if(on && !floating && !fixed)
if(on && !(movement_type & FLOATING) && !fixed)
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
sleep(10)
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
floating = TRUE
else if(((!on || fixed) && floating))
setMovetype(movement_type | FLOATING)
else if(((!on || fixed) && (movement_type & FLOATING)))
animate(src, pixel_y = get_standard_pixel_y_offset(lying), time = 10)
floating = FALSE
setMovetype(movement_type & ~FLOATING)
// The src mob is trying to strip an item from someone
// Override if a certain type of mob should be behave differently when stripping items (can't, for example)
@@ -800,7 +813,7 @@
var/final_pixel_y = get_standard_pixel_y_offset(lying)
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff , time = 2, loop = 6)
animate(pixel_x = final_pixel_x , pixel_y = final_pixel_y , time = 2)
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life().
setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure to restart it in next life().
/mob/living/proc/get_temperature(datum/gas_mixture/environment)
var/loc_temp = environment ? environment.temperature : T0C
@@ -940,7 +953,7 @@
apply_effect((amount*RAD_MOB_COEFFICIENT)/max(1, (radiation**2)*RAD_OVERDOSE_REDUCTION), EFFECT_IRRADIATE, blocked)
/mob/living/anti_magic_check(magic = TRUE, holy = FALSE)
/mob/living/anti_magic_check(magic = TRUE, holy = FALSE, chargecost = 1, self = FALSE)
. = ..()
if(.)
return
+1 -1
View File
@@ -422,4 +422,4 @@
if(!used_item)
used_item = get_active_held_item()
..()
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
setMovetype(movement_type & ~FLOATING) // If we were without gravity, the bouncing animation got stopped, so we make sure we restart the bouncing after the next movement.
+4 -1
View File
@@ -32,4 +32,7 @@
if(drag_slowdown && L.lying && !L.buckled && grab_state < GRAB_AGGRESSIVE)
add_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING, multiplicative_slowdown = PULL_PRONE_SLOWDOWN)
return
remove_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING)
remove_movespeed_modifier(MOVESPEED_ID_PRONE_DRAGGING)
/mob/living/canZMove(dir, turf/target)
return can_zTravel(target, dir) && (movement_type & FLYING)
+2 -1
View File
@@ -783,7 +783,7 @@
/mob/living/silicon/ai/can_buckle()
return 0
/mob/living/silicon/ai/incapacitated()
/mob/living/silicon/ai/incapacitated(ignore_restraints, ignore_grab)
if(aiRestorePowerRoutine)
return TRUE
return ..()
@@ -882,6 +882,7 @@
/mob/living/silicon/ai/revive(full_heal = 0, admin_revive = 0)
. = ..()
if(.) //successfully ressuscitated from death
set_eyeobj_visible(TRUE)
set_core_display_icon(display_icon_override)
/mob/living/silicon/ai/proc/malfhacked(obj/machinery/power/apc/apc)
@@ -18,6 +18,7 @@
update_canmove()
if(eyeobj)
eyeobj.setLoc(get_turf(src))
set_eyeobj_visible(FALSE)
GLOB.shuttle_caller_list -= src
SSshuttle.autoEvac()
@@ -36,6 +37,8 @@
if(istype(loc, /obj/item/aicard/aitater))
loc.icon_state = "aitater-404"
else if(istype(loc, /obj/item/aicard/aispook))
loc.icon_state = "aispook-404"
else if(istype(loc, /obj/item/aicard))
loc.icon_state = "aicard-404"
@@ -6,6 +6,8 @@
/mob/camera/aiEye
name = "Inactive AI Eye"
icon_state = "ai_camera"
icon = 'icons/mob/cameramob.dmi'
invisibility = INVISIBILITY_MAXIMUM
hud_possible = list(ANTAG_HUD, AI_DETECT_HUD = HUD_LIST_LIST)
var/list/visibleCameraChunks = list()
@@ -158,11 +160,11 @@
cameraFollow = null
unset_machine()
if(!eyeobj || !eyeobj.loc || QDELETED(eyeobj))
if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc))
to_chat(src, "ERROR: Eyeobj not found. Creating new eye...")
create_eye()
eyeobj.setLoc(loc)
eyeobj?.setLoc(loc)
/mob/living/silicon/ai/proc/create_eye()
if(eyeobj)
@@ -172,6 +174,13 @@
eyeobj.ai = src
eyeobj.setLoc(loc)
eyeobj.name = "[name] (AI Eye)"
set_eyeobj_visible(TRUE)
/mob/living/silicon/ai/proc/set_eyeobj_visible(state = TRUE)
if(!eyeobj)
return
eyeobj.mouse_opacity = state ? MOUSE_OPACITY_ICON : initial(eyeobj.mouse_opacity)
eyeobj.invisibility = state ? INVISIBILITY_OBSERVER : initial(eyeobj.invisibility)
/mob/living/silicon/ai/verb/toggle_acceleration()
set category = "AI Commands"
+1 -1
View File
@@ -19,7 +19,7 @@
// messenging the client
malfhacked(malfhack)
if(!eyeobj || QDELETED(eyeobj) || !eyeobj.loc)
if(isturf(loc) && (QDELETED(eyeobj) || !eyeobj.loc))
view_core()
if(machine)
@@ -6,6 +6,7 @@
O.mode = 1
O.emotion = "Neutral"
O.update()
set_eyeobj_visible(TRUE)
if(multicam_on)
end_multicam()
view_core()
@@ -4,4 +4,5 @@
var/obj/machinery/status_display/ai/O = each
O.mode = 0
O.update()
set_eyeobj_visible(FALSE)
view_core()
@@ -120,6 +120,9 @@ GLOBAL_DATUM(ai_camera_room_landmark, /obj/effect/landmark/ai_multicam_room)
/mob/camera/aiEye/pic_in_pic
name = "Secondary AI Eye"
invisibility = INVISIBILITY_OBSERVER
mouse_opacity = MOUSE_OPACITY_ICON
icon_state = "ai_pip_camera"
var/obj/screen/movable/pic_in_pic/ai/screen
var/list/cameras_telegraphed = list()
var/telegraph_cameras = TRUE
+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", message_language = language)
send_speech(message, 7, T, "robot", 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.")
+2 -2
View File
@@ -1,5 +1,5 @@
/mob/living/silicon/spawn_gibs()
new /obj/effect/gibspawner/robot(drop_location())
/mob/living/silicon/spawn_gibs(with_bodyparts, atom/loc_override)
new /obj/effect/gibspawner/robot(loc_override ? loc_override.drop_location() : drop_location(), src)
/mob/living/silicon/spawn_dust()
new /obj/effect/decal/remains/robot(loc)
@@ -140,7 +140,7 @@
radio.attack_self(src)
if("image")
var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", "Face", "Laugh", "Off", "Sad", "Angry", "What" , "Exclamation" ,"Question") // CITADEL EDIT
var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", "Face", "Laugh", "Off", "Sad", "Angry", "What" , "Exclamation" ,"Question", "Sunglasses")
var/pID = 1
switch(newImage)
@@ -164,10 +164,12 @@
pID = 9
if("Null")
pID = 10
if("Exclamation") // CITADEL EDIT
if("Exclamation")
pID = 11
if("Question") // CITADEL EDIT
if("Question")
pID = 12
if("Sunglasses")
pID = 13
card.setEmotion(pID)
if("signaller")
@@ -8,6 +8,8 @@
righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi'
flags_1 = CONDUCT_1
var/borghealth = 100
var/list/basic_modules = list() //a list of paths, converted to a list of instances on New()
var/list/emag_modules = list() //ditto
var/list/ratvar_modules = list() //ditto ditto
@@ -195,6 +197,8 @@
R.update_module_innate()
RM.rebuild_modules()
INVOKE_ASYNC(RM, .proc/do_transform_animation)
R.maxHealth = borghealth
R.health = min(borghealth, R.health)
qdel(src)
return RM
@@ -311,6 +315,10 @@
/obj/item/multitool/cyborg,
/obj/item/t_scanner,
/obj/item/analyzer,
/obj/item/storage/part_replacer/cyborg,
/obj/item/holosign_creator/atmos,
/obj/item/weapon/gripper,
/obj/item/lightreplacer/cyborg,
/obj/item/geiger_counter/cyborg,
/obj/item/assembly/signaler/cyborg,
/obj/item/areaeditor/blueprints/cyborg,
@@ -352,6 +360,14 @@
to_chat(loc, "<span class='userdanger'>While you have picked the security 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/security/Initialize()
. = ..()
if(!CONFIG_GET(flag/weaken_secborg))
for(var/obj/item/gun/energy/disabler/cyborg/pewpew in basic_modules)
basic_modules -= pewpew
basic_modules += new /obj/item/gun/energy/e_gun/advtaser/cyborg(src)
qdel(pewpew)
/obj/item/robot_module/peacekeeper
name = "Peacekeeper"
basic_modules = list(
@@ -362,6 +378,7 @@
/obj/item/holosign_creator/cyborg,
/obj/item/borg/cyborghug/peacekeeper,
/obj/item/extinguisher,
/obj/item/megaphone,
/obj/item/borg/projectile_dampen)
emag_modules = list(/obj/item/reagent_containers/borghypo/peace/hacked)
ratvar_modules = list(
@@ -101,7 +101,7 @@
if(ASSEMBLY_FOURTH_STEP)
if(istype(W, /obj/item/weldingtool))
if(W.use_tool(src, user, 0, volume=40))
if(W.use_tool(src, user, 0, volume=40) && build_step == 4)
name = "shielded frame assembly"
to_chat(user, "<span class='notice'>You weld the vest to [src].</span>")
build_step++
@@ -183,7 +183,7 @@
if(8)
if(istype(W, /obj/item/screwdriver))
to_chat(user, "<span class='notice'>You start attaching the gun to the frame...</span>")
if(W.use_tool(src, user, 40, volume=100))
if(W.use_tool(src, user, 40, volume=100) && build_step == 8)
name = "armed [name]"
to_chat(user, "<span class='notice'>Taser gun attached.</span>")
build_step++
@@ -383,7 +383,7 @@
if((!C.reagents.has_reagent(treatment_fire_avoid)) && (C.getFireLoss() >= heal_threshold) && (!C.reagents.has_reagent(treatment_fire)))
return TRUE
var/treatment_toxavoid = get_avoidchem_toxin(C)
if(((treatment_toxavoid && !C.reagents.has_reagent(treatment_toxavoid))) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(get_healchem_toxin(C))))
if(((isnull(treatment_toxavoid) || !C.reagents.has_reagent(treatment_toxavoid))) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(get_healchem_toxin(C))))
return TRUE
if(treat_virus && !C.reagents.has_reagent(treatment_virus_avoid) && !C.reagents.has_reagent(treatment_virus))
@@ -472,7 +472,7 @@
if(!reagent_id && (C.getToxLoss() >= heal_threshold))
var/toxin_heal_avoid = get_avoidchem_toxin(C)
var/toxin_healchem = get_healchem_toxin(C)
if(!C.reagents.has_reagent(toxin_healchem) && (toxin_heal_avoid && !C.reagents.has_reagent(toxin_heal_avoid)))
if(!C.reagents.has_reagent(toxin_healchem) && (isnull(toxin_heal_avoid) || !C.reagents.has_reagent(toxin_heal_avoid)))
reagent_id = toxin_healchem
//If the patient is injured but doesn't have our special reagent in them then we should give it to them first
@@ -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)
/mob/living/simple_animal/bot/mulebot/bot_control(command, mob/user, pda = 0, turf/user_turf, list/user_access = list())
if(pda && wires.is_cut(WIRE_RX)) // MULE wireless is controlled by wires.
return
@@ -159,16 +159,16 @@ Auto Patrol: []"},
mode = BOT_HUNT
/mob/living/simple_animal/bot/secbot/proc/judgement_criteria()
var/final = FALSE
if(idcheck)
final = final|JUDGE_IDCHECK
if(check_records)
final = final|JUDGE_RECORDCHECK
if(weaponscheck)
final = final|JUDGE_WEAPONCHECK
if(emagged == 2)
final = final|JUDGE_EMAGGED
return final
var/final = FALSE
if(idcheck)
final = final|JUDGE_IDCHECK
if(check_records)
final = final|JUDGE_RECORDCHECK
if(weaponscheck)
final = final|JUDGE_WEAPONCHECK
if(emagged == 2)
final = final|JUDGE_EMAGGED
return final
/mob/living/simple_animal/bot/secbot/proc/special_retaliate_after_attack(mob/user) //allows special actions to take place after being attacked.
return
@@ -21,7 +21,7 @@
. = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("A drone shell has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_DRONE)
notify_ghosts("A drone shell has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_key = POLL_IGNORE_DRONE, ignore_dnr_observers = TRUE)
GLOB.poi_list |= src
if(isnull(possible_seasonal_hats))
build_seasonal_hats()
@@ -40,7 +40,7 @@
. = ..()
//ATTACK GHOST IGNORING PARENT RETURN VALUE
/obj/item/drone_shell/attack_ghost(mob/user)
/obj/item/drone_shell/attack_ghost(mob/dead/observer/user)
if(jobban_isbanned(user,"drone") || QDELETED(src) || QDELETED(user))
return
if(CONFIG_GET(flag/use_age_restriction_for_jobs))
@@ -49,6 +49,8 @@
if(user.client.player_age < DRONE_MINIMUM_AGE)
to_chat(user, "<span class='danger'>You're too new to play as a drone! Please try again in [DRONE_MINIMUM_AGE - user.client.player_age] days.</span>")
return
if(!user.can_reenter_round())
return FALSE
if(!SSticker.mode)
to_chat(user, "Can't become a drone before the game has started.")
return
@@ -323,6 +323,132 @@
else
STOP_PROCESSING(SSobj, src)
// Space kiwis, ergo quite a copypasta of chickens.
/mob/living/simple_animal/kiwi
name = "space kiwi"
desc = "Exposure to low gravity made them grow larger."
gender = FEMALE
icon_state = "kiwi"
icon_living = "kiwi"
icon_dead = "kiwi_dead"
speak = list("Chirp!","Cheep cheep chirp!!","Cheep.")
speak_emote = list("chirps","trills")
emote_hear = list("chirps.")
emote_see = list("pecks at the ground.","jumps in place.")
density = FALSE
speak_chance = 2
turns_per_move = 3
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
var/egg_type = /obj/item/reagent_containers/food/snacks/egg/kiwiEgg
var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
attacktext = "kicks"
health = 25
maxHealth = 25
ventcrawler = VENTCRAWLER_ALWAYS
var/eggsleft = 0
var/eggsFertile = TRUE
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
var/list/feedMessages = list("It chirps happily.","It chirps happily.")
var/list/layMessage = list("lays an egg.","squats down and croons.","begins making a huge racket.","begins chirping raucously.")
gold_core_spawnable = FRIENDLY_SPAWN
var/static/kiwi_count = 0
/mob/living/simple_animal/kiwi/Destroy()
--kiwi_count
return ..()
/mob/living/simple_animal/kiwi/Initialize()
. = ..()
++kiwi_count
/mob/living/simple_animal/kiwi/Life()
. =..()
if(!.)
return
if((!stat && prob(3) && eggsleft > 0) && egg_type)
visible_message("[src] [pick(layMessage)]")
eggsleft--
var/obj/item/E = new egg_type(get_turf(src))
E.pixel_x = rand(-6,6)
E.pixel_y = rand(-6,6)
if(eggsFertile)
if(kiwi_count < MAX_CHICKENS && prob(25))
START_PROCESSING(SSobj, E)
/obj/item/reagent_containers/food/snacks/egg/kiwiEgg/process()
if(isturf(loc))
amount_grown += rand(1,2)
if(amount_grown >= 100)
visible_message("[src] hatches with a quiet cracking sound.")
new /mob/living/simple_animal/babyKiwi(get_turf(src))
STOP_PROCESSING(SSobj, src)
qdel(src)
else
STOP_PROCESSING(SSobj, src)
/mob/living/simple_animal/kiwi/attackby(obj/item/O, mob/user, params)
if(istype(O, food_type)) //feedin' dem kiwis
if(!stat && eggsleft < 8)
var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
user.visible_message(feedmsg)
qdel(O)
eggsleft += rand(1, 4)
else
to_chat(user, "<span class='warning'>[name] doesn't seem hungry!</span>")
else
..()
/mob/living/simple_animal/babyKiwi
name = "baby space kiwi"
desc = "So huggable."
icon_state = "babykiwi"
icon_living = "babykiwi"
icon_dead = "babykiwi_dead"
gender = FEMALE
speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
speak_emote = list("chirps")
emote_hear = list("chirps.")
emote_see = list("pecks at the ground.","Happily bounces in place.")
density = FALSE
speak_chance = 2
turns_per_move = 2
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "kicks"
attacktext = "kicks"
health = 10
maxHealth = 10
ventcrawler = VENTCRAWLER_ALWAYS
var/amount_grown = 0
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
gold_core_spawnable = FRIENDLY_SPAWN
/mob/living/simple_animal/babyKiwi/Initialize()
. = ..()
pixel_x = rand(-6, 6)
pixel_y = rand(0, 10)
/mob/living/simple_animal/babyKiwi/Life()
. =..()
if(!.)
return
if(!stat && !ckey)
amount_grown += rand(1,2)
if(amount_grown >= 100)
new /mob/living/simple_animal/kiwi(src.loc)
qdel(src)
/obj/item/reagent_containers/food/snacks/egg/kiwiEgg
name = "kiwi egg"
desc = "A slightly bigger egg!"
icon_state = "kiwiegg"
/obj/item/udder
name = "udder"
@@ -1,39 +1,39 @@
/mob/living/simple_animal/hostile/retaliate/poison
var/poison_per_bite = 0
var/poison_type = "toxin"
var/poison_per_bite = 0
var/poison_type = "toxin"
/mob/living/simple_animal/hostile/retaliate/poison/AttackingTarget()
. = ..()
if(. && isliving(target))
var/mob/living/L = target
if(L.reagents && !poison_per_bite == 0)
L.reagents.add_reagent(poison_type, poison_per_bite)
return .
. = ..()
if(. && isliving(target))
var/mob/living/L = target
if(L.reagents && !poison_per_bite == 0)
L.reagents.add_reagent(poison_type, poison_per_bite)
return
/mob/living/simple_animal/hostile/retaliate/poison/snake
name = "snake"
desc = "A slithery snake. These legless reptiles are the bane of mice and adventurers alike."
icon_state = "snake"
icon_living = "snake"
icon_dead = "snake_dead"
speak_emote = list("hisses")
health = 20
maxHealth = 20
attacktext = "bites"
melee_damage_lower = 5
melee_damage_upper = 6
response_help = "pets"
response_disarm = "shoos"
response_harm = "steps on"
faction = list("hostile")
ventcrawler = VENTCRAWLER_ALWAYS
density = FALSE
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST, MOB_REPTILE)
gold_core_spawnable = FRIENDLY_SPAWN
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
name = "snake"
desc = "A slithery snake. These legless reptiles are the bane of mice and adventurers alike."
icon_state = "snake"
icon_living = "snake"
icon_dead = "snake_dead"
speak_emote = list("hisses")
health = 20
maxHealth = 20
attacktext = "bites"
melee_damage_lower = 5
melee_damage_upper = 6
response_help = "pets"
response_disarm = "shoos"
response_harm = "steps on"
faction = list("hostile")
ventcrawler = VENTCRAWLER_ALWAYS
density = FALSE
pass_flags = PASSTABLE | PASSMOB
mob_size = MOB_SIZE_SMALL
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST, MOB_REPTILE)
gold_core_spawnable = FRIENDLY_SPAWN
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
/mob/living/simple_animal/hostile/retaliate/poison/snake/ListTargets(atom/the_target)
@@ -54,9 +54,9 @@
return mice
/mob/living/simple_animal/hostile/retaliate/poison/snake/AttackingTarget()
if(istype(target, /mob/living/simple_animal/mouse))
visible_message("<span class='notice'>[name] consumes [target] in a single gulp!</span>", "<span class='notice'>You consume [target] in a single gulp!</span>")
QDEL_NULL(target)
adjustBruteLoss(-2)
else
return ..()
if(istype(target, /mob/living/simple_animal/mouse))
visible_message("<span class='notice'>[name] consumes [target] in a single gulp!</span>", "<span class='notice'>You consume [target] in a single gulp!</span>")
QDEL_NULL(target)
adjustBruteLoss(-2)
else
return ..()
@@ -0,0 +1,107 @@
/mob/living/simple_animal/banana_spider
name = "banana spider"
desc = "What the fuck is this abomination?"
icon_state = "bananaspider"
icon_dead = "bananaspider_peel"
health = 1
maxHealth = 1
turns_per_move = 5 //this isn't player speed =|
speed = 2 //this is player speed
loot = list(/obj/item/reagent_containers/food/snacks/deadbanana_spider)
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)
minbodytemp = 270
maxbodytemp = INFINITY
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
mob_size = MOB_SIZE_TINY
response_help = "pokes"
response_disarm = "shoos"
response_harm = "splats"
speak_emote = list("chitters")
mouse_opacity = 2
density = TRUE
ventcrawler = VENTCRAWLER_ALWAYS
gold_core_spawnable = FRIENDLY_SPAWN
verb_say = "chitters"
verb_ask = "chitters inquisitively"
verb_exclaim = "chitters loudly"
verb_yell = "chitters loudly"
var/squish_chance = 50
var/projectile_density = TRUE //griffons get shot
del_on_death = TRUE
/mob/living/simple_animal/banana_spider/Initialize()
. = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("A banana spider has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
/mob/living/simple_animal/banana_spider/attack_ghost(mob/user)
if(key) //please stop using src. without a good reason.
return
if(CONFIG_GET(flag/use_age_restriction_for_jobs))
if(!isnum(user.client.player_age))
return
if(isobserver(user))
var/mob/dead/observer/O = user
if(!O.can_reenter_round())
return
if(!SSticker.mode)
to_chat(user, "Can't become a banana spider before the game has started.")
return
var/be_spider = alert("Become a banana spider? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_spider == "No" || QDELETED(src) || !isobserver(user))
return
if(key)
to_chat(user, "<span class='notice'>Someone else already took this banana spider.</span>")
return
sentience_act()
user.transfer_ckey(src, FALSE)
density = TRUE
/mob/living/simple_animal/banana_spider/ComponentInitialize()
. = ..()
AddComponent(/datum/component/slippery, 40)
/mob/living/simple_animal/banana_spider/Crossed(atom/movable/AM) //no /var in proc headers
. = ..()
if(istype(AM, /obj/item/projectile) && projectile_density) //forced projectile density
var/obj/item/projectile/P = AM
P.Bump(src)
if(ismob(AM))
if(isliving(AM))
var/mob/living/A = AM
if(A.mob_size > MOB_SIZE_SMALL && !(A.movement_type & FLYING))
if(prob(squish_chance))
A.visible_message("<span class='notice'>[A] squashed [src].</span>", "<span class='notice'>You squashed [src] under your weight as you fell.</span>")
adjustBruteLoss(1)
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
else
if(isstructure(AM))
if(prob(squish_chance))
AM.visible_message("<span class='notice'>[src] was crushed under [AM]'s weight as they fell.</span>")
adjustBruteLoss(1)
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
/mob/living/simple_animal/banana_spider/ex_act()
return
/mob/living/simple_animal/banana_spider/start_pulling()
return FALSE //No.
/obj/item/reagent_containers/food/snacks/deadbanana_spider
name = "dead banana spider"
desc = "Thank god it's gone...but it does look slippery."
icon_state = "bananaspider"
bitesize = 3
eatverb = "devours"
list_reagents = list("nutriment" = 3, "vitamin" = 2)
foodtype = GROSS | MEAT | RAW
grind_results = list("blood" = 20, "liquidgibs" = 5)
juice_results = list("banana" = 0)
/obj/item/reagent_containers/food/snacks/deadbanana_spider/Initialize()
. = ..()
AddComponent(/datum/component/slippery, 20)
@@ -83,15 +83,19 @@
/mob/living/simple_animal/hostile/poison/giant_spider/proc/humanize_spider(mob/user)
if(key || !playable_spider || stat)//Someone is in it, it's dead, or the fun police are shutting it down
return 0
return FALSE
if(isobserver(user))
var/mob/dead/observer/O = user
if(!O.can_reenter_round())
return FALSE
var/spider_ask = alert("Become a spider?", "Are you australian?", "Yes", "No")
if(spider_ask == "No" || !src || QDELETED(src))
return 1
return TRUE
if(key)
to_chat(user, "<span class='notice'>Someone else already took this spider.</span>")
return 1
return TRUE
user.transfer_ckey(src, FALSE)
return 1
return TRUE
//nursemaids - these create webs and eggs
/mob/living/simple_animal/hostile/poison/giant_spider/nurse
@@ -175,14 +179,17 @@
status_flags = NONE
mob_size = MOB_SIZE_LARGE
gold_core_spawnable = NO_SPAWN
var/slowed_by_webs = FALSE
/mob/living/simple_animal/hostile/poison/giant_spider/tarantula/movement_delay()
var/turf/T = get_turf(src)
if(locate(/obj/structure/spider/stickyweb) in T)
speed = 2
else
speed = 7
/mob/living/simple_animal/hostile/poison/giant_spider/tarantula/Moved(atom/oldloc, dir)
. = ..()
if(slowed_by_webs)
if(!(locate(/obj/structure/spider/stickyweb) in loc))
remove_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB)
slowed_by_webs = FALSE
else if(locate(/obj/structure/spider/stickyweb) in loc)
add_movespeed_modifier(MOVESPEED_ID_TARANTULA_WEB, priority=100, multiplicative_slowdown=3)
slowed_by_webs = TRUE
//midwives are the queen of the spiders, can send messages to all them and web faster. That rare round where you get a queen spider and turn your 'for honor' players into 'r6siege' players will be a fun one.
/mob/living/simple_animal/hostile/poison/giant_spider/nurse/midwife
@@ -2,7 +2,7 @@
#define GORILLA_TOTAL_LAYERS 1
/mob/living/simple_animal/hostile/gorilla
name = "Gorilla"
name = "gorilla"
desc = "A ground-dwelling, predominantly herbivorous ape that inhabits the forests of central Africa."
icon = 'icons/mob/gorilla.dmi'
icon_state = "crawling"
@@ -108,3 +108,10 @@
playsound(src, 'sound/creatures/gorilla.ogg', 200)
oogas = 0
/mob/living/simple_animal/hostile/gorilla/familiar
name = "familiar gorilla"
desc = "There is no need to be upset."
unique_name = FALSE
AIStatus = AI_OFF
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)
minbodytemp = 0
@@ -344,6 +344,7 @@
/mob/living/simple_animal/hostile/proc/AttackingTarget()
SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target)
in_melee = TRUE
if(vore_active)
if(isliving(target))
@@ -426,12 +427,13 @@
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())
casing.fire_casing(targeted_atom, src, null, null, null, ran_zone(), src)
else if(projectiletype)
var/obj/item/projectile/P = new projectiletype(startloc)
playsound(src, projectilesound, 100, 1)
P.starting = startloc
P.firer = src
P.fired_from = src
P.yo = targeted_atom.y - startloc.y
P.xo = targeted_atom.x - startloc.x
if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space
@@ -388,7 +388,7 @@ Difficulty: Very Hard
ActivationReaction(user, ACTIVATE_TOUCH)
/obj/machinery/anomalous_crystal/attackby(obj/item/I, mob/user, params)
if(I.is_hot())
if(I.get_temperature())
ActivationReaction(user, ACTIVATE_HEAT)
else
ActivationReaction(user, ACTIVATE_WEAPON)
@@ -575,13 +575,15 @@ Difficulty: Very Hard
if(..() && !ready_to_deploy)
GLOB.poi_list |= src
ready_to_deploy = TRUE
notify_ghosts("An anomalous crystal has been activated in [get_area(src)]! This crystal can always be used by ghosts hereafter.", enter_link = "<a href=?src=[REF(src)];ghostjoin=1>(Click to enter)</a>", ghost_sound = 'sound/effects/ghost2.ogg', source = src, action = NOTIFY_ATTACK)
notify_ghosts("An anomalous crystal has been activated in [get_area(src)]! This crystal can always be used by ghosts hereafter.", enter_link = "<a href=?src=[REF(src)];ghostjoin=1>(Click to enter)</a>", ghost_sound = 'sound/effects/ghost2.ogg', source = src, action = NOTIFY_ATTACK, ignore_dnr_observers = TRUE)
/obj/machinery/anomalous_crystal/helpers/attack_ghost(mob/dead/observer/user)
. = ..()
if(.)
return
if(ready_to_deploy)
if(!user.can_reenter_round())
return FALSE
var/be_helper = alert("Become a Lightgeist? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_helper == "Yes" && !QDELETED(src) && isobserver(user))
var/mob/living/simple_animal/hostile/lightgeist/W = new /mob/living/simple_animal/hostile/lightgeist(get_turf(loc))
@@ -649,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, send_the_signal = TRUE)
/mob/living/simple_animal/hostile/lightgeist/ghostize(can_reenter_corpse = TRUE, special = FALSE)
. = ..()
if(.)
death()
@@ -728,7 +730,7 @@ Difficulty: Very Hard
holder_animal.mind.AddSpell(P)
holder_animal.verbs -= /mob/living/verb/pulled
/obj/structure/closet/stasis/dump_contents(var/kill = 1)
/obj/structure/closet/stasis/dump_contents(override = TRUE, kill = 1)
STOP_PROCESSING(SSobj, src)
for(var/mob/living/L in src)
REMOVE_TRAIT(L, TRAIT_MUTE, STASIS_MUTE)
@@ -774,7 +776,7 @@ Difficulty: Very Hard
for(var/i in user)
if(istype(i, /obj/structure/closet/stasis))
var/obj/structure/closet/stasis/S = i
S.dump_contents(0)
S.dump_contents(kill=0)
qdel(S)
break
user.gib()
@@ -34,7 +34,7 @@
/mob/living/simple_animal/hostile/netherworld/migo/Initialize()
. = ..()
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_aler.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/ratvar_reveal.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshot_silenced.ogg', 'sound/weapons/gunshot2.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/machines/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/outbreak5.ogg', 'sound/ai/outbreak7.ogg', 'sound/ai/poweroff.ogg', 'sound/ai/radiation.ogg', 'sound/ai/shuttlecalled.ogg', 'sound/ai/shuttledock.ogg', 'sound/ai/shuttlerecalled.ogg', 'sound/ai/aimalf.ogg') //hahahaha fuck you code divers
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_aler.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/hyperspace_begin.ogg', 'sound/effects/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/ratvar_reveal.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desceration-01.ogg', 'sound/misc/desceration-02.ogg', 'sound/misc/desceration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gunshot_silenced.ogg', 'sound/weapons/gunshot2.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/machines/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', get_announcer_sound("outbreak5"), get_announcer_sound("outbreak7"), get_announcer_sound("poweroff"), get_announcer_sound("radiation"), get_announcer_sound("shuttlerecalled"), get_announcer_sound("shuttledock"), get_announcer_sound("shuttlecalled"), get_announcer_sound("aimalf")) //hahahaha fuck you code divers
/mob/living/simple_animal/hostile/netherworld/migo/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
..()
@@ -95,7 +95,7 @@
if(M)
playsound(src, 'sound/magic/demon_consume.ogg', 50, 1)
M.adjustBruteLoss(60)
new /obj/effect/gibspawner/generic(get_turf(M))
M.spawn_gibs()
if(M.stat == DEAD)
var/mob/living/simple_animal/hostile/netherworld/blankbody/blank
blank = new(loc)
@@ -363,7 +363,7 @@
density = initial(density)
lying = 0
. = 1
movement_type = initial(movement_type)
setMovetype(initial(movement_type))
/mob/living/simple_animal/proc/make_babies() // <3 <3 <3
if(gender != FEMALE || stat || next_scan_time > world.time || !childtype || !animal_species || !SSticker.IsRoundInProgress())
@@ -462,8 +462,8 @@
return
sync_lighting_plane_alpha()
/mob/living/simple_animal/get_idcard()
return access_card
/mob/living/simple_animal/get_idcard(hand_first = TRUE)
return ..() || access_card
/mob/living/simple_animal/OpenCraftingMenu()
if(dextrous)
+2 -2
View File
@@ -100,7 +100,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
A.pipe_vision_img.plane = ABOVE_HUD_PLANE
client.images += A.pipe_vision_img
pipes_shown += A.pipe_vision_img
movement_type |= VENTCRAWLING
setMovetype(movement_type | VENTCRAWLING)
/mob/living/proc/remove_ventcrawl()
@@ -108,7 +108,7 @@ GLOBAL_LIST_INIT(ventcrawl_machinery, typecacheof(list(
for(var/image/current_image in pipes_shown)
client.images -= current_image
pipes_shown.len = 0
movement_type &= ~VENTCRAWLING
setMovetype(movement_type & ~VENTCRAWLING)
+15 -10
View File
@@ -307,8 +307,11 @@
set name = "Examine"
set category = "IC"
if(isturf(A) && !(sight & SEE_TURFS) && !(A in view(client ? client.view : world.view, src)))
// shift-click catcher may issue examinate() calls for out-of-sight turfs
if(!client)
return
if(!(SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A) & COMPONENT_ALLOW_EXAMINE) && ((client.eye != src && client.eye != loc) || (isturf(A) && !(sight & SEE_TURFS) && !(A in view(client ? client.view : world.view, src)))))
//cameras & co don't allow users to examine far away things, also shift-click catcher may issue examinate() calls for out-of-sight turfs
return
if(is_blind(src))
@@ -737,15 +740,17 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
mob_spell_list -= S
qdel(S)
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE)
if(!magic && !holy)
/mob/proc/anti_magic_check(magic = TRUE, holy = FALSE, tinfoil = FALSE, chargecost = 1, self = FALSE)
if(!magic && !holy && !tinfoil)
return
var/list/protection_sources = list()
if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, magic, holy, protection_sources) & COMPONENT_BLOCK_MAGIC)
if(SEND_SIGNAL(src, COMSIG_MOB_RECEIVE_MAGIC, src, magic, holy, tinfoil, chargecost, self, protection_sources) & COMPONENT_BLOCK_MAGIC)
if(protection_sources.len)
return pick(protection_sources)
else
return src
if((magic && HAS_TRAIT(src, TRAIT_ANTIMAGIC)) || (holy && HAS_TRAIT(src, TRAIT_HOLY)))
return src
//You can buckle on mobs if you're next to them since most are dense
/mob/buckle_mob(mob/living/M, force = FALSE, check_loc = TRUE)
@@ -862,7 +867,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
replace_identification_name(oldname,newname)
for(var/datum/mind/T in SSticker.minds)
for(var/datum/objective/obj in T.objectives)
for(var/datum/objective/obj in T.get_all_objectives())
// Only update if this player is a target
if(obj.target && obj.target.current && obj.target.current.real_name == name)
obj.update_explanation_text()
@@ -928,10 +933,6 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
/mob/proc/can_hold_items()
return FALSE
/mob/proc/get_idcard()
return
/mob/vv_get_dropdown()
. = ..()
. += "---"
@@ -959,3 +960,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
var/datum/language_holder/H = get_language_holder()
H.open_language_menu(usr)
/mob/setMovetype(newval)
. = ..()
update_movespeed(FALSE)
+20 -6
View File
@@ -67,8 +67,8 @@
/proc/slur(n,var/strength=50)
strength = min(strength,50)
var/phrase = html_decode(n)
var/leng = lentext(phrase)
var/counter=lentext(phrase)
var/leng = length(phrase)
var/counter=length(phrase)
var/newphrase=""
var/newletter=""
while(counter>=1)
@@ -102,8 +102,8 @@
/proc/cultslur(n) // Inflicted on victims of a stun talisman
var/phrase = html_decode(n)
var/leng = lentext(phrase)
var/counter=lentext(phrase)
var/leng = length(phrase)
var/counter=length(phrase)
var/newphrase=""
var/newletter=""
while(counter>=1)
@@ -352,12 +352,12 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
/mob/proc/reagent_check(datum/reagent/R) // utilized in the species code
return 1
/proc/notify_ghosts(var/message, var/ghost_sound = null, var/enter_link = null, var/atom/source = null, var/mutable_appearance/alert_overlay = null, var/action = NOTIFY_JUMP, flashwindow = TRUE, ignore_mapload = TRUE, ignore_key) //Easy notification of ghosts.
/proc/notify_ghosts(message, ghost_sound, enter_link, atom/source, mutable_appearance/alert_overlay, action = NOTIFY_JUMP, flashwindow = TRUE, ignore_mapload = TRUE, ignore_key, ignore_dnr_observers = FALSE) //Easy notification of ghosts.
if(ignore_mapload && SSatoms.initialized != INITIALIZATION_INNEW_REGULAR) //don't notify for objects created during a map load
return
for(var/mob/dead/observer/O in GLOB.player_list)
if(O.client)
if (ignore_key && O.ckey in GLOB.poll_ignore[ignore_key])
if ((ignore_key && (O.ckey in GLOB.poll_ignore[ignore_key])) || (ignore_dnr_observers && !O.can_reenter_round(TRUE)))
continue
to_chat(O, "<span class='ghostalert'>[message][(enter_link) ? " [enter_link]" : ""]</span>")
if(ghost_sound)
@@ -518,3 +518,17 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
else if(HAS_TRAIT_FROM(src, TRAIT_DISSECTED,"Thorough Dissection"))
dissectionmsg = " via Thorough Dissection"
. += "<span class='notice'>This body has been dissected and analyzed[dissectionmsg].</span><br>"
//gets ID card object from special clothes slot or null.
/mob/proc/get_idcard(hand_first = TRUE)
var/obj/item/held_item = get_active_held_item()
. = held_item?.GetID()
if(!.) //If so, then check the inactive hand
held_item = get_inactive_held_item()
. = held_item?.GetID()
/mob/proc/get_id_in_hand()
var/obj/item/held_item = get_active_held_item()
if(!held_item)
return
return held_item.GetID()
+32
View File
@@ -370,3 +370,35 @@
if(hud_used && hud_used.static_inventory)
for(var/obj/screen/mov_intent/selector in hud_used.static_inventory)
selector.update_icon(src)
/mob/verb/up()
set name = "Move Upwards"
set category = "IC"
if(zMove(UP, TRUE))
to_chat(src, "<span class='notice'>You move upwards.</span>")
/mob/verb/down()
set name = "Move Down"
set category = "IC"
if(zMove(DOWN, TRUE))
to_chat(src, "<span class='notice'>You move down.</span>")
/mob/proc/zMove(dir, feedback = FALSE)
if(dir != UP && dir != DOWN)
return FALSE
var/turf/target = get_step_multiz(src, dir)
if(!target)
if(feedback)
to_chat(src, "<span class='warning'>There's nothing in that direction!</span>")
return FALSE
if(!canZMove(dir, target))
if(feedback)
to_chat(src, "<span class='warning'>You couldn't move there!</span>")
return FALSE
forceMove(target)
return TRUE
/mob/proc/canZMove(direction, turf/target)
return FALSE
+28 -8
View File
@@ -1,23 +1,29 @@
/*Current movespeed modification list format: list(id = list(
priority,
flags,
legacy slowdown/speedup amount,
movetype_flags,
blacklisted_movetypes,
conflict
))
*/
//ANY ADD/REMOVE DONE IN UPDATE_MOVESPEED MUST HAVE THE UPDATE ARGUMENT SET AS FALSE!
/mob/proc/add_movespeed_modifier(id, update = TRUE, priority = 0, flags = NONE, override = FALSE, multiplicative_slowdown = 0)
var/list/temp = list(priority, flags, multiplicative_slowdown) //build the modification list
/mob/proc/add_movespeed_modifier(id, update=TRUE, priority=0, flags=NONE, override=FALSE, multiplicative_slowdown=0, movetypes=ALL, blacklisted_movetypes=NONE, conflict=FALSE)
var/list/temp = list(priority, flags, multiplicative_slowdown, movetypes, blacklisted_movetypes, conflict) //build the modification list
var/resort = TRUE
if(LAZYACCESS(movespeed_modification, id))
if(movespeed_modifier_identical_check(movespeed_modification[id], temp))
var/list/existing_data = movespeed_modification[id]
if(movespeed_modifier_identical_check(existing_data, temp))
return FALSE
if(!override)
return FALSE
else
remove_movespeed_modifier(id, update)
LAZYSET(movespeed_modification, id, list(priority, flags, multiplicative_slowdown))
if(priority == existing_data[MOVESPEED_DATA_INDEX_PRIORITY])
resort = FALSE // We don't need to re-sort if we're replacing something already there and it's the same priority
LAZYSET(movespeed_modification, id, temp)
if(update)
update_movespeed(TRUE)
update_movespeed(resort)
return TRUE
/mob/proc/remove_movespeed_modifier(id, update = TRUE)
@@ -55,9 +61,23 @@
if(resort)
sort_movespeed_modlist()
. = 0
var/list/conflict_tracker = list()
for(var/id in get_movespeed_modifiers())
var/list/data = movespeed_modification[id]
. += data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN]
if(!(data[MOVESPEED_DATA_INDEX_MOVETYPE] & movement_type)) // We don't affect any of these move types, skip
continue
if(data[MOVESPEED_DATA_INDEX_BL_MOVETYPE] & movement_type) // There's a movetype here that disables this modifier, skip
continue
var/conflict = data[MOVESPEED_DATA_INDEX_CONFLICT]
var/amt = data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN]
if(conflict)
// Conflicting modifiers prioritize the larger slowdown or the larger speedup
// We purposefuly don't handle mixing speedups and slowdowns on the same id
if(abs(conflict_tracker[conflict]) < abs(amt))
conflict_tracker[conflict] = amt
else
continue
. += amt
cached_multiplicative_slowdown = .
/mob/proc/get_movespeed_modifiers()
@@ -47,7 +47,7 @@
D.updateappearance(mutcolor_update=1, mutations_overlay_update=1)
else if(ishuman(M))
var/mob/living/carbon/human/H = M
client.prefs.copy_to(H)
client?.prefs.copy_to(H)
H.dna.update_dna_identity()
if(mind && isliving(M))
+1 -1
View File
@@ -25,7 +25,7 @@
if(flavor_text && flavor_text != "")
// We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown.
var/msg = html_decode(replacetext(flavor_text, "\n", " "))
if(lentext(msg) <= 40)
if(length(msg) <= 40)
return "<span class='notice'>[html_encode(msg)]</span>"
else
return "<span class='notice'>[html_encode(copytext(msg, 1, 37))]... <a href='?src=[REF(src)];flavor_more=1'>More...</span></a>"