Merge branch 'master' of https://github.com/raspy-on-osu/Citadel-Station-13 into ventcrawl-refactor

This commit is contained in:
raspy-on-osu
2021-01-24 19:21:24 -05:00
888 changed files with 17584 additions and 11569 deletions
+5 -3
View File
@@ -8,6 +8,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
throwforce = 0
/mob/dead/Initialize()
SHOULD_CALL_PARENT(FALSE)
if(flags_1 & INITIALIZED_1)
stack_trace("Warning: [src]([type]) initialized multiple times!")
flags_1 |= INITIALIZED_1
@@ -68,14 +69,15 @@ INITIALIZE_IMMEDIATE(/mob/dead)
set desc= "Jump to the other server"
if(mob_transforming)
return
var/list/csa = CONFIG_GET(keyed_list/cross_server)
var/list/our_id = CONFIG_GET(string/cross_comms_name)
var/list/csa = CONFIG_GET(keyed_list/cross_server) - our_id
var/pick
switch(csa.len)
if(0)
remove_verb(src, /mob/dead/proc/server_hop)
to_chat(src, "<span class='notice'>Server Hop has been disabled.</span>")
if(1)
pick = csa[0]
pick = csa[1]
else
pick = input(src, "Pick a server to jump to", "Server Hop") as null|anything in csa
@@ -100,7 +102,7 @@ INITIALIZE_IMMEDIATE(/mob/dead)
winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources
C << link("[addr]?server_hop=[key]")
C << link("[addr]")
/mob/dead/proc/update_z(new_z) // 1+ to register, null to unregister
if (registered_z != new_z)
@@ -375,7 +375,9 @@
ready = PLAYER_NOT_READY
return FALSE
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No")
var/mintime = max(CONFIG_GET(number/respawn_delay), (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time, 0)
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to respawn for [round(mintime / 600, 0.1)] minutes!!","Player Setup","Yes","No")
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
ready = PLAYER_NOT_READY
@@ -397,6 +399,7 @@
stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised")
transfer_ckey(observer, FALSE)
observer.client = client
observer.client.prefs?.respawn_time_of_death = world.time
observer.set_ghost_appearance()
if(observer.client && observer.client.prefs)
observer.real_name = observer.client.prefs.real_name
@@ -463,6 +466,9 @@
alert(src, "An administrator has disabled late join spawning.")
return FALSE
if(!respawn_latejoin_check(notify = TRUE))
return FALSE
var/arrivals_docked = TRUE
if(SSshuttle.arrivals)
close_spawn_windows() //In case we get held up
@@ -526,6 +532,8 @@
GLOB.joined_player_list += character.ckey
GLOB.latejoiners += character
LAZYOR(character.client.prefs.slots_joined_as, character.client.prefs.default_slot)
LAZYOR(character.client.prefs.characters_joined_as, character.real_name)
if(CONFIG_GET(flag/allow_latejoin_antagonists) && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
if(SSshuttle.emergency)
@@ -243,6 +243,10 @@
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/insect_fluff/brown
name = "Brown"
icon_state = "brown"
/datum/sprite_accessory/insect_fluff/punished
name = "Burnt Off"
icon_state = "punished"
@@ -271,6 +275,10 @@
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_fluff/featherymoth
name = "Feathery Moth"
icon_state = "featherymoth"
/datum/sprite_accessory/insect_fluff/firewatch
name = "Firewatch"
icon_state = "firewatch"
@@ -291,18 +299,22 @@
name = "Moon Fly"
icon_state = "moonfly"
/datum/sprite_accessory/insect_fluff/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/insect_fluff/plain
name = "Plain"
icon_state = "plain"
/datum/sprite_accessory/insect_fluff/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
/datum/sprite_accessory/insect_fluff/poison
name = "Poison"
icon_state = "poison"
/datum/sprite_accessory/insect_fluff/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/insect_fluff/ragged
name = "Ragged"
icon_state = "ragged"
@@ -311,6 +323,10 @@
name = "Reddish"
icon_state = "redish"
/datum/sprite_accessory/insect_fluff/rosy
name = "Rosy"
icon_state = "rosy"
/datum/sprite_accessory/insect_fluff/royal
name = "Royal"
icon_state = "royal"
@@ -1,4 +1,4 @@
datum/sprite_accessory/caps
/datum/sprite_accessory/caps
icon = 'icons/mob/mutant_bodyparts.dmi'
color_src = HAIR
relevant_layers = list(BODY_ADJ_LAYER)
@@ -11,6 +11,11 @@
// please make sure they're sorted alphabetically and categorized
/datum/sprite_accessory/underwear/socks/garter
name = "Garter"
icon_state = "garter"
has_color = TRUE
/datum/sprite_accessory/underwear/socks/socks_knee
name = "Knee-high"
icon_state = "socks_knee"
@@ -757,7 +757,7 @@
icon_state = "husky"
matrixed_sections = MATRIX_RED_GREEN
datum/sprite_accessory/tails/mam_tails/insect
/datum/sprite_accessory/tails/mam_tails/insect
name = "Insect"
icon_state = "insect"
matrixed_sections = MATRIX_RED
@@ -58,9 +58,7 @@
dimension_y = 34
relevant_layers = list(BODY_BEHIND_LAYER, BODY_ADJ_LAYER, BODY_FRONT_LAYER)
/datum/sprite_accessory/deco_wings/atlas
name = "Atlas"
icon_state = "atlas"
//nonmoth wings
/datum/sprite_accessory/deco_wings/bat
name = "Bat"
@@ -70,18 +68,76 @@
name = "Bee"
icon_state = "bee"
/datum/sprite_accessory/deco_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/deco_wings/bee2
name = "Small Bee"
icon_state = "beewings"
/datum/sprite_accessory/deco_wings/dragon
name = "Dragon"
icon_state = "dragon"
/datum/sprite_accessory/deco_wings/dragonfly
name = "Dragonfly"
icon_state = "dragonfly"
/datum/sprite_accessory/deco_wings/fairy
name = "Fairy"
icon_state = "fairy"
/datum/sprite_accessory/deco_wings/feathery
/datum/sprite_accessory/deco_wings/featheredwing
name = "Feathery"
icon_state = "feathery"
/datum/sprite_accessory/deco_wings/featheredwingmedium
name = "Medium Feathered"
icon_state = "feathered3"
/datum/sprite_accessory/deco_wings/featheredwinglarge
name = "Large Feathered"
icon_state = "feathered2"
/datum/sprite_accessory/deco_wings/harpywings
name = "Harpy"
icon_state = "harpywings"
/datum/sprite_accessory/deco_wings/roboticwing
name = "Robotic"
icon_state = "drago"
/datum/sprite_accessory/deco_wings/succubusblack
name = "Succubus Black"
icon_state = "succubusblack"
/datum/sprite_accessory/deco_wings/succubuspurple
name = "Succubus Purple"
icon_state = "succubuspurple"
/datum/sprite_accessory/deco_wings/succubusred
name = "Succubus Red"
icon_state = "succubusred"
/datum/sprite_accessory/deco_wings/xenobackplate
name = "Xenomorph Backplate"
icon_state = "snagbackplate"
//moth wings
/datum/sprite_accessory/deco_wings/atlas
name = "Atlas"
icon_state = "atlas"
/datum/sprite_accessory/deco_wings/brown
name = "Brown"
icon_state = "brown"
/datum/sprite_accessory/deco_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/deco_wings/featherymoth
name = "Feathery Moth Wings"
icon_state = "featherymoth"
/datum/sprite_accessory/deco_wings/firewatch
name = "Firewatch"
icon_state = "firewatch"
@@ -90,6 +146,10 @@
name = "Gothic"
icon_state = "gothic"
/datum/sprite_accessory/deco_wings/jungle
name = "Jungle"
icon_state = "jungle"
/datum/sprite_accessory/deco_wings/lovers
name = "Lovers"
icon_state = "lovers"
@@ -106,10 +166,18 @@
name = "Moon Fly"
icon_state = "moonfly"
/datum/sprite_accessory/deco_wings/oakworm
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/deco_wings/plain
name = "Plain"
icon_state = "plain"
/datum/sprite_accessory/deco_wings/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
/datum/sprite_accessory/deco_wings/poison
name = "Poison"
icon_state = "poison"
@@ -126,6 +194,10 @@
name = "Reddish"
icon_state = "redish"
/datum/sprite_accessory/deco_wings/rosy
name = "Rosy"
icon_state = "rosy"
/datum/sprite_accessory/deco_wings/royal
name = "Royal"
icon_state = "royal"
@@ -138,6 +210,10 @@
name = "White Fly"
icon_state = "whitefly"
/datum/sprite_accessory/deco_wings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
//INSECT WINGS
/datum/sprite_accessory/insect_wings
@@ -145,6 +221,69 @@
color_src = WINGCOLOR
relevant_layers = list(BODY_BEHIND_LAYER, BODY_FRONT_LAYER)
//non insect wings
/datum/sprite_accessory/deco_wings/bat
name = "Bat"
icon_state = "bat"
/datum/sprite_accessory/insect_wings/bee
name = "Bee"
icon_state = "bee"
/datum/sprite_accessory/insect_wings/bee2
name = "Small Bee"
icon_state = "beewings"
/datum/sprite_accessory/insect_wings/dragon
name = "Dragon"
icon_state = "dragon"
/datum/sprite_accessory/insect_wings/dragonfly
name = "Dragonfly"
icon_state = "dragonfly"
/datum/sprite_accessory/insect_wings/fairy
name = "Fairy"
icon_state = "fairy"
/datum/sprite_accessory/insect_wings/featheredwing
name = "Feathery"
icon_state = "feathery"
/datum/sprite_accessory/insect_wings/featheredwingmedium
name = "Medium Feathered"
icon_state = "feathered3"
/datum/sprite_accessory/insect_wings/featheredwinglarge
name = "Large Feathered"
icon_state = "feathered2"
/datum/sprite_accessory/insect_wings/harpywings
name = "Harpy"
icon_state = "harpywings"
/datum/sprite_accessory/insect_wings/roboticwing
name = "Robotic"
icon_state = "drago"
/datum/sprite_accessory/insect_wings/succubusblack
name = "Succubus Black"
icon_state = "succubusblack"
/datum/sprite_accessory/insect_wings/succubuspurple
name = "Succubus Purple"
icon_state = "succubuspurple"
/datum/sprite_accessory/insect_wings/succubusred
name = "Succubus Red"
icon_state = "succubusred"
/datum/sprite_accessory/insect_wings/xenobackplate
name = "Xenomorph Backplate"
icon_state = "snagbackplate"
//moth wings
/datum/sprite_accessory/insect_wings/none
name = "None"
icon_state = "none"
@@ -154,25 +293,17 @@
name = "Atlas"
icon_state = "atlas"
/datum/sprite_accessory/insect_wings/bat
name = "Bat"
icon_state = "bat"
/datum/sprite_accessory/insect_wings/bee
name = "Bee"
icon_state = "bee"
/datum/sprite_accessory/insect_wings/brown
name = "Brown"
icon_state = "brown"
/datum/sprite_accessory/insect_wings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_wings/fairy
name = "Fairy"
icon_state = "fairy"
/datum/sprite_accessory/insect_wings/feathery
name = "Feathery"
icon_state = "feathery"
/datum/sprite_accessory/insect_wings/featherymoth
name = "Feathery Moth Wings"
icon_state = "featherymoth"
/datum/sprite_accessory/insect_wings/firewatch
name = "Firewatch"
@@ -210,6 +341,10 @@
name = "Plain"
icon_state = "plain"
/datum/sprite_accessory/insect_wings/plasmafire
name = "Plasma Fire"
icon_state = "plasmafire"
/datum/sprite_accessory/insect_wings/poison
name = "Poison"
icon_state = "poison"
@@ -226,6 +361,10 @@
name = "Reddish"
icon_state = "redish"
/datum/sprite_accessory/insect_wings/rosy
name = "Rosy"
icon_state = "rosy"
/datum/sprite_accessory/insect_wings/royal
name = "Royal"
icon_state = "royal"
@@ -253,45 +392,25 @@
icon_state = "none"
relevant_layers = null
/datum/sprite_accessory/insect_markings/reddish
name = "Reddish"
icon_state = "reddish"
/datum/sprite_accessory/insect_markings/royal
name = "Royal"
icon_state = "royal"
/datum/sprite_accessory/insect_markings/gothic
name = "Gothic"
icon_state = "gothic"
/datum/sprite_accessory/insect_markings/whitefly
name = "White Fly"
icon_state = "whitefly"
/datum/sprite_accessory/insect_markings/lovers
name = "Lovers"
icon_state = "lovers"
/datum/sprite_accessory/insect_markings/punished
name = "Punished"
icon_state = "punished"
/datum/sprite_accessory/insect_markings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_markings/firewatch
name = "Firewatch"
icon_state = "firewatch"
/datum/sprite_accessory/insect_markings/deathhead
name = "Deathshead"
icon_state = "deathhead"
/datum/sprite_accessory/insect_markings/gothic
name = "Gothic"
icon_state = "gothic"
/datum/sprite_accessory/insect_markings/poison
name = "Poison"
icon_state = "poison"
/datum/sprite_accessory/insect_markings/jungle
name = "Jungle"
icon_state = "jungle"
/datum/sprite_accessory/insect_markings/ragged
name = "Ragged"
icon_state = "ragged"
/datum/sprite_accessory/insect_markings/lovers
name = "Lovers"
icon_state = "lovers"
/datum/sprite_accessory/insect_markings/moonfly
name = "Moon Fly"
@@ -301,10 +420,42 @@
name = "Oak Worm"
icon_state = "oakworm"
/datum/sprite_accessory/insect_markings/jungle
name = "Jungle"
icon_state = "jungle"
/datum/sprite_accessory/insect_markings/poison
name = "Poison"
icon_state = "poison"
/datum/sprite_accessory/insect_markings/punished
name = "Punished"
icon_state = "punished"
/datum/sprite_accessory/insect_markings/ragged
name = "Ragged"
icon_state = "ragged"
/datum/sprite_accessory/insect_markings/reddish
name = "Reddish"
icon_state = "reddish"
/datum/sprite_accessory/insect_markings/royal
name = "Royal"
icon_state = "royal"
/datum/sprite_accessory/insect_markings/whitefly
name = "White Fly"
icon_state = "whitefly"
/datum/sprite_accessory/insect_markings/witchwing
name = "Witch Wing"
icon_state = "witchwing"
//DONATOR WINGS
/datum/sprite_accessory/deco_wings/eyestalks
name = "gazer eyestalks"
icon_state = "eyestalks"
//ckeys_allowed = list("liquidfirefly","seiga") //At request.
/datum/sprite_accessory/insect_wings/eyestalks
name = "gazer eyestalks"
icon_state = "eyestalks"
//ckeys_allowed = list("liquidfirefly","seiga") //At request.
+13 -3
View File
@@ -264,7 +264,7 @@ 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, penalize = FALSE, voluntary = FALSE)
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE, cryo = FALSE)
var/sig_flags = SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize)
penalize = !(sig_flags & COMPONENT_DO_NOT_PENALIZE_GHOSTING) && (suiciding || penalize) // suicide squad.
voluntary_ghosted = voluntary
@@ -277,6 +277,12 @@ Works together with spawning an observer, noted above.
if (client && client.prefs && client.prefs.auto_ooc)
if (!(client.prefs.chat_toggles & CHAT_OOC))
client.prefs.chat_toggles ^= CHAT_OOC
if(ckey && penalize)
var/datum/preferences/P = GLOB.preferences_datums[ckey]
if(P)
P.respawn_restrictions_active = TRUE
P.respawn_time_of_death = world.time
P.respawn_did_cryo = cryo
transfer_ckey(ghost, FALSE)
ghost.client.init_verbs()
if(penalize)
@@ -374,6 +380,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Move(NewLoc, direct)
if (SEND_SIGNAL(src, COMSIG_MOVABLE_PRE_MOVE, NewLoc) & COMPONENT_MOVABLE_BLOCK_PRE_MOVE)
return
if(updatedir)
setDir(direct)//only update dir if we actually need it, so overlays won't spin on base sprites that don't have directions of their own
var/oldloc = loc
@@ -423,12 +431,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, "<span class='warning'>You're already stuck out of your body!</span>")
return FALSE
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. ","Are you sure you want to stay dead?","Yes","No")
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. THIS WILL ALSO STOP YOU FROM RESPAWNING!!!","Are you sure you want to stay dead and never respawn?","Yes","No")
if(response != "Yes")
return
can_reenter_corpse = FALSE
to_chat(src, "You can no longer be brought back into your body.")
client.prefs?.dnr_triggered = TRUE
to_chat(src, "You can no longer be brought back into your body or respawn.")
return TRUE
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source, flashwindow = TRUE)
+184
View File
@@ -0,0 +1,184 @@
// ADMIN VERBS BEGIN
/**
* Fully returns a player to lobby, allowing them to bypass all respawn restrictions
* Works on ghosts or new players (lobby players)
* If a lobby player is selected, their restrictions are removed.
*/
/client/proc/admin_cmd_respawn_return_to_lobby()
set name = "Respawn Player (Unrestricted)"
set desc = "Gives a player an unrestricted respawn, resetting all respawn restrictions for them."
set category = "Admin"
var/list/mob/valid = list()
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
if(!I.client)
continue
valid["[I.ckey] - Observing: [I]"] = I.ckey
for(var/mob/dead/new_player/I in GLOB.dead_mob_list)
if(!I.client || !I.client.prefs.respawn_restrictions_active)
continue
valid["[I.ckey] - IN LOBBY"] = I.ckey
if(!valid.len)
to_chat(src, "<span class='warning'>No player found that is either a ghost or is in lobby with restrictions active.</span>")
return
var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid]
var/client/player = GLOB.directory[ckey]
if(!player)
to_chat(src, "<span class='warning'>Client not found.</span>")
return
var/mob/M = player.mob
if(istype(M, /mob/dead/observer))
var/mob/dead/observer/O = M
var/confirm = alert(src, "Send [O]([ckey]) back to the lobby without respawn restrictions?", "Send to Lobby", "Yes", "No")
if(confirm != "Yes")
return
message_admins("[key_name_admin(src)] gave [key_name_admin(O)] a full respawn and sent them back to the lobby.")
log_admin("[key_name(src)] gave [key_name(O)] a full respawn and sent them back to the lobby.")
to_chat(O, "<span class='userdanger'>You have been given a full respawn.</span>")
O.do_respawn(FALSE)
O.client.prefs.dnr_triggered = FALSE
else if(istype(M, /mob/dead/new_player))
var/mob/dead/new_player/NP = M
var/confirm = alert(src, "Remove [NP]'s respawn restrictions?", "Remove Restrictions", "Yes", "No")
if(confirm != "Yes")
return
message_admins("[key_name_admin(src)] removed [ckey]'s respawn restrictions.")
log_admin("[key_name(src)] removed [ckey]'s respawn restrictions")
NP.client.prefs.respawn_restrictions_active = FALSE
NP.client.prefs.dnr_triggered = FALSE
to_chat(NP, "<span class='boldnotie'>Your respawn restrictions have been removed.")
else
CRASH("Invalid mobtype")
/**
* Allows a ghost to bypass respawn delay without lifting respawn restrictions
*/
/client/proc/admin_cmd_remove_ghost_respawn_timer()
set name = "Remove Respawn Timer for Player"
set desc = "Removes a player's respawn timer without removing their respawning restrictions."
set category = "Admin"
var/list/mob/dead/observer/valid = list()
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
if(!I.client)
continue
valid["[I.ckey] - [I.name]"] = I
if(!valid.len)
to_chat(src, "<span class='warning'>No logged in ghosts found.</span>")
return
var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid]
if(!O.client)
to_chat(src, "<span class='warning'>[O] has no client.</span>")
return
var/timeleft = O.time_left_to_respawn()
if(!timeleft)
to_chat(src, "<span class='warning'>[O] can already respawn.")
return
message_admins("[key_name_admin(src)] removed [key_name_admin(O)]'s respawn timer.")
log_admin("[key_name(src)] removed [key_name(O)]'s respawn timer.")
O.client.prefs.respawn_time_of_death = -INFINITY
to_chat(O, "<span class='boldnotice'>Your respawn timer has been removed.")
// ADMIN VERBS END
/**
* Checks if we can latejoin on the currently selected slot, taking into account respawn status.
*/
/mob/dead/new_player/proc/respawn_latejoin_check(notify = FALSE)
if(!client.prefs.respawn_restrictions_active)
return TRUE
var/can_same_person = CONFIG_GET(flag/allow_same_character_respawn)
if(can_same_person)
return TRUE
var/nameless = client.prefs.nameless
var/randomname = client.prefs.be_random_name
var/randombody = client.prefs.be_random_body
if(randombody && (nameless || randomname))
return TRUE // somewhat unrecognizable
if(client.prefs.slots_joined_as && (client.prefs.default_slot in client.prefs.slots_joined_as))
if(notify)
to_chat(src, "<span class='userdanger'>You cannot respawn on the same slot. Joined slots: [english_list(client.prefs.slots_joined_as)].")
return FALSE
if((!nameless && !randomname) && (client.prefs.characters_joined_as && (client.prefs.real_name in client.prefs.characters_joined_as)))
if(notify)
to_chat(src, "<span class='userdanger'>You cannot respawn on the same character. Joined slots: [english_list(client.prefs.characters_joined_as)].")
return FALSE
return TRUE
/**
* Attempts to respawn.
*/
/mob/dead/observer/verb/respawn()
set name = "Respawn"
set category = "OOC"
if(!CONFIG_GET(flag/respawns_enabled))
to_chat(src, "<span class='warning'>Respawns are disabled in configuration.</span>")
return
if(client.prefs.dnr_triggered)
to_chat(src, "<span class='danger'>You cannot respawn as you have enabled DNR.</span>")
return
var/roundstart_timeleft = (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time
if(roundstart_timeleft > 0)
to_chat(src, "<span class='warning'>It's been too short of a time since the round started! Please wait [CEILING(roundstart_timeleft / 600, 0.1)] more minutes.</span>")
return
var/list/banned_modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes)
if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)])
to_chat(src, "<span class='warning'>The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.</span>")
return
var/timeleft = time_left_to_respawn()
if(timeleft)
to_chat(src, "<span class='warning'>It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.</span>")
return
do_respawn(TRUE)
/**
* Gets time left until we can respawn. Returns 0 if we can respawn now.
*/
/mob/dead/observer/verb/time_left_to_respawn()
ASSERT(client)
return max(0, ((client.prefs.respawn_did_cryo? CONFIG_GET(number/respawn_delay_cryo) : CONFIG_GET(number/respawn_delay)) MINUTES + client.prefs.respawn_time_of_death) - world.time)
/**
* Handles respawning
*/
/mob/dead/observer/proc/do_respawn(penalize)
if(!client)
return
if(isnull(penalize))
penalize = client.prefs.respawn_restrictions_active
client.prefs.respawn_restrictions_active = penalize
message_admins("[key_name_admin(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
log_game("[key_name(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
var/mob/dead/new_player/N = transfer_to_lobby()
to_chat(N, "<span class='userdanger'>You have been respawned to the lobby. \
Remember to take heed of rules regarding round knowledge - notably, that ALL past lives are forgotten. \
Any character you join as has NO knowledge of round events unless specified otherwise by an admin.</span>")
/**
* Actual proc that removes us and puts us back on lobby
*
* Returns the new mob.
*/
/mob/dead/observer/proc/transfer_to_lobby()
if(!client) // if no one's in us we can just be deleted
qdel(src)
return
client.screen.Cut()
client.view_size.resetToDefault()
client.generate_clickcatcher()
client.apply_clickcatcher()
client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref))
client.view_size.resetToDefault()
var/mob/dead/new_player/M = new /mob/dead/new_player
M.ckey = ckey
return M
@@ -18,7 +18,6 @@
/// How much brute damage they do to simple animals
var/meleeSlashSAPower = 35
var/obj/item/card/id/wear_id = null // Fix for station bounced radios -- Skie
var/has_fine_manipulation = 0
var/move_delay_add = 0 // movement delay to add
@@ -68,7 +68,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/plant
name = "Plant Weeds"
desc = "Plants some alien weeds."
desc = "Plants Alien weeds which spread resin which heals any alien. These weeds also regenerate plasma faster. Costs 50 Plasma."
plasma_cost = 50
check_turf = TRUE
action_icon_state = "alien_plant"
@@ -83,7 +83,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/whisper
name = "Whisper"
desc = "Whisper to someone."
desc = "Whisper to someone through the hivemind. Costs 10 Plasma."
plasma_cost = 10
action_icon_state = "alien_whisper"
@@ -143,7 +143,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/acid
name = "Corrosive Acid"
desc = "Drench an object in acid, destroying it over time."
desc = "Drench an object in acid, destroying it over time. Costs 200 Plasma."
plasma_cost = 200
action_icon_state = "alien_acid"
@@ -189,7 +189,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/neurotoxin
name = "Spit Neurotoxin"
desc = "Spits neurotoxin at someone, paralyzing them for a short time."
desc = "Activates your Neurotoxin glands. You can shoot paralyzing shots. Each shot costs 50 Plasma."
action_icon_state = "alien_neurotoxin_0"
active = FALSE
@@ -254,7 +254,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/resin
name = "Secrete Resin"
desc = "Secrete tough malleable resin."
desc = "Secrete tough malleable resin. Costs 55 Plasma."
plasma_cost = 55
check_turf = TRUE
var/list/structures = list(
@@ -20,7 +20,7 @@
/obj/effect/proc_holder/alien/royal/praetorian/evolve
name = "Evolve"
desc = "Produce an internal egg sac capable of spawning children. Only one queen can exist at a time."
desc = "Produce an internal egg sac capable of spawning children. Only one queen can exist at a time. Costs 500 Plasma."
plasma_cost = 500
action_icon_state = "alien_evolve_praetorian"
@@ -56,7 +56,7 @@
//Queen verbs
/obj/effect/proc_holder/alien/lay_egg
name = "Lay Egg"
desc = "Lay an egg to produce huggers to impregnate prey with."
desc = "Lay an egg to produce huggers to impregnate prey with. Costs 75 Plasma."
plasma_cost = 75
check_turf = TRUE
action_icon_state = "alien_egg"
@@ -76,7 +76,7 @@
//Button to let queen choose her praetorian.
/obj/effect/proc_holder/alien/royal/queen/promote
name = "Create Royal Parasite"
desc = "Produce a royal parasite to grant one of your children the honor of being your Praetorian."
desc = "Produce a royal parasite to grant one of your children the honor of being your Praetorian. Costs 500 Plasma."
plasma_cost = 500 //Plasma cost used on promotion, not spawning the parasite.
action_icon_state = "alien_queen_promote"
@@ -91,8 +91,8 @@
Attach(M)
/obj/item/clothing/mask/facehugger/Crossed(atom/target)
. = ..()
HasProximity(target)
return
/obj/item/clothing/mask/facehugger/on_found(mob/finder)
if(stat == CONSCIOUS)
@@ -304,10 +304,16 @@
emote("wag")
else if(check_zone(M.zone_selected) == BODY_ZONE_R_ARM || check_zone(M.zone_selected) == BODY_ZONE_L_ARM)
M.visible_message( \
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
"<span class='notice'>You shake [src]'s hand.</span>", target = src,
target_message = "<span class='notice'>[M] shakes your hand.</span>")
if((pulling == M) && (grab_state == GRAB_PASSIVE))
M.visible_message( \
"<span class='notice'>[M] squeezes [src]'s hand.</span>", \
"<span class='notice'>You squeeze [src]'s hand.</span>", target = src,
target_message = "<span class='notice'>[M] squeezes your hand.</span>")
else
M.visible_message( \
"<span class='notice'>[M] shakes [src]'s hand.</span>", \
"<span class='notice'>You shake [src]'s hand.</span>", target = src,
target_message = "<span class='notice'>[M] shakes your hand.</span>")
else
M.visible_message("<span class='notice'>[M] hugs [src] to make [p_them()] feel better!</span>", \
@@ -62,8 +62,8 @@
amount += BP.burn_dam
return amount
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
//In both these procs, only_organic / only_robotic are only used for healing, not for damaging. For now at least.
/mob/living/carbon/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL))
return FALSE
if(!forced && (status_flags & GODMODE))
@@ -71,10 +71,10 @@
if(amount > 0)
take_overall_damage(amount, 0, 0, updating_health)
else
heal_overall_damage(abs(amount), 0, 0, FALSE, TRUE, updating_health)
heal_overall_damage(abs(amount), 0, 0, only_robotic, only_organic, updating_health)
return amount
/mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/carbon/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && amount < 0 && HAS_TRAIT(src,TRAIT_NONATURALHEAL)) //Vamps don't heal naturally.
return FALSE
if(!forced && (status_flags & GODMODE))
@@ -82,7 +82,7 @@
if(amount > 0)
take_overall_damage(0, amount, 0, updating_health)
else
heal_overall_damage(0, abs(amount), 0, FALSE, TRUE, updating_health)
heal_overall_damage(0, abs(amount), 0, only_robotic, only_organic, updating_health)
return amount
+1 -1
View File
@@ -5,7 +5,7 @@
silent = FALSE
losebreath = 0
if(!gibbed)
if(!gibbed && !HAS_TRAIT(src, TRAIT_DEATHCOMA))
emote("deathgasp")
. = ..()
@@ -80,10 +80,11 @@
if("shortlimbdisable")
var/disabled_type = pick(list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG))
ADD_TRAIT(src, disabled_type, CORRUPTED_SYSTEM)
update_disabled_bodyparts()
addtimer(CALLBACK(src, .proc/reenable_limb, disabled_type), 5 SECONDS)
to_chat(src, "<span class='warning'>Error - Limb control subsystem partially shutdown, rebooting.</span>")
if("shortblind")
ADD_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
become_blind(CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_vision), 5 SECONDS)
to_chat(src, "<span class='warning'>Visual receptor shutdown detected - Initiating reboot.</span>")
if("shortstun")
@@ -105,10 +106,11 @@
if("longlimbdisable")
var/disabled_type = pick(list(TRAIT_PARALYSIS_L_ARM, TRAIT_PARALYSIS_R_ARM, TRAIT_PARALYSIS_L_LEG, TRAIT_PARALYSIS_R_LEG))
ADD_TRAIT(src, disabled_type, CORRUPTED_SYSTEM)
update_disabled_bodyparts()
addtimer(CALLBACK(src, .proc/reenable_limb, disabled_type), 25 SECONDS)
to_chat(src, "<span class='warning'>Fatal error in limb control subsystem - rebooting.</span>")
if("blindmutedeaf")
ADD_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
become_blind(CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_vision), (rand(10, 25)) SECONDS)
ADD_TRAIT(src, TRAIT_DEAF, CORRUPTED_SYSTEM)
addtimer(CALLBACK(src, .proc/reenable_hearing), (rand(15, 35)) SECONDS)
@@ -140,6 +142,7 @@
/mob/living/carbon/proc/reenable_limb(disabled_limb)
REMOVE_TRAIT(src, disabled_limb, CORRUPTED_SYSTEM)
update_disabled_bodyparts()
to_chat(src, "<span class='notice'>Limb control subsystem successfully rebooted.</span>")
/mob/living/carbon/proc/reenable_hearing()
@@ -147,7 +150,7 @@
to_chat(src, "<span class='notice'>Hearing restored.</span>")
/mob/living/carbon/proc/reenable_vision()
REMOVE_TRAIT(src, TRAIT_BLIND, CORRUPTED_SYSTEM)
cure_blind(CORRUPTED_SYSTEM)
to_chat(src, "<span class='notice'>Visual receptors back online.</span>")
/mob/living/carbon/proc/reenable_speech()
@@ -190,6 +190,11 @@
message = "chimes."
sound = 'sound/machines/chime.ogg'
/datum/emote/sound/human/squeak
key = "squeak"
message = "squeaks."
sound = 'sound/effects/mousesqueek.ogg'
//rock paper scissors emote handling
/mob/living/carbon/human/proc/beginRockPaperScissors(var/chosen_move)
GLOB.rockpaperscissors_players[src] = list(chosen_move, ROCKPAPERSCISSORS_NOT_DECIDED)
@@ -3,7 +3,7 @@
real_name = "Unknown"
icon = 'icons/mob/human.dmi'
icon_state = "caucasian_m"
appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE
SET_APPEARANCE_FLAGS(KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE)
/mob/living/carbon/human/Initialize()
add_verb(src, /mob/living/proc/mob_sleep)
@@ -43,7 +43,7 @@
AddComponent(/datum/component/mood)
AddComponent(/datum/component/combat_mode)
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
AddElement(/datum/element/flavor_text/carbon/temporary, "", "Set Pose (Temporary Flavor Text)", "This should be used only for things pertaining to the current round!", _save_key = null)
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
/mob/living/carbon/human/Destroy()
@@ -1028,7 +1028,7 @@
return
stop_pulling()
riding_datum.handle_vehicle_layer()
riding_datum.handle_vehicle_layer(dir)
riding_datum.fireman_carrying = fireman
. = ..(target, force, check_loc)
@@ -411,15 +411,18 @@
if(isrobotic(src))
apply_status_effect(/datum/status_effect/no_combat_mode/robotic_emp, severity / 20)
severity *= 0.5
var/do_not_stun = FALSE
if(HAS_TRAIT(src, TRAIT_ROBOTIC_ORGANISM))
severity *= 0.5 //Robotpeople take less limb damage, but instead suffer system corruption (see carbon emp_act)
do_not_stun = TRUE
for(var/obj/item/bodypart/L in src.bodyparts)
if(L.is_robotic_limb())
if(!informed)
to_chat(src, "<span class='userdanger'>You feel a sharp pain as your robotic limbs overload.</span>")
informed = TRUE
L.receive_damage(0,severity/10)
Stun(severity*2)
if(!do_not_stun) //Tiny bit better than checking for the trait another six times in succession
Stun(severity*2)
/mob/living/carbon/human/acid_act(acidpwr, acid_volume, bodyzone_hit)
var/list/damaged = list()
@@ -14,6 +14,8 @@
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
block_parry_data = /datum/block_parry_data/unarmed/human
default_block_parry_data = /datum/block_parry_data/unarmed/human
causes_dirt_buildup_on_floor = TRUE
//Hair colour and style
var/hair_color = "000"
@@ -98,20 +100,54 @@
parry_failed_clickcd_duration = 0.4
parry_data = list( // yeah it's snowflake
"HUMAN_PARRY_STAGGER" = 3 SECONDS,
"HUMAN_PARRY_PUNCH" = TRUE,
"HUMAN_PARRY_MININUM_EFFICIENCY" = 0.9
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
"UNARMED_PARRY_PUNCH" = TRUE,
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
)
/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/mob/living/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
var/datum/block_parry_data/D = return_block_parry_datum(block_parry_data)
. = ..()
if(!owner.Adjacent(attacker))
return ..()
if(parry_efficiency < D.parry_data["HUMAN_PARRY_MINIMUM_EFFICIENCY"])
return ..()
return
if(parry_efficiency < D.parry_data["UNARMED_PARRY_MINIMUM_EFFICIENCY"])
return
visible_message("<span class='warning'>[src] strikes back perfectly at [attacker], staggering them!</span>")
if(D.parry_data["HUMAN_PARRY_PUNCH"])
if(D.parry_data["UNARMED_PARRY_PUNCH"])
UnarmedAttack(attacker, TRUE, INTENT_HARM, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_ACTION | ATTACK_IGNORE_CLICKDELAY | NO_AUTO_CLICKDELAY_HANDLING)
var/mob/living/L = attacker
if(istype(L))
L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"])
L.Stagger(D.parry_data["UNARMED_PARRY_STAGGER"])
/// Unarmed parry data for pugilists
/datum/block_parry_data/unarmed/pugilist
parry_respect_clickdelay = FALSE
parry_stamina_cost = 4
parry_attack_types = ATTACK_TYPE_UNARMED | ATTACK_TYPE_PROJECTILE | ATTACK_TYPE_TACKLE | ATTACK_TYPE_THROWN | ATTACK_TYPE_MELEE
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
parry_time_windup = 0
parry_time_spindown = 0
parry_time_active = 5
parry_time_perfect = 1.5
parry_time_perfect_leeway = 1.5
parry_imperfect_falloff_percent = 20
parry_efficiency_perfect = 100
parry_efficiency_perfect_override = list(
ATTACK_TYPE_PROJECTILE_TEXT = 60,
)
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 0
parry_cooldown = 0
parry_failed_clickcd_duration = 0.8
parry_data = list( // yeah it's snowflake
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
"UNARMED_PARRY_PUNCH" = TRUE,
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
)
@@ -9,11 +9,6 @@
return
return considering
/mob/living/carbon/human/movement_delay()
. = ..()
if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP))
. -= 1.5
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube)
if(HAS_TRAIT(src, TRAIT_NOSLIPALL))
return 0
@@ -100,3 +95,8 @@
if(dna.species.space_move(src))
return TRUE
return ..()
/mob/living/carbon/human/dirt_buildup(strength)
if(!shoes || !(shoes.body_parts_covered & FEET))
return // barefoot advantage
return ..()
@@ -62,7 +62,6 @@
H.add_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer -= 1 //go one layer down so people go over you
ENABLE_BITFIELD(H.pass_flags, PASSMOB) //this actually lets people pass over you
squeak = H.AddComponent(/datum/component/squeak, custom_sounds = list('sound/effects/blobattack.ogg')) //blorble noise when people step on you
@@ -103,7 +102,6 @@
REMOVE_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
H.update_disabled_bodyparts(silent = TRUE)
H.remove_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer += 1 //go one layer back above!
DISABLE_BITFIELD(H.pass_flags, PASSMOB)
is_puddle = FALSE
if(squeak)
@@ -1796,12 +1796,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
"<span class='warning'>[M] attempted to touch you!</span>", target = M, \
target_message = "<span class='warning'>You attempted to touch [H]!</span>")
return TRUE
if(M == H)
althelp(M, H, attacker_style)
return TRUE
switch(M.a_intent)
if(INTENT_HELP)
if(M == H)
althelp(M, H, attacker_style)
return TRUE
return FALSE
if(INTENT_DISARM)
altdisarm(M, H, attacker_style)
return TRUE
@@ -18,3 +18,33 @@
species_category = SPECIES_CATEGORY_FURRY
allowed_limb_ids = list("mammal","aquatic","avian")
/datum/species/mammal/synthetic
name = "Synthetic Anthromorph"
id = SPECIES_MAMMAL_SYNTHETIC
species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,ROBOTIC_LIMBS,HAS_FLESH,HAS_BONE,WINGCOLOR,HORNCOLOR)
inherent_traits = list(TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NO_PROCESS_FOOD, TRAIT_ROBOTIC_ORGANISM)
inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID|MOB_BEAST
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc
gib_types = list(/obj/effect/gibspawner/ipc, /obj/effect/gibspawner/ipc/bodypartless)
//Just robo looking parts.
mutant_heart = /obj/item/organ/heart/ipc
mutantlungs = /obj/item/organ/lungs/ipc
mutantliver = /obj/item/organ/liver/ipc
mutantstomach = /obj/item/organ/stomach/ipc
mutanteyes = /obj/item/organ/eyes/ipc
mutantears = /obj/item/organ/ears/ipc
mutanttongue = /obj/item/organ/tongue/robot/ipc
mutant_brain = /obj/item/organ/brain/ipc
//special cybernetic organ for getting power from apcs
mutant_organs = list(/obj/item/organ/cyberimp/arm/power_cord)
attack_verb = "claw"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
allowed_limb_ids = list("mammal","aquatic","avian", "human")
@@ -4,7 +4,7 @@
override_bp_icon = 'icons/mob/arachnid_parts.dmi'
say_mod = "chitters"
default_color = "00FF00"
species_traits = list(LIPS, NOEYES, NO_UNDERWEAR)
species_traits = list(LIPS, NOEYES, NO_UNDERWEAR, HAS_FLESH, HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG
mutant_bodyparts = list("arachnid_legs" = "Plain", "arachnid_spinneret" = "Plain", "arachnid_mandibles" = "Plain")
attack_verb = "slash"
@@ -139,6 +139,18 @@
if(E.web_ready == FALSE)
to_chat(H, "<span class='warning'>You need to wait awhile to regenerate web fluid.</span>")
return
if(!H.Adjacent(A)) //No.
return
if(!isliving(A) && A.anchored)
to_chat(H, "<span class='warning'>[A] is bolted to the floor!</span>")
return
if(istype(A, /obj/structure/arachnid))
to_chat(H, "<span class='warning'>No double wrapping.</span>")
return
if(istype(A, /obj/effect))
to_chat(H, "<span class='warning'>You cannot wrap this.</span>")
return
H.visible_message("<span class='danger'>[H] starts to wrap [A] into a cocoon!</span>","<span class='warning'>You start to wrap [A] into a cocoon.</span>")
if(!do_after(H, 10 SECONDS, 1, A))
to_chat(H, "<span class='warning'>Your web spinning was interrupted!</span>")
return
@@ -27,7 +27,7 @@
/datum/species/dullahan/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
return FALSE
return ..()
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
. = ..()
@@ -7,7 +7,7 @@
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR,HAS_FLESH)
mutantlungs = /obj/item/organ/lungs/slime
mutant_heart = /obj/item/organ/heart/slime
mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None", "legs" = "Plantigrade")
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)
@@ -94,7 +94,7 @@
name = "Xenobiological Slime Entity"
id = SPECIES_SLIME
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,HAS_FLESH)
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 150
@@ -404,9 +404,9 @@
id = SPECIES_SLIME_HYBRID
limbs_id = SPECIES_SLIME
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,HAS_FLESH)
inherent_traits = list(TRAIT_TOXINLOVER)
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None", "legs" = "Plantigrade")
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 160 //a notch brighter so it blends better.
@@ -4,7 +4,7 @@
id = SPECIES_LIZARD
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE)
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,CAN_SCAR,HAS_FLESH,HAS_BONE)
inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE
mutanttongue = /obj/item/organ/tongue/lizard
mutanttail = /obj/item/organ/tail/lizard
@@ -48,7 +48,7 @@
name = "Ash Walker"
id = SPECIES_ASHWALKER
limbs_id = SPECIES_LIZARD
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE)
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,DIGITIGRADE,CAN_SCAR,HAS_FLESH,HAS_BONE)
inherent_traits = list(TRAIT_CHUNKYFINGERS)
mutantlungs = /obj/item/organ/lungs/ashwalker
mutanteyes = /obj/item/organ/eyes/night_vision
@@ -68,7 +68,7 @@
/datum/species/pod/pseudo_weak
name = "Anthromorphic Plant"
id = SPECIES_POD_WEAK
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS)
species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS,CAN_SCAR,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "mam_body_markings" = "Husky", "taur" = "None", "legs" = "Normal Legs")
limbs_id = SPECIES_POD
light_nutrition_gain_factor = 3
@@ -203,6 +203,15 @@
var/obj/item/I = AM
if(I.light_range && I.light_power)
disintegrate(I)
else if (isstructure(AM))
var/obj/structure/S = AM
if(istype(S, /obj/structure/glowshroom) || istype(S, /obj/structure/marker_beacon))
qdel(S)
visible_message("<span class='danger'>[S] is disintegrated by [src]!</span>")
else if(AM.light_range && AM.light_power && !(istype(AM, /obj/machinery/power/apc) || istype(AM, /obj/machinery/airalarm)))
var/obj/target_object = AM
target_object.take_damage(force * 5, BRUTE, "melee", 0)
/obj/item/light_eater/proc/disintegrate(obj/item/O)
if(istype(O, /obj/item/pda))
@@ -4,8 +4,8 @@
id = SPECIES_XENOHYBRID
say_mod = "hisses"
default_color = "00FF00"
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR)
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade")
species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR,HAS_FLESH,HAS_BONE)
mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade","deco_wings"= "None")
attack_verb = "slash"
attack_sound = 'sound/weapons/slash.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
@@ -159,3 +159,57 @@
/mob/living/carbon/proc/get_holding_bodypart_of_item(obj/item/I)
var/index = get_held_index_of_item(I)
return index && hand_bodyparts[index]
/**
* Proc called when giving an item to another player
*
* This handles creating an alert and adding an overlay to it
*/
/mob/living/carbon/proc/give(target)
var/obj/item/receiving = get_active_held_item()
if(!receiving)
to_chat(src, "<span class='warning'>You're not holding anything to give!</span>")
return
visible_message("<span class='notice'>[src] is offering [receiving]</span>", \
"<span class='notice'>You offer [receiving]</span>", null, 2)
var/mob/living/carbon/targets = list()
if(!target)
for(var/mob/living/carbon/C in orange(1, src))
if(!CanReach(C))
return
targets += C
else
targets += target
if(!targets)
return
for(var/mob/living/carbon/C in targets)
var/obj/screen/alert/give/G = C.throw_alert("[src]", /obj/screen/alert/give)
if(!G)
return
G.setup(C, src, receiving)
/**
* Proc called when the player clicks the give alert
*
* Handles checking if the player taking the item has open slots and is in range of the giver
* Also deals with the actual transferring of the item to the players hands
* Arguments:
* * giver - The person giving the original item
* * I - The item being given by the giver
*/
/mob/living/carbon/proc/take(mob/living/carbon/giver, obj/item/I)
clear_alert("[giver]")
if(get_dist(src, giver) > 1)
to_chat(src, "<span class='warning'>[giver] is out of range! </span>")
return
if(!I || giver.get_active_held_item() != I)
to_chat(src, "<span class='warning'>[giver] is no longer holding the item they were offering! </span>")
return
if(!get_empty_held_indexes())
to_chat(src, "<span class='warning'>You have no empty hands!</span>")
return
if(!giver.temporarilyRemoveItemFromInventory(I))
visible_message("<span class='notice'>[src] tries to hand over [I] but it's stuck to them....", \
"<span class'notice'> You make a fool of yourself trying to give away an item stuck to your hands")
return
put_in_hands(I)
+8
View File
@@ -594,10 +594,18 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put
drunkenness = max(drunkenness - (drunkenness * 0.04), 0)
if(drunkenness >= 6)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "drunk", /datum/mood_event/drunk)
if(prob(25))
slurring += 2
jitteriness = max(jitteriness - 3, 0)
// throw_alert("drunk", /atom/movable/screen/alert/drunk)
if(HAS_TRAIT(src, TRAIT_DRUNK_HEALING))
adjustBruteLoss(-0.12, FALSE)
adjustFireLoss(-0.06, FALSE)
sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC
else
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "drunk")
clear_alert("drunk")
sound_environment_override = SOUND_ENVIRONMENT_NONE
if(mind && (mind.assigned_role == "Scientist" || mind.assigned_role == "Research Director"))
if(SSresearch.science_tech)
@@ -8,10 +8,12 @@
overlay_fullscreen("high", /obj/screen/fullscreen/high)
throw_alert("high", /obj/screen/alert/high)
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "high", /datum/mood_event/high)
sound_environment_override = SOUND_ENVIRONMENT_DRUGGED
else
clear_fullscreen("high")
clear_alert("high")
SEND_SIGNAL(src, COMSIG_CLEAR_MOOD_EVENT, "high")
sound_environment_override = SOUND_ENVIRONMENT_NONE
/mob/living/carbon/set_drugginess(amount)
druggy = max(amount, 0)
+4 -2
View File
@@ -141,7 +141,8 @@
/mob/living/proc/getBruteLoss()
return bruteloss
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
//only_robotic and only_organic arg only relevant for carbons
/mob/living/proc/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && (status_flags & GODMODE))
return FALSE
bruteloss = clamp((bruteloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
@@ -215,7 +216,8 @@
/mob/living/proc/getFireLoss()
return fireloss
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
//only_robotic and only_organic arg only relevant for carbons
/mob/living/proc/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced && (status_flags & GODMODE))
return FALSE
fireloss = clamp((fireloss + (amount * CONFIG_GET(number/damage_multiplier))), 0, maxHealth * 2)
+4
View File
@@ -66,6 +66,10 @@
GLOB.alive_mob_list -= src
if(!gibbed)
GLOB.dead_mob_list += src
if(ckey)
var/datum/preferences/P = GLOB.preferences_datums[ckey]
if(P)
P.respawn_time_of_death = world.time
set_drugginess(0)
set_disgust(0)
SetSleeping(0, 0)
+2 -2
View File
@@ -264,9 +264,9 @@
return FALSE
/mob/living/carbon/human/has_tail()
if(!dna || !dna.features)
if(!dna || !dna.species)
return ..()
var/list/L = dna.features // caches list because i refuse to type it out and because performance
var/list/L = dna.species.mutant_bodyparts // caches list because i refuse to type it out and because performance
return (L["mam_tail"] && (L["mam_tail"] != "None")) || (L["tail_human"] && (L["tail_human"] != "None")) || (L["tail_lizard"] && (L["tail_lizard"] != "None"))
/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE)
@@ -17,6 +17,9 @@
/mob/living/proc/initiate_parry_sequence()
if(parrying)
return // already parrying
if(!(mobility_flags & MOBILITY_USE))
to_chat(src, "<span class='warning'>You can't move your arms!</span>")
return
if(!(combat_flags & COMBAT_FLAG_PARRY_CAPABLE))
to_chat(src, "<span class='warning'>You are not something that can parry attacks.</span>")
return
@@ -127,7 +130,7 @@
handle_parry_ending_effects(data, effect_text)
parrying = NOT_PARRYING
parry_start_time = 0
parry_end_time_last = world.time
parry_end_time_last = world.time + (successful? 0 : data.parry_failed_cooldown_duration)
successful_parries = null
/**
@@ -154,6 +154,8 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/parry_failed_stagger_duration = 3.5 SECONDS
/// Clickdelay duration post-parry if you fail to parry an attack
var/parry_failed_clickcd_duration = 2 SECONDS
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
var/parry_failed_cooldown_duration = 0 SECONDS
/**
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
@@ -32,6 +32,10 @@
// Combat - Blocking/Parrying system
/// Our block_parry_data for unarmed blocks/parries. Currently only used for parrying, as unarmed block isn't implemented yet. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
var/datum/block_parry_data/block_parry_data = /datum/block_parry_data // defaults to *something* because [combat_flags] dictates whether or not we can unarmed block/parry.
/// Default
var/datum/block_parry_data/default_block_parry_data = /datum/block_parry_data
/// If we're a pugilist
var/datum/block_parry_data/pugilist_block_parry_data = /datum/block_parry_data/unarmed/pugilist
// Blocking
/// The item the user is actively blocking with if any.
var/obj/item/active_block_item
@@ -59,6 +63,8 @@
//Allows mobs to move through dense areas without restriction. For instance, in space or out of holder objects.
var/incorporeal_move = FALSE //FALSE is off, INCORPOREAL_MOVE_BASIC is normal, INCORPOREAL_MOVE_SHADOW is for ninjas
//and INCORPOREAL_MOVE_JAUNT is blocked by holy water/salt
/// Do we make floors dirty as we move?
var/causes_dirt_buildup_on_floor = FALSE
var/list/roundstart_quirks = list()
@@ -1,12 +1,3 @@
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
/mob/living/ComponentInitialize()
. = ..()
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_LIVING_NO_DENSITY), .proc/update_density)
//Stuff like mobility flag updates, resting updates, etc.
@@ -102,6 +102,30 @@
if(lying && !buckled && prob(getBruteLoss()*200/maxHealth))
makeTrail(newloc, T, old_direction)
if(causes_dirt_buildup_on_floor && (movement_type & GROUND))
dirt_buildup()
/**
* Attempts to make the floor dirty.
*/
/mob/living/proc/dirt_buildup(strength = 1)
var/turf/open/T = loc
if(!istype(T) || !T.dirt_buildup_allowed)
return
var/area/A = T.loc
if(!A.dirt_buildup_allowed)
return
var/multiplier = CONFIG_GET(number/turf_dirty_multiplier)
strength *= multiplier
var/obj/effect/decal/cleanable/dirt/D = locate() in T
if(D)
D.dirty(strength)
else
T.dirtyness += strength
if(T.dirtyness >= (isnull(T.dirt_spawn_threshold)? CONFIG_GET(number/turf_dirt_threshold) : T.dirt_spawn_threshold))
D = new /obj/effect/decal/cleanable/dirt(T)
D.dirty(T.dirt_spawn_threshold - T.dirtyness)
T.dirtyness = 0 // reset.
/mob/living/Move_Pulled(atom/A)
. = ..()
+20
View File
@@ -0,0 +1,20 @@
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
/mob/living/ComponentInitialize()
. = ..()
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_LIVING_NO_DENSITY), .proc/update_density)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_PUGILIST), .proc/update_pugilism)
/mob/living/proc/update_pugilism()
if(HAS_TRAIT(src, TRAIT_PUGILIST))
combat_flags |= COMBAT_FLAG_UNARMED_PARRY
block_parry_data = pugilist_block_parry_data
else
var/initial_combat_flags = initial(combat_flags)
if(!(initial_combat_flags & COMBAT_FLAG_UNARMED_PARRY))
combat_flags &= ~COMBAT_FLAG_UNARMED_PARRY
block_parry_data = default_block_parry_data
+6 -3
View File
@@ -911,10 +911,10 @@
if(!istype(apc) || QDELETED(apc) || apc.stat & BROKEN)
to_chat(src, "<span class='danger'>Hack aborted. The designated APC no longer exists on the power network.</span>")
playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, 1)
playsound(get_turf(src), 'sound/machines/buzz-two.ogg', 50, TRUE, ignore_walls = FALSE)
else if(apc.aidisabled)
to_chat(src, "<span class='danger'>Hack aborted. \The [apc] is no longer responding to our systems.</span>")
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 1)
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, TRUE, ignore_walls = FALSE)
else
malf_picker.processing_time += 10
@@ -923,7 +923,7 @@
apc.locked = TRUE
apc.coverlocked = TRUE
playsound(get_turf(src), 'sound/machines/ding.ogg', 50, 1)
playsound(get_turf(src), 'sound/machines/ding.ogg', 50, TRUE, ignore_walls = FALSE)
to_chat(src, "Hack complete. \The [apc] is now under your exclusive control.")
apc.update_icon()
@@ -1039,3 +1039,6 @@
if(current && eyeobj)
return eyeobj.emote(act, m_type, message, intentional, forced = TRUE)
return ..()
/mob/living/silicon/ai/zMove(dir, feedback = FALSE)
. = eyeobj.zMove(dir, feedback)
@@ -94,6 +94,25 @@
if(ai.master_multicam)
ai.master_multicam.refresh_view()
//it uses setLoc not forceMove, talks to the sillycone and not the camera mob
/mob/camera/aiEye/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(ai, "<span class='warning'>There's nowhere to go in that direction!</span>")
return FALSE
if(!canZMove(dir, target))
if(feedback)
to_chat(ai, "<span class='warning'>You couldn't move there!</span>")
return FALSE
setLoc(target, TRUE)
return TRUE
/mob/camera/aiEye/canZMove(direction, turf/target) //cameras do not respect these FLOORS you speak so much of
return TRUE
/mob/camera/aiEye/Move()
return 0
@@ -1,3 +1,30 @@
/mob/living/silicon/verb/clear_custom_holoform()
set name = "Clear Custom Holoform"
set desc = "Clear your current custom holoform"
set category = "OOC"
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
return
client.prefs.custom_holoform_icon = null
client.prefs.cached_holoform_icons = null
to_chat(src, "<span class='boldnotice'>Holoform removed.</span>")
/mob/living/silicon/verb/set_custom_holoform()
set name = "Set Custom Holoform"
set desc = "Set your custom holoform using your current preferences slot and a specified set of gear."
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
return
if(client.prefs.last_custom_holoform > world.time - CUSTOM_HOLOFORM_DELAY)
to_chat(src, "<span class='warning'>You are attempting to change custom holoforms too fast!</span>")
var/icon/new_holoform = user_interface_custom_holoform(client)
if(new_holoform)
client.prefs.custom_holoform_icon = new_holoform
client.prefs.cached_holoform_icons = null
client.prefs.last_custom_holoform = world.time
to_chat(src, "<span class='boldnotice'>Holoform set.</span>")
/mob/living/silicon/proc/attempt_set_custom_holoform()
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
@@ -426,6 +426,10 @@
//Misc
.["Cyborg - Misc (dog - blade)"] = process_holoform_icon_filter(icon('modular_citadel/icons/mob/widerobot.dmi', "blade"), HOLOFORM_FILTER_PAI, FALSE)
// Gorillas
.["Gorilla (standing)"] = process_holoform_icon_filter(icon('icons/mob/gorilla.dmi', "standing"), HOLOFORM_FILTER_PAI, FALSE)
.["Gorilla (crawling)"] = process_holoform_icon_filter(icon('icons/mob/gorilla.dmi', "crawling"), HOLOFORM_FILTER_PAI, FALSE)
/mob/living/silicon/pai/proc/default_chassis_pixel_offsets_x()
. = list()
//Engi
@@ -81,10 +81,10 @@
to_chat(src, "<span class='userdanger'>The impact degrades your holochassis!</span>")
return amount
/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/silicon/pai/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
return take_holo_damage(amount)
/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/silicon/pai/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
return take_holo_damage(amount)
/mob/living/silicon/pai/adjustToxLoss(amount, updating_health = TRUE, forced = FALSE, toxins_type = TOX_DEFAULT)
@@ -923,7 +923,8 @@
/obj/item/cyborg_clamp,
/obj/item/stack/marker_beacon,
/obj/item/destTagger,
/obj/item/stack/packageWrap)
/obj/item/stack/packageWrap,
/obj/item/card/id/miningborg)
emag_modules = list(/obj/item/borg/stun)
ratvar_modules = list(
/obj/item/clockwork/slab/cyborg/miner,
@@ -7,13 +7,13 @@
updatehealth()
return amount
/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/simple_animal/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[BRUTE])
. = adjustHealth(amount * damage_coeff[BRUTE] * CONFIG_GET(number/damage_multiplier), updating_health, forced)
/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/simple_animal/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(forced)
. = adjustHealth(amount * CONFIG_GET(number/damage_multiplier), updating_health, forced)
else if(damage_coeff[BURN])
@@ -40,23 +40,25 @@
return
..()
/mob/living/simple_animal/cockroach/Crossed(var/atom/movable/AM)
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].</span>")
adjustBruteLoss(1) //kills a normal cockroach
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
else
if(isstructure(AM))
/mob/living/simple_animal/cockroach/Crossed(atom/movable/AM)
. = ..()
if(isliving(AM))
var/mob/living/A = AM
if(A.mob_size > MOB_SIZE_SMALL && !(A.movement_type & FLYING))
if(HAS_TRAIT(A, TRAIT_PACIFISM))
A.visible_message("<span class='notice'>[A] carefully steps over [src].</span>", "<span class='notice'>You carefully step over [src] to avoid hurting it.</span>")
return
if(prob(squish_chance))
AM.visible_message("<span class='notice'>[src] was crushed under [AM].</span>")
adjustBruteLoss(1)
A.visible_message("<span class='notice'>[A] squashed [src].</span>", "<span class='notice'>You squashed [src].</span>")
adjustBruteLoss(1) //kills a normal cockroach
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] is crushed under [AM].</span>")
adjustBruteLoss(1)
else
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
/mob/living/simple_animal/cockroach/ex_act() //Explosions are a terrible way to handle a cockroach.
return
@@ -263,7 +263,7 @@
/mob/living/simple_animal/pet/dog/corgi/proc/place_on_head(obj/item/item_to_add, mob/user)
if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess
item_to_add.afterattack(src,user,1)
INVOKE_ASYNC(item_to_add, /obj/item.proc/afterattack, src, user, 1)
return
if(inventory_head)
@@ -271,13 +271,15 @@
to_chat(user, "<span class='warning'>You can't put more than one hat on [src]!</span>")
return
if(!item_to_add)
user.visible_message("[user] pets [src].","<span class='notice'>You rest your hand on [src]'s head for a moment.</span>")
user.visible_message("<span class='notice'>[user] pets [src].</span>", "<span class='notice'>You rest your hand on [src]'s head for a moment.</span>")
if(flags_1 & HOLOGRAM_1)
return
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, src, /datum/mood_event/pet_animal, src)
return
if(user && !user.temporarilyRemoveItemFromInventory(item_to_add))
to_chat(user, "<span class='warning'>\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s head!</span>")
return 0
return
var/valid = FALSE
if(ispath(item_to_add.dog_fashion, /datum/dog_fashion/head))
@@ -287,11 +289,11 @@
if(valid)
if(health <= 0)
to_chat(user, "<span class ='notice'>There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on [p_them()].</span>")
to_chat(user, "<span class='notice'>There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on [p_them()].</span>")
else if(user)
user.visible_message("[user] puts [item_to_add] on [real_name]'s head. [src] looks at [user] and barks once.",
"<span class='notice'>You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags [p_their()] tail once and barks.</span>",
"<span class='italics'>You hear a friendly-sounding bark.</span>")
user.visible_message("<span class='notice'>[user] puts [item_to_add] on [real_name]'s head. [src] looks at [user] and barks once.</span>",
"<span class='notice'>You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags [p_their()] tail once and barks.</span>",
"<span class='hear'>You hear a friendly-sounding bark.</span>")
item_to_add.forceMove(src)
src.inventory_head = item_to_add
update_corgi_fluff()
@@ -361,7 +363,7 @@
icon_state = "old_corgi"
icon_living = "old_corgi"
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
desc = "At a ripe old age of [record_age], Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
RemoveElement(/datum/element/mob_holder, held_icon)
AddElement(/datum/element/mob_holder, "old_corgi")
@@ -9,6 +9,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
real_name = "Guardian Spirit"
desc = "A mysterious being that stands by its charge, ever vigilant."
speak_emote = list("hisses")
rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS
gender = NEUTER
mob_biotypes = NONE
bubble_icon = "guardian"
@@ -110,6 +110,7 @@
/obj/effect/snare/Crossed(AM as mob|obj)
. = ..()
if(isliving(AM) && spawner && spawner.summoner && AM != spawner && !spawner.hasmatchingsummoner(AM))
to_chat(spawner.summoner, "<span class='danger'><B>[AM] has crossed surveillance snare, [name].</span></B>")
var/list/guardians = spawner.summoner.hasparasites()
@@ -109,7 +109,7 @@
to_chat(user, "<span class='info'>You strap the armor plating to [A] and sharpen [A.p_their()] claws with the nail filer. This was a great idea.</span>")
qdel(src)
mob/living/simple_animal/hostile/bear/butter //The mighty companion to Cak. Several functions used from it.
/mob/living/simple_animal/hostile/bear/butter //The mighty companion to Cak. Several functions used from it.
name = "Terrygold"
icon_state = "butterbear"
icon_living = "butterbear"
@@ -155,7 +155,7 @@ mob/living/simple_animal/hostile/bear/butter //The mighty companion to Cak. Seve
to_chat(src, "<span class='notice'>Your name is now <b>\"new_name\"</b>!</span>")
name = new_name
mob/living/simple_animal/hostile/bear/butter/AttackingTarget() //Makes some attacks by the butter bear slip those who dare cross its path.
/mob/living/simple_animal/hostile/bear/butter/AttackingTarget() //Makes some attacks by the butter bear slip those who dare cross its path.
if(isliving(target))
var/mob/living/L = target
if((L.mobility_flags & MOBILITY_STAND))
@@ -0,0 +1,69 @@
//funny reference to the video 'Expiration Date'
/mob/living/simple_animal/hostile/bread
name = "tumor bread"
desc = "I have done nothing but teleport bread for three days."
icon_state = "tumorbread"
health = 1
maxHealth = 1
turns_per_move = 5 //this isn't player speed =|
speed = 2 //this is player speed
melee_damage_lower = 1
melee_damage_upper = 2
obj_damage = 0
loot = list(/obj/item/reagent_containers/food/snacks/store/bread/tumor_bread)
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_continuous = "pokes"
response_help_simple = "poke"
response_disarm_continuous = "shoos"
response_disarm_simple = "shoo"
response_harm_continuous = "punches"
response_harm_simple = "punch"
speak_emote = list("growls")
mouse_opacity = 2
density = TRUE
ventcrawler = VENTCRAWLER_ALWAYS
verb_say = "growls"
verb_ask = "growls inquisitively"
verb_exclaim = "growls loudly"
verb_yell = "growls loudly"
del_on_death = TRUE
/mob/living/simple_animal/bread/hostile/Initialize()
. = ..()
var/area/A = get_area(src)
if(A)
notify_ghosts("A tumor bread has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE, ignore_dnr_observers = TRUE)
/mob/living/simple_animal/hostile/bread/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 tumor bread before the game has started.")
return
var/be_bread = alert("Become a tumor bread? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_bread == "No" || QDELETED(src) || !isobserver(user))
return
if(key)
to_chat(user, "<span class='notice'>Someone else already took this tumor bread.</span>")
return
sentience_act()
user.transfer_ckey(src, FALSE)
density = TRUE
/mob/living/simple_animal/hostile/bread/ex_act()
return
/mob/living/simple_animal/hostile/bread/start_pulling()
return FALSE
@@ -390,7 +390,6 @@
name = "Wrap"
panel = "Spider"
active = FALSE
datum/action/spell_action/action = null
desc = "Wrap something or someone in a cocoon. If it's a living being, you'll also consume them, allowing you to lay eggs."
ranged_mousepointer = 'icons/effects/wrap_target.dmi'
action_icon = 'icons/mob/actions/actions_animal.dmi'
@@ -511,7 +511,7 @@
DestroyObjectsInDirection(direction)
mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with megafauna destroying everything around them
/mob/living/simple_animal/hostile/proc/DestroySurroundings() // for use with megafauna destroying everything around them
if(environment_smash)
EscapeConfinement()
for(var/dir in GLOB.cardinals)
@@ -94,16 +94,17 @@
consume_bait()
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/proc/consume_bait()
var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in oview(src, 9)
var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in oview(src, 9)
if(!diamonds && !bait)
return
var/list/L = list()
for(var/obj/O in view(src, 9))
L += O
var/obj/item/stack/ore/diamond/diamonds = locate(/obj/item/stack/ore/diamond) in L
if(diamonds)
var/distanced = 0
distanced = get_dist(loc,diamonds.loc)
if(distanced <= 1 && diamonds)
qdel(diamonds)
src.visible_message("<span class='notice'>[src] consumes [diamonds], and it disappears! ...At least, you think.</span>")
var/obj/item/pen/survival/bait = locate(/obj/item/pen/survival) in L
if(bait)
var/distanceb = 0
distanceb = get_dist(loc,bait.loc)
@@ -219,6 +219,9 @@
/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner)
. = ..()
INVOKE_ASYNC(src, .proc/createpatch)
/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/proc/createpatch()
var/tentacle_locs = spiral_range_turfs(1, get_turf(src))
for(var/T in tentacle_locs)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
@@ -42,7 +42,8 @@
AddElement(/datum/element/ventcrawling, given_tier = VENTCRAWLER_ALWAYS)
/mob/living/simple_animal/hostile/retaliate/frog/Crossed(AM as mob|obj)
. = ..()
if(!stat && isliving(AM))
var/mob/living/L = AM
if(L.mob_size > MOB_SIZE_TINY)
playsound(src, stepped_sound, 50, 1)
playsound(src, stepped_sound, 50, TRUE)
@@ -190,5 +190,5 @@
* Arguments:
* * datum/beam/vine - The vine to be removed from the list.
*/
mob/living/simple_animal/hostile/venus_human_trap/proc/remove_vine(datum/beam/vine, force)
/mob/living/simple_animal/hostile/venus_human_trap/proc/remove_vine(datum/beam/vine, force)
vines -= vine
+167 -7
View File
@@ -83,6 +83,8 @@
//Headset for Poly to yell at engineers :)
var/obj/item/radio/headset/ears = null
/// spawns with headset
var/spawns_with_headset = FALSE
//The thing the parrot is currently interested in. This gets used for items the parrot wants to pick up, mobs it wants to steal from,
//mobs it wants to attack or mobs that have attacked it
@@ -105,13 +107,14 @@
/mob/living/simple_animal/parrot/Initialize()
. = ..()
if(!ears)
var/headset = pick(/obj/item/radio/headset/headset_sec, \
/obj/item/radio/headset/headset_eng, \
/obj/item/radio/headset/headset_med, \
/obj/item/radio/headset/headset_sci, \
/obj/item/radio/headset/headset_cargo)
ears = new headset(src)
if(spawns_with_headset)
if(!ears)
var/headset = pick(/obj/item/radio/headset/headset_sec, \
/obj/item/radio/headset/headset_eng, \
/obj/item/radio/headset/headset_med, \
/obj/item/radio/headset/headset_sci, \
/obj/item/radio/headset/headset_cargo)
ears = new headset(src)
parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var
@@ -881,6 +884,7 @@
speak = list("Poly wanna cracker!", ":e Check the crystal, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS ABOUT TO DELAMINATE CALL THE SHUTTLE")
gold_core_spawnable = NO_SPAWN
speak_chance = 3
spawns_with_headset = TRUE
var/memory_saved = FALSE
var/rounds_survived = 0
var/longest_survival = 0
@@ -1034,3 +1038,159 @@
/mob/living/simple_animal/parrot/clock_hawk/ratvar_act()
return
// Different Parrot Breeds
/mob/living/simple_animal/parrot/kea
name = "Kea"
icon_state = "kea-flap"
icon_living = "kea-flap"
icon_dead = "kea-dead"
icon_sit = "kea_sit"
/mob/living/simple_animal/parrot/eclectusr
name = "Eclectus"
icon_state = "eclectusr-flap"
icon_living = "eclectusr-flap"
icon_dead = "eclectusr-dead"
icon_sit = "electusr_sit"
/mob/living/simple_animal/parrot/eclectus
name = "Eclectus"
icon_state = "eclectus-flap"
icon_living = "eclectus-flap"
icon_dead = "eclectus-dead"
icon_sit = "electus_sit"
/mob/living/simple_animal/parrot/eclectusf
name = "Eclectus"
icon_state = "eclectusf-flap"
icon_living = "eclectusf-flap"
icon_dead = "eclectusf-dead"
icon_sit = "electusf_sit"
/mob/living/simple_animal/parrot/greybird
name = "Grey Bird"
icon_state = "agrey-flap"
icon_living = "agrey-flap"
icon_dead = "agrey-dead"
icon_sit = "agrey_sit"
/mob/living/simple_animal/parrot/blue_caique
name = "Blue Caique "
icon_state = "bcaique-flap"
icon_living = "bcaique-flap"
icon_dead = "bcaique-dead"
icon_sit = "bcaique_sit"
/mob/living/simple_animal/parrot/white_caique
name = "White caique"
icon_state = "wcaique-flap"
icon_living = "wcaique-flap"
icon_dead = "wcaique-dead"
icon_sit = "wcaique_sit"
/mob/living/simple_animal/parrot/green_budgerigar
name = "Green Budgerigar"
icon_state = "gbudge-flap"
icon_living = "gbudge-flap"
icon_dead = "gbudge-dead"
icon_sit = "gbudge_sit"
/mob/living/simple_animal/parrot/blue_Budgerigar
name = "Blue Budgerigar"
icon_state = "bbudge-flap"
icon_living = "bbudge-flap"
icon_dead = "bbudge-dead"
icon_sit = "bbudge_sit"
/mob/living/simple_animal/parrot/bluegreen_Budgerigar
name = "Bluegreen Budgerigar"
icon_state = "bgbudge-flap"
icon_living = "bgbudge-flap"
icon_dead = "bgbudge-dead"
icon_sit = "bgbudge_sit"
/mob/living/simple_animal/parrot/commonblackbird
name = "Black Bird"
icon_state = "commonblackbird"
icon_living = "commonblackbird"
icon_dead = "commonblackbird-dead"
icon_sit = "commonblackbird_sit"
/mob/living/simple_animal/parrot/azuretit
name = "Azure Tit"
icon_state = "azuretit"
icon_living = "azuretit"
icon_dead = "azuretit-dead"
icon_sit = "azuretit_sit"
/mob/living/simple_animal/parrot/europeanrobin
name = "European Robin"
icon_state = "europeanrobin"
icon_living = "europeanrobin"
icon_dead = "europeanrobin-dead"
icon_sit = "europeanrobin_sit"
/mob/living/simple_animal/parrot/goldcrest
name = "Goldcrest"
icon_state = "goldcrest"
icon_living = "goldcrest"
icon_dead = "goldcrest-dead"
icon_sit = "goldencrest_sit"
/mob/living/simple_animal/parrot/ringneckdove
name = "Ringneck Dove"
icon_state = "ringneckdove"
icon_living = "ringneckdove"
icon_dead = "ringneckdove-dead"
icon_sit = "ringneckdove_sit"
/mob/living/simple_animal/parrot/cockatiel
name = "Cockatiel"
icon_state = "tiel-flap"
icon_living = "tiel-flap"
icon_dead = "tiel-dead"
icon_sit = "tiel_sit"
/mob/living/simple_animal/parrot/white_cockatiel
name = "White Cockatiel"
icon_state = "wtiel-flap"
icon_living = "wtiel-flap"
icon_dead = "wtiel-dead"
icon_sit = "wtiel_sit"
/mob/living/simple_animal/parrot/yellowish_cockatiel
name = "Yellowish Cockatiel"
icon_state = "luttiel-flap"
icon_living = "luttiel-flap"
icon_dead = "luttiel-dead"
icon_sit = "luttiel_sit"
/mob/living/simple_animal/parrot/grey_cockatiel
name = "Grey Cockatiel"
icon_state = "blutiel-flap"
icon_living = "blutiel-flap"
icon_dead = "blutiel-dead"
icon_sit = "blutiel_sit"
/mob/living/simple_animal/parrot/too
name = "Too"
icon_state = "too-flap"
icon_living = "too-flap"
icon_dead = "too-dead"
icon_sit = "too_sit"
/mob/living/simple_animal/parrot/hooded_too
name = "Utoo"
icon_state = "utoo-flap"
icon_living = "utoo-flap"
icon_dead = "utoo-dead"
icon_sit = "utoo_sit"
/mob/living/simple_animal/parrot/pink_too
name = "Mtoo"
icon_state = "mtoo-flap"
icon_living = "mtoo-flap"
icon_dead = "mtoo-dead"
icon_sit = "mtoo_sit"
@@ -226,7 +226,7 @@
. += "Power Level: [powerlevel]"
/mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE)
/mob/living/simple_animal/slime/adjustFireLoss(amount, updating_health = TRUE, forced = FALSE, only_robotic = FALSE, only_organic = TRUE)
if(!forced)
amount = -abs(amount)
return ..() //Heals them
+6 -33
View File
@@ -457,39 +457,6 @@
else
to_chat(src, "You don't have a mind datum for some reason, so you can't add a note to it.")
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
if (CONFIG_GET(flag/norespawn))
return
if ((stat != DEAD || !( SSticker )))
to_chat(usr, "<span class='boldnotice'>You must be dead to use this!</span>")
return
log_game("[key_name(usr)] used abandon mob.")
to_chat(usr, "<span class='boldnotice'>Please roleplay correctly!</span>")
if(!client)
log_game("[key_name(usr)] AM failed due to disconnect.")
return
client.screen.Cut()
client.screen += client.void
if(!client)
log_game("[key_name(usr)] AM failed due to disconnect.")
return
var/mob/dead/new_player/M = new /mob/dead/new_player()
if(!client)
log_game("[key_name(usr)] AM failed due to disconnect.")
qdel(M)
return
M.key = key
// M.Login() //wat
return
/mob/proc/transfer_ckey(mob/new_mob, send_signal = TRUE)
if(!new_mob || (!ckey && new_mob.ckey))
CRASH("transfer_ckey() called [new_mob ? "on ckey-less mob with a player mob as target" : "without a valid mob target"]!")
@@ -1002,6 +969,12 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
switch(var_name)
if("logging")
return debug_variable(var_name, logging, 0, src, FALSE)
if(NAMEOF(src, lastKnownIP))
if(!check_rights(R_SENSITIVE, FALSE))
return "SENSITIVE"
if(NAMEOF(src, computer_id))
if(!check_rights(R_SENSITIVE, FALSE))
return "SENSITIVE"
. = ..()
/mob/vv_auto_rename(new_name)
+3
View File
@@ -177,3 +177,6 @@
var/list/ability_actions
/// ability = list(data). see __DEFINES/mobs/innate_abilities.dm
var/list/ability_properties
///Override for sound_environments. If this is set the user will always hear a specific type of reverb (Instead of the area defined reverb)
var/sound_environment_override = SOUND_ENVIRONMENT_NONE
+1 -1
View File
@@ -508,7 +508,7 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
if(LOG_EMOTE)
colored_message = "(EMOTE) [colored_message]"
var/list/timestamped_message = list("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(src)] [loc_name(src)]" = colored_message)
var/list/timestamped_message = list("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(src)] [loc_name(src)] (Event #[LAZYLEN(logging[smessage_type])])" = colored_message)
logging[smessage_type] += timestamped_message
+4
View File
@@ -73,6 +73,7 @@
return FALSE
//We are now going to move
var/add_delay = mob.movement_delay()
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay * ( (NSCOMPONENT(direction) && EWCOMPONENT(direction)) ? 2 : 1 ) ), FALSE) // set it now in case of pulled objects
if(old_move_delay + (add_delay*MOVEMENT_DELAY_BUFFER_DELTA) + MOVEMENT_DELAY_BUFFER > world.time)
move_delay = old_move_delay
else
@@ -95,6 +96,7 @@
if((direction & (direction - 1)) && mob.loc == n) //moved diagonally successfully
add_delay *= 2
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay), FALSE)
move_delay += add_delay
if(.) // If mob is null here, we deserve the runtime
if(mob.throwing)
@@ -104,6 +106,8 @@
if(AM && AM.density && !SEND_SIGNAL(L, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && !ismob(AM))
L.setDir(turn(L.dir, 180))
last_move = world.time
SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay)
/// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement.
+88 -14
View File
@@ -3,14 +3,14 @@
//////////////////////////////////////////////////////
/mob/proc/get_top_level_mob()
if(istype(src.loc,/mob)&&src.loc!=src)
var/mob/M=src.loc
if(ismob(src.loc) && src.loc != src)
var/mob/M = src.loc
return M.get_top_level_mob()
return src
proc/get_top_level_mob(var/mob/S)
if(istype(S.loc,/mob)&&S.loc!=S)
var/mob/M=S.loc
/proc/get_top_level_mob(mob/S)
if(ismob(S.loc) && S.loc != S)
var/mob/M = S.loc
return M.get_top_level_mob()
return S
@@ -86,15 +86,6 @@ proc/get_top_level_mob(var/mob/S)
else if(!params)
var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN)
if(subtle_emote && !check_invalid(user, subtle_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
if("Visible")
emote_type = EMOTE_VISIBLE
if("Hearable")
emote_type = EMOTE_AUDIBLE
else
alert("Unable to use this emote, must be either hearable or visible.")
return
message = subtle_emote
else
return FALSE
@@ -111,6 +102,80 @@ proc/get_top_level_mob(var/mob/S)
user.visible_message(message = message, self_message = message, vision_distance = 1, ignored_mobs = GLOB.dead_mob_list, omni = TRUE)
///////////////// SUBTLE 3: DARE DICE
/datum/emote/living/subtler_table
key = "subtler_table"
key_third_person = "subtler_table"
message = null
mob_type_blacklist_typecache = list(/mob/living/brain)
/datum/emote/living/subtler_table/proc/check_invalid(mob/user, input)
if(stop_bad_mime.Find(input, 1, 1))
to_chat(user, "<span class='danger'>Invalid emote.</span>")
return TRUE
return FALSE
/datum/emote/living/subtler_table/run_emote(mob/user, params, type_override = null)
if(!locate(/obj/structure/table) in range(user, 1))
to_chat(user, "There are no tables around you.")
return FALSE
if(jobban_isbanned(user, "emote"))
to_chat(user, "You cannot send subtle emotes (banned).")
return FALSE
else if(user.client && user.client.prefs.muted & MUTE_IC)
to_chat(user, "You cannot send IC messages (muted).")
return FALSE
else if(!params)
var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN)
if(subtle_emote && !check_invalid(user, subtle_emote))
message = subtle_emote
else
return FALSE
else
message = params
if(type_override)
emote_type = type_override
. = TRUE
if(!can_run_emote(user))
return FALSE
user.log_message("[message] (TABLE-WRAPPING)", LOG_SUBTLER)
message = "<span class='emote'><b>[user]</b> <i>[user.say_emphasis(message)]</i></span>"
var/list/show_to = list()
var/list/processing = list()
var/safety = 25
for(var/obj/structure/table/T in range(user, 1))
processing |= T
for(var/i = 1; i <= processing.len; ++i)
var/obj/structure/table/T = processing[i]
if(safety-- <= 0)
to_chat(user, "Table scan aborted early, some people might have not received the message (max 25)")
break
if(get_dist(T, user) > 7)
continue // nah
processing |= T
for(var/mob/living/M in range(T, 1)) // no ghosts/cameramobs
show_to |= M
var/obj/structure/table/other
other = locate() in get_step(T, NORTH)
if(other)
processing |= other
other = locate() in get_step(T, SOUTH)
if(other)
processing |= other
other = locate() in get_step(T, WEST)
if(other)
processing |= other
other = locate() in get_step(T, EAST)
if(other)
processing |= other
for(var/i in show_to)
var/mob/M = i
M.show_message(message)
///////////////// VERB CODE
/mob/living/verb/subtle()
set name = "Subtle"
@@ -128,3 +193,12 @@ proc/get_top_level_mob(var/mob/S)
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.emote("subtler")
///////////////// VERB CODE 3
/mob/living/verb/subtler_table()
set name = "Subtler Around Table"
set category = "IC"
if(GLOB.say_disabled) //This is dumb but it's here because heehoo copypaste, who the FUCK uses this to identify lag?
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.emote("subtler_table")
+3
View File
@@ -175,6 +175,7 @@
icon = null
cut_overlays()
invisibility = INVISIBILITY_MAXIMUM
new /obj/effect/temp_visual/monkeyify/humanify(loc)
transformation_timer = addtimer(CALLBACK(src, .proc/finish_humanize, tr_flags), TRANSFORMATION_DURATION, TIMER_UNIQUE)
@@ -202,6 +203,8 @@
var/mob/living/carbon/human/O = new( loc )
for(var/obj/item/C in O.loc)
if(C.anchored)
continue
O.equip_to_appropriate_slot(C)
dna.transfer_identity(O)