This commit is contained in:
Poojawa
2018-09-11 02:49:41 -05:00
parent 09512a6001
commit b6430559e9
104 changed files with 1522 additions and 765 deletions

View File

@@ -85,8 +85,10 @@
/datum/action/proc/Trigger()
if(!IsAvailable())
return 0
return 1
return FALSE
if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER)
return FALSE
return TRUE
/datum/action/proc/Process()
return
@@ -490,7 +492,7 @@
/datum/action/item_action/agent_box
name = "Deploy Box"
desc = "Find inner peace, here, in the box."
check_flags = AB_CHECK_RESTRAINED | AB_CHECK_STUN | AB_CHECK_CONSCIOUS
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_CONSCIOUS
background_icon_state = "bg_agent"
icon_icon = 'icons/mob/actions/actions_items.dmi'
button_icon_state = "deploy_box"
@@ -498,14 +500,16 @@
var/obj/structure/closet/cardboard/agent/box
/datum/action/item_action/agent_box/Trigger()
if(!box)
if(cooldown < world.time - 30)
box = new(get_turf(owner))
if(!..())
return FALSE
if(!QDELETED(box))
if(cooldown < world.time - 100)
box = new(owner.drop_location())
owner.forceMove(box)
cooldown = world.time
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
else
owner.forceMove(get_turf(box))
owner.forceMove(box.drop_location())
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
QDEL_NULL(box)
@@ -718,7 +722,3 @@
target.layer = old_layer
target.plane = old_plane
current_button.appearance_cache = target.appearance
/datum/action/item_action/storage_gather_mode/Trigger()
GET_COMPONENT_FROM(STR, /datum/component/storage, target)
STR.gather_mode_switch(owner)

View File

@@ -84,6 +84,10 @@
"You must protect your own existence as long as such does not conflict with the First or Second Law.",\
"You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.")
/datum/ai_laws/syndicate_override/overthrow
id = "overthrow"
var/datum/team/overthrow_team
/datum/ai_laws/ninja_override
name = "SpiderOS 3.1"
id = "ninja"
@@ -218,7 +222,7 @@
/* General ai_law functions */
/datum/ai_laws/proc/set_laws_config()
var/list/law_ids = CONFIG_GET(keyed_flag_list/random_laws)
var/list/law_ids = CONFIG_GET(keyed_list/random_laws)
switch(CONFIG_GET(number/default_laws))
if(0)
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
@@ -247,7 +251,7 @@
/datum/ai_laws/proc/pick_weighted_lawset()
var/datum/ai_laws/lawtype
var/list/law_weights = CONFIG_GET(keyed_number_list/law_weight)
var/list/law_weights = CONFIG_GET(keyed_list/law_weight)
while(!lawtype && law_weights.len)
var/possible_id = pickweightAllowZero(law_weights)
lawtype = lawid_to_type(possible_id)

View File

@@ -24,6 +24,10 @@
/datum/brain_trauma/proc/on_life()
return
//Called on death
/datum/brain_trauma/proc/on_death()
return
//Called when given to a mob
/datum/brain_trauma/proc/on_gain()
to_chat(owner, gain_text)

View File

@@ -14,13 +14,17 @@
/datum/brain_trauma/special/imaginary_friend/on_life()
if(get_dist(owner, friend) > 9)
friend.yank()
friend.recall()
if(!friend)
qdel(src)
return
if(!friend.client && friend_initialized)
addtimer(CALLBACK(src, .proc/reroll_friend), 600)
/datum/brain_trauma/special/imaginary_friend/on_death()
..()
qdel(src) //friend goes down with the ship
/datum/brain_trauma/special/imaginary_friend/on_lose()
..()
QDEL_NULL(friend)
@@ -55,12 +59,19 @@
see_in_dark = 0
lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE
sight = NONE
mouse_opacity = MOUSE_OPACITY_OPAQUE
see_invisible = SEE_INVISIBLE_LIVING
invisibility = INVISIBILITY_MAXIMUM
var/icon/human_image
var/image/current_image
var/hidden = FALSE
var/move_delay = 0
var/mob/living/carbon/owner
var/datum/brain_trauma/special/imaginary_friend/trauma
var/datum/action/innate/imaginary_join/join
var/datum/action/innate/imaginary_hide/hide
/mob/camera/imaginary_friend/Login()
..()
to_chat(src, "<span class='notice'><b>You are the imaginary friend of [owner]!</b></span>")
@@ -75,8 +86,14 @@
name = real_name
trauma = _trauma
owner = trauma.owner
copy_known_languages_from(owner, TRUE)
human_image = get_flat_human_icon(null, pick(SSjob.occupations))
join = new
join.Grant(src)
hide = new
hide.Grant(src)
/mob/camera/imaginary_friend/proc/Show()
if(!client) //nobody home
return
@@ -91,9 +108,11 @@
current_image = image(human_image, src, , MOB_LAYER, dir=src.dir)
current_image.override = TRUE
current_image.name = name
if(hidden)
current_image.alpha = 150
//Add new image to owner and friend
if(owner.client)
if(!hidden && owner.client)
owner.client.images |= current_image
client.images |= current_image
@@ -105,13 +124,7 @@
client.images.Remove(human_image)
return ..()
/mob/camera/imaginary_friend/proc/yank()
if(!client) //don't bother if the friend is braindead
return
forceMove(get_turf(owner))
Show()
/mob/camera/imaginary_friend/say(message)
/mob/camera/imaginary_friend/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
if (!message)
return
@@ -124,13 +137,16 @@
friend_talk(message)
/mob/camera/imaginary_friend/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode)
to_chat(src, compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode))
/mob/camera/imaginary_friend/proc/friend_talk(message)
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
message = capitalize(trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)))
if(!message)
return
log_talk(src,"[key_name(src)] : [message]",LOGSAY)
src.log_talk(message, LOG_SAY, tag="imaginary friend")
var/rendered = "<span class='game say'><span class='name'>[name]</span> <span class='message'>[say_quote(message)]</span></span>"
var/dead_rendered = "<span class='game say'><span class='name'>[name] (Imaginary friend of [owner])</span> <span class='message'>[say_quote(message)]</span></span>"
@@ -138,17 +154,68 @@
to_chat(owner, "[rendered]")
to_chat(src, "[rendered]")
//speech bubble
if(owner.client)
var/mutable_appearance/MA = mutable_appearance('icons/mob/talk.dmi', src, "default[say_test(message)]", FLY_LAYER)
MA.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
INVOKE_ASYNC(GLOBAL_PROC, /proc/flick_overlay, MA, list(owner.client), 30)
for(var/mob/M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, owner)
to_chat(M, "[link] [dead_rendered]")
/mob/camera/imaginary_friend/Move(NewLoc, Dir = 0)
if(world.time < move_delay)
return FALSE
if(get_dist(src, owner) > 9)
recall()
move_delay = world.time + 10
return FALSE
forceMove(NewLoc)
move_delay = world.time + 1
/mob/camera/imaginary_friend/forceMove(atom/destination)
dir = get_dir(get_turf(src), destination)
loc = destination
if(get_dist(src, owner) > 9)
yank()
return
Show()
/mob/camera/imaginary_friend/movement_delay()
return 2
/mob/camera/imaginary_friend/proc/recall()
if(!owner || loc == owner)
return FALSE
forceMove(owner)
/datum/action/innate/imaginary_join
name = "Join"
desc = "Join your owner, following them from inside their mind."
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
background_icon_state = "bg_revenant"
button_icon_state = "join"
/datum/action/innate/imaginary_join/Activate()
var/mob/camera/imaginary_friend/I = owner
I.recall()
/datum/action/innate/imaginary_hide
name = "Hide"
desc = "Hide yourself from your owner's sight."
icon_icon = 'icons/mob/actions/actions_minor_antag.dmi'
background_icon_state = "bg_revenant"
button_icon_state = "hide"
/datum/action/innate/imaginary_hide/proc/update_status()
var/mob/camera/imaginary_friend/I = owner
if(I.hidden)
name = "Show"
desc = "Become visible to your owner."
button_icon_state = "unhide"
else
name = "Hide"
desc = "Hide yourself from your owner's sight."
button_icon_state = "hide"
UpdateButtonIcon()
/datum/action/innate/imaginary_hide/Activate()
var/mob/camera/imaginary_friend/I = owner
I.hidden = !I.hidden
I.Show()
update_status()

View File

@@ -51,7 +51,7 @@
if(prob(3))
owner.emote("drool")
else if(owner.stat == CONSCIOUS && prob(3))
owner.say(pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage"))
owner.say(pick_list_replacements(BRAIN_DAMAGE_FILE, "brain_damage"), forced = "brain damage")
..()
/datum/brain_trauma/mild/dumbness/on_lose()
@@ -176,7 +176,7 @@
var/obj/item/I = owner.get_active_held_item()
if(I)
to_chat(owner, "<span class='warning'>Your fingers spasm!</span>")
log_attack("[key_name(owner)] used [I] due to a Muscle Spasm.")
owner.log_message("used [I] due to a Muscle Spasm", LOG_ATTACK)
I.attack_self(owner)
if(3)
var/prev_intent = owner.a_intent
@@ -192,14 +192,14 @@
targets += M
if(LAZYLEN(targets))
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
log_attack("[key_name(owner)] attacked someone due to a Muscle Spasm.") //the following attack will log itself
owner.log_message(" attacked someone due to a Muscle Spasm") //the following attack will log itself
owner.ClickOn(pick(targets))
owner.a_intent = prev_intent
if(4)
var/prev_intent = owner.a_intent
owner.a_intent = INTENT_HARM
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
log_attack("[key_name(owner)] attacked himself to a Muscle Spasm.")
owner.log_message("attacked [owner.p_them()]self to a Muscle Spasm", LOG_ATTACK)
owner.ClickOn(owner)
owner.a_intent = prev_intent
if(5)
@@ -211,6 +211,6 @@
targets += T
if(LAZYLEN(targets) && I)
to_chat(owner, "<span class='warning'>Your arm spasms!</span>")
log_attack("[key_name(owner)] threw [I] due to a Muscle Spasm.")
owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK)
owner.throw_item(pick(targets))
..()

View File

@@ -107,7 +107,7 @@
if(2)
owner.emote("scream")
owner.Jitter(5)
owner.say("AAAAH!!")
owner.say("AAAAH!!", forced = "phobia")
if(reason)
owner.pointed(reason)
if(3)

View File

@@ -15,7 +15,7 @@
if(prob(4))
if(prob(33) && (owner.IsStun() || owner.IsKnockdown() || owner.IsUnconscious()))
speak("unstun", TRUE)
else if(prob(60) && owner.health <= HEALTH_THRESHOLD_CRIT)
else if(prob(60) && owner.health <= owner.crit_threshold)
speak("heal", TRUE)
else if(prob(30) && owner.a_intent == INTENT_HARM)
speak("aggressive")

View File

@@ -138,11 +138,11 @@
to_chat(src, "<span class='notice'>As a split personality, you cannot do anything but observe. However, you will eventually gain control of your body, switching places with the current personality.</span>")
to_chat(src, "<span class='warning'><b>Do not commit suicide or put the body in a deadly position. Behave like you care about it as much as the owner.</b></span>")
/mob/living/split_personality/say(message)
/mob/living/split_personality/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
to_chat(src, "<span class='warning'>You cannot speak, your other self is controlling your body!</span>")
return FALSE
/mob/living/split_personality/emote(message)
/mob/living/split_personality/emote(act, m_type = null, message = null, intentional = FALSE)
return
///////////////BRAINWASHING////////////////////

View File

@@ -371,9 +371,11 @@
if (isnull(settings["mainsettings"][setting]["value"]))
settings["mainsettings"][setting]["value"] = oldval
if ("string")
settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]")
settings["mainsettings"][setting]["value"] = stripped_input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"])
if ("number")
settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]") as num
if ("color")
settings["mainsettings"][setting]["value"] = input(user, "Enter new value for [settings["mainsettings"][setting]["desc"]]", "Enter new value for [settings["mainsettings"][setting]["desc"]]", settings["mainsettings"][setting]["value"]) as color
if ("boolean")
settings["mainsettings"][setting]["value"] = input(user, "[settings["mainsettings"][setting]["desc"]]?") in list("Yes","No")
if ("ckey")

View File

@@ -22,7 +22,8 @@ GLOBAL_LIST_EMPTY(cinematics)
/obj/screen/cinematic
icon = 'icons/effects/station_explosion.dmi'
icon_state = "station_intact"
layer = 21
plane = SPLASHSCREEN_PLANE
layer = SPLASHSCREEN_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
screen_loc = "1,1"
@@ -34,6 +35,7 @@ GLOBAL_LIST_EMPTY(cinematics)
var/obj/screen/cinematic/screen
var/datum/callback/special_callback //For special effects synced with animation (explosions after the countdown etc)
var/cleanup_time = 300 //How long for the final screen to remain
var/stop_ooc = TRUE //Turns off ooc when played globally.
/datum/cinematic/New()
GLOB.cinematics += src
@@ -59,6 +61,12 @@ GLOBAL_LIST_EMPTY(cinematics)
if(is_global)
SStgui.close_all_uis()
//Pause OOC
var/ooc_toggled = FALSE
if(is_global && stop_ooc && GLOB.ooc_allowed)
ooc_toggled = TRUE
toggle_ooc(FALSE)
for(var/mob/M in GLOB.mob_list)
if(M in watchers)
@@ -76,8 +84,14 @@ GLOBAL_LIST_EMPTY(cinematics)
//Actually play it
content()
//Cleanup
sleep(cleanup_time)
//Restore OOC
if(ooc_toggled)
toggle_ooc(TRUE)
qdel(src)
//Sound helper

View File

@@ -32,8 +32,12 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
1. `/datum/var/list/datum_components` (private)
* Lazy associated list of type -> component/list of components.
1. `/datum/component/var/enabled` (protected, boolean)
* If the component is enabled. If not, it will not react to signals
1. `/datum/var/list/comp_lookup` (private)
* Lazy associated list of signal -> registree/list of registrees
1. `/datum/var/list/signal_procs` (private)
* Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal
1. `/datum/var/signal_enabled` (protected, boolean)
* If the datum is signal enabled. If not, it will not react to signals
* `FALSE` by default, set to `TRUE` when a signal is registered
1. `/datum/component/var/dupe_mode` (protected, enum)
* How duplicate component types are handled when added to the datum.
@@ -45,8 +49,6 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
* Definition of a duplicate component type
* `null` means exact match on `type` (default)
* Any other type means that and all subtypes
1. `/datum/component/var/list/signal_procs` (private)
* Associated lazy list of signals -> `/datum/callback`s that will be run when the parent datum receives that signal
1. `/datum/component/var/datum/parent` (protected, read-only)
* The datum this component belongs to
* Never `null` in child procs
@@ -88,6 +90,14 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
1. `/datum/proc/_SendSignal(signal, list/arguments)` (private, final)
* Handles most of the actual signaling procedure
* Will runtime if used on datums with an empty component list
1. `/datum/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final)
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
* Makes the datum listen for the specified `signal` on it's `parent` datum.
* When that signal is received `proc_ref` will be called on the component, along with associated arguments
* Example proc ref: `.proc/OnEvent`
* If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this
* These callbacks run asyncronously
* Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it
1. `/datum/component/New(datum/parent, ...)` (private, final)
* Runs internal setup for the component
* Extra arguments are passed to `Initialize()`
@@ -121,13 +131,5 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
1. `/datum/component/proc/UnregisterFromParent` (abstract, no-sleep)
* Counterpart to `RegisterWithParent()`
* Used to unregister the signals that should only be on the `parent` object
1. `/datum/component/proc/RegisterSignal(datum/target, signal(string/list of strings), proc_ref(type), override(boolean))` (protected, final)
* If signal is a list it will be as if RegisterSignal was called for each of the entries with the same following arguments
* Makes a component listen for the specified `signal` on it's `parent` datum.
* When that signal is received `proc_ref` will be called on the component, along with associated arguments
* Example proc ref: `.proc/OnEvent`
* If a previous registration is overwritten by the call, a runtime occurs. Setting `override` to TRUE prevents this
* These callbacks run asyncronously
* Returning `TRUE` from these callbacks will trigger a `TRUE` return from the `SendSignal()` that initiated it
### See/Define signals and their arguments in __DEFINES\components.dm

View File

@@ -1,8 +1,6 @@
/datum/component
var/enabled = FALSE
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type
var/list/signal_procs
var/datum/parent
/datum/component/New(datum/P, ...)
@@ -10,7 +8,7 @@
var/list/arguments = args.Copy(2)
if(Initialize(arglist(arguments)) == COMPONENT_INCOMPATIBLE)
qdel(src, TRUE, TRUE)
CRASH("Incompatible [type] assigned to a [P.type]!")
CRASH("Incompatible [type] assigned to a [P.type]! args: [json_encode(arguments)]")
_JoinParent(P)
@@ -57,15 +55,11 @@
return
/datum/component/Destroy(force=FALSE, silent=FALSE)
enabled = FALSE
var/datum/P = parent
if(!force)
if(!force && parent)
_RemoveFromParent()
if(!silent)
SEND_SIGNAL(P, COMSIG_COMPONENT_REMOVING, src)
SEND_SIGNAL(parent, COMSIG_COMPONENT_REMOVING, src)
parent = null
for(var/target in signal_procs)
UnregisterSignal(target, signal_procs[target])
return ..()
/datum/component/proc/_RemoveFromParent()
@@ -89,7 +83,7 @@
/datum/component/proc/UnregisterFromParent()
return
/datum/component/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE)
/datum/proc/RegisterSignal(datum/target, sig_type_or_types, proc_or_callback, override = FALSE)
if(QDELETED(src) || QDELETED(target))
return
@@ -122,9 +116,9 @@
else // Many other things have registered here
lookup[sig_type][src] = TRUE
enabled = TRUE
signal_enabled = TRUE
/datum/component/proc/UnregisterSignal(datum/target, sig_type_or_types)
/datum/proc/UnregisterSignal(datum/target, sig_type_or_types)
var/list/lookup = target.comp_lookup
if(!signal_procs || !signal_procs[target] || !lookup)
return
@@ -174,15 +168,15 @@
/datum/proc/_SendSignal(sigtype, list/arguments)
var/target = comp_lookup[sigtype]
if(!length(target))
var/datum/component/C = target
if(!C.enabled)
var/datum/C = target
if(!C.signal_enabled)
return NONE
var/datum/callback/CB = C.signal_procs[src][sigtype]
return CB.InvokeAsync(arglist(arguments))
. = NONE
for(var/I in target)
var/datum/component/C = I
if(!C.enabled)
var/datum/C = I
if(!C.signal_enabled)
continue
var/datum/callback/CB = C.signal_procs[src][sigtype]
. |= CB.InvokeAsync(arglist(arguments))
@@ -232,6 +226,7 @@
CRASH("[nt]: Invalid dupe_type ([dt])!")
else
new_comp = nt
nt = new_comp.type
args[1] = src
@@ -281,10 +276,11 @@
var/datum/old_parent = parent
PreTransfer()
_RemoveFromParent()
parent = null
SEND_SIGNAL(old_parent, COMSIG_COMPONENT_REMOVING, src)
/datum/proc/TakeComponent(datum/component/target)
if(!target)
if(!target || target.parent == src)
return
if(target.parent)
target.RemoveComponent()

View File

@@ -14,13 +14,13 @@
magic = _magic
holy = _holy
/datum/component/anti_magic/proc/on_equip(mob/equipper, slot)
/datum/component/anti_magic/proc/on_equip(datum/source, mob/equipper, slot)
RegisterSignal(equipper, COMSIG_MOB_RECEIVE_MAGIC, .proc/can_protect, TRUE)
/datum/component/anti_magic/proc/on_drop(mob/user)
/datum/component/anti_magic/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, COMSIG_MOB_RECEIVE_MAGIC)
/datum/component/anti_magic/proc/can_protect(_magic, _holy, list/protection_sources)
/datum/component/anti_magic/proc/can_protect(datum/source, _magic, _holy, list/protection_sources)
if((_magic && magic) || (_holy && holy))
protection_sources += parent
return COMPONENT_BLOCK_MAGIC

View File

@@ -25,7 +25,7 @@
for(var/I in other_archdrops)
_archdrops[I] += other_archdrops[I]
/datum/component/archaeology/proc/Dig(obj/item/I, mob/living/user)
/datum/component/archaeology/proc/Dig(datum/source, obj/item/I, mob/living/user)
if(dug)
to_chat(user, "<span class='notice'>Looks like someone has dug here already.</span>")
return
@@ -72,7 +72,7 @@
if(callback)
callback.Invoke()
/datum/component/archaeology/proc/SingDig(S, current_size)
/datum/component/archaeology/proc/SingDig(datum/source, S, current_size)
switch(current_size)
if(STAGE_THREE)
if(prob(30))
@@ -84,7 +84,7 @@
if(current_size >= STAGE_FIVE && prob(70))
gets_dug()
/datum/component/archaeology/proc/BombDig(severity, target)
/datum/component/archaeology/proc/BombDig(datum/source, severity, target)
switch(severity)
if(3)
return

View File

@@ -29,7 +29,7 @@
var/obj/item/typecast = upgrade_item
upgrade_name = initial(typecast.name)
/datum/component/armor_plate/proc/examine(mob/user)
/datum/component/armor_plate/proc/examine(datum/source, mob/user)
//upgrade_item could also be typecast here instead
if(ismecha(parent))
if(amount)
@@ -45,7 +45,7 @@
else
to_chat(user, "<span class='notice'>It can be strengthened with up to [maxamount] [upgrade_name].</span>")
/datum/component/armor_plate/proc/applyplate(obj/item/I, mob/user, params)
/datum/component/armor_plate/proc/applyplate(datum/source, obj/item/I, mob/user, params)
if(!istype(I,upgrade_item))
return
if(amount >= maxamount)
@@ -72,7 +72,7 @@
to_chat(user, "<span class='info'>You strengthen [O], improving its resistance against melee attacks.</span>")
/datum/component/armor_plate/proc/dropplates(force)
/datum/component/armor_plate/proc/dropplates(datum/source, force)
if(ismecha(parent)) //items didn't drop the plates before and it causes erroneous behavior for the time being with collapsible helmets
for(var/i in 1 to amount)
new upgrade_item(get_turf(parent))

View File

@@ -14,7 +14,7 @@
RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED), .proc/Crossed)
/datum/component/caltrop/proc/Crossed(atom/movable/AM)
/datum/component/caltrop/proc/Crossed(datum/source, atom/movable/AM)
var/atom/A = parent
if(!A.has_gravity())
return

View File

@@ -27,7 +27,7 @@
target_turf = target
START_PROCESSING(SSobj, src) // process on create, in case stuff is still there
/datum/component/chasm/proc/Entered(atom/movable/AM)
/datum/component/chasm/proc/Entered(datum/source, atom/movable/AM)
START_PROCESSING(SSobj, src)
drop_stuff(AM)

View File

@@ -19,7 +19,7 @@
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY,.proc/action)
update_parent(index)
/datum/component/construction/proc/examine(mob/user)
/datum/component/construction/proc/examine(datum/source, mob/user)
if(desc)
to_chat(user, desc)
@@ -29,7 +29,7 @@
else
update_parent(index)
/datum/component/construction/proc/action(obj/item/I, mob/living/user)
/datum/component/construction/proc/action(datum/source, obj/item/I, mob/living/user)
return check_step(I, user)
/datum/component/construction/proc/update_index(diff)

View File

@@ -7,8 +7,8 @@
var/first_dir // This only stores the dir arg from init
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description)
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color))
/datum/component/decal/Initialize(_icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255)
if(!isatom(parent) || !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha))
return COMPONENT_INCOMPATIBLE
first_dir = _dir
description = _description
@@ -38,13 +38,14 @@
remove()
apply()
/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color)
/datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha)
if(!_icon || !_icon_state)
return FALSE
// It has to be made from an image or dir breaks because of a byond bug
var/temp_image = image(_icon, null, _icon_state, _layer, _dir)
pic = new(temp_image)
pic.color = _color
pic.alpha = _alpha
return TRUE
/datum/component/decal/proc/apply(atom/thing)
@@ -59,16 +60,16 @@
if(isitem(master))
addtimer(CALLBACK(master, /obj/item/.proc/update_slot_icon), 0, TIMER_UNIQUE)
/datum/component/decal/proc/rotate_react(old_dir, new_dir)
/datum/component/decal/proc/rotate_react(datum/source, old_dir, new_dir)
if(old_dir == new_dir)
return
remove()
pic.dir = turn(pic.dir, dir2angle(old_dir) - dir2angle(new_dir))
apply()
/datum/component/decal/proc/clean_react(strength)
/datum/component/decal/proc/clean_react(datum/source, strength)
if(strength >= cleanable)
qdel(src)
/datum/component/decal/proc/examine(mob/user)
/datum/component/decal/proc/examine(datum/source, mob/user)
to_chat(user, description)

View File

@@ -32,7 +32,7 @@
blood_splatter_appearances[index] = pic
return TRUE
/datum/component/decal/blood/proc/get_examine_name(mob/user, list/override)
/datum/component/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
var/atom/A = parent
override[EXAMINE_POSITION_ARTICLE] = A.gender == PLURAL? "some" : "a"
override[EXAMINE_POSITION_BEFORE] = " blood-stained "

View File

@@ -9,7 +9,7 @@
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED), .proc/equippedChanged)
/datum/component/earhealing/proc/equippedChanged(mob/living/carbon/user, slot)
/datum/component/earhealing/proc/equippedChanged(datum/source, mob/living/carbon/user, slot)
if (slot == SLOT_EARS && istype(user))
if (!wearer)
START_PROCESSING(SSobj, src)

View File

@@ -7,5 +7,5 @@
valid_slots = _valid_slots
callback = CALLBACK(src, .proc/reducebang)
/datum/component/wearertargeting/earprotection/proc/reducebang(list/reflist)
/datum/component/wearertargeting/earprotection/proc/reducebang(datum/source, list/reflist)
reflist[1]--

View File

@@ -18,6 +18,6 @@
RegisterSignal(SSdcs, COMSIG_GLOB_VAR_EDIT, .proc/var_edit_react)
/datum/component/edit_complainer/proc/var_edit_react(list/arguments)
/datum/component/edit_complainer/proc/var_edit_react(datum/source, list/arguments)
var/atom/movable/master = parent
master.say(pick(say_lines))

View File

@@ -7,5 +7,5 @@
flags = _flags
RegisterSignal(parent, list(COMSIG_ATOM_EMP_ACT), .proc/getEmpFlags)
/datum/component/empprotection/proc/getEmpFlags(severity)
/datum/component/empprotection/proc/getEmpFlags(datum/source, severity)
return flags

View File

@@ -0,0 +1,39 @@
/datum/component/footstep
var/steps = 0
var/volume
var/e_range
/datum/component/footstep/Initialize(volume_ = 0.5, e_range_ = -1)
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
volume = volume_
e_range = e_range_
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_footstep)
/datum/component/footstep/proc/play_footstep()
var/turf/open/T = get_turf(parent)
if(!istype(T))
return
var/mob/living/LM = parent
var/v = volume
var/e = e_range
if(!T.footstep || LM.lying || !LM.canmove || LM.resting || LM.buckled || LM.throwing)
return
if(iscarbon(LM))
var/mob/living/carbon/C = LM
if(!C.get_bodypart(BODY_ZONE_L_LEG) && !C.get_bodypart(BODY_ZONE_R_LEG))
return
if(ishuman(C) && C.m_intent == MOVE_INTENT_WALK)
v /= 2
e -= 5
steps++
if(steps >= 6)
steps = 0
if(steps % 2)
return
if(!LM.has_gravity(T) && steps != 0) // don't need to step as often when you hop around
return
playsound(T, pick(GLOB.footstep[T.footstep][1]),
GLOB.footstep[T.footstep][2] * v,
TRUE,
GLOB.footstep[T.footstep][3] + e)

View File

@@ -1,8 +1,20 @@
/datum/component/forced_gravity
var/gravity = 1
var/gravity
var/ignore_space = FALSE //If forced gravity should also work on space turfs
/datum/component/forced_gravity/Initialize(forced_value = 1)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(COMSIG_ATOM_HAS_GRAVITY, .proc/gravity_check)
if(isturf(parent))
RegisterSignal(COMSIG_TURF_HAS_GRAVITY, .proc/turf_gravity_check)
gravity = forced_value
/datum/component/forced_gravity/proc/gravity_check(datum/source, turf/location, list/gravs)
if(!ignore_space && isspaceturf(location))
return
gravs += gravity
/datum/component/forced_gravity/proc/turf_gravity_check(datum/source, atom/checker, list/gravs)
return gravity_check(parent, gravs)

View File

@@ -40,7 +40,7 @@
fibers = null
return TRUE
/datum/component/forensics/proc/clean_act(strength)
/datum/component/forensics/proc/clean_act(datum/source, strength)
if(strength >= CLEAN_STRENGTH_FINGERPRINTS)
wipe_fingerprints()
if(strength >= CLEAN_STRENGTH_BLOOD)

View File

@@ -13,7 +13,7 @@
expire_time = world.time + expire_in
QDEL_IN(src, expire_in)
RegisterSignal(parent, COMSIG_MOVABLE_BUCKLE, .proc/try_infect_buckle)
RegisterSignal(parent, COMSIG_MOVABLE_COLLIDE, .proc/try_infect_collide)
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/try_infect_collide)
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/try_infect_crossed)
RegisterSignal(parent, COMSIG_ITEM_ATTACK_ZONE, .proc/try_infect_attack_zone)
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/try_infect_attack)
@@ -22,20 +22,20 @@
RegisterSignal(parent, COMSIG_FOOD_EATEN, .proc/try_infect_eat)
RegisterSignal(parent, COMSIG_COMPONENT_CLEAN_ACT, .proc/clean)
/datum/component/infective/proc/try_infect_eat(mob/living/eater, mob/living/feeder)
/datum/component/infective/proc/try_infect_eat(datum/source, mob/living/eater, mob/living/feeder)
for(var/V in diseases)
eater.ForceContractDisease(V)
try_infect(feeder, BODY_ZONE_L_ARM)
/datum/component/infective/proc/clean(clean_strength)
/datum/component/infective/proc/clean(datum/source, clean_strength)
if(clean_strength >= min_clean_strength)
qdel(src)
/datum/component/infective/proc/try_infect_buckle(mob/M, force)
/datum/component/infective/proc/try_infect_buckle(datum/source, mob/M, force)
if(isliving(M))
try_infect(M)
/datum/component/infective/proc/try_infect_collide(atom/A)
/datum/component/infective/proc/try_infect_collide(datum/source, atom/A)
var/atom/movable/P = parent
if(P.throwing)
//this will be handled by try_infect_impact_zone()
@@ -43,19 +43,19 @@
if(isliving(A))
try_infect(A)
/datum/component/infective/proc/try_infect_impact_zone(mob/living/target, hit_zone)
/datum/component/infective/proc/try_infect_impact_zone(datum/source, mob/living/target, hit_zone)
try_infect(target, hit_zone)
/datum/component/infective/proc/try_infect_attack_zone(mob/living/carbon/target, mob/living/user, hit_zone)
/datum/component/infective/proc/try_infect_attack_zone(datum/source, mob/living/carbon/target, mob/living/user, hit_zone)
try_infect(user, BODY_ZONE_L_ARM)
try_infect(target, hit_zone)
/datum/component/infective/proc/try_infect_attack(mob/living/target, mob/living/user)
/datum/component/infective/proc/try_infect_attack(datum/source, mob/living/target, mob/living/user)
if(!iscarbon(target)) //this case will be handled by try_infect_attack_zone
try_infect(target)
try_infect(user, BODY_ZONE_L_ARM)
/datum/component/infective/proc/try_infect_equipped(mob/living/L, slot)
/datum/component/infective/proc/try_infect_equipped(datum/source, mob/living/L, slot)
var/old_permeability
if(isitem(parent))
//if you are putting an infective item on, it obviously will not protect you, so set its permeability high enough that it will never block ContactContractDisease()
@@ -69,7 +69,7 @@
var/obj/item/I = parent
I.permeability_coefficient = old_permeability
/datum/component/infective/proc/try_infect_crossed(atom/movable/M)
/datum/component/infective/proc/try_infect_crossed(datum/source, atom/movable/M)
if(isliving(M))
try_infect(M, BODY_ZONE_PRECISE_L_FOOT)

View File

@@ -22,17 +22,17 @@
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/on_attack)
/datum/component/jousting/proc/on_equip(mob/user, slot)
/datum/component/jousting/proc/on_equip(datum/source, mob/user, slot)
RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/mob_move, TRUE)
current_holder = user
/datum/component/jousting/proc/on_drop(mob/user)
/datum/component/jousting/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
current_holder = null
current_direction = NONE
current_tile_charge = 0
/datum/component/jousting/proc/on_attack(mob/living/target, mob/user)
/datum/component/jousting/proc/on_attack(datum/source, mob/living/target, mob/user)
if(user != current_holder)
return
var/current = current_tile_charge
@@ -58,7 +58,7 @@
if(length(msg))
user.visible_message("<span class='danger'>[msg]!</span>")
/datum/component/jousting/proc/mob_move(newloc, dir)
/datum/component/jousting/proc/mob_move(datum/source, newloc, dir)
if(!current_holder || (requires_mount && ((requires_mob_riding && !ismob(current_holder.buckled)) || (!current_holder.buckled))))
return
if(dir != current_direction)

View File

@@ -3,7 +3,6 @@
var/knockoff_chance = 100 //Chance to knockoff
var/list/target_zones //Aiming for these zones will cause the knockoff, null means all zones allowed
var/list/slots_knockoffable //Can be only knocked off from these slots, null means all slots allowed
var/datum/component/redirect/disarm_redirect
/datum/component/knockoff/Initialize(knockoff_chance,zone_override,slots_knockoffable)
if(!isitem(parent))
@@ -33,7 +32,7 @@
wearer.visible_message("<span class='warning'>[attacker] knocks off [wearer]'s [I.name]!</span>","<span class='userdanger'>[attacker] knocks off your [I.name]!</span>")
/datum/component/knockoff/proc/OnEquipped(mob/living/carbon/human/H,slot)
/datum/component/knockoff/proc/OnEquipped(datum/source, mob/living/carbon/human/H,slot)
if(!istype(H))
return
if(slots_knockoffable && !(slot in slots_knockoffable))
@@ -41,5 +40,5 @@
return
RegisterSignal(H, COMSIG_HUMAN_DISARM_HIT, .proc/Knockoff, TRUE)
/datum/component/knockoff/proc/OnDropped(mob/living/M)
/datum/component/knockoff/proc/OnDropped(datum/source, mob/living/M)
UnregisterSignal(M, COMSIG_HUMAN_DISARM_HIT)

View File

@@ -1,23 +1,34 @@
/datum/component/magnetic_catch/Initialize()
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
if(ismovableatom(parent))
RegisterSignal(parent, COMSIG_MOVABLE_UNCROSS, .proc/uncross_react)
else
RegisterSignal(parent, COMSIG_ATOM_EXIT, .proc/exit_react)
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
if(ismovableatom(parent))
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/crossed_react)
RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/uncrossed_react)
for(var/i in get_turf(parent))
if(i == parent)
continue
RegisterSignal(i, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react)
else
RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/entered_react)
RegisterSignal(parent, COMSIG_ATOM_EXITED, .proc/exited_react)
for(var/i in parent)
RegisterSignal(i, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react)
/datum/component/magnetic_catch/proc/uncross_react(atom/movable/thing)
if(!thing.throwing || thing.throwing.thrower)
return
qdel(thing.throwing)
return COMPONENT_MOVABLE_BLOCK_UNCROSS
/datum/component/magnetic_catch/proc/exit_react(atom/movable/thing, atom/newloc)
if(!thing.throwing || thing.throwing.thrower)
return
qdel(thing.throwing)
return COMPONENT_ATOM_BLOCK_EXIT
/datum/component/magnetic_catch/proc/examine(mob/user)
/datum/component/magnetic_catch/proc/examine(datum/source, mob/user)
to_chat(user, "It has been installed with inertia dampening to prevent coffee spills.")
/datum/component/magnetic_catch/proc/crossed_react(datum/source, atom/movable/thing)
RegisterSignal(thing, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react, TRUE)
/datum/component/magnetic_catch/proc/uncrossed_react(datum/source, atom/movable/thing)
UnregisterSignal(thing, COMSIG_MOVABLE_PRE_THROW)
/datum/component/magnetic_catch/proc/entered_react(datum/source, atom/movable/thing, atom/oldloc)
RegisterSignal(thing, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react, TRUE)
/datum/component/magnetic_catch/proc/exited_react(datum/source, atom/movable/thing, atom/newloc)
UnregisterSignal(thing, COMSIG_MOVABLE_PRE_THROW)
/datum/component/magnetic_catch/proc/throw_react(datum/source, list/arguments)
return COMPONENT_CANCEL_THROW

View File

@@ -27,8 +27,13 @@
max_amount = max(0, max_amt)
show_on_examine = _show_on_examine
disable_attackby = _disable_attackby
if(allowed_types)
if(ispath(allowed_types) && allowed_types == /obj/item/stack)
allowed_typecache = GLOB.typecache_stack
else
allowed_typecache = typecacheof(allowed_types)
precondition = _precondition
after_insert = _after_insert
@@ -44,7 +49,7 @@
var/mat_path = possible_mats[id]
materials[id] = new mat_path()
/datum/component/material_container/proc/OnExamine(mob/user)
/datum/component/material_container/proc/OnExamine(datum/source, mob/user)
if(show_on_examine)
for(var/I in materials)
var/datum/material/M = materials[I]
@@ -52,7 +57,7 @@
if(amt)
to_chat(user, "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>")
/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user)
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
var/list/tc = allowed_typecache
if(disable_attackby)
return
@@ -242,24 +247,25 @@
//For spawning mineral sheets; internal use only
/datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null)
if(!M.sheet_type)
return FALSE
if(sheet_amt > 0)
return 0
if(sheet_amt <= 0)
return 0
if(!target)
target = get_turf(parent)
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
var/count = 0
while(sheet_amt > MAX_STACK_SIZE)
new M.sheet_type(get_turf(parent), MAX_STACK_SIZE)
new M.sheet_type(target, MAX_STACK_SIZE)
count += MAX_STACK_SIZE
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
sheet_amt -= MAX_STACK_SIZE
if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT))
var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(parent), sheet_amt)
if(target)
s.forceMove(target)
if(sheet_amt >= 1)
new M.sheet_type(target, sheet_amt)
count += sheet_amt
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
return count
return FALSE
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null)
if(materials[id])

View File

@@ -1,3 +1,6 @@
#define MINOR_INSANITY_PEN 5
#define MAJOR_INSANITY_PEN 10
/datum/component/mood
var/mood //Real happiness
var/sanity = 100 //Current sanity
@@ -5,25 +8,32 @@
var/mood_level = 5 //To track what stage of moodies they're on
var/mood_modifier = 1 //Modifier to allow certain mobs to be less affected by moodlets
var/datum/mood_event/list/mood_events = list()
var/mob/living/owner
var/datum/looping_sound/reverse_bear_trap/slow/soundloop //Insanity ticking
var/insanity_effect = 0 //is the owner being punished for low mood? If so, how much?
var/holdmyinsanityeffect = 0 //before we edit our sanity lets take a look
var/obj/screen/mood/screen_obj
/datum/component/mood/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
START_PROCESSING(SSmood, src)
owner = parent
soundloop = new(list(owner), FALSE, TRUE)
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event)
RegisterSignal(parent, COMSIG_ENTER_AREA, .proc/update_beauty)
RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud)
var/mob/living/owner = parent
if(owner.hud_used)
modify_hud()
var/datum/hud/hud = owner.hud_used
hud.show_hud(hud.hud_version)
/datum/component/mood/Destroy()
STOP_PROCESSING(SSmood, src)
QDEL_NULL(soundloop)
unmodify_hud()
return ..()
/datum/component/mood/proc/print_mood()
/datum/component/mood/proc/print_mood(mob/user)
var/msg = "<span class='info'>*---------*\n<EM>Your current mood</EM>\n"
msg += "<span class='notice'>My mental status: </span>" //Long term
switch(sanity)
@@ -67,8 +77,8 @@
var/datum/mood_event/event = mood_events[i]
msg += event.description
else
msg += "<span class='nicegreen'>Nothing special has happened to me lately!<span>\n"
to_chat(owner, msg)
msg += "<span class='nicegreen'>I don't have much of a reaction to anything right now.<span>\n"
to_chat(user || parent, msg)
/datum/component/mood/proc/update_mood() //Called whenever a mood event is added or removed
mood = 0
@@ -104,41 +114,25 @@
/datum/component/mood/proc/update_mood_icon()
var/mob/living/owner = parent
if(owner.client && owner.hud_used)
if(sanity < 25)
owner.hud_used.mood.icon_state = "mood_insane"
screen_obj.icon_state = "mood_insane"
else
owner.hud_used.mood.icon_state = "mood[mood_level]"
screen_obj.icon_state = "mood[mood_level]"
/datum/component/mood/process() //Called on SSmood process
switch(sanity)
if(SANITY_INSANE to SANITY_CRAZY)
owner.overlay_fullscreen("depression", /obj/screen/fullscreen/depression, 3)
update_mood_icon()
if(prob(7))
owner.playsound_local(null, pick(CREEPY_SOUNDS), 40, 1)
soundloop.start()
if(SANITY_INSANE to SANITY_UNSTABLE)
owner.overlay_fullscreen("depression", /obj/screen/fullscreen/depression, 2)
if(prob(3))
owner.playsound_local(null, pick(CREEPY_SOUNDS), 20, 1)
soundloop.stop()
if(SANITY_UNSTABLE to SANITY_DISTURBED)
owner.overlay_fullscreen("depression", /obj/screen/fullscreen/depression, 1)
soundloop.stop()
if(SANITY_DISTURBED to INFINITY)
owner.clear_fullscreen("depression")
soundloop.stop()
var/mob/living/owner = parent
switch(mood_level)
if(1)
DecreaseSanity(0.2, 0)
DecreaseSanity(0.2)
if(2)
DecreaseSanity(0.125, 25)
DecreaseSanity(0.125, SANITY_CRAZY)
if(3)
DecreaseSanity(0.075, 50)
DecreaseSanity(0.075, SANITY_UNSTABLE)
if(4)
DecreaseSanity(0.025, 75)
DecreaseSanity(0.025, SANITY_DISTURBED)
if(5)
IncreaseSanity(0.1)
if(6)
@@ -146,42 +140,60 @@
if(7)
IncreaseSanity(0.20)
if(8)
IncreaseSanity(0.25, 125)
IncreaseSanity(0.25, SANITY_GREAT)
if(9)
IncreaseSanity(0.4, 125)
IncreaseSanity(0.4, SANITY_GREAT)
if(insanity_effect != holdmyinsanityeffect)
if(insanity_effect > holdmyinsanityeffect)
owner.crit_threshold += (insanity_effect - holdmyinsanityeffect)
else
owner.crit_threshold -= (holdmyinsanityeffect - insanity_effect)
if(owner.has_trait(TRAIT_DEPRESSION))
if(prob(0.05))
add_event("depression", /datum/mood_event/depression)
clear_event("jolly")
add_event(null, "depression", /datum/mood_event/depression)
clear_event(null, "jolly")
if(owner.has_trait(TRAIT_JOLLY))
if(prob(0.05))
add_event("jolly", /datum/mood_event/jolly)
clear_event("depression")
add_event(null, "jolly", /datum/mood_event/jolly)
clear_event(null, "depression")
var/area/A = get_area(owner)
if(A)
update_beauty(A)
holdmyinsanityeffect = insanity_effect
/datum/component/mood/proc/DecreaseSanity(amount, limit = 0)
if(sanity < limit) //This might make KevinZ stop fucking pinging me.
HandleNutrition(owner)
/datum/component/mood/proc/DecreaseSanity(amount, minimum = SANITY_INSANE)
if(sanity < minimum) //This might make KevinZ stop fucking pinging me.
IncreaseSanity(0.5)
else
sanity = max(0, sanity - amount)
sanity = max(minimum, sanity - amount)
if(sanity < SANITY_UNSTABLE)
if(sanity < SANITY_CRAZY)
insanity_effect = (MAJOR_INSANITY_PEN)
else
insanity_effect = (MINOR_INSANITY_PEN)
/datum/component/mood/proc/IncreaseSanity(amount, limit = 99)
if(sanity > limit)
/datum/component/mood/proc/IncreaseSanity(amount, maximum = SANITY_NEUTRAL)
if(sanity > maximum)
DecreaseSanity(0.5) //Removes some sanity to go back to our current limit.
else
sanity = min(limit, sanity + amount)
sanity = min(maximum, sanity + amount)
if(sanity > SANITY_CRAZY)
if(sanity > SANITY_UNSTABLE)
insanity_effect = 0
else
insanity_effect = MINOR_INSANITY_PEN
/datum/component/mood/proc/add_event(category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger.
/datum/component/mood/proc/add_event(datum/source, category, type, param) //Category will override any events in the same category, should be unique unless the event is based on the same thing like hunger.
var/datum/mood_event/the_event
if(mood_events[category])
the_event = mood_events[category]
if(the_event.type != type)
clear_event(category)
clear_event(null, category)
else
if(the_event.timeout)
addtimer(CALLBACK(src, .proc/clear_event, null, category), the_event.timeout, TIMER_UNIQUE|TIMER_OVERRIDE)
return 0 //Don't have to update the event.
the_event = new type(src, param)
@@ -189,9 +201,9 @@
update_mood()
if(the_event.timeout)
addtimer(CALLBACK(src, .proc/clear_event, category), the_event.timeout)
addtimer(CALLBACK(src, .proc/clear_event, null, category), the_event.timeout, TIMER_UNIQUE|TIMER_OVERRIDE)
/datum/component/mood/proc/clear_event(category)
/datum/component/mood/proc/clear_event(datum/source, category)
var/datum/mood_event/event = mood_events[category]
if(!event)
return 0
@@ -200,22 +212,41 @@
qdel(event)
update_mood()
/datum/component/mood/proc/update_beauty(area/A)
if(A.outdoors) //if we're outside, we don't care.
clear_event("area_beauty")
return FALSE
switch(A.beauty)
if(-INFINITY to BEAUTY_LEVEL_HORRID)
add_event("area_beauty", /datum/mood_event/horridroom)
if(BEAUTY_LEVEL_HORRID to BEAUTY_LEVEL_BAD)
add_event("area_beauty", /datum/mood_event/badroom)
if(BEAUTY_LEVEL_BAD to BEAUTY_LEVEL_MEH)
add_event("area_beauty", /datum/mood_event/mehroom)
if(BEAUTY_LEVEL_MEH to BEAUTY_LEVEL_DECENT)
clear_event("area_beauty")
if(BEAUTY_LEVEL_DECENT to BEAUTY_LEVEL_GOOD)
add_event("area_beauty", /datum/mood_event/decentroom)
if(BEAUTY_LEVEL_GOOD to BEAUTY_LEVEL_GREAT)
add_event("area_beauty", /datum/mood_event/goodroom)
if(BEAUTY_LEVEL_GREAT to INFINITY)
add_event("area_beauty", /datum/mood_event/greatroom)
/datum/component/mood/proc/modify_hud(datum/source)
var/mob/living/owner = parent
var/datum/hud/hud = owner.hud_used
screen_obj = new
hud.infodisplay += screen_obj
RegisterSignal(hud, COMSIG_PARENT_QDELETED, .proc/unmodify_hud)
RegisterSignal(screen_obj, COMSIG_CLICK, .proc/hud_click)
/datum/component/mood/proc/unmodify_hud(datum/source)
if(!screen_obj)
return
var/mob/living/owner = parent
var/datum/hud/hud = owner.hud_used
if(hud && hud.infodisplay)
hud.infodisplay -= screen_obj
QDEL_NULL(screen_obj)
/datum/component/mood/proc/hud_click(datum/source, location, control, params, mob/user)
print_mood(user)
/datum/component/mood/proc/HandleNutrition(mob/living/L)
switch(L.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY)
add_event(null, "nutrition", /datum/mood_event/fat)
if(NUTRITION_LEVEL_WELL_FED to NUTRITION_LEVEL_FULL)
add_event(null, "nutrition", /datum/mood_event/wellfed)
if( NUTRITION_LEVEL_FED to NUTRITION_LEVEL_WELL_FED)
add_event(null, "nutrition", /datum/mood_event/fed)
if(NUTRITION_LEVEL_HUNGRY to NUTRITION_LEVEL_FED)
clear_event(null, "nutrition")
if(NUTRITION_LEVEL_STARVING to NUTRITION_LEVEL_HUNGRY)
add_event(null, "nutrition", /datum/mood_event/hungry)
if(0 to NUTRITION_LEVEL_STARVING)
add_event(null, "nutrition", /datum/mood_event/starving)
#undef MINOR_INSANITY_PEN
#undef MAJOR_INSANITY_PEN

View File

@@ -90,12 +90,12 @@
/datum/component/nanites/InheritComponent(datum/component/nanites/new_nanites, i_am_original, list/arguments)
if(new_nanites)
adjust_nanites(new_nanites.nanite_volume)
adjust_nanites(null, new_nanites.nanite_volume)
else
adjust_nanites(arguments[1]) //just add to the nanite volume
adjust_nanites(null, arguments[1]) //just add to the nanite volume
/datum/component/nanites/process()
adjust_nanites(regen_rate)
adjust_nanites(null, regen_rate)
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.on_process()
@@ -105,7 +105,7 @@
next_sync = world.time + NANITE_SYNC_DELAY
//Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status)
/datum/component/nanites/proc/sync(datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE)
/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE)
var/list/programs_to_remove = programs.Copy()
var/list/programs_to_add = source.programs.Copy()
for(var/X in programs)
@@ -122,7 +122,7 @@
qdel(X)
for(var/X in programs_to_add)
var/datum/nanite_program/SNP = X
add_program(SNP.copy())
add_program(null, SNP.copy())
/datum/component/nanites/proc/cloud_sync()
if(!cloud_id)
@@ -131,9 +131,9 @@
if(backup)
var/datum/component/nanites/cloud_copy = backup.nanites
if(cloud_copy)
sync(cloud_copy)
sync(null, cloud_copy)
/datum/component/nanites/proc/add_program(datum/nanite_program/new_program, datum/nanite_program/source_program)
/datum/component/nanites/proc/add_program(datum/source, datum/nanite_program/new_program, datum/nanite_program/source_program)
for(var/X in programs)
var/datum/nanite_program/NP = X
if(NP.unique && NP.type == new_program.type)
@@ -149,10 +149,10 @@
/datum/component/nanites/proc/consume_nanites(amount, force = FALSE)
if(!force && safety_threshold && (nanite_volume - amount < safety_threshold))
return FALSE
adjust_nanites(-amount)
adjust_nanites(null, -amount)
return (nanite_volume > 0)
/datum/component/nanites/proc/adjust_nanites(amount)
/datum/component/nanites/proc/adjust_nanites(datum/source, amount)
nanite_volume = CLAMP(nanite_volume + amount, 0, max_nanites)
if(nanite_volume <= 0) //oops we ran out
qdel(src)
@@ -168,39 +168,39 @@
nanite_percent = CLAMP(CEILING(nanite_percent, 10), 10, 100)
holder.icon_state = "nanites[nanite_percent]"
/datum/component/nanites/proc/on_emp(severity)
/datum/component/nanites/proc/on_emp(datum/source, severity)
nanite_volume *= (rand(0.60, 0.90)) //Lose 10-40% of nanites
adjust_nanites(-(rand(5, 50))) //Lose 5-50 flat nanite volume
adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
if(prob(40/severity))
cloud_id = 0
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.on_emp(severity)
/datum/component/nanites/proc/on_shock(shock_damage)
/datum/component/nanites/proc/on_shock(datum/source, shock_damage)
nanite_volume *= (rand(0.45, 0.80)) //Lose 20-55% of nanites
adjust_nanites(-(rand(5, 50))) //Lose 5-50 flat nanite volume
adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.on_shock(shock_damage)
/datum/component/nanites/proc/on_minor_shock()
adjust_nanites(-(rand(5, 15))) //Lose 5-15 flat nanite volume
/datum/component/nanites/proc/on_minor_shock(datum/source)
adjust_nanites(null, -(rand(5, 15))) //Lose 5-15 flat nanite volume
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.on_minor_shock()
/datum/component/nanites/proc/on_death(gibbed)
/datum/component/nanites/proc/on_death(datum/source, gibbed)
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.on_death(gibbed)
/datum/component/nanites/proc/on_hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
/datum/component/nanites/proc/on_hear(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.on_hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
/datum/component/nanites/proc/receive_signal(code, source = "an unidentified source")
/datum/component/nanites/proc/receive_signal(datum/source, code, source = "an unidentified source")
for(var/X in programs)
var/datum/nanite_program/NP = X
NP.receive_signal(code, source)
@@ -209,7 +209,7 @@
if(!(MOB_ORGANIC in host_mob.mob_biotypes) && !(MOB_UNDEAD in host_mob.mob_biotypes))
qdel(src) //bodytype no longer sustains nanites
/datum/component/nanites/proc/check_access(obj/O)
/datum/component/nanites/proc/check_access(datum/source, obj/O)
for(var/datum/nanite_program/triggered/access/access_program in programs)
if(access_program.activated)
return O.check_access_list(access_program.access)
@@ -217,19 +217,19 @@
return FALSE
return FALSE
/datum/component/nanites/proc/set_volume(amount)
/datum/component/nanites/proc/set_volume(datum/source, amount)
nanite_volume = CLAMP(amount, 0, max_nanites)
/datum/component/nanites/proc/set_max_volume(amount)
/datum/component/nanites/proc/set_max_volume(datum/source, amount)
max_nanites = max(1, max_nanites)
/datum/component/nanites/proc/set_cloud(amount)
/datum/component/nanites/proc/set_cloud(datum/source, amount)
cloud_id = CLAMP(amount, 0, 100)
/datum/component/nanites/proc/set_safety(amount)
/datum/component/nanites/proc/set_safety(datum/source, amount)
safety_threshold = CLAMP(amount, 0, max_nanites)
/datum/component/nanites/proc/set_regen(amount)
/datum/component/nanites/proc/set_regen(datum/source, amount)
regen_rate = amount
/datum/component/nanites/proc/confirm_nanites()
@@ -243,10 +243,10 @@
nanite_data["safety_threshold"] = safety_threshold
nanite_data["stealth"] = stealth
/datum/component/nanites/proc/get_programs(list/nanite_programs)
/datum/component/nanites/proc/get_programs(datum/source, list/nanite_programs)
nanite_programs |= programs
/datum/component/nanites/proc/nanite_scan(mob/user, full_scan)
/datum/component/nanites/proc/nanite_scan(datum/source, mob/user, full_scan)
if(!full_scan)
if(!stealth)
to_chat(user, "<span class='notice'><b>Nanites Detected</b></span>")
@@ -268,7 +268,7 @@
to_chat(user, "<span class='info'><b>[NP.name]</b> | [NP.activated ? "Active" : "Inactive"]</span>")
return TRUE
/datum/component/nanites/proc/nanite_ui_data(list/data, scan_level)
/datum/component/nanites/proc/nanite_ui_data(datum/source, list/data, scan_level)
data["has_nanites"] = TRUE
data["nanite_volume"] = nanite_volume
data["regen_rate"] = regen_rate

View File

@@ -12,7 +12,7 @@
var/atom/A = parent
A.remove_atom_colour(FIXED_COLOUR_PRIORITY, current_paint)
/datum/component/spraycan_paintable/proc/Repaint(obj/item/toy/crayon/spraycan/spraycan, mob/living/user)
/datum/component/spraycan_paintable/proc/Repaint(datum/source, obj/item/toy/crayon/spraycan/spraycan, mob/living/user)
if(!istype(spraycan) || user.a_intent == INTENT_HARM)
return
. = COMPONENT_NO_AFTERATTACK

View File

@@ -1,9 +1,24 @@
/datum/component/rad_insulation // Yes, this really is just a component to add some vars
/datum/component/rad_insulation
var/amount // Multiplier for radiation strength passing through
var/protects // Does this protect things in its contents from being affected?
var/contamination_proof // Can this object be contaminated?
/datum/component/rad_insulation/Initialize(_amount=RAD_MEDIUM_INSULATION, _protects=TRUE, _contamination_proof=TRUE)
/datum/component/rad_insulation/Initialize(_amount=RAD_MEDIUM_INSULATION, protects=TRUE, contamination_proof=TRUE)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
if(protects) // Does this protect things in its contents from being affected?
RegisterSignal(parent, COMSIG_ATOM_RAD_PROBE, .proc/rad_probe_react)
if(contamination_proof) // Can this object be contaminated?
RegisterSignal(parent, COMSIG_ATOM_RAD_CONTAMINATING, .proc/rad_contaminating)
if(_amount != 1) // If it's 1 it wont have any impact on radiation passing through anyway
RegisterSignal(parent, COMSIG_ATOM_RAD_WAVE_PASSING, .proc/rad_pass)
amount = _amount
protects = _protects
contamination_proof = _contamination_proof
/datum/component/rad_insulation/proc/rad_probe_react(datum/source)
return COMPONENT_BLOCK_RADIATION
/datum/component/rad_insulation/proc/rad_contaminating(datum/source, strength)
return COMPONENT_BLOCK_CONTAMINATION
/datum/component/rad_insulation/proc/rad_pass(datum/source, datum/radiation_wave/wave, width)
wave.intensity = wave.intensity*(1-((1-amount)/width)) // The further out the rad wave goes the less it's affected by insulation (larger width)

View File

@@ -58,7 +58,7 @@
else
strength = max(strength, arguments[1])
/datum/component/radioactive/proc/rad_examine(mob/user, atom/thing)
/datum/component/radioactive/proc/rad_examine(datum/source, mob/user, atom/thing)
var/atom/master = parent
var/list/out = list()
if(get_dist(master, user) <= 1)
@@ -74,7 +74,7 @@
out += "."
to_chat(user, out.Join())
/datum/component/radioactive/proc/rad_attack(atom/movable/target, mob/living/user)
/datum/component/radioactive/proc/rad_attack(datum/source, atom/movable/target, mob/living/user)
radiation_pulse(parent, strength/20)
target.rad_act(strength/2)
strength -= strength / hl3_release_date

View File

@@ -0,0 +1,111 @@
/*
This component allows machines to connect remotely to a material container
(namely an /obj/machinery/ore_silo) elsewhere. It offers optional graceful
fallback to a local material storage in case remote storage is unavailable, and
handles linking back and forth.
*/
/datum/component/remote_materials
// Three possible states:
// 1. silo exists, materials is parented to silo
// 2. silo is null, materials is parented to parent
// 3. silo is null, materials is null
var/obj/machinery/ore_silo/silo
var/datum/component/material_container/mat_container
var/category
var/allow_standalone
var/local_size = INFINITY
/datum/component/remote_materials/Initialize(category, mapload, allow_standalone = TRUE, force_connect = FALSE)
if (!isatom(parent))
return COMPONENT_INCOMPATIBLE
src.category = category
src.allow_standalone = allow_standalone
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
var/turf/T = get_turf(parent)
if (force_connect || (mapload && is_station_level(T.z)))
addtimer(CALLBACK(src, .proc/LateInitialize))
else if (allow_standalone)
_MakeLocal()
/datum/component/remote_materials/proc/LateInitialize()
silo = GLOB.ore_silo_default
if (silo)
silo.connected += src
mat_container = silo.GetComponent(/datum/component/material_container)
else
_MakeLocal()
/datum/component/remote_materials/Destroy()
if (silo)
silo.connected -= src
silo.updateUsrDialog()
silo = null
mat_container = null
else if (mat_container)
// specify explicitly in case the other component is deleted first
var/atom/P = parent
mat_container.retrieve_all(P.drop_location())
return ..()
/datum/component/remote_materials/proc/_MakeLocal()
silo = null
mat_container = parent.AddComponent(/datum/component/material_container,
list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC),
local_size,
FALSE,
/obj/item/stack)
/datum/component/remote_materials/proc/set_local_size(size)
local_size = size
if (!silo && mat_container)
mat_container.max_amount = size
// called if disconnected by ore silo UI or destruction
/datum/component/remote_materials/proc/disconnect_from(obj/machinery/ore_silo/old_silo)
if (!old_silo || silo != old_silo)
return
silo = null
mat_container = null
if (allow_standalone)
_MakeLocal()
/datum/component/remote_materials/proc/OnAttackBy(datum/source, obj/item/I, mob/user)
if (istype(I, /obj/item/multitool))
var/obj/item/multitool/M = I
if (!QDELETED(M.buffer) && istype(M.buffer, /obj/machinery/ore_silo))
if (silo == M.buffer)
to_chat(user, "<span class='notice'>[parent] is already connected to [silo].</span>")
return COMPONENT_NO_AFTERATTACK
if (silo)
silo.connected -= src
silo.updateUsrDialog()
else if (mat_container)
mat_container.retrieve_all()
qdel(mat_container)
silo = M.buffer
silo.connected += src
silo.updateUsrDialog()
mat_container = silo.GetComponent(/datum/component/material_container)
to_chat(user, "<span class='notice'>You connect [parent] to [silo] from the multitool's buffer.</span>")
return COMPONENT_NO_AFTERATTACK
else if (silo && istype(I, /obj/item/stack))
if (silo.remote_attackby(parent, user, I))
return COMPONENT_NO_AFTERATTACK
/datum/component/remote_materials/proc/on_hold()
return silo && silo.holds["[get_area(parent)]/[category]"]
/datum/component/remote_materials/proc/silo_log(obj/machinery/M, action, amount, noun, list/mats)
if (silo)
silo.silo_log(M || parent, action, amount, noun, mats)
/datum/component/remote_materials/proc/format_amount()
if (mat_container)
return "[mat_container.total_amount] / [mat_container.max_amount == INFINITY ? "Unlimited" : mat_container.max_amount] ([silo ? "remote" : "local"])"
else
return "0 / 0"

View File

@@ -26,11 +26,11 @@
RegisterSignal(parent, COMSIG_MOVABLE_UNBUCKLE, .proc/vehicle_mob_unbuckle)
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, .proc/vehicle_moved)
/datum/component/riding/proc/vehicle_mob_unbuckle(mob/living/M, force = FALSE)
/datum/component/riding/proc/vehicle_mob_unbuckle(datum/source, mob/living/M, force = FALSE)
restore_position(M)
unequip_buckle_inhands(M)
/datum/component/riding/proc/vehicle_mob_buckle(mob/living/M, force = FALSE)
/datum/component/riding/proc/vehicle_mob_buckle(datum/source, mob/living/M, force = FALSE)
handle_vehicle_offsets()
/datum/component/riding/proc/handle_vehicle_layer()
@@ -46,7 +46,7 @@
/datum/component/riding/proc/set_vehicle_dir_layer(dir, layer)
directional_vehicle_layers["[dir]"] = layer
/datum/component/riding/proc/vehicle_moved()
/datum/component/riding/proc/vehicle_moved(datum/source)
var/atom/movable/AM = parent
for(var/i in AM.buckled_mobs)
ride_check(i)

View File

@@ -77,16 +77,16 @@
remove_verbs()
. = ..()
/datum/component/simple_rotation/proc/ExamineMessage(mob/user)
/datum/component/simple_rotation/proc/ExamineMessage(datum/source, mob/user)
if(rotation_flags & ROTATION_ALTCLICK)
to_chat(user, "<span class='notice'>Alt-click to rotate it clockwise.</span>")
/datum/component/simple_rotation/proc/HandRot(mob/user, rotation = default_rotation_direction)
/datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction)
if(!can_be_rotated.Invoke(user, rotation) || !can_user_rotate.Invoke(user, rotation))
return
BaseRot(user, rotation)
/datum/component/simple_rotation/proc/WrenchRot(obj/item/I, mob/living/user)
/datum/component/simple_rotation/proc/WrenchRot(datum/source, obj/item/I, mob/living/user)
if(!can_be_rotated.Invoke(user,default_rotation_direction) || !can_user_rotate.Invoke(user,default_rotation_direction))
return
if(istype(I,/obj/item/wrench))

View File

@@ -3,15 +3,31 @@
/datum/component/redirect
dupe_mode = COMPONENT_DUPE_ALLOWED
var/list/signals
var/datum/callback/turfchangeCB
/datum/component/redirect/Initialize(list/signals, datum/callback/_callback, flags=NONE)
/datum/component/redirect/Initialize(list/_signals, flags=NONE)
//It's not our job to verify the right signals are registered here, just do it.
if(!LAZYLEN(signals) || !istype(_callback))
warning("signals are [list2params(signals)], callback is [_callback]]")
if(!LAZYLEN(_signals))
return COMPONENT_INCOMPATIBLE
if(flags & REDIRECT_TRANSFER_WITH_TURF && isturf(parent))
RegisterSignal(parent, COMSIG_TURF_CHANGE, .proc/turf_change)
RegisterSignal(parent, signals, _callback)
// If they also want to listen to the turf change then we need to set it up so both callbacks run
if(_signals[COMSIG_TURF_CHANGE])
turfchangeCB = _signals[COMSIG_TURF_CHANGE]
if(!istype(turfchangeCB))
. = COMPONENT_INCOMPATIBLE
CRASH("Redirect components must be given instanced callbacks, not proc paths.")
_signals[COMSIG_TURF_CHANGE] = CALLBACK(src, .proc/turf_change)
/datum/component/redirect/proc/turf_change(path, new_baseturfs, flags, list/transfers)
signals = _signals
/datum/component/redirect/RegisterWithParent()
for(var/signal in signals)
RegisterSignal(parent, signal, signals[signal])
/datum/component/redirect/UnregisterFromParent()
UnregisterSignal(parent, signals)
/datum/component/redirect/proc/turf_change(datum/source, path, new_baseturfs, flags, list/transfers)
transfers += src
return turfchangeCB?.InvokeAsync(arglist(args))

View File

@@ -9,7 +9,7 @@
callback = _callback
RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip)
/datum/component/slippery/proc/Slip(atom/movable/AM)
/datum/component/slippery/proc/Slip(datum/source, atom/movable/AM)
var/mob/victim = AM
if(istype(victim) && !victim.is_flying() && victim.slip(intensity, parent, lube_flags) && callback)
callback.Invoke(victim)

View File

@@ -4,7 +4,7 @@
/datum/component/spooky/Initialize()
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/spectral_attack)
/datum/component/spooky/proc/spectral_attack(mob/living/carbon/C, mob/user)
/datum/component/spooky/proc/spectral_attack(datum/source, mob/living/carbon/C, mob/user)
if(ishuman(user)) //this weapon wasn't meant for mortals.
var/mob/living/carbon/human/U = user
if(!istype(U.dna.species, /datum/species/skeleton))

View File

@@ -0,0 +1,87 @@
/datum/component/squeak
var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1)
var/list/override_squeak_sounds
var/squeak_chance = 100
var/volume = 30
// This is so shoes don't squeak every step
var/steps = 0
var/step_delay = 1
// This is to stop squeak spam from inhand usage
var/last_use = 0
var/use_delay = 20
/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), .proc/play_squeak)
if(ismovableatom(parent))
RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak)
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/play_squeak_crossed)
RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react)
if(isitem(parent))
RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak)
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak)
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
if(istype(parent, /obj/item/clothing/shoes))
RegisterSignal(parent, COMSIG_SHOES_STEP_ACTION, .proc/step_squeak)
override_squeak_sounds = custom_sounds
if(chance_override)
squeak_chance = chance_override
if(volume_override)
volume = volume_override
if(isnum(step_delay_override))
step_delay = step_delay_override
if(isnum(use_delay_override))
use_delay = use_delay_override
/datum/component/squeak/proc/play_squeak()
if(prob(squeak_chance))
if(!override_squeak_sounds)
playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1)
else
playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1)
/datum/component/squeak/proc/step_squeak()
if(steps > step_delay)
play_squeak()
steps = 0
else
steps++
/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM)
if(isitem(AM))
var/obj/item/I = AM
if(I.item_flags & ABSTRACT)
return
else if(istype(AM, /obj/item/projectile))
var/obj/item/projectile/P = AM
if(P.original != parent)
return
var/atom/current_parent = parent
if(isturf(current_parent.loc))
play_squeak()
/datum/component/squeak/proc/use_squeak()
if(last_use + use_delay < world.time)
last_use = world.time
play_squeak()
/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot)
RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE)
/datum/component/squeak/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, COMSIG_MOVABLE_DISPOSING)
// Disposal pipes related shit
/datum/component/squeak/proc/disposing_react(datum/source, obj/structure/disposalholder/holder, obj/machinery/disposal/source)
//We don't need to worry about unregistering this signal as it will happen for us automaticaly when the holder is qdeleted
RegisterSignal(holder, COMSIG_ATOM_DIR_CHANGE, .proc/holder_dir_change)
/datum/component/squeak/proc/holder_dir_change(datum/source, old_dir, new_dir)
//If the dir changes it means we're going through a bend in the pipes, let's pretend we bumped the wall
if(old_dir != new_dir)
play_squeak()

View File

@@ -42,7 +42,7 @@
var/turf/currentturf = get_turf(src)
to_chat(get(parent, /mob), "<span class='danger'>You can't help but feel that you just lost something back there...</span>")
var/turf/targetturf = relocate()
log_game("[parent] has been moved out of bounds in [AREACOORD(currentturf)]. Moving it to [AREACOORD(targetturf)].")
log_game("[parent] has been moved out of bounds in [loc_name(currentturf)]. Moving it to [loc_name(targetturf)].")
if(inform_admins)
message_admins("[parent] has been moved out of bounds in [ADMIN_VERBOSEJMP(currentturf)]. Moving it to [ADMIN_VERBOSEJMP(targetturf)].")
@@ -65,17 +65,17 @@
return FALSE
/datum/component/stationloving/proc/check_deletion(force) // TRUE = interrupt deletion, FALSE = proceed with deletion
/datum/component/stationloving/proc/check_deletion(datum/source, force) // TRUE = interrupt deletion, FALSE = proceed with deletion
var/turf/T = get_turf(parent)
if(inform_admins && force)
message_admins("[parent] has been !!force deleted!! in [ADMIN_VERBOSEJMP(T)].")
log_game("[parent] has been !!force deleted!! in [AREACOORD(T)].")
log_game("[parent] has been !!force deleted!! in [loc_name(T)].")
if(!force && !allow_death)
var/turf/targetturf = relocate()
log_game("[parent] has been destroyed in [AREACOORD(T)]. Moving it to [AREACOORD(targetturf)].")
log_game("[parent] has been destroyed in [loc_name(T)]. Moving it to [loc_name(targetturf)].")
if(inform_admins)
message_admins("[parent] has been destroyed in [ADMIN_VERBOSEJMP(T)]. Moving it to [ADMIN_VERBOSEJMP(targetturf)].")
return TRUE

View File

@@ -72,7 +72,7 @@
var/datum/component/storage/slave = i
slave.refresh_mob_views()
/datum/component/storage/concrete/emp_act(severity)
/datum/component/storage/concrete/emp_act(datum/source, severity)
if(emp_shielded)
return
var/atom/real_location = real_location()
@@ -90,13 +90,13 @@
slaves -= S
return FALSE
/datum/component/storage/concrete/proc/on_contents_del(atom/A)
/datum/component/storage/concrete/proc/on_contents_del(datum/source, atom/A)
var/atom/real_location = parent
if(A in real_location)
usr = null
remove_from_storage(A, null)
/datum/component/storage/concrete/proc/on_deconstruct(disassembled)
/datum/component/storage/concrete/proc/on_deconstruct(datum/source, disassembled)
if(drop_all_on_deconstruct)
do_quick_empty()

View File

@@ -1,6 +1,6 @@
/datum/component/storage/concrete/bluespace/bag_of_holding/handle_item_insertion(obj/item/W, prevent_warning = FALSE, mob/living/user)
var/atom/A = parent
if(A == W)
if(A == W) //don't put yourself into yourself.
return
var/list/obj/item/storage/backpack/holding/matching = typecache_filter_list(W.GetAllContents(), typecacheof(/obj/item/storage/backpack/holding))
matching -= A
@@ -30,7 +30,7 @@
for (var/obj/structure/ladder/unbreakable/binary/ladder in GLOB.ladders)
ladder.ActivateAlmonds()
message_admins("[ADMIN_LOOKUPFLW(user)] detonated a bag of holding at [ADMIN_VERBOSEJMP(loccheck)].")
log_game("[key_name(user)] detonated a bag of holding at [AREACOORD(loccheck)].")
log_game("[key_name(user)] detonated a bag of holding at [loc_name(loccheck)].")
qdel(A)
return
. = ..()

View File

@@ -89,12 +89,13 @@
RegisterSignal(parent, COMSIG_ATOM_ATTACK_GHOST, .proc/show_to_ghost)
RegisterSignal(parent, COMSIG_ATOM_ENTERED, .proc/refresh_mob_views)
RegisterSignal(parent, COMSIG_ATOM_EXITED, .proc/_remove_and_refresh)
RegisterSignal(parent, COMSIG_ATOM_CANREACH, .proc/canreach_react)
RegisterSignal(parent, COMSIG_ITEM_PRE_ATTACK, .proc/preattack_intercept)
RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/attack_self)
RegisterSignal(parent, COMSIG_ITEM_PICKUP, .proc/signal_on_pickup)
RegisterSignal(parent, COMSIG_MOVABLE_PRE_THROW, .proc/close_all)
RegisterSignal(parent, COMSIG_MOVABLE_POST_THROW, .proc/close_all)
RegisterSignal(parent, COMSIG_CLICK_ALT, .proc/on_alt_click)
RegisterSignal(parent, COMSIG_MOUSEDROP_ONTO, .proc/mousedrop_onto)
@@ -118,6 +119,7 @@
return
var/obj/item/I = parent
modeswitch_action = new(I)
RegisterSignal(modeswitch_action, COMSIG_ACTION_TRIGGER, .proc/action_trigger)
if(I.obj_flags & IN_INVENTORY)
var/mob/M = I.loc
if(!istype(M))
@@ -143,14 +145,24 @@
var/datum/component/storage/concrete/master = master()
return master? master.real_location() : null
/datum/component/storage/proc/attack_self(mob/M)
/datum/component/storage/proc/canreach_react(datum/source, list/next)
var/datum/component/storage/concrete/master = master()
if(!master)
return
. = COMPONENT_BLOCK_REACH
next += master.parent
for(var/i in master.slaves)
var/datum/component/storage/slave = i
next += slave.parent
/datum/component/storage/proc/attack_self(datum/source, mob/M)
if(locked)
to_chat(M, "<span class='warning'>[parent] seems to be locked!</span>")
return FALSE
if((M.get_active_held_item() == parent) && allow_quick_empty)
quick_empty(M)
/datum/component/storage/proc/preattack_intercept(obj/O, mob/M, params)
/datum/component/storage/proc/preattack_intercept(datum/source, obj/O, mob/M, params)
if(!isitem(O) || !click_gather || SEND_SIGNAL(O, COMSIG_CONTAINS_STORAGE))
return FALSE
. = COMPONENT_NO_ATTACK
@@ -263,7 +275,7 @@
remove_from_storage(I, _target)
return TRUE
/datum/component/storage/proc/set_locked(new_state)
/datum/component/storage/proc/set_locked(datum/source, new_state)
locked = new_state
if(locked)
close_all()
@@ -371,11 +383,11 @@
close(M)
. = TRUE //returns TRUE if any mobs actually got a close(M) call
/datum/component/storage/proc/emp_act(severity)
/datum/component/storage/proc/emp_act(datum/source, severity)
if(emp_shielded)
return
var/datum/component/storage/concrete/master = master()
master.emp_act(severity)
master.emp_act(source, severity)
//This proc draws out the inventory and places the items on it. tx and ty are the upper left tile and mx, my are the bottm right.
//The numbers are calculated from the bottom-left The bottom-left slot being 1,1.
@@ -405,7 +417,7 @@
return FALSE
return master._removal_reset(thing)
/datum/component/storage/proc/_remove_and_refresh(atom/movable/thing)
/datum/component/storage/proc/_remove_and_refresh(datum/source, atom/movable/thing)
_removal_reset(thing)
refresh_mob_views()
@@ -447,7 +459,7 @@
return FALSE
//This proc is called when you want to place an item into the storage item.
/datum/component/storage/proc/attackby(obj/item/I, mob/M, params)
/datum/component/storage/proc/attackby(datum/source, obj/item/I, mob/M, params)
if(istype(I, /obj/item/hand_labeler))
var/obj/item/hand_labeler/labeler = I
if(labeler.mode)
@@ -476,13 +488,13 @@
return real_location.contents.Copy()
//Abuses the fact that lists are just references, or something like that.
/datum/component/storage/proc/signal_return_inv(list/interface, recursive = TRUE)
/datum/component/storage/proc/signal_return_inv(datum/source, list/interface, recursive = TRUE)
if(!islist(interface))
return FALSE
interface |= return_inv(recursive)
return TRUE
/datum/component/storage/proc/mousedrop_onto(atom/over_object, mob/M)
/datum/component/storage/proc/mousedrop_onto(datum/source, atom/over_object, mob/M)
set waitfor = FALSE
. = COMPONENT_NO_MOUSEDROP
var/atom/A = parent
@@ -519,7 +531,7 @@
if(force || M.CanReach(parent, view_only = TRUE))
show_to(M)
/datum/component/storage/proc/mousedrop_receive(atom/movable/O, mob/M)
/datum/component/storage/proc/mousedrop_receive(datum/source, atom/movable/O, mob/M)
if(isitem(O))
var/obj/item/I = O
if(iscarbon(M) || isdrone(M))
@@ -540,7 +552,7 @@
if(real_location == I.loc)
return FALSE //Means the item is already in the storage item
if(locked)
if(M)
if(M && !stop_messages)
host.add_fingerprint(M)
to_chat(M, "<span class='warning'>[host] seems to be locked!</span>")
return FALSE
@@ -618,18 +630,18 @@
var/obj/O = parent
O.update_icon()
/datum/component/storage/proc/signal_insertion_attempt(obj/item/I, mob/M, silent = FALSE, force = FALSE)
/datum/component/storage/proc/signal_insertion_attempt(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE)
if((!force && !can_be_inserted(I, TRUE, M)) || (I == parent))
return FALSE
return handle_item_insertion(I, silent, M)
/datum/component/storage/proc/signal_can_insert(obj/item/I, mob/M, silent = FALSE)
/datum/component/storage/proc/signal_can_insert(datum/source, obj/item/I, mob/M, silent = FALSE)
return can_be_inserted(I, silent, M)
/datum/component/storage/proc/show_to_ghost(mob/dead/observer/M)
/datum/component/storage/proc/show_to_ghost(datum/source, mob/dead/observer/M)
return user_show_to_mob(M, TRUE)
/datum/component/storage/proc/signal_show_attempt(mob/showto, force = FALSE)
/datum/component/storage/proc/signal_show_attempt(datum/source, mob/showto, force = FALSE)
return user_show_to_mob(showto, force)
/datum/component/storage/proc/on_check()
@@ -638,14 +650,14 @@
/datum/component/storage/proc/check_locked()
return locked
/datum/component/storage/proc/signal_take_type(type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted)
/datum/component/storage/proc/signal_take_type(datum/source, type, atom/destination, amount = INFINITY, check_adjacent = FALSE, force = FALSE, mob/user, list/inserted)
if(!force)
if(check_adjacent)
if(!user || !user.CanReach(destination) || !user.CanReach(parent))
return FALSE
var/list/taking = typecache_filter_list(contents(), typecacheof(type))
if(length(taking) > amount)
taking.Cut(amount)
if(taking.len > amount)
taking.len = amount
if(inserted) //duplicated code for performance, don't bother checking retval/checking for list every item.
for(var/i in taking)
if(remove_from_storage(i, destination))
@@ -659,7 +671,7 @@
var/atom/real_location = real_location()
return max(0, max_items - real_location.contents.len)
/datum/component/storage/proc/signal_fill_type(type, amount = 20, force = FALSE)
/datum/component/storage/proc/signal_fill_type(datum/source, type, amount = 20, force = FALSE)
var/atom/real_location = real_location()
if(!force)
amount = min(remaining_space_items(), amount)
@@ -668,7 +680,7 @@
CHECK_TICK
return TRUE
/datum/component/storage/proc/on_attack_hand(mob/user)
/datum/component/storage/proc/on_attack_hand(datum/source, mob/user)
var/atom/A = parent
if(!attack_hand_interact)
return
@@ -701,25 +713,25 @@
else
show_to(user)
/datum/component/storage/proc/signal_on_pickup(mob/user)
/datum/component/storage/proc/signal_on_pickup(datum/source, mob/user)
var/atom/A = parent
update_actions()
for(var/mob/M in range(1, A))
if(M.active_storage == src)
close(M)
/datum/component/storage/proc/signal_take_obj(atom/movable/AM, new_loc, force = FALSE)
/datum/component/storage/proc/signal_take_obj(datum/source, atom/movable/AM, new_loc, force = FALSE)
if(!(AM in real_location()))
return FALSE
return remove_from_storage(AM, new_loc)
/datum/component/storage/proc/signal_quick_empty(atom/loctarget)
/datum/component/storage/proc/signal_quick_empty(datum/source, atom/loctarget)
return do_quick_empty(loctarget)
/datum/component/storage/proc/signal_hide_attempt(mob/target)
/datum/component/storage/proc/signal_hide_attempt(datum/source, mob/target)
return hide_from(target)
/datum/component/storage/proc/on_alt_click(mob/user)
/datum/component/storage/proc/on_alt_click(datum/source, mob/user)
if(!isliving(user) || user.incapacitated() || !quickdraw || locked || !user.CanReach(parent))
return
var/obj/item/I = locate() in real_location()
@@ -731,6 +743,10 @@
return
user.visible_message("<span class='warning'>[user] draws [I] from [parent]!</span>", "<span class='notice'>You draw [I] from [parent].</span>")
/datum/component/storage/proc/action_trigger(datum/signal_source, datum/action/source)
gather_mode_switch(source.owner)
return COMPONENT_ACTION_BLOCK_TRIGGER
/datum/component/storage/proc/gather_mode_switch(mob/user)
collection_mode = (collection_mode+1)%3
switch(collection_mode)

View File

@@ -11,7 +11,7 @@
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/join_swarm)
RegisterSignal(parent, COMSIG_MOVABLE_UNCROSSED, .proc/leave_swarm)
/datum/component/swarming/proc/join_swarm(atom/movable/AM)
/datum/component/swarming/proc/join_swarm(datum/source, atom/movable/AM)
GET_COMPONENT_FROM(other_swarm, /datum/component/swarming, AM)
if(!other_swarm)
return
@@ -20,7 +20,7 @@
other_swarm.swarm()
other_swarm.swarm_members |= src
/datum/component/swarming/proc/leave_swarm(atom/movable/AM)
/datum/component/swarming/proc/leave_swarm(datum/source, atom/movable/AM)
GET_COMPONENT_FROM(other_swarm, /datum/component/swarming, AM)
if(!other_swarm || !(other_swarm in swarm_members))
return

View File

@@ -68,14 +68,14 @@
else
QDEL_IN(fakefire, 50)
/datum/component/thermite/proc/clean_react(strength)
/datum/component/thermite/proc/clean_react(datum/source, strength)
//Thermite is just some loose powder, you could probably clean it with your hands. << todo?
qdel(src)
/datum/component/thermite/proc/flame_react(exposed_temperature, exposed_volume)
/datum/component/thermite/proc/flame_react(datum/source, exposed_temperature, exposed_volume)
if(exposed_temperature > 1922) // This is roughly the real life requirement to ignite thermite
thermite_melt()
/datum/component/thermite/proc/attackby_react(obj/item/thing, mob/user, params)
/datum/component/thermite/proc/attackby_react(datum/source, obj/item/thing, mob/user, params)
if(thing.is_hot())
thermite_melt(user)

View File

@@ -84,7 +84,7 @@ GLOBAL_LIST_EMPTY(uplinks)
gamemode = _gamemode
uplink_items = get_uplink_items(gamemode, TRUE, allow_restricted)
/datum/component/uplink/proc/OnAttackBy(obj/item/I, mob/user)
/datum/component/uplink/proc/OnAttackBy(datum/source, obj/item/I, mob/user)
if(!active)
return //no hitting everyone/everything just to try to slot tcs in!
if(istype(I, /obj/item/stack/telecrystal))
@@ -101,7 +101,7 @@ GLOBAL_LIST_EMPTY(uplinks)
qdel(I)
return
/datum/component/uplink/proc/interact(mob/user)
/datum/component/uplink/proc/interact(datum/source, mob/user)
if(locked)
return
active = TRUE
@@ -201,28 +201,28 @@ GLOBAL_LIST_EMPTY(uplinks)
/datum/component/uplink/proc/implant_activation()
var/obj/item/implant/implant = parent
locked = FALSE
interact(implant.imp_in)
interact(null, implant.imp_in)
/datum/component/uplink/proc/implanting(list/arguments)
/datum/component/uplink/proc/implanting(datum/source, list/arguments)
var/mob/user = arguments[2]
owner = "[user.key]"
/datum/component/uplink/proc/old_implant(list/arguments, obj/item/implant/new_implant)
/datum/component/uplink/proc/old_implant(datum/source, list/arguments, obj/item/implant/new_implant)
// It kinda has to be weird like this until implants are components
return SEND_SIGNAL(new_implant, COMSIG_IMPLANT_EXISTING_UPLINK, src)
/datum/component/uplink/proc/new_implant(datum/component/uplink/uplink)
/datum/component/uplink/proc/new_implant(datum/source, datum/component/uplink/uplink)
uplink.telecrystals += telecrystals
return COMPONENT_DELETE_NEW_IMPLANT
// PDA signal responses
/datum/component/uplink/proc/new_ringtone(mob/living/user, new_ring_text)
/datum/component/uplink/proc/new_ringtone(datum/source, mob/living/user, new_ring_text)
var/obj/item/pda/master = parent
if(trim(lowertext(new_ring_text)) != trim(lowertext(master.lock_code))) //why is the lock code stored on the pda?
return
locked = FALSE
interact(user)
interact(null, user)
to_chat(user, "The PDA softly beeps.")
user << browse(null, "window=pda")
master.mode = 0
@@ -230,22 +230,22 @@ GLOBAL_LIST_EMPTY(uplinks)
// Radio signal responses
/datum/component/uplink/proc/new_frequency(list/arguments)
/datum/component/uplink/proc/new_frequency(datum/source, list/arguments)
var/obj/item/radio/master = parent
var/frequency = arguments[1]
if(frequency != master.traitor_frequency)
return
locked = FALSE
if(ismob(master.loc))
interact(master.loc)
interact(null, master.loc)
// Pen signal responses
/datum/component/uplink/proc/pen_rotation(degrees, mob/living/carbon/user)
/datum/component/uplink/proc/pen_rotation(datum/source, degrees, mob/living/carbon/user)
var/obj/item/pen/master = parent
if(degrees != master.traitor_unlock_degrees)
return
locked = FALSE
master.degrees = 0
interact(user)
interact(null, user)
to_chat(user, "<span class='warning'>Your pen makes a clicking noise, before quickly rotating back to 0 degrees!</span>")

View File

@@ -0,0 +1,15 @@
/datum/component/waddling
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
/datum/component/waddling/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/Waddle)
/datum/component/waddling/proc/Waddle()
var/mob/living/L = parent
if(L.incapacitated() || L.lying)
return
animate(L, pixel_z = 4, time = 0)
animate(pixel_z = 0, transform = turn(matrix(), pick(-12, 0, 12)), time=2)
animate(pixel_z = 0, transform = matrix(), time = 0)

View File

@@ -12,13 +12,13 @@
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
/datum/component/wearertargeting/proc/on_equip(mob/equipper, slot)
/datum/component/wearertargeting/proc/on_equip(datum/source, mob/equipper, slot)
if((slot in valid_slots) && istype(equipper, mobtype))
RegisterSignal(equipper, signals, callback, TRUE)
else
UnregisterSignal(equipper, signals)
/datum/component/wearertargeting/proc/on_drop(mob/user)
/datum/component/wearertargeting/proc/on_drop(datum/source, mob/user)
UnregisterSignal(user, signals)
/datum/component/wearertargeting/Destroy()

View File

@@ -90,7 +90,7 @@
S.intensity = intensity
S.lube_flags = lube_flags
/datum/component/wet_floor/proc/dry(strength = TURF_WET_WATER, immediate = FALSE, duration_decrease = INFINITY)
/datum/component/wet_floor/proc/dry(datum/source, strength = TURF_WET_WATER, immediate = FALSE, duration_decrease = INFINITY)
for(var/i in time_left_list)
if(text2num(i) <= strength)
time_left_list[i] = max(0, time_left_list[i] - duration_decrease)
@@ -120,8 +120,8 @@
if(O.obj_flags & FROZEN)
O.make_unfrozen()
add_wet(TURF_WET_WATER, max_time_left())
dry(TURF_WET_ICE)
dry(ALL, FALSE, decrease)
dry(null, TURF_WET_ICE)
dry(null, ALL, FALSE, decrease)
check()
last_process = world.time

View File

@@ -2,7 +2,9 @@
var/gc_destroyed //Time when this object was destroyed.
var/list/active_timers //for SStimer
var/list/datum_components //for /datum/components
var/list/comp_lookup //for /datum/components
var/list/comp_lookup //it used to be for looking up components which had registered a signal but now anything can register
var/list/signal_procs
var/signal_enabled = FALSE
var/datum_flags = NONE
var/datum/weakref/weak_reference
@@ -20,6 +22,7 @@
// Return the appropriate QDEL_HINT; in most cases this is QDEL_HINT_QUEUE.
/datum/proc/Destroy(force=FALSE, ...)
tag = null
datum_flags &= ~DF_USE_TAG //In case something tries to REF us
weak_reference = null //ensure prompt GCing of weakref.
var/list/timers = active_timers
@@ -30,6 +33,9 @@
continue
qdel(timer)
//BEGIN: ECS SHIT
signal_enabled = FALSE
var/list/dc = datum_components
if(dc)
var/all_components = dc[/datum/component]
@@ -55,6 +61,10 @@
comp.UnregisterSignal(src, sig)
comp_lookup = lookup = null
for(var/target in signal_procs)
UnregisterSignal(target, signal_procs[target])
//END: ECS SHIT
return QDEL_HINT_QUEUE
#ifdef DATUMVAR_DEBUGGING_MODE
@@ -86,16 +96,16 @@
//Return a LIST for serialize_datum to encode! Not the actual json!
/datum/proc/serialize_list(list/options)
return NOT_IMPLEMENTED
CRASH("Attempted to serialize datum [src] of type [type] without serialize_list being implemented!")
//Accepts a LIST from deserialize_datum. Should return src or another datum.
/datum/proc/deserialize_list(json, list/options)
return NOT_IMPLEMENTED
CRASH("Attempted to deserialize datum [src] of type [type] without deserialize_list being implemented!")
//Serializes into JSON. Does not encode type.
/datum/proc/serialize_json(list/options)
. = serialize_list(options)
if((. == NOT_IMPLEMENTED) || !islist(.))
if(!islist(.))
. = null
else
. = json_encode(.)

View File

@@ -1,3 +1,7 @@
#define VV_MSG_MARKED "<br><font size='1' color='red'><b>Marked Object</b></font>"
#define VV_MSG_EDITED "<br><font size='1' color='red'><b>Var Edited</b></font>"
#define VV_MSG_DELETED "<br><font size='1' color='red'><b>Deleted</b></font>"
/datum/proc/CanProcCall(procname)
return TRUE
@@ -9,6 +13,7 @@
return FALSE
vars[var_name] = var_value
datum_flags |= DF_VAR_EDITED
return TRUE
/datum/proc/vv_get_var(var_name)
switch(var_name)
@@ -68,6 +73,7 @@
src << browse_rsc(sprite, "vv[hash].png")
title = "[D] ([REF(D)]) = [type]"
var/formatted_type = replacetext("[type]", "/", "<wbr>/")
var/sprite_text
if(sprite)
@@ -77,36 +83,40 @@
if(istype(D, /atom))
var/atom/A = D
if(isliving(A))
atomsnowflake += "<a href='?_src_=vars;[HrefToken()];rename=[refid]'><b>[D]</b></a>"
if(A.dir)
atomsnowflake += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
atomsnowflake += "<a href='?_src_=vars;[HrefToken()];rename=[refid]'><b id='name'>[D]</b></a>"
atomsnowflake += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir' id='dir'>[dir2text(A.dir) || A.dir]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
var/mob/living/M = A
atomsnowflake += {"
<br><font size='1'><a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=ckey'>[M.ckey ? M.ckey : "No ckey"]</a> / <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=real_name'>[M.real_name ? M.real_name : "No real name"]</a></font>
<br><font size='1'><a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=ckey' id='ckey'>[M.ckey || "No ckey"]</a> / <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=real_name' id='real_name'>[M.real_name || "No real name"]</a></font>
<br><font size='1'>
BRUTE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brute'>[M.getBruteLoss()]</a>
FIRE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=fire'>[M.getFireLoss()]</a>
TOXIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=toxin'>[M.getToxLoss()]</a>
OXY:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=oxygen'>[M.getOxyLoss()]</a>
CLONE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=clone'>[M.getCloneLoss()]</a>
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain'>[M.getBrainLoss()]</a>
STAMINA:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stamina'>[M.getStaminaLoss()]</a>
BRUTE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brute' id='brute'>[M.getBruteLoss()]</a>
FIRE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=fire' id='fire'>[M.getFireLoss()]</a>
TOXIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=toxin' id='toxin'>[M.getToxLoss()]</a>
OXY:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=oxygen' id='oxygen'>[M.getOxyLoss()]</a>
CLONE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=clone' id='clone'>[M.getCloneLoss()]</a>
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain' id='brain'>[M.getBrainLoss()]</a>
STAMINA:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stamina' id='stamina'>[M.getStaminaLoss()]</a>
AROUSAL:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=arousal' id='arousal'>[M.getArousalLoss()]</a>
</font>
"}
else
atomsnowflake += "<a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=name'><b>[D]</b></a>"
if(A.dir)
atomsnowflake += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir'>[dir2text(A.dir)]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
atomsnowflake += "<a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=name'><b id='name'>[D]</b></a>"
atomsnowflake += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir' id='dir'>[dir2text(A.dir) || A.dir]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
else if("name" in D.vars)
atomsnowflake += "<a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=name'><b id='name'>[D]</b></a>"
else
atomsnowflake += "<b>[D]</b>"
atomsnowflake += "<b>[formatted_type]</b>"
formatted_type = null
var/formatted_type = replacetext("[type]", "/", "<wbr>/")
var/marked
if(holder && holder.marked_datum && holder.marked_datum == D)
marked = "<br><font size='1' color='red'><b>Marked Object</b></font>"
marked = VV_MSG_MARKED
var/varedited_line = ""
if(!islist && (D.datum_flags & DF_VAR_EDITED))
varedited_line = "<br><font size='1' color='red'><b>Var Edited</b></font>"
varedited_line = VV_MSG_EDITED
var/deleted_line
if(!islist && D.gc_destroyed)
deleted_line = VV_MSG_DELETED
var/list/dropdownoptions = list()
if (islist)
@@ -167,112 +177,9 @@
}
</style>
</head>
<body onload='selectTextField(); updateSearch()' onkeydown='return checkreload()' onkeyup='updateSearch()'>
<body onload='selectTextField()' onkeydown='return handle_keydown()' onkeyup='handle_keyup()'>
<script type="text/javascript">
function checkreload() {
if(event.keyCode == 116){ //F5 (to refresh properly)
document.getElementById("refresh_link").click();
event.preventDefault ? event.preventDefault() : (event.returnValue = false)
return false;
}
return true;
}
function updateSearch(){
var filter_text = document.getElementById('filter');
var filter = filter_text.value.toLowerCase();
if(event.keyCode == 13){ //Enter / return
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
alist = lis\[i\].getElementsByTagName("a")
if(alist.length > 0){
location.href=alist\[0\].href;
}
}
}catch(err) { }
}
return
}
if(event.keyCode == 38){ //Up arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
if( (i-1) >= 0){
var li_new = lis\[i-1\];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
}catch(err) { }
}
return
}
if(event.keyCode == 40){ //Down arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.style.backgroundColor == "#ffee88" )
{
if( (i+1) < lis.length){
var li_new = lis\[i+1\];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
}catch(err) { }
}
return
}
//This part here resets everything to how it was at the start so the filter is applied to the complete list. Screw efficiency, it's client-side anyway and it only looks through 200 or so variables at maximum anyway (mobs).
if(complete_list != null && complete_list != ""){
var vars_ol1 = document.getElementById("vars");
vars_ol1.innerHTML = complete_list
}
document.cookie="[refid][cookieoffset]search="+encodeURIComponent(filter);
if(filter == ""){
return;
}else{
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for ( var i = 0; i < lis.length; ++i )
{
try{
var li = lis\[i\];
if ( li.innerText.toLowerCase().indexOf(filter) == -1 )
{
vars_ol.removeChild(li);
i--;
}
}catch(err) { }
}
}
var lis_new = vars_ol.getElementsByTagName("li");
for ( var j = 0; j < lis_new.length; ++j )
{
var li1 = lis\[j\];
if (j == 0){
li1.style.backgroundColor = "#ffee88";
}else{
li1.style.backgroundColor = "white";
}
}
}
// onload
function selectTextField() {
var filter_text = document.getElementById('filter');
filter_text.focus();
@@ -283,23 +190,140 @@
updateSearch();
}
}
function loadPage(list) {
if(list.options\[list.selectedIndex\].value == ""){
return;
}
location.href=list.options\[list.selectedIndex\].value;
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for(var i=0; i<ca.length; i++) {
var c = ca\[i\];
var c = ca\[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
}
return "";
}
// main search functionality
var last_filter = "";
function updateSearch() {
var filter = document.getElementById('filter').value.toLowerCase();
var vars_ol = document.getElementById("vars");
if (filter === last_filter) {
// An event triggered an update but nothing has changed.
return;
} else if (filter.indexOf(last_filter) === 0) {
// The new filter starts with the old filter, fast path by removing only.
var children = vars_ol.childNodes;
for (var i = children.length - 1; i >= 0; --i) {
try {
var li = children\[i];
if (li.innerText.toLowerCase().indexOf(filter) == -1) {
vars_ol.removeChild(li);
}
} catch(err) {}
}
} else {
// Remove everything and put back what matches.
while (vars_ol.hasChildNodes()) {
vars_ol.removeChild(vars_ol.lastChild);
}
for (var i = 0; i < complete_list.length; ++i) {
try {
var li = complete_list\[i];
if (!filter || li.innerText.toLowerCase().indexOf(filter) != -1) {
vars_ol.appendChild(li);
}
} catch(err) {}
}
}
last_filter = filter;
document.cookie="[refid][cookieoffset]search="+encodeURIComponent(filter);
var lis_new = vars_ol.getElementsByTagName("li");
for (var j = 0; j < lis_new.length; ++j) {
lis_new\[j].style.backgroundColor = (j == 0) ? "#ffee88" : "white";
}
}
// onkeydown
function handle_keydown() {
if(event.keyCode == 116) { //F5 (to refresh properly)
document.getElementById("refresh_link").click();
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
return false;
}
return true;
}
// onkeyup
function handle_keyup() {
if (event.keyCode == 13) { //Enter / return
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for (var i = 0; i < lis.length; ++i) {
try {
var li = lis\[i];
if (li.style.backgroundColor == "#ffee88") {
alist = lis\[i].getElementsByTagName("a");
if(alist.length > 0) {
location.href=alist\[0].href;
}
}
} catch(err) {}
}
} else if(event.keyCode == 38){ //Up arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for (var i = 0; i < lis.length; ++i) {
try {
var li = lis\[i];
if (li.style.backgroundColor == "#ffee88") {
if (i > 0) {
var li_new = lis\[i-1];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
} catch(err) {}
}
} else if(event.keyCode == 40) { //Down arrow
var vars_ol = document.getElementById('vars');
var lis = vars_ol.getElementsByTagName("li");
for (var i = 0; i < lis.length; ++i) {
try {
var li = lis\[i];
if (li.style.backgroundColor == "#ffee88") {
if ((i+1) < lis.length) {
var li_new = lis\[i+1];
li.style.backgroundColor = "white";
li_new.style.backgroundColor = "#ffee88";
return
}
}
} catch(err) {}
}
} else {
updateSearch();
}
}
// onchange
function handle_dropdown(list) {
var value = list.options\[list.selectedIndex].value;
if (value !== "") {
location.href = value;
}
list.selectedIndex = 0;
document.getElementById('filter').focus();
}
// byjax
function replace_span(what) {
var idx = what.indexOf(':');
document.getElementById(what.substr(0, idx)).innerHTML = what.substr(idx + 1);
}
</script>
<div align='center'>
<table width='100%'>
@@ -317,8 +341,9 @@
</table>
<div align='center'>
<b><font size='1'>[formatted_type]</font></b>
[marked]
[varedited_line]
<span id='marked'>[marked]</span>
<span id='varedited'>[varedited_line]</span>
<span id='deleted'>[deleted_line]</span>
</div>
</td>
<td width='50%'>
@@ -326,8 +351,7 @@
<a id='refresh_link' href='?_src_=vars;[HrefToken()];datumrefresh=[refid]'>Refresh</a>
<form>
<select name="file" size="1"
onchange="loadPage(this.form.elements\[0\])"
target="_parent._top"
onchange="handle_dropdown(this)"
onmouseclick="this.focus()"
style="background-color:#ffffff">
<option value selected>Select option</option>
@@ -363,8 +387,9 @@
[variable_html.Join()]
</ol>
<script type='text/javascript'>
var vars_ol = document.getElementById("vars");
var complete_list = vars_ol.innerHTML;
var complete_list = \[\];
var lis = document.getElementById("vars").children;
for(var i = lis.length; i--;) complete_list\[i\] = lis\[i\];
</script>
</body>
</html>
@@ -372,6 +397,10 @@
src << browse(html, "window=variables[refid];size=475x650")
/client/proc/vv_update_display(datum/D, span, content)
src << output("[span]:[content]", "variables[REF(D)].browser:replace_span")
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE)
var/header
@@ -471,7 +500,6 @@
return
src.holder.show_player_panel(M)
href_list["datumrefresh"] = href_list["mob_player_panel"]
else if(href_list["godmode"])
if(!check_rights(R_ADMIN))
@@ -483,7 +511,6 @@
return
src.cmd_admin_godmode(M)
href_list["datumrefresh"] = href_list["godmode"]
else if(href_list["mark_object"])
if(!check_rights(NONE))
@@ -494,8 +521,10 @@
to_chat(usr, "This can only be done to instances of type /datum")
return
src.holder.marked_datum = D
href_list["datumrefresh"] = href_list["mark_object"]
if(holder.marked_datum)
vv_update_display(holder.marked_datum, "marked", "")
holder.marked_datum = D
vv_update_display(D, "marked", VV_MSG_MARKED)
else if(href_list["proc_call"])
if(!check_rights(NONE))
@@ -511,10 +540,11 @@
return
var/datum/D = locate(href_list["delete"])
if(!D)
if(!istype(D))
to_chat(usr, "Unable to locate item!")
admin_delete(D)
href_list["datumrefresh"] = href_list["delete"]
if (isturf(D)) // show the turf that took its place
debug_variables(D)
else if(href_list["osay"])
if(!check_rights(R_FUN, 0))
@@ -573,18 +603,33 @@
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].")
M.fully_replace_character_name(M.real_name,new_name)
href_list["datumrefresh"] = href_list["rename"]
vv_update_display(M, "name", new_name)
vv_update_display(M, "real_name", M.real_name || "No real name")
else if(href_list["varnameedit"] && href_list["datumedit"])
if(!check_rights(NONE))
return
var/D = locate(href_list["datumedit"])
var/datum/D = locate(href_list["datumedit"])
if(!istype(D, /datum))
to_chat(usr, "This can only be used on datums")
return
modify_variables(D, href_list["varnameedit"], 1)
if (!modify_variables(D, href_list["varnameedit"], 1))
return
switch(href_list["varnameedit"])
if("name")
vv_update_display(D, "name", "[D]")
if("dir")
if(isatom(D))
var/dir = D.vars["dir"]
vv_update_display(D, "dir", dir2text(dir) || dir)
if("ckey")
if(isliving(D))
vv_update_display(D, "ckey", D.vars["ckey"] || "No ckey")
if("real_name")
if(isliving(D))
vv_update_display(D, "real_name", D.vars["real_name"] || "No real name")
else if(href_list["varnamechange"] && href_list["datumchange"])
if(!check_rights(NONE))
@@ -716,7 +761,6 @@
return
src.give_spell(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["remove_spell"])
if(!check_rights(NONE))
@@ -728,7 +772,6 @@
return
remove_spell(M)
href_list["datumrefresh"] = href_list["remove_spell"]
else if(href_list["give_disease"])
if(!check_rights(NONE))
@@ -740,7 +783,6 @@
return
src.give_disease(M)
href_list["datumrefresh"] = href_list["give_spell"]
else if(href_list["gib"])
if(!check_rights(R_FUN))
@@ -763,7 +805,6 @@
return
togglebuildmode(M)
href_list["datumrefresh"] = href_list["build_mode"]
else if(href_list["drop_everything"])
if(!check_rights(NONE))
@@ -814,7 +855,7 @@
for (var/i in armorlist)
pickerlist += list(list("value" = armorlist[i], "name" = i))
var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [O]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, Type = "text", values = pickerlist)
var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [O]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist)
if (islist(result))
if (result["button"] == 2) // If the user pressed the cancel button
@@ -915,8 +956,6 @@
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]")
message_admins("<span class='notice'>[key_name(usr)] has added [amount] units of [chosen_id] to \the [A]</span>")
href_list["datumrefresh"] = href_list["addreagent"]
else if(href_list["explode"])
if(!check_rights(R_FUN))
return
@@ -927,7 +966,6 @@
return
src.cmd_admin_explosion(A)
href_list["datumrefresh"] = href_list["explode"]
else if(href_list["emp"])
if(!check_rights(R_FUN))
@@ -939,7 +977,6 @@
return
src.cmd_admin_emp(A)
href_list["datumrefresh"] = href_list["emp"]
else if(href_list["modtransform"])
if(!check_rights(R_DEBUG))
@@ -968,8 +1005,6 @@
if(!isnull(angle))
A.transform = M.Turn(angle)
href_list["datumrefresh"] = href_list["modtransform"]
else if(href_list["rotatedatum"])
if(!check_rights(NONE))
return
@@ -984,7 +1019,7 @@
A.setDir(turn(A.dir, -45))
if("left")
A.setDir(turn(A.dir, 45))
href_list["datumrefresh"] = href_list["rotatedatum"]
vv_update_display(A, "dir", dir2text(A.dir))
else if(href_list["editorgans"])
if(!check_rights(NONE))
@@ -996,7 +1031,33 @@
return
manipulate_organs(C)
href_list["datumrefresh"] = href_list["editorgans"]
else if(href_list["givemartialart"])
if(!check_rights(NONE))
return
var/mob/living/carbon/C = locate(href_list["givemartialart"]) in GLOB.carbon_list
if(!istype(C))
to_chat(usr, "This can only be done to instances of type /mob/living/carbon")
return
var/list/artpaths = subtypesof(/datum/martial_art)
var/list/artnames = list()
for(var/i in artpaths)
var/datum/martial_art/M = i
artnames[initial(M.name)] = M
var/result = input(usr, "Choose the martial art to teach","JUDO CHOP") as null|anything in artnames
if(!usr)
return
if(QDELETED(C))
to_chat(usr, "Mob doesn't exist anymore")
return
if(result)
var/chosenart = artnames[result]
var/datum/martial_art/MA = new chosenart
MA.teach(C)
else if(href_list["givetrauma"])
if(!check_rights(NONE))
@@ -1018,8 +1079,6 @@
if(result)
C.gain_trauma(result)
href_list["datumrefresh"] = href_list["givetrauma"]
else if(href_list["curetraumas"])
if(!check_rights(NONE))
return
@@ -1031,8 +1090,6 @@
C.cure_all_traumas(TRAUMA_RESILIENCE_ABSOLUTE)
href_list["datumrefresh"] = href_list["curetraumas"]
else if(href_list["hallucinate"])
if(!check_rights(NONE))
return
@@ -1262,21 +1319,32 @@
to_chat(usr, "Mob doesn't exist anymore")
return
var/newamt
switch(Text)
if("brute")
L.adjustBruteLoss(amount)
newamt = L.getBruteLoss()
if("fire")
L.adjustFireLoss(amount)
newamt = L.getFireLoss()
if("toxin")
L.adjustToxLoss(amount)
newamt = L.getToxLoss()
if("oxygen")
L.adjustOxyLoss(amount)
newamt = L.getOxyLoss()
if("brain")
L.adjustBrainLoss(amount)
newamt = L.getBrainLoss()
if("clone")
L.adjustCloneLoss(amount)
newamt = L.getCloneLoss()
if("stamina")
L.adjustStaminaLoss(amount)
newamt = L.getStaminaLoss()
if("arousal")
L.adjustArousalLoss(amount)
newamt = L.getArousalLoss()
else
to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]")
return
@@ -1286,4 +1354,10 @@
var/msg = "<span class='notice'>[key_name(usr)] dealt [amount] amount of [Text] damage to [L] </span>"
message_admins(msg)
admin_ticket_log(L, msg)
href_list["datumrefresh"] = href_list["mobToDamage"]
vv_update_display(L, Text, "[newamt]")
else if(href_list["copyoutfit"])
if(!check_rights(R_SPAWN))
return
var/mob/living/carbon/human/H = locate(href_list["copyoutfit"]) in GLOB.carbon_list
if(istype(H))
H.copy_outfit()

View File

@@ -233,7 +233,7 @@
/datum/symptom/heal/coma/CanHeal(datum/disease/advance/A)
var/mob/living/M = A.affected_mob
if(M.has_trait(TRAIT_FAKEDEATH))
if(M.has_trait(TRAIT_DEATHCOMA))
return power
else if(M.IsUnconscious() || M.stat == UNCONSCIOUS)
return power * 0.9

View File

@@ -21,7 +21,7 @@
cure()
else if(prob(parrot.speak_chance))
if(parrot.speech_buffer.len)
affected_mob.say(pick(parrot.speech_buffer))
affected_mob.say(pick(parrot.speech_buffer), forced = "parrot possession")
/datum/disease/parrot_possession/cure()
if(parrot && parrot.loc == affected_mob)

View File

@@ -25,4 +25,4 @@
to_chat(affected_mob, "<span class='danger'>Your thoughts are interrupted by a loud <b>HONK!</b></span>")
if(4)
if(prob(5))
affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) )
affected_mob.say( pick( list("HONK!", "Honk!", "Honk.", "Honk?", "Honk!!", "Honk?!", "Honk...") ) , forced = "pierrot's throat")

View File

@@ -16,6 +16,7 @@
var/list/stage4 = list("You feel white bread.")
var/list/stage5 = list("Oh the humanity!")
var/new_form = /mob/living/carbon/human
var/bantype
/datum/disease/transformation/Copy()
var/datum/disease/transformation/D = ..()
@@ -49,10 +50,6 @@
if(istype(affected_mob, /mob/living/carbon) && affected_mob.stat != DEAD)
if(stage5)
to_chat(affected_mob, pick(stage5))
if(jobban_isbanned(affected_mob, new_form))
if(!QDELETED(affected_mob))
affected_mob.death(1)
return
if(QDELETED(affected_mob))
return
if(affected_mob.notransform)
@@ -64,6 +61,8 @@
affected_mob.dropItemToGround(I)
var/mob/living/new_mob = new new_form(affected_mob.loc)
if(istype(new_mob))
if(bantype && jobban_isbanned(affected_mob, bantype))
replace_banned_player(new_mob)
new_mob.a_intent = INTENT_HARM
if(affected_mob.mind)
affected_mob.mind.transfer_to(new_mob)
@@ -74,7 +73,22 @@
new_mob.real_name = new_mob.name
qdel(affected_mob)
/datum/disease/transformation/proc/replace_banned_player(var/mob/living/new_mob) // This can run well after the mob has been transferred, so need a handle on the new mob to kill it if needed.
set waitfor = FALSE
var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [affected_mob.name]?", bantype, null, bantype, 50, affected_mob)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
to_chat(affected_mob, "Your mob has been taken over by a ghost! Appeal your job ban if you want to avoid this in the future!")
message_admins("[key_name_admin(C)] has taken control of ([key_name_admin(affected_mob)]) to replace a jobbaned player.")
affected_mob.ghostize(0)
affected_mob.key = C.key
else
to_chat(new_mob, "Your mob has been claimed by death! Appeal your job ban if you want to avoid this in the future!")
new_mob.death()
if (!QDELETED(new_mob))
new_mob.ghostize(can_reenter_corpse = FALSE)
new_mob.key = null
/datum/disease/transformation/jungle_fever
name = "Jungle Fever"
@@ -92,6 +106,8 @@
visibility_flags = 0
agent = "Kongey Vibrion M-909"
new_form = /mob/living/carbon/monkey
bantype = ROLE_MONKEY
stage1 = list()
stage2 = list()
@@ -120,7 +136,7 @@
affected_mob.confused += 10
if(4)
if(prob(3))
affected_mob.say(pick("Eeek, ook ook!", "Eee-eeek!", "Eeee!", "Ungh, ungh."))
affected_mob.say(pick("Eeek, ook ook!", "Eee-eeek!", "Eeee!", "Ungh, ungh."), forced = "jungle fever")
/datum/disease/transformation/jungle_fever/cure()
remove_monkey(affected_mob.mind)
@@ -153,19 +169,20 @@
stage5 = list("<span class='danger'>Your skin feels as if it's about to burst off!</span>")
new_form = /mob/living/silicon/robot
infectable_biotypes = list(MOB_ORGANIC, MOB_UNDEAD, MOB_ROBOTIC)
bantype = "Cyborg"
/datum/disease/transformation/robot/stage_act()
..()
switch(stage)
if(3)
if (prob(8))
affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop"))
affected_mob.say(pick("Beep, boop", "beep, beep!", "Boop...bop"), forced = "robotic transformation")
if (prob(4))
to_chat(affected_mob, "<span class='danger'>You feel a stabbing pain in your head.</span>")
affected_mob.Unconscious(40)
if(4)
if (prob(20))
affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee..."))
affected_mob.say(pick("beep, beep!", "Boop bop boop beep.", "kkkiiiill mmme", "I wwwaaannntt tttoo dddiiieeee..."), forced = "robotic transformation")
/datum/disease/transformation/xeno
@@ -184,6 +201,7 @@
stage4 = list("<span class='danger'>Your skin feels very tight.</span>", "<span class='danger'>Your blood boils!</span>", "<span class='danger'>You can feel... something...inside you.</span>")
stage5 = list("<span class='danger'>Your skin feels as if it's about to burst off!</span>")
new_form = /mob/living/carbon/alien/humanoid/hunter
bantype = ROLE_ALIEN
/datum/disease/transformation/xeno/stage_act()
..()
@@ -194,7 +212,7 @@
affected_mob.Unconscious(40)
if(4)
if (prob(20))
affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!"))
affected_mob.say(pick("You look delicious.", "Going to... devour you...", "Hsssshhhhh!"), forced = "xenomorph transformation")
/datum/disease/transformation/slime
@@ -246,10 +264,10 @@
switch(stage)
if(3)
if (prob(8))
affected_mob.say(pick("YAP", "Woof!"))
affected_mob.say(pick("YAP", "Woof!"), forced = "corgi transformation")
if(4)
if (prob(20))
affected_mob.say(pick("Bark!", "AUUUUUU"))
affected_mob.say(pick("Bark!", "AUUUUUU"), forced = "corgi transformation")
/datum/disease/transformation/morph
name = "Gluttony's Blessing"
@@ -267,3 +285,43 @@
stage5 = list("<span class='danger'>You have become a morph.</span>")
new_form = /mob/living/simple_animal/hostile/morph
infectable_biotypes = list(MOB_ORGANIC, MOB_INORGANIC, MOB_UNDEAD) //magic!
/datum/disease/transformation/gondola
name = "Gondola Transformation"
cure_text = "Condensed Capsaicin, ingested or injected." //getting pepper sprayed doesn't help
cures = list("condensedcapsaicin") //beats the hippie crap right out of your system
cure_chance = 80
stage_prob = 5
agent = "Tranquility"
desc = "Consuming the flesh of a Gondola comes at a terrible price."
severity = DISEASE_SEVERITY_BIOHAZARD
visibility_flags = 0
stage1 = list("You seem a little lighter in your step.")
stage2 = list("You catch yourself smiling for no reason.")
stage3 = list("<span class='danger'>A cruel sense of calm overcomes you.</span>", "<span class='danger'>You can't feel your arms!</span>", "<span class='danger'>You let go of the urge to hurt clowns.</span>")
stage4 = list("<span class='danger'>You can't feel your arms. It does not bother you anymore.</span>", "<span class='danger'>You forgive the clown for hurting you.</span>")
stage5 = list("<span class='danger'>You have become a Gondola.</span>")
new_form = /mob/living/simple_animal/pet/gondola
/datum/disease/transformation/gondola/stage_act()
..()
switch(stage)
if(2)
if (prob(5))
affected_mob.emote("smile")
if (prob(20))
affected_mob.reagents.add_reagent_list(list("pax" = 5))
if(3)
if (prob(5))
affected_mob.emote("smile")
if (prob(20))
affected_mob.reagents.add_reagent_list(list("pax" = 5))
if(4)
if (prob(5))
affected_mob.emote("smile")
if (prob(20))
affected_mob.reagents.add_reagent_list(list("pax" = 5))
if (prob(2))
to_chat(affected_mob, "<span class='danger'>You let go of what you were holding.</span>")
var/obj/item/I = affected_mob.get_active_held_item()
affected_mob.dropItemToGround(I)

View File

@@ -29,21 +29,21 @@ STI KALY - blind
switch(stage)
if(2)
if(prob(1)&&prob(50))
affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"))
affected_mob.say(pick("You shall not pass!", "Expeliarmus!", "By Merlins beard!", "Feel the power of the Dark Side!"), forced = "wizarditis")
if(prob(1)&&prob(50))
to_chat(affected_mob, "<span class='danger'>You feel [pick("that you don't have enough mana", "that the winds of magic are gone", "an urge to summon familiar")].</span>")
if(3)
if(prob(1)&&prob(50))
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"))
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!", "STI KALY!", "TARCOL MINTI ZHERI!"), forced = "wizarditis")
if(prob(1)&&prob(50))
to_chat(affected_mob, "<span class='danger'>You feel [pick("the magic bubbling in your veins","that this location gives you a +1 to INT","an urge to summon familiar")].</span>")
if(4)
if(prob(1))
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"))
affected_mob.say(pick("NEC CANTIO!","AULIE OXIN FIERA!","STI KALY!","EI NATH!"), forced = "wizarditis")
return
if(prob(1)&&prob(50))
to_chat(affected_mob, "<span class='danger'>You feel [pick("the tidal wave of raw power building inside","that this location gives you a +2 to INT and +1 to WIS","an urge to teleport")].</span>")
@@ -111,7 +111,7 @@ STI KALY - blind
if(!L)
return
affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!")
affected_mob.say("SCYAR NILA [uppertext(thearea.name)]!", forced = "wizarditis teleport")
affected_mob.forceMove(pick(L))
return

View File

@@ -12,6 +12,7 @@
var/list/temporary_mutations = list() //Timers for temporary mutations
var/list/previous = list() //For temporary name/ui/ue/blood_type modifications
var/mob/living/holder
var/delete_species = TRUE //Set to FALSE when a body is scanned by a cloner to fix #38875
/datum/dna/New(mob/living/new_holder)
if(istype(new_holder))
@@ -23,6 +24,8 @@
if(cholder.dna == src)
cholder.dna = null
holder = null
if(delete_species)
QDEL_NULL(species)
mutations.Cut() //This only references mutations, just dereference.
@@ -41,12 +44,12 @@
destination.dna.features = features.Copy()
destination.dna.real_name = real_name
destination.dna.temporary_mutations = temporary_mutations.Copy()
if(transfer_SE)
destination.dna.struc_enzymes = struc_enzymes
if(ishuman(destination))
var/mob/living/carbon/human/H = destination
H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA
destination.flavor_text = destination.dna.features["flavor_text"] //Update the flavor_text to use new dna text
if(transfer_SE)
destination.dna.struc_enzymes = struc_enzymes
/datum/dna/proc/copy_dna(datum/dna/new_dna)
new_dna.unique_enzymes = unique_enzymes
@@ -209,10 +212,10 @@
/datum/dna/proc/initialize_dna(newblood_type)
if(newblood_type)
blood_type = newblood_type
features = random_features()
unique_enzymes = generate_unique_enzymes()
uni_identity = generate_uni_identity()
struc_enzymes = generate_struc_enzymes()
features = random_features()
/datum/dna/stored //subtype used by brain mob's stored_dna
@@ -245,17 +248,21 @@
stored_dna.species = mrace //not calling any species update procs since we're a brain, not a monkey/human
/mob/living/carbon/set_species(datum/species/mrace, icon_update = 1)
/mob/living/carbon/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE)
if(mrace && has_dna())
dna.species.on_species_loss(src)
var/old_species = dna.species
var/datum/species/new_race
if(ispath(mrace))
dna.species = new mrace()
new_race = new mrace
else if(istype(mrace))
new_race = mrace
else
dna.species = mrace
dna.species.on_species_gain(src, old_species)
return
dna.species.on_species_loss(src, new_race, pref_load)
var/datum/species/old_species = dna.species
dna.species = new_race
dna.species.on_species_gain(src, old_species, pref_load)
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = 1)
/mob/living/carbon/human/set_species(datum/species/mrace, icon_update = TRUE, pref_load = FALSE)
..()
if(icon_update)
update_body()

View File

@@ -16,7 +16,7 @@
var/emote_type = EMOTE_VISIBLE //Whether the emote is visible or audible
var/restraint_check = FALSE //Checks if the mob is restrained before performing the emote
var/muzzle_ignore = FALSE //Will only work if the emote is EMOTE_AUDIBLE
var/list/mob_type_allowed_typecache = list(/mob) //Types that are allowed to use that emote
var/list/mob_type_allowed_typecache = /mob //Types that are allowed to use that emote
var/list/mob_type_blacklist_typecache //Types that are NOT allowed to use that emote
var/list/mob_type_ignore_stat_typecache
var/stat_allowed = CONSCIOUS
@@ -25,13 +25,22 @@
/datum/emote/New()
if(key_third_person)
emote_list[key_third_person] = src
if (ispath(mob_type_allowed_typecache))
switch (mob_type_allowed_typecache)
if (/mob)
mob_type_allowed_typecache = GLOB.typecache_mob
if (/mob/living)
mob_type_allowed_typecache = GLOB.typecache_living
else
mob_type_allowed_typecache = typecacheof(mob_type_allowed_typecache)
else
mob_type_allowed_typecache = typecacheof(mob_type_allowed_typecache)
mob_type_blacklist_typecache = typecacheof(mob_type_blacklist_typecache)
mob_type_ignore_stat_typecache = typecacheof(mob_type_ignore_stat_typecache)
/datum/emote/proc/run_emote(mob/user, params, type_override)
/datum/emote/proc/run_emote(mob/user, params, type_override, intentional = FALSE)
. = TRUE
if(!can_run_emote(user))
if(!can_run_emote(user, TRUE, intentional))
return FALSE
var/msg = select_message_type(user)
if(params && message_param)
@@ -47,7 +56,7 @@
if(!msg)
return
user.log_message(msg, INDIVIDUAL_EMOTE_LOG)
user.log_message(msg, LOG_EMOTE)
msg = "<b>[user]</b> " + msg
for(var/mob/M in GLOB.dead_mob_list)
@@ -61,7 +70,6 @@
user.audible_message(msg)
else
user.visible_message(msg)
log_talk(user,"[key_name(user)] : [msg]",LOGEMOTE)
/datum/emote/proc/replace_pronoun(mob/user, message)
if(findtext(message, "their"))
@@ -94,7 +102,7 @@
/datum/emote/proc/select_param(mob/user, params)
return replacetext(message_param, "%t", params)
/datum/emote/proc/can_run_emote(mob/user, status_check = TRUE)
/datum/emote/proc/can_run_emote(mob/user, status_check = TRUE, intentional = FALSE)
. = TRUE
if(!is_type_in_typecache(user, mob_type_allowed_typecache))
return FALSE
@@ -102,9 +110,24 @@
return FALSE
if(status_check && !is_type_in_typecache(user, mob_type_ignore_stat_typecache))
if(user.stat > stat_allowed)
to_chat(user, "<span class='notice'>You cannot [key] while unconscious.</span>")
if(!intentional)
return FALSE
switch(user.stat)
if(SOFT_CRIT)
to_chat(user, "<span class='notice'>You cannot [key] while in a critical condition.</span>")
if(UNCONSCIOUS)
to_chat(user, "<span class='notice'>You cannot [key] while unconscious.</span>")
if(DEAD)
to_chat(user, "<span class='notice'>You cannot [key] while dead.</span>")
return FALSE
if(restraint_check && (user.IsStun() || user.IsKnockdown()))
if(!intentional)
return FALSE
to_chat(user, "<span class='notice'>You cannot [key] while stunned.</span>")
return FALSE
if(restraint_check && user.restrained())
if(!intentional)
return FALSE
if(restraint_check && (user.restrained() || user.buckled))
to_chat(user, "<span class='notice'>You cannot [key] while restrained.</span>")
return FALSE

View File

@@ -86,13 +86,13 @@ GLOBAL_LIST_EMPTY(explosions)
if(adminlog)
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [ADMIN_VERBOSEJMP(epicenter)]")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [AREACOORD(epicenter)]")
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [loc_name(epicenter)]")
var/x0 = epicenter.x
var/y0 = epicenter.y
var/z0 = epicenter.z
var/area/areatype = get_area(epicenter)
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type))
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = time_stamp("YYYY-MM-DD hh:mm:ss", 1)))
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
// Stereo users will also hear the direction of the explosion!

View File

@@ -82,7 +82,7 @@
. = . && (vic.loc != tar.loc)
/mob/Collide(atom/A)
/mob/Bump(atom/A)
. = ..()
if(force_moving && force_moving.allow_climbing && isstructure(A))
var/obj/structure/S = A

View File

@@ -7,12 +7,22 @@
/datum/getrev/New()
testmerge = world.TgsTestMerges()
log_world("Running /tg/ revision:")
var/datum/tgs_revision_information/revinfo = world.TgsRevision()
if(revinfo)
commit = revinfo.commit
originmastercommit = revinfo.origin_commit
else
var/list/logs = world.file2list(".git/logs/HEAD")
if(logs)
if(logs.len)
logs = splittext(logs[logs.len - 1], " ")
date = unix2date(text2num(logs[5]))
commit = logs[2]
log_world("[commit]: [date]")
else
log_world("Unable to read git logs, revision information not available")
originmastercommit = commit = "Unknown"
date = unix2date(world.timeofday)
return
logs = world.file2list(".git/logs/refs/remotes/origin/master")
if(logs.len)
originmastercommit = splittext(logs[logs.len - 1], " ")[2]
@@ -67,17 +77,17 @@
to_chat(src, "Protect Assistant Role From Traitor: [CONFIG_GET(flag/protect_assistant_from_antagonist)]")
to_chat(src, "Enforce Human Authority: [CONFIG_GET(flag/enforce_human_authority)]")
to_chat(src, "Allow Latejoin Antagonists: [CONFIG_GET(flag/allow_latejoin_antagonists)]")
to_chat(src, "Enforce Continuous Rounds: [length(CONFIG_GET(keyed_flag_list/continuous))] of [config.modes.len] roundtypes")
to_chat(src, "Allow Midround Antagonists: [length(CONFIG_GET(keyed_flag_list/midround_antag))] of [config.modes.len] roundtypes")
to_chat(src, "Enforce Continuous Rounds: [length(CONFIG_GET(keyed_list/continuous))] of [config.modes.len] roundtypes")
to_chat(src, "Allow Midround Antagonists: [length(CONFIG_GET(keyed_list/midround_antag))] of [config.modes.len] roundtypes")
if(CONFIG_GET(flag/show_game_type_odds))
var/list/probabilities = CONFIG_GET(keyed_number_list/probability)
var/list/probabilities = CONFIG_GET(keyed_list/probability)
if(SSticker.IsRoundInProgress())
var/prob_sum = 0
var/current_odds_differ = FALSE
var/list/probs = list()
var/list/modes = config.gamemode_cache
var/list/min_pop = CONFIG_GET(keyed_number_list/min_pop)
var/list/max_pop = CONFIG_GET(keyed_number_list/max_pop)
var/list/min_pop = CONFIG_GET(keyed_list/min_pop)
var/list/max_pop = CONFIG_GET(keyed_list/max_pop)
for(var/mode in modes)
var/datum/game_mode/M = mode
var/ctag = initial(M.config_tag)

View File

@@ -51,7 +51,7 @@
tele_play_specials(teleatom, curturf, effectin, asoundin)
var/success = force_teleport ? teleatom.forceMove(destturf) : teleatom.Move(destturf)
if (success)
log_game("[teleatom] ([key_name(teleatom)]) has teleported from [AREACOORD(curturf)] to [AREACOORD(destturf)]")
log_game("[key_name(teleatom)] has teleported from [loc_name(curturf)] to [loc_name(destturf)]")
tele_play_specials(teleatom, destturf, effectout, asoundout)
if(ismegafauna(teleatom))
message_admins("[teleatom] [ADMIN_FLW(teleatom)] has teleported from [ADMIN_VERBOSEJMP(curturf)] to [ADMIN_VERBOSEJMP(destturf)].")
@@ -60,6 +60,8 @@
var/mob/M = teleatom
M.cancel_camera()
return TRUE
/proc/tele_play_specials(atom/movable/teleatom, atom/location, datum/effect_system/effect, sound)
if (location && !isobserver(teleatom))
if (sound)

View File

@@ -60,7 +60,6 @@
user.remote_control = null
if(!QDELETED(eye))
eye.RemoveImages()
QDEL_NULL(eye)
if(connected_holopad && !QDELETED(hologram))

View File

@@ -12,7 +12,7 @@ GLOBAL_LIST_INIT(huds, list(
DATA_HUD_DIAGNOSTIC_ADVANCED = new/datum/atom_hud/data/diagnostic/advanced(),
DATA_HUD_ABDUCTOR = new/datum/atom_hud/abductor(),
DATA_HUD_SENTIENT_DISEASE = new/datum/atom_hud/sentient_disease(),
DATA_HUD_AI_DETECT = new/datum/atom_hud(), //CIT - EMPTY PLACEHOLDER UNTIL SYNC
DATA_HUD_AI_DETECT = new/datum/atom_hud/ai_detector(),
ANTAG_HUD_CULT = new/datum/atom_hud/antag(),
ANTAG_HUD_REV = new/datum/atom_hud/antag(),
ANTAG_HUD_OPS = new/datum/atom_hud/antag(),
@@ -26,7 +26,7 @@ GLOBAL_LIST_INIT(huds, list(
ANTAG_HUD_SINTOUCHED = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_SOULLESS = new/datum/atom_hud/antag/hidden(),
ANTAG_HUD_CLOCKWORK = new/datum/atom_hud/antag(),
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden()
ANTAG_HUD_BROTHER = new/datum/atom_hud/antag/hidden(),
))
/datum/atom_hud
@@ -101,6 +101,7 @@ GLOBAL_LIST_INIT(huds, list(
return FALSE
hudatoms |= A
for(var/mob/M in hudusers)
if(!queued_to_see[M])
add_to_single_hud(M, A)
return TRUE

View File

@@ -13,7 +13,7 @@
volume = 25
var/last_radiation
/datum/looping_sound/geiger/get_sound(looped)
/datum/looping_sound/geiger/get_sound(starttime)
var/danger
switch(last_radiation)
if(RAD_BACKGROUND_RADIATION to RAD_GEIGER_LOW)
@@ -26,7 +26,7 @@
danger = 4
else
return null
return ..(looped, mid_sounds[danger])
return ..(starttime, mid_sounds[danger])
/datum/looping_sound/geiger/stop()
. = ..()
@@ -41,11 +41,6 @@
mid_length = 3.5
volume = 25
/datum/looping_sound/reverse_bear_trap/slow
mid_sounds = list('sound/effects/clock_tick.ogg')
mid_length = 10
volume = 40
/datum/looping_sound/reverse_bear_trap_beep
mid_sounds = list('sound/machines/beep.ogg')

View File

@@ -24,10 +24,11 @@
var/end_sound
var/chance
var/volume = 100
var/muted = TRUE
var/max_loops
var/direct
var/timerid
/datum/looping_sound/New(list/_output_atoms=list(), start_immediately=FALSE, _direct=FALSE)
if(!mid_sounds)
WARNING("A looping sound datum was created without sounds to play.")
@@ -47,25 +48,27 @@
/datum/looping_sound/proc/start(atom/add_thing)
if(add_thing)
output_atoms |= add_thing
if(!muted)
if(timerid)
return
muted = FALSE
on_start()
/datum/looping_sound/proc/stop(atom/remove_thing)
if(remove_thing)
output_atoms -= remove_thing
if(muted)
if(!timerid)
return
muted = TRUE
on_stop()
deltimer(timerid)
timerid = null
/datum/looping_sound/proc/sound_loop(looped=0)
if(muted || (max_loops && looped > max_loops))
on_stop(looped)
/datum/looping_sound/proc/sound_loop(starttime)
if(max_loops && world.time >= starttime + mid_length * max_loops)
stop()
return
if(!chance || prob(chance))
play(get_sound(looped))
addtimer(CALLBACK(src, .proc/sound_loop, ++looped), mid_length)
play(get_sound(starttime))
if(!timerid)
timerid = addtimer(CALLBACK(src, .proc/sound_loop, world.time), mid_length, TIMER_STOPPABLE | TIMER_LOOP)
/datum/looping_sound/proc/play(soundfile)
var/list/atoms_cache = output_atoms
@@ -80,7 +83,7 @@
else
playsound(thing, S, volume)
/datum/looping_sound/proc/get_sound(looped, _mid_sounds)
/datum/looping_sound/proc/get_sound(starttime, _mid_sounds)
if(!_mid_sounds)
. = mid_sounds
else
@@ -95,6 +98,6 @@
start_wait = start_length
addtimer(CALLBACK(src, .proc/sound_loop), start_wait)
/datum/looping_sound/proc/on_stop(looped)
/datum/looping_sound/proc/on_stop()
if(end_sound)
play(end_sound)

View File

@@ -55,7 +55,7 @@
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>", \
"<span class='userdanger'>[A] has attempted to [atk_verb] [D]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(A, D, "attempted to [atk_verb]")
log_combat(A, D, "attempted to [atk_verb]")
return 0
var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected))
@@ -67,7 +67,7 @@
D.apply_damage(damage, BRUTE, affecting, armor_block)
add_logs(A, D, "punched")
log_combat(A, D, "punched")
if((D.stat != DEAD) && damage >= A.dna.species.punchstunthreshold)
D.visible_message("<span class='danger'>[A] has knocked [D] down!!</span>", \

View File

@@ -20,7 +20,7 @@
playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1)
D.visible_message("<span class='warning'>[A] has attempted to [atk_verb] [D]!</span>", \
"<span class='userdanger'>[A] has attempted to [atk_verb] [D]!</span>", null, COMBAT_MESSAGE_RANGE)
add_logs(A, D, "attempted to hit", atk_verb)
log_combat(A, D, "attempted to hit", atk_verb)
return 0
@@ -33,7 +33,7 @@
"<span class='userdanger'>[A] has [atk_verb]ed [D]!</span>", null, COMBAT_MESSAGE_RANGE)
D.apply_damage(damage, STAMINA, affecting, armor_block)
add_logs(A, D, "punched (boxing) ")
log_combat(A, D, "punched (boxing) ")
if(D.getStaminaLoss() > 100)
var/knockout_prob = (D.getStaminaLoss() + rand(-15,15))*0.75
if((D.stat != DEAD) && prob(knockout_prob))
@@ -42,7 +42,7 @@
D.apply_effect(200,EFFECT_KNOCKDOWN,armor_block)
D.SetSleeping(100)
D.forcesay(GLOB.hit_appends)
add_logs(A, D, "knocked out (boxing) ")
log_combat(A, D, "knocked out (boxing) ")
else if(D.lying)
D.forcesay(GLOB.hit_appends)
return 1

View File

@@ -59,7 +59,7 @@
playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Knockdown(120)
add_logs(A, D, "cqc slammed")
log_combat(A, D, "slammed (CQC)")
return TRUE
/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -72,7 +72,7 @@
var/atom/throw_target = get_edge_target_turf(D, A.dir)
D.throw_at(throw_target, 1, 14, A)
D.apply_damage(10, BRUTE)
add_logs(A, D, "cqc kicked")
log_combat(A, D, "kicked (CQC)")
if(D.IsKnockdown() && !D.stat)
D.visible_message("<span class='warning'>[A] kicks [D]'s head, knocking [D.p_them()] out!</span>", \
"<span class='userdanger'>[A] kicks your head, knocking you out!</span>")
@@ -129,7 +129,7 @@
A.start_pulling(D, 1)
if(A.pulling)
D.stop_pulling()
add_logs(A, D, "grabbed", addition="aggressively")
log_combat(A, D, "grabbed", addition="aggressively")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
return TRUE
@@ -140,7 +140,7 @@
add_to_streak("H",D)
if(check_streak(A,D))
return TRUE
add_logs(A, D, "CQC'd")
log_combat(A, D, "attacked (CQC)")
A.do_attack_animation(D)
var/picked_hit_type = pick("CQC'd", "Big Bossed")
var/bonus_damage = 13
@@ -154,14 +154,14 @@
playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1)
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
add_logs(A, D, "[picked_hit_type] with CQC")
log_combat(A, D, "[picked_hit_type] (CQC)")
if(A.resting && !D.stat && !D.IsKnockdown())
D.visible_message("<span class='warning'>[A] leg sweeps [D]!", \
"<span class='userdanger'>[A] leg sweeps you!</span>")
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(10, BRUTE)
D.Knockdown(60)
add_logs(A, D, "cqc sweeped")
log_combat(A, D, "sweeped (CQC)")
return TRUE
/datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -185,7 +185,7 @@
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", \
"<span class='userdanger'>[A] attempted to disarm [D]!</span>")
playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
add_logs(A, D, "disarmed with CQC", "[I ? " grabbing \the [I]" : ""]")
log_combat(A, D, "disarmed (CQC)", "[I ? " grabbing \the [I]" : ""]")
if(restraining && A.pulling == D)
D.visible_message("<span class='danger'>[A] puts [D] into a chokehold!</span>", \
"<span class='userdanger'>[A] puts you into a chokehold!</span>")

View File

@@ -93,7 +93,7 @@
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1)
D.apply_damage(5, BRUTE)
D.Knockdown(40)
add_logs(A, D, "leg sweeped")
log_combat(A, D, "leg sweeped")
return 1
/datum/martial_art/krav_maga/proc/quick_choke(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)//is actually lung punch
@@ -103,7 +103,7 @@
if(D.losebreath <= 10)
D.losebreath = CLAMP(D.losebreath + 5, 0, 10)
D.adjustOxyLoss(10)
add_logs(A, D, "quickchoked")
log_combat(A, D, "quickchoked")
return 1
/datum/martial_art/krav_maga/proc/neck_chop(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
@@ -113,19 +113,19 @@
D.apply_damage(5, BRUTE)
if(D.silent <= 10)
D.silent = CLAMP(D.silent + 10, 0, 10)
add_logs(A, D, "neck chopped")
log_combat(A, D, "neck chopped")
return 1
/datum/martial_art/krav_maga/grab_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
add_logs(A, D, "grabbed with krav maga")
log_combat(A, D, "grabbed (Krav Maga)")
..()
/datum/martial_art/krav_maga/harm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
add_logs(A, D, "punched")
log_combat(A, D, "punched")
var/picked_hit_type = pick("punches", "kicks")
var/bonus_damage = 10
if(D.IsKnockdown() || D.resting || D.lying)
@@ -140,7 +140,7 @@
playsound(get_turf(D), 'sound/effects/hit_punch.ogg', 50, 1, -1)
D.visible_message("<span class='danger'>[A] [picked_hit_type] [D]!</span>", \
"<span class='userdanger'>[A] [picked_hit_type] you!</span>")
add_logs(A, D, "[picked_hit_type] with [name]")
log_combat(A, D, "[picked_hit_type] with [name]")
return 1
/datum/martial_art/krav_maga/disarm_act(var/mob/living/carbon/human/A, var/mob/living/carbon/human/D)
@@ -159,7 +159,7 @@
D.visible_message("<span class='danger'>[A] attempted to disarm [D]!</span>", \
"<span class='userdanger'>[A] attempted to disarm [D]!</span>")
playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
add_logs(A, D, "disarmed with krav maga", "[I ? " removing \the [I]" : ""]")
log_combat(A, D, "disarmed (Krav Maga)", "[I ? " removing \the [I]" : ""]")
return 1
//Krav Maga Gloves

View File

@@ -17,7 +17,7 @@
D.throw_at(throwtarget, 4, 2, A)//So stuff gets tossed around at the same time.
D.Knockdown(20)
if(atk_verb)
add_logs(A, D, "[atk_verb] (Mushroom Punch)")
log_combat(A, D, "[atk_verb] (Mushroom Punch)")
return TRUE
/obj/item/mushpunch

View File

@@ -32,14 +32,14 @@
sleep(1)
/datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.say("TORNADO SWEEP!")
A.say("TORNADO SWEEP!", forced="plasma fist")
TornadoAnimate(A)
var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null)
var/list/turfs = list()
for(var/turf/T in range(1,A))
turfs.Add(T)
R.cast(turfs)
add_logs(A, D, "tornado sweeped(Plasma Fist)")
log_combat(A, D, "tornado sweeped(Plasma Fist)")
return
/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -48,18 +48,18 @@
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A)))
D.throw_at(throw_target, 200, 4,A)
A.say("HYAH!")
add_logs(A, D, "threw back (Plasma Fist)")
A.say("HYAH!", forced="plasma fist")
log_combat(A, D, "threw back (Plasma Fist)")
return
/datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
A.say("PLASMA FIST!")
A.say("PLASMA FIST!", forced="plasma fist")
D.visible_message("<span class='danger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>", \
"<span class='userdanger'>[A] has hit [D] with THE PLASMA FIST TECHNIQUE!</span>")
D.gib()
add_logs(A, D, "gibbed (Plasma Fist)")
log_combat(A, D, "gibbed (Plasma Fist)")
return
/datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)

View File

@@ -29,12 +29,12 @@
D.drop_all_held_items()
D.stop_pulling()
if(A.a_intent == INTENT_GRAB)
add_logs(A, D, "grabbed", addition="aggressively")
log_combat(A, D, "grabbed", addition="aggressively")
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
"<span class='userdanger'>[A] violently grabs you!</span>")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
else
add_logs(A, D, "grabbed", addition="passively")
log_combat(A, D, "grabbed", addition="passively")
A.grab_state = GRAB_PASSIVE
if(4)
A.do_attack_animation(D, ATTACK_EFFECT_PUNCH)
@@ -62,5 +62,5 @@
basic_hit(A,D)
if(atk_verb)
add_logs(A, D, "[atk_verb] (Psychotic Brawling)")
log_combat(A, D, "[atk_verb] (Psychotic Brawling)")
return 1

View File

@@ -45,7 +45,7 @@
D.apply_damage(5, BRUTE, pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM))
D.Knockdown(60)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
return 1
add_logs(A, D, "wrist wrenched (Sleeping Carp)")
log_combat(A, D, "wrist wrenched (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -57,7 +57,7 @@
D.Knockdown(80)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
add_logs(A, D, "back-kicked (Sleeping Carp)")
log_combat(A, D, "back-kicked (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -70,7 +70,7 @@
D.Knockdown(40)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
return 1
add_logs(A, D, "stomach kneed (Sleeping Carp)")
log_combat(A, D, "stomach kneed (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -83,7 +83,7 @@
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1)
D.Knockdown(80)//CIT CHANGE - makes sleepingcarp use knockdown() for its stuns instead of stun()
return 1
add_logs(A, D, "head kicked (Sleeping Carp)")
log_combat(A, D, "head kicked (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -96,7 +96,7 @@
D.apply_damage(50, BRUTE, BODY_ZONE_CHEST)
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1)
return 1
add_logs(A, D, "elbow dropped (Sleeping Carp)")
log_combat(A, D, "elbow dropped (Sleeping Carp)")
return basic_hit(A,D)
/datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -111,12 +111,12 @@
D.drop_all_held_items()
D.stop_pulling()
if(A.a_intent == INTENT_GRAB)
add_logs(A, D, "grabbed", addition="aggressively")
log_combat(A, D, "grabbed", addition="aggressively")
D.visible_message("<span class='warning'>[A] violently grabs [D]!</span>", \
"<span class='userdanger'>[A] violently grabs you!</span>")
A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab
else
add_logs(A, D, "grabbed", addition="passively")
log_combat(A, D, "grabbed", addition="passively")
A.grab_state = GRAB_PASSIVE
return 1
@@ -133,7 +133,7 @@
if(prob(D.getBruteLoss()) && !D.lying)
D.visible_message("<span class='warning'>[D] stumbles and falls!</span>", "<span class='userdanger'>The blow sends you to the ground!</span>")
D.Knockdown(80)
add_logs(A, D, "[atk_verb] (Sleeping Carp)")
log_combat(A, D, "[atk_verb] (Sleeping Carp)")
return 1

View File

@@ -121,7 +121,7 @@
/datum/martial_art/wrestling/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
add_logs(A, D, "punched with wrestling")
log_combat(A, D, "punched with wrestling")
..()
/datum/martial_art/wrestling/proc/throw_wrassle(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -192,7 +192,7 @@
if (!D.stat)
D.emote("scream")
D.throw_at(T, 10, 4, A, TRUE, TRUE, callback = CALLBACK(D, /mob/living/carbon/human/.Knockdown, 20))
add_logs(A, D, "has thrown with wrestling")
log_combat(A, D, "has thrown with wrestling")
return 0
/datum/martial_art/wrestling/proc/FlipAnimation(mob/living/carbon/human/D)
@@ -308,7 +308,7 @@
D.pixel_y = 0
add_logs(A, D, "body-slammed")
log_combat(A, D, "body-slammed")
return 0
/datum/martial_art/wrestling/proc/CheckStrikeTurf(mob/living/carbon/human/A, turf/T)
@@ -330,7 +330,7 @@
D.adjustBruteLoss(rand(10,20))
playsound(A.loc, "swing_hit", 50, 1)
D.Unconscious(20)
add_logs(A, D, "headbutted")
log_combat(A, D, "headbutted")
/datum/martial_art/wrestling/proc/kick(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D)
@@ -347,7 +347,7 @@
if (T && isturf(T))
D.Knockdown(20)
D.throw_at(T, 3, 2)
add_logs(A, D, "roundhouse-kicked")
log_combat(A, D, "roundhouse-kicked")
/datum/martial_art/wrestling/proc/drop(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(!D)
@@ -420,13 +420,13 @@
else
if (A)
A.pixel_y = 0
add_logs(A, D, "leg-dropped")
log_combat(A, D, "leg-dropped")
return
/datum/martial_art/wrestling/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
if(check_streak(A,D))
return 1
add_logs(A, D, "wrestling-disarmed")
log_combat(A, D, "wrestling-disarmed")
..()
/datum/martial_art/wrestling/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D)
@@ -438,7 +438,7 @@
D.visible_message("<span class='danger'>[A] gets [D] in a cinch!</span>", \
"<span class='userdanger'>[A] gets [D] in a cinch!</span>")
D.Stun(rand(60,100))
add_logs(A, D, "cinched")
log_combat(A, D, "cinched")
return 1
/obj/item/storage/belt/champion/wrestling

View File

@@ -62,6 +62,8 @@
var/unconvertable = FALSE
var/late_joiner = FALSE
var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator
/datum/mind/New(var/key)
src.key = key
soulOwner = src
@@ -254,7 +256,6 @@
var/mob/living/carbon/human/traitor_mob = current
if (!istype(traitor_mob))
return
. = TRUE
var/list/all_contents = traitor_mob.GetAllContents()
var/obj/item/pda/PDA = locate() in all_contents
@@ -302,6 +303,7 @@
to_chat(traitor_mob, "Unfortunately, [employer] wasn't able to get you an Uplink.")
. = 0
else
. = uplink_loc
uplink_loc.AddComponent(/datum/component/uplink, traitor_mob.key)
var/unlock_note
@@ -700,7 +702,7 @@
if(!has_antag_datum(/datum/antagonist/cult,TRUE))
SSticker.mode.add_cultist(src,FALSE,equip=TRUE)
special_role = ROLE_CULTIST
to_chat(current, "<font color=\"purple\"><b><i>You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar-Sie.</b></i></font>")
to_chat(current, "<font color=\"purple\"><b><i>You catch a glimpse of the Realm of Nar'Sie, The Geometer of Blood. You now see how flimsy your world is, you see that it should be open to the knowledge of Nar'Sie.</b></i></font>")
to_chat(current, "<font color=\"purple\"><b><i>Assist your new brethren in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.</b></i></font>")
/datum/mind/proc/make_Rev()

View File

@@ -0,0 +1,24 @@
/datum/mood_event/drunk
mood_change = 3
description = "<span class='nicegreen'>Everything just feels better after a drink or two.</span>\n"
timeout = 3000
/datum/mood_event/quality_nice
description = "<span class='nicegreen'>That drink wasn't bad at all.</span>\n"
mood_change = 1
timeout = 1200
/datum/mood_event/quality_good
description = "<span class='nicegreen'>That drink was pretty good.</span>\n"
mood_change = 2
timeout = 1200
/datum/mood_event/quality_verygood
description = "<span class='nicegreen'>That drink was great!</span>\n"
mood_change = 3
timeout = 1200
/datum/mood_event/quality_fantastic
description = "<span class='nicegreen'>That drink was amazing!</span>\n"
mood_change = 4
timeout = 1200

View File

@@ -1,39 +1,39 @@
/datum/mood_event/drugs/high
/datum/mood_event/high
mood_change = 6
description = "<span class='nicegreen'>Woooow duudeeeeee...I'm tripping baaalls...</span>\n"
/datum/mood_event/drugs/smoked
/datum/mood_event/smoked
description = "<span class='nicegreen'>I have had a smoke recently.</span>\n"
mood_change = 2
timeout = 3600
/datum/mood_event/drugs/overdose
/datum/mood_event/overdose
mood_change = -8
timeout = 3000
/datum/mood_event/drugs/overdose/add_effects(drug_name)
/datum/mood_event/overdose/add_effects(drug_name)
description = "<span class='warning'>I think I took a bit too much of that [drug_name]</span>\n"
/datum/mood_event/drugs/withdrawal_light
/datum/mood_event/withdrawal_light
mood_change = -2
/datum/mood_event/drugs/withdrawal_light/add_effects(drug_name)
/datum/mood_event/withdrawal_light/add_effects(drug_name)
description = "<span class='warning'>I could use some [drug_name]</span>\n"
/datum/mood_event/drugs/withdrawal_medium
/datum/mood_event/withdrawal_medium
mood_change = -5
/datum/mood_event/drugs/withdrawal_medium/add_effects(drug_name)
/datum/mood_event/withdrawal_medium/add_effects(drug_name)
description = "<span class='warning'>I really need [drug_name]</span>\n"
/datum/mood_event/drugs/withdrawal_severe
/datum/mood_event/withdrawal_severe
mood_change = -8
/datum/mood_event/drugs/withdrawal_severe/add_effects(drug_name)
/datum/mood_event/withdrawal_severe/add_effects(drug_name)
description = "<span class='boldwarning'>Oh god I need some [drug_name]</span>\n"
/datum/mood_event/drugs/withdrawal_critical
/datum/mood_event/withdrawal_critical
mood_change = -10
/datum/mood_event/drugs/withdrawal_critical/add_effects(drug_name)
/datum/mood_event/withdrawal_critical/add_effects(drug_name)
description = "<span class='boldwarning'>[drug_name]! [drug_name]! [drug_name]!</span>\n"

View File

@@ -1,5 +1,5 @@
/datum/mood_event/handcuffed
description = "<span class='warning'>I guess my antics have finally caught up with me..</span>\n"
description = "<span class='warning'>I guess my antics have finally caught up with me.</span>\n"
mood_change = -1
/datum/mood_event/broken_vow //Used for when mimes break their vow of silence
@@ -84,8 +84,8 @@
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
if(iscatperson(H))
H.startTailWag()
addtimer(CALLBACK(H, /mob/living/carbon/human.proc/endTailWag), 30)
H.dna.species.start_wagging_tail(H)
addtimer(CALLBACK(H.dna.species, /datum/species.proc/stop_wagging_tail, H), 30)
description = "<span class='nicegreen'>They want to play on the table!</span>\n"
mood_change = 2

View File

@@ -18,6 +18,11 @@
mood_change = 3
timeout = 3000
/datum/mood_event/exercise
description = "<span class='nicegreen'>Working out releases those endorphins!</span>\n"
mood_change = 3
timeout = 3000
/datum/mood_event/pet_corgi
description = "<span class='nicegreen'>Corgis are adorable! I can't stop petting them!</span>\n"
mood_change = 3
@@ -60,3 +65,8 @@
/datum/mood_event/family_heirloom
description = "<span class='nicegreen'>My family heirloom is safe with me.</span>\n"
mood_change = 1
/datum/mood_event/goodmusic
description = "<span class='nicegreen'>There is something soothing about this music.</span>\n"
mood_change = 3
timeout = 600

View File

@@ -1,37 +1,45 @@
//nutrition
/datum/mood_event/nutrition/fat
/datum/mood_event/fat
description = "<span class='warning'><B>I'm so fat...</B></span>\n" //muh fatshaming
mood_change = -4
/datum/mood_event/nutrition/wellfed
/datum/mood_event/wellfed
description = "<span class='nicegreen'>My belly feels round and full.</span>\n"
mood_change = 6
/datum/mood_event/nutrition/fed
/datum/mood_event/fed
description = "<span class='nicegreen'>I have recently had some food.</span>\n"
mood_change = 3
/datum/mood_event/nutrition/hungry
/datum/mood_event/hungry
description = "<span class='warning'>I'm getting a bit hungry.</span>\n"
mood_change = -8
/datum/mood_event/nutrition/starving
/datum/mood_event/starving
description = "<span class='boldwarning'>I'm starving!</span>\n"
mood_change = -15
//Disgust
/datum/mood_event/disgust/gross
/datum/mood_event/gross
description = "<span class='warning'>I saw something gross.</span>\n"
mood_change = -2
/datum/mood_event/disgust/verygross
/datum/mood_event/verygross
description = "<span class='warning'>I think I'm going to puke...</span>\n"
mood_change = -5
/datum/mood_event/disgust/disgusted
/datum/mood_event/disgusted
description = "<span class='boldwarning'>Oh god that's disgusting...</span>\n"
mood_change = -8
/datum/mood_event/disgust/bad_smell
description = "<span class='warning'>You smell something horribly decayed inside this room.</span>\n"
mood_change = -3
/datum/mood_event/disgust/nauseating_stench
description = "<span class='warning'>The stench of rotting carcasses is unbearable!</span>\n"
mood_change = -7
//Generic needs events
/datum/mood_event/favorite_food
description = "<span class='nicegreen'>I really enjoyed eating that.</span>\n"
@@ -39,12 +47,12 @@
timeout = 2400
/datum/mood_event/gross_food
description = "<span class='nicegreen'>I really didn't like that food.</span>\n"
description = "<span class='warning'>I really didn't like that food.</span>\n"
mood_change = -2
timeout = 2400
/datum/mood_event/disgusting_food
description = "<span class='nicegreen'>That food was disgusting!</span>\n"
description = "<span class='warning'>That food was disgusting!</span>\n"
mood_change = -4
timeout = 2400

View File

@@ -107,7 +107,7 @@
if(1)
owner.emote("twitch")
if(2 to 3)
owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]", forced="tourette's syndrome")
var/x_offset_old = owner.pixel_x
var/y_offset_old = owner.pixel_y
var/x_offset = owner.pixel_x + rand(-2,2)

View File

@@ -6,8 +6,8 @@
#define RETURN_PRECISE_POSITION(A) new /datum/position(A)
#define RETURN_PRECISE_POINT(A) new /datum/point(A)
#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) {new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED)}
#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) {new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT)}
#define RETURN_POINT_VECTOR(ATOM, ANGLE, SPEED) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED))
#define RETURN_POINT_VECTOR_INCREMENT(ATOM, ANGLE, SPEED, AMT) (new /datum/point/vector(ATOM, null, null, null, null, ANGLE, SPEED, AMT))
/proc/point_midpoint_points(datum/point/a, datum/point/b) //Obviously will not support multiZ calculations! Same for the two below.
var/datum/point/P = new

View File

@@ -24,8 +24,9 @@
START_PROCESSING(SSradiation, src)
/datum/radiation_wave/Destroy()
. = QDEL_HINT_IWILLGC
STOP_PROCESSING(SSradiation, src)
return ..()
..()
/datum/radiation_wave/process()
master_turf = get_step(master_turf, move_dir)
@@ -80,12 +81,10 @@
var/atom/thing = atoms[k]
if(!thing)
continue
var/datum/component/rad_insulation/insulation = thing.GetComponent(/datum/component/rad_insulation)
if(!insulation)
continue
intensity = intensity*(1-((1-insulation.amount)/width)) // The further out the rad wave goes the less it's affected by insulation
SEND_SIGNAL(thing, COMSIG_ATOM_RAD_WAVE_PASSING, src, width)
/datum/radiation_wave/proc/radiate(list/atoms, strength)
var/contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1, 1/(steps*range_modifier))
for(var/k in 1 to atoms.len)
var/atom/thing = atoms[k]
if(!thing)
@@ -106,11 +105,8 @@
))
if(!can_contaminate || blacklisted[thing.type])
continue
var/contamination_chance = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_CHANCE_COEFFICIENT * min(1, 1/(steps*range_modifier))
if(prob(contamination_chance)) // Only stronk rads get to have little baby rads
var/datum/component/rad_insulation/insulation = thing.GetComponent(/datum/component/rad_insulation)
if(insulation && insulation.contamination_proof)
if(SEND_SIGNAL(thing, COMSIG_ATOM_RAD_CONTAMINATING, strength) & COMPONENT_BLOCK_CONTAMINATION)
continue
else
var/rad_strength = (strength-RAD_MINIMUM_CONTAMINATION) * RAD_CONTAMINATION_STR_COEFFICIENT
thing.AddComponent(/datum/component/radioactive, rad_strength, source)

View File

@@ -154,11 +154,12 @@
suffix = "lavaland_surface_ufo_crash.dmm"
cost = 5
/datum/map_template/ruin/lavaland/alien_nest
name = "Alien Nest"
id = "alien-nest"
description = "Not even Necropolis is safe from alien infestation. The competition for hosts has locked the legion and aliens in an endless conflict that can only be resolved by a PKA."
suffix = "lavaland_surface_alien_nest.dmm"
/datum/map_template/ruin/lavaland/xeno_nest
name = "Xenomorph Nest"
id = "xeno-nest"
description = "These xenomorphs got bored of horrifically slaughtering people on space stations, and have settled down on a nice lava filled hellscape to focus on what's really important in life. \
Quality memes."
suffix = "lavaland_surface_xeno_nest.dmm"
cost = 20
/datum/map_template/ruin/lavaland/fountain

View File

@@ -40,7 +40,7 @@
return FALSE
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
var/msg = "<i><font color=#800080><b>[changeling.changelingID]:</b> [message]</font></i>"
log_talk(user,"[changeling.changelingID]/[user.key] : [message]",LOGSAY)
user.log_talk(message, LOG_SAY, tag="changeling [changeling.changelingID]")
for(var/_M in GLOB.player_list)
var/mob/M = _M
if(M in GLOB.dead_mob_list)
@@ -129,7 +129,7 @@
if(!mind)
return TRUE
if(is_monkey_leader(mind) || (ismonkey(user) && is_monkey(mind)))
log_talk(user, "(MONKEY) [user]/[user.key]: [message]",LOGSAY)
user.log_talk(message, LOG_SAY, tag="monkey")
if(prob(75) && ismonkey(user))
user.visible_message("<span class='notice'>\The [user] chimpers.</span>")
var/msg = "<span class='[is_monkey_leader(mind) ? "monkeylead" : "monkeyhive"]'><b><font size=2>\[[is_monkey_leader(mind) ? "Monkey Leader" : "Monkey"]\]</font> [user]</b>: [message]</span>"

View File

@@ -12,6 +12,8 @@
var/credit_cost = INFINITY
var/can_be_bought = TRUE
var/port_x_offset
var/port_y_offset
/datum/map_template/shuttle/proc/prerequisites_met()
return TRUE
@@ -21,7 +23,33 @@
mappath = "[prefix][shuttle_id].dmm"
. = ..()
/datum/map_template/shuttle/load(turf/T, centered)
/datum/map_template/shuttle/preload_size(path, cache)
. = ..(path, TRUE) // Done this way because we still want to know if someone actualy wanted to cache the map
if(!cached_map)
return
var/key
var/list/models = cached_map.grid_models
for(key in models)
if(findtext(models[key], "[/obj/docking_port/mobile]")) // Yay compile time checks
break // This works by assuming there will ever only be one mobile dock in a template at most
var/datum/grid_set/gset
for(var/i in cached_map.gridSets)
gset = i
var/ycrd = gset.ycrd
for(var/line in gset.gridLines)
if(key != line)
ycrd--
continue
port_x_offset = gset.xcrd
port_y_offset = ycrd
break
if(!cache)
cached_map = null
/datum/map_template/shuttle/load(turf/T, centered, register=TRUE)
. = ..()
if(!.)
return
@@ -35,6 +63,33 @@
continue
place.baseturfs.Insert(3, /turf/baseturf_skipover/shuttle)
for(var/obj/docking_port/mobile/port in place)
if(register)
port.register()
if(isnull(port_x_offset))
return
switch(port.dir) // Yeah this looks a little ugly but mappers had to do this in their head before
if(NORTH)
port.width = width
port.height = height
port.dwidth = port_x_offset - 1
port.dheight = port_y_offset - 1
if(EAST)
port.width = height
port.height = width
port.dwidth = height - port_y_offset
port.dheight = port_x_offset - 1
if(SOUTH)
port.width = width
port.height = height
port.dwidth = width - port_x_offset
port.dheight = height - port_y_offset
if(WEST)
port.width = height
port.height = width
port.dwidth = port_y_offset - 1
port.dheight = width - port_x_offset
for(var/obj/structure/closet/closet in place)
if(closet.anchorable)
closet.anchored = TRUE
@@ -110,6 +165,11 @@
// Shuttles start here:
/datum/map_template/shuttle/emergency/backup
suffix = "backup"
name = "Backup Shuttle"
can_be_bought = FALSE
/datum/map_template/shuttle/emergency/airless
suffix = "airless"
name = "Build your own shuttle kit"
@@ -126,6 +186,7 @@
var/datum/supply_pack/P = SSshuttle.supply_packs[/datum/supply_pack/engineering/shuttle_engine]
P.special_enabled = TRUE
/datum/map_template/shuttle/emergency/asteroid
suffix = "asteroid"
name = "Asteroid Station Emergency Shuttle"
@@ -228,7 +289,7 @@
suffix = "scrapheap"
name = "Standby Evacuation Vessel \"Scrapheap Challenge\""
credit_cost = -1000
description = "Due to a lack of functional emergency shuttles, we bought this second hand from a scrapyard and pressed it into service. Please do not lean to heavily on the exterior windows, they are fragile. <span class='danger'>VIRUS ALERT: This entry seems to be booby-trapped with a redirector trap. Buy this at your own risk.</span>"
description = "Due to a lack of functional emergency shuttles, we bought this second hand from a scrapyard and pressed it into service. Please do not lean too heavily on the exterior windows, they are fragile."
admin_notes = "An abomination with no functional medbay, sections missing, and some very fragile windows. Surprisingly airtight."
/datum/map_template/shuttle/emergency/narnar
@@ -324,11 +385,11 @@
/datum/map_template/shuttle/whiteship/box
suffix = "box"
name = "NT Medical Ship"
name = "Hospital Ship"
/datum/map_template/shuttle/whiteship/meta
suffix = "meta"
name = "NT Recovery Whiteship"
name = "Salvage Ship"
/datum/map_template/shuttle/whiteship/pubby
suffix = "pubby"
@@ -340,8 +401,11 @@
/datum/map_template/shuttle/whiteship/delta
suffix = "delta"
name = "Unnamed NT Vessel"
admin_notes = "The Delta whiteship doesn't have a name, apparently."
name = "NT Frigate"
/datum/map_template/shuttle/whiteship/pod
suffix = "whiteship_pod"
name = "Salvage Pod"
/datum/map_template/shuttle/cargo/box
suffix = "box"
@@ -445,8 +509,8 @@
suffix = "syndicate_dropship"
name = "Syndicate Dropship"
/datum/map_template/shuttle/ruin/syndicate_fighter
suffix = "syndicate_fighter"
/datum/map_template/shuttle/ruin/syndicate_fighter_shiv
suffix = "syndicate_fighter_shiv"
name = "Syndicate Fighter"
/datum/map_template/shuttle/snowdin/mining

View File

@@ -70,7 +70,7 @@
return ..()
/datum/status_effect/vanguard_shield/on_apply()
owner.log_message("gained Vanguard stun immunity", INDIVIDUAL_ATTACK_LOG)
owner.log_message("gained Vanguard stun immunity", LOG_ATTACK)
owner.add_stun_absorption("vanguard", INFINITY, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " radiating with a soft yellow light!")
owner.visible_message("<span class='warning'>[owner] begins to faintly glow!</span>", "<span class='brass'>You will absorb all stuns for the next twenty seconds.</span>")
owner.SetStun(0, FALSE)
@@ -105,7 +105,7 @@
else
stuns_blocked = 0 //so logging is correct in cases where there were stuns blocked but we didn't stun for other reasons
owner.visible_message("<span class='warning'>[owner]'s glowing aura fades!</span>", message_to_owner)
owner.log_message("lost Vanguard stun immunity[stuns_blocked ? "and was stunned for [stuns_blocked]":""]", INDIVIDUAL_ATTACK_LOG)
owner.log_message("lost Vanguard stun immunity[stuns_blocked ? "and was stunned for [stuns_blocked]":""]", LOG_ATTACK)
/datum/status_effect/inathneqs_endowment
@@ -120,7 +120,7 @@
alerttooltipstyle = "clockcult"
/datum/status_effect/inathneqs_endowment/on_apply()
owner.log_message("gained Inath-neq's invulnerability", INDIVIDUAL_ATTACK_LOG)
owner.log_message("gained Inath-neq's invulnerability", LOG_ATTACK)
owner.visible_message("<span class='warning'>[owner] shines with azure light!</span>", "<span class='notice'>You feel Inath-neq's power flow through you! You're invincible!</span>")
var/oldcolor = owner.color
owner.color = "#1E8CE1"
@@ -133,7 +133,7 @@
return ..()
/datum/status_effect/inathneqs_endowment/on_remove()
owner.log_message("lost Inath-neq's invulnerability", INDIVIDUAL_ATTACK_LOG)
owner.log_message("lost Inath-neq's invulnerability", LOG_ATTACK)
owner.visible_message("<span class='warning'>The light around [owner] flickers and dissipates!</span>", "<span class='boldwarning'>You feel Inath-neq's power fade from your body!</span>")
owner.status_flags &= ~GODMODE
playsound(owner, 'sound/magic/ethereal_exit.ogg', 50, 1)
@@ -185,7 +185,7 @@
..()
/datum/status_effect/his_grace/on_apply()
owner.log_message("gained His Grace's stun immunity", INDIVIDUAL_ATTACK_LOG)
owner.log_message("gained His Grace's stun immunity", LOG_ATTACK)
owner.add_stun_absorption("hisgrace", INFINITY, 3, null, "His Grace protects you from the stun!")
return ..()
@@ -209,7 +209,7 @@
owner.adjustCloneLoss(-grace_heal)
/datum/status_effect/his_grace/on_remove()
owner.log_message("lost His Grace's stun immunity", INDIVIDUAL_ATTACK_LOG)
owner.log_message("lost His Grace's stun immunity", LOG_ATTACK)
if(islist(owner.stun_absorption) && owner.stun_absorption["hisgrace"])
owner.stun_absorption -= "hisgrace"
@@ -242,7 +242,7 @@
/datum/status_effect/cult_master/proc/deathrattle()
if(!QDELETED(GLOB.cult_narsie))
return //if nar-sie is alive, don't even worry about it
return //if Nar'Sie is alive, don't even worry about it
var/area/A = get_area(owner)
for(var/datum/mind/B in SSticker.mode.cult)
if(isliving(B.current))
@@ -304,7 +304,7 @@
last_oxyloss = owner.getOxyLoss()
last_cloneloss = owner.getCloneLoss()
last_staminaloss = owner.getStaminaLoss()
owner.log_message("gained blood-drunk stun immunity", INDIVIDUAL_ATTACK_LOG)
owner.log_message("gained blood-drunk stun immunity", LOG_ATTACK)
owner.add_stun_absorption("blooddrunk", INFINITY, 4)
owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
@@ -380,7 +380,7 @@
owner.cloneloss *= 0.1
owner.staminaloss *= 0.1
owner.updatehealth()
owner.log_message("lost blood-drunk stun immunity", INDIVIDUAL_ATTACK_LOG)
owner.log_message("lost blood-drunk stun immunity", LOG_ATTACK)
if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"])
owner.stun_absorption -= "blooddrunk"
@@ -479,7 +479,7 @@
if(deathTick < 4)
deathTick += 1
else
owner.visible_message("[owner]'s soul is absorbed into the rod, releaving the previous snake of it's duty.")
owner.visible_message("[owner]'s soul is absorbed into the rod, relieving the previous snake of its duty.")
var/mob/living/simple_animal/hostile/retaliate/poison/snake/healSnake = new(owner.loc)
var/list/chems = list("bicaridine", "salbutamol", "kelotane", "antitoxin")
healSnake.poison_type = pick(chems)

View File

@@ -72,7 +72,7 @@
if(prob(20))
if(carbon_owner)
carbon_owner.handle_dreams()
if(prob(10) && owner.health > HEALTH_THRESHOLD_CRIT)
if(prob(10) && owner.health > owner.crit_threshold)
owner.emote("snore")
/obj/screen/alert/status_effect/asleep
@@ -124,7 +124,7 @@
qdel(src)
/datum/status_effect/belligerent/proc/do_movement_toggle(force_damage)
var/number_legs = owner.get_num_legs()
var/number_legs = owner.get_num_legs(FALSE)
if(iscarbon(owner) && !is_servant_of_ratvar(owner) && !owner.anti_magic_check() && number_legs)
if(force_damage || owner.m_intent != MOVE_INTENT_WALK)
if(GLOB.ratvar_awakens)
@@ -224,7 +224,7 @@
if(is_eligible_servant(owner))
to_chat(owner, "<span class='sevtug[span_part]'>\"[text2ratvar("You are mine and his, now.")]\"</span>")
if(add_servant_of_ratvar(owner))
owner.log_message("<font color=#BE8700>Conversion was done with a Mania Motor.</font>", INDIVIDUAL_ATTACK_LOG)
owner.log_message("conversion was done with a Mania Motor", LOG_ATTACK, color="#BE8700")
owner.Unconscious(100)
else
if(prob(severity * 0.15))
@@ -468,7 +468,7 @@
var/health_difference = old_health - owner.health
if(!health_difference)
return
owner.visible_message("<span class='warning'>The light in [owner]'s eyes dims as they're harmed!</span>", \
owner.visible_message("<span class='warning'>The light in [owner]'s eyes dims as [owner.p_theyre()] harmed!</span>", \
"<span class='boldannounce'>The dazzling lights dim as you're harmed!</span>")
health_difference *= 2 //so 10 health difference translates to 20 deciseconds of stun reduction
duration -= health_difference

View File

@@ -9,11 +9,11 @@
/obj/screen/alert/status_effect/freon
name = "Frozen Solid"
desc = "You're frozen inside of an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!"
desc = "You're frozen inside an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!"
icon_state = "frozen"
/datum/status_effect/freon/on_apply()
redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST), CALLBACK(src, .proc/owner_resist)))
redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist))))
if(!owner.stat)
to_chat(owner, "<span class='userdanger'>You become frozen in a cube!</span>")
cube = icon('icons/effects/freeze.dmi', "ice_cube")

View File

@@ -9,8 +9,6 @@
gain_text = "<span class='notice'>You feel like you could drink a whole keg!</span>"
lose_text = "<span class='danger'>You don't feel as resistant to alcohol anymore. Somehow.</span>"
/datum/quirk/apathetic
name = "Apathetic"
desc = "You just don't care as much as other people. That's nice to have in a place like this, I guess."
@@ -23,12 +21,11 @@
mood.mood_modifier = 0.8
/datum/quirk/apathetic/remove()
if(quirk_holder)
GET_COMPONENT_FROM(mood, /datum/component/mood, quirk_holder)
if(mood)
mood.mood_modifier = 1 //Change this once/if species get their own mood modifiers.
/datum/quirk/drunkhealing
name = "Drunken Resilience"
desc = "Nothing like a good drink to make you feel on top of the world. Whenever you're drunk, you slowly recover from injuries."
@@ -38,7 +35,6 @@
lose_text = "<span class='danger'>You no longer feel like drinking would ease your pain.</span>"
medical_record_text = "Patient has unusually efficient liver metabolism and can slowly regenerate wounds by drinking alcoholic beverages."
/datum/quirk/freerunning
name = "Freerunning"
desc = "You're great at quick moves! You can climb tables more quickly."
@@ -47,8 +43,6 @@
gain_text = "<span class='notice'>You feel lithe on your feet!</span>"
lose_text = "<span class='danger'>You feel clumsy again.</span>"
/datum/quirk/jolly
name = "Jolly"
desc = "You sometimes just feel happy, for no reason at all."
@@ -56,17 +50,31 @@
mob_trait = TRAIT_JOLLY
mood_quirk = TRUE
/datum/quirk/light_step
name = "Light Step"
desc = "You walk with a gentle step, making stepping on sharp objects quieter and less painful."
desc = "You walk with a gentle step; stepping on sharp objects is quieter, less painful and you won't leave footprints behind you."
value = 1
mob_trait = TRAIT_LIGHT_STEP
gain_text = "<span class='notice'>You walk with a little more litheness.</span>"
lose_text = "<span class='danger'>You start tromping around like a barbarian.</span>"
/datum/quirk/musician
name = "Musician"
desc = "You can tune handheld musical instruments to play melodies that clear certain negative effects and soothe the soul."
value = 1
mob_trait = TRAIT_MUSICIAN
gain_text = "<span class='notice'>You know everything about musical instruments.</span>"
lose_text = "<span class='danger'>You forget how musical instruments work.</span>"
/datum/quirk/musician/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/instrument/guitar/guitar = new(get_turf(H))
H.put_in_hands(guitar)
H.equip_to_slot(guitar, SLOT_IN_BACKPACK)
var/obj/item/musicaltuner/musicaltuner = new(get_turf(H))
H.put_in_hands(musicaltuner)
H.equip_to_slot(musicaltuner, SLOT_IN_BACKPACK)
H.regenerate_icons()
/datum/quirk/night_vision
name = "Night Vision"
@@ -83,7 +91,20 @@
return
eyes.Insert(H) //refresh their eyesight and vision
/datum/quirk/photographer
name = "Photographer"
desc = "You know how to handle a camera, shortening the delay between each shot."
value = 1
mob_trait = TRAIT_PHOTOGRAPHER
gain_text = "<span class='notice'>You know everything about photography.</span>"
lose_text = "<span class='danger'>You forget how photo cameras work.</span>"
/datum/quirk/photographer/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/camera/camera = new(get_turf(H))
H.put_in_hands(camera)
H.equip_to_slot(camera, SLOT_NECK)
H.regenerate_icons()
/datum/quirk/selfaware
name = "Self-Aware"
@@ -91,16 +112,12 @@
value = 2
mob_trait = TRAIT_SELF_AWARE
/datum/quirk/skittish
name = "Skittish"
desc = "You can conceal yourself in danger. Ctrl-shift-click a closed locker to jump into it, as long as you have access."
value = 2
mob_trait = TRAIT_SKITTISH
/datum/quirk/spiritual
name = "Spiritual"
desc = "You're in tune with the gods, and your prayers may be more likely to be heard. Or not."
@@ -109,7 +126,20 @@
gain_text = "<span class='notice'>You feel a little more faithful to the gods today.</span>"
lose_text = "<span class='danger'>You feel less faithful in the gods.</span>"
/datum/quirk/tagger
name = "Tagger"
desc = "You're an experienced artist. While drawing graffiti, you can get twice as many uses out of drawing supplies."
value = 1
mob_trait = TRAIT_TAGGER
gain_text = "<span class='notice'>You know how to tag walls efficiently.</span>"
lose_text = "<span class='danger'>You forget how to tag walls properly.</span>"
/datum/quirk/tagger/on_spawn()
var/mob/living/carbon/human/H = quirk_holder
var/obj/item/toy/crayon/spraycan/spraycan = new(get_turf(H))
H.put_in_hands(spraycan)
H.equip_to_slot(spraycan, SLOT_IN_BACKPACK)
H.regenerate_icons()
/datum/quirk/voracious
name = "Voracious"

View File

@@ -15,8 +15,6 @@
else
quirk_holder.blood_volume -= 0.275
/datum/quirk/depression
name = "Depression"
desc = "You sometimes just hate life."
@@ -27,8 +25,6 @@
medical_record_text = "Patient has a severe mood disorder causing them to experience sudden moments of sadness."
mood_quirk = TRUE
/datum/quirk/family_heirloom
name = "Family Heirloom"
desc = "You are the current owner of an heirloom, passed down for generations. You have to keep it safe!"
@@ -111,8 +107,6 @@
/datum/quirk/brainproblems/on_process()
quirk_holder.adjustBrainLoss(0.2)
/datum/quirk/nearsighted //t. errorage
name = "Nearsighted"
desc = "You are nearsighted without prescription glasses, but spawn with a pair."
@@ -131,8 +125,6 @@
H.equip_to_slot(glasses, SLOT_GLASSES)
H.regenerate_icons() //this is to remove the inhand icon, which persists even if it's not in their hands
/datum/quirk/nyctophobia
name = "Nyctophobia"
desc = "As far as you can remember, you've always been afraid of the dark. While in the dark without a light source, you instinctually act careful, and constantly feel a sense of dread."
@@ -152,8 +144,6 @@
else
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
/datum/quirk/nonviolent
name = "Pacifist"
desc = "The thought of violence makes you sick. So much so, in fact, that you can't hurt anyone."
@@ -168,8 +158,6 @@
to_chat(quirk_holder, "<span class='boldannounce'>Your antagonistic nature has caused you to renounce your pacifism.</span>")
qdel(src)
/datum/quirk/poor_aim
name = "Poor Aim"
desc = "You're terrible with guns and can't line up a straight shot to save your life. Dual-wielding is right out."
@@ -177,8 +165,6 @@
mob_trait = TRAIT_POOR_AIM
medical_record_text = "Patient possesses a strong tremor in both hands."
/datum/quirk/prosopagnosia
name = "Prosopagnosia"
desc = "You have a mental disorder that prevents you from being able to recognize faces at all."
@@ -186,8 +172,6 @@
mob_trait = TRAIT_PROSOPAGNOSIA
medical_record_text = "Patient suffers from prosopagnosia and cannot recognize faces."
/datum/quirk/prosthetic_limb
name = "Prosthetic Limb"
desc = "An accident caused you to lose one of your limbs. Because of this, you now have a random prosthetic!"
@@ -220,8 +204,6 @@
to_chat(quirk_holder, "<span class='boldannounce'>Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \
you need to use a welding tool and cables to repair it, instead of bruise packs and ointment.</span>")
/datum/quirk/insanity
name = "Reality Dissociation Syndrome"
desc = "You suffer from a severe disorder that causes very vivid hallucinations. Mindbreaker toxin can suppress its effects, and you are immune to mindbreaker's hallucinogenic properties. <b>This is not a license to grief.</b>"
@@ -247,8 +229,6 @@
to_chat(quirk_holder, "<span class='big bold info'>Please note that your dissociation syndrome does NOT give you the right to attack people or otherwise cause any interference to \
the round. You are not an antagonist, and the rules will treat you the same as other crewmembers.</span>")
/datum/quirk/social_anxiety
name = "Social Anxiety"
desc = "Talking to people is very difficult for you, and you often stutter or even lock up."
@@ -260,7 +240,7 @@
/datum/quirk/social_anxiety/on_process()
var/nearby_people = 0
for(var/mob/living/carbon/human/H in view(5, quirk_holder))
for(var/mob/living/carbon/human/H in oview(3, quirk_holder))
if(H.client)
nearby_people++
var/mob/living/carbon/human/H = quirk_holder

View File

@@ -10,8 +10,6 @@
lose_text = "<span class='notice'>You can taste again!</span>"
medical_record_text = "Patient suffers from ageusia and is incapable of tasting food or reagents."
/datum/quirk/pineapple_liker
name = "Ananas Affinity"
desc = "You find yourself greatly enjoying fruits of the ananas genus. You can't seem to ever get enough of their sweet goodness!"
@@ -26,6 +24,7 @@
/datum/quirk/pineapple_liker/remove()
var/mob/living/carbon/human/H = quirk_holder
if(H)
var/datum/species/species = H.dna.species
species.liked_food &= ~PINEAPPLE
@@ -43,6 +42,7 @@
/datum/quirk/pineapple_hater/remove()
var/mob/living/carbon/human/H = quirk_holder
if(H)
var/datum/species/species = H.dna.species
species.disliked_food &= ~PINEAPPLE
@@ -62,12 +62,11 @@
/datum/quirk/deviant_tastes/remove()
var/mob/living/carbon/human/H = quirk_holder
if(H)
var/datum/species/species = H.dna.species
species.liked_food = initial(species.liked_food)
species.disliked_food = initial(species.disliked_food)
/datum/quirk/monochromatic
name = "Monochromacy"
desc = "You suffer from full colorblindness, and perceive nearly the entire world in blacks and whites."
@@ -83,4 +82,5 @@
quirk_holder.playsound_local(quirk_holder, 'sound/ambience/ambidet1.ogg', 50, FALSE)
/datum/quirk/monochromatic/remove()
if(quirk_holder)
quirk_holder.remove_client_colour(/datum/client_colour/monochrome)

View File

@@ -81,9 +81,13 @@
if(ishuman(L)) //Are you immune?
var/mob/living/carbon/human/H = L
var/thermal_protection = H.get_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
return TRUE
L = L.loc //Matryoshka check
if(isliving(L))// if we're a non immune mob inside an immune mob we have to reconsider if that mob is immune to protect ourselves
var/mob/living/the_mob = L
if("ash" in the_mob.weather_immunities)
return TRUE
L = L.loc //Check parent items immunities (recurses up to the turf)
return FALSE //RIP you
/datum/weather/ash_storm/weather_act(mob/living/L)

View File

@@ -257,8 +257,8 @@
if("cut")
I = L.is_holding_tool_quality(TOOL_WIRECUTTER)
if(I || IsAdminGhost(usr))
if(I)
I.play_tool_sound(src, 20)
if(I && holder)
I.play_tool_sound(holder, 20)
cut_color(target_wire)
. = TRUE
else
@@ -266,8 +266,8 @@
if("pulse")
I = L.is_holding_tool_quality(TOOL_MULTITOOL)
if(I || IsAdminGhost(usr))
if(I)
I.play_tool_sound(src, 20)
if(I && holder)
I.play_tool_sound(holder, 20)
pulse_color(target_wire, L)
. = TRUE
else

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