Merge remote-tracking branch 'upstream/master' into unlockable-loadout-items

This commit is contained in:
Timothy Teakettle
2021-01-01 22:30:04 +00:00
187 changed files with 6110 additions and 4666 deletions
+2 -2
View File
@@ -679,8 +679,8 @@
set category = "Server"
set desc="Respawn basically"
set name="Toggle Respawn"
var/new_nores = !CONFIG_GET(flag/norespawn)
CONFIG_SET(flag/norespawn, new_nores)
var/new_nores = CONFIG_GET(flag/respawns_enabled)
CONFIG_SET(flag/respawns_enabled, !new_nores)
if (!new_nores)
to_chat(world, "<B>You may now respawn.</B>", confidential = TRUE)
else
+7
View File
@@ -44,6 +44,11 @@ GLOBAL_PROTECT(protected_ranks)
/datum/admin_rank/vv_edit_var(var_name, var_value)
return FALSE
/datum/admin_rank/CanProcCall(procname)
. = ..()
if(!check_rights(R_SENSITIVE))
return FALSE
/proc/admin_keyword_to_flag(word, previous_rights=0)
var/flag = 0
switch(ckey(word))
@@ -79,6 +84,8 @@ GLOBAL_PROTECT(protected_ranks)
flag = R_AUTOLOGIN
if("dbranks")
flag = R_DBRANKS
if("sensitive")
flag = R_SENSITIVE
if("@","prev")
flag = previous_rights
return flag
+4 -1
View File
@@ -78,8 +78,11 @@ GLOBAL_PROTECT(admin_verbs_admin)
/client/proc/mark_datum_mapview,
/client/proc/hide_verbs, /*hides all our adminverbs*/
/client/proc/hide_most_verbs, /*hides all our hideable adminverbs*/
/datum/admins/proc/open_borgopanel
/datum/admins/proc/open_borgopanel,
/client/proc/admin_cmd_respawn_return_to_lobby,
/client/proc/admin_cmd_remove_ghost_respawn_timer
)
GLOBAL_LIST_INIT(admin_verbs_ban, list(/client/proc/unban_panel, /client/proc/DB_ban_panel, /client/proc/stickybanpanel))
GLOBAL_PROTECT(admin_verbs_ban)
GLOBAL_LIST_INIT(admin_verbs_sounds, list(/client/proc/play_local_sound, /client/proc/play_sound, /client/proc/manual_play_web_sound, /client/proc/set_round_end_sound))
+7
View File
@@ -28,6 +28,11 @@ GLOBAL_PROTECT(href_token)
var/deadmined
/datum/admins/CanProcCall(procname)
. = ..()
if(!check_rights(R_SENSITIVE))
return FALSE
/datum/admins/New(datum/admin_rank/R, ckey, force_active = FALSE, protected)
if(IsAdminAdvancedProcCall())
var/msg = " has tried to elevate permissions!"
@@ -147,6 +152,8 @@ GLOBAL_PROTECT(href_token)
return 0
/datum/admins/vv_edit_var(var_name, var_value)
if(var_name == NAMEOF(src, fakekey))
return ..()
return FALSE //nice try trialmin
/*
+3 -1
View File
@@ -298,7 +298,9 @@
browse_messages(target_ckey = ckey(target_key), agegate = TRUE)
qdel(query_find_message_secret)
/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE)
/proc/browse_messages(type, target_ckey, index, linkless = FALSE, filter, agegate = FALSE, override = FALSE)
if((!override || IsAdminAdvancedProcCall()) && !check_rights(R_SENSITIVE))
return
if(!SSdbcore.Connect())
to_chat(usr, "<span class='danger'>Failed to establish database connection.</span>")
return
+11 -2
View File
@@ -936,6 +936,12 @@
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_MIND_TRANSFER];jobban4=[REF(M)]'>Mind Transfer Potion</a></td>"
//Respawns
if(jobban_isbanned(M, ROLE_RESPAWN))
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_RESPAWN];jobban4=[REF(M)]'><font color=red>Respawns</font></a></td>"
else
dat += "<td width='20%'><a href='?src=[REF(src)];[HrefToken()];jobban3=[ROLE_RESPAWN];jobban4=[REF(M)]'>Respawns</a></td>"
dat += "</tr></table>"
usr << browse(dat, "window=jobban2;size=800x450")
return
@@ -1799,12 +1805,15 @@
if(alert(usr, "Send [key_name(M)] back to Lobby?", "Message", "Yes", "No") != "Yes")
return
log_admin("[key_name(usr)] has sent [key_name(M)] back to the Lobby.")
message_admins("[key_name(usr)] has sent [key_name(M)] back to the Lobby.")
log_admin("[key_name(usr)] has sent [key_name(M)] back to the Lobby, removing their respawn restrictions if they existed.")
message_admins("[key_name(usr)] has sent [key_name(M)] back to the Lobby, removing their respawn restrictions if they existed.")
var/mob/dead/new_player/NP = new()
NP.ckey = M.ckey
qdel(M)
if(GLOB.preferences_datums[NP.ckey])
var/datum/preferences/P = GLOB.preferences_datums[NP.ckey]
P.respawn_restrictions_active = FALSE
else if(href_list["tdome1"])
if(!check_rights(R_FUN))
-7
View File
@@ -23,13 +23,6 @@
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[uppertext(holder.rank)]([src.holder.fakekey ? pick(nicknames) : src.key])</span> says, <span class='message'>\"[emoji_parse(msg)]\"</span></span>"
// var/rank_name = holder.rank
// var/admin_name = key
// if(holder.fakekey)
// rank_name = pick(strings("admin_nicknames.json", "ranks", "config")) please use this soon.
// admin_name = pick(strings("admin_nicknames.json", "names", "config"))
// var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[rank_name]([admin_name])</span> says, <span class='message'>\"[emoji_parse(msg)]\"</span></span>"
for (var/mob/M in GLOB.player_list)
if(isnewplayer(M))
continue
+2
View File
@@ -14,6 +14,8 @@
browseserverlogs("[GLOB.log_directory]/")
/client/proc/browseserverlogs(path = "data/logs/")
if(!check_rights(R_SENSITIVE))
return
path = browse_files(path)
if(!path)
return
+1 -1
View File
@@ -98,7 +98,7 @@
L.adjustFireLoss(amount)
newamt = L.getFireLoss()
if("toxin")
L.adjustToxLoss(amount, toxins_type = TOX_OMNI)
L.adjustToxLoss(amount, toxins_type = TOX_OMNI, forced = TRUE)
newamt = L.getToxLoss()
if("oxygen")
L.adjustOxyLoss(amount)
@@ -120,9 +120,14 @@
if(bruteheal + fireheal + toxinheal > 0) // Just a check? Don't heal/spend, and return.
if(mult == 0)
return TRUE
// We have damage. Let's heal (one time)
C.adjustBruteLoss(-bruteheal * mult, forced = TRUE)// Heal BRUTE / BURN in random portions throughout the body.
C.adjustFireLoss(-fireheal * mult, forced = TRUE)
var/list/damaged_parts = C.get_damaged_bodyparts(TRUE,TRUE, status = list(BODYPART_ORGANIC, BODYPART_HYBRID, BODYPART_NANITES))
if(damaged_parts.len)
for(var/obj/item/bodypart/part in damaged_parts) // Heal BRUTE / BURN equally distibuted over all damaged bodyparts.
part.heal_damage((bruteheal * mult)/damaged_parts.len, (fireheal * mult)/damaged_parts.len, only_organic = FALSE, updating_health = FALSE)
C.updatehealth()
C.update_damage_overlays()
C.adjustToxLoss(-toxinheal * mult * 2, forced = TRUE) //Toxin healing because vamps arent immune
//C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above.
AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + toxinheal * -0.2) / mult * costMult) // Costs blood to heal
@@ -276,7 +281,7 @@
/datum/antagonist/bloodsucker/proc/FinalDeath()
//Dont bother if we are already supposed to be dead
if(FinalDeath)
return
return
FinalDeath = TRUE //We are now supposed to die. Lets not spam it.
if(!iscarbon(owner.current)) //Check for non carbons.
owner.current.gib()
@@ -30,6 +30,7 @@
var/can_be_staked = FALSE // Only Feed can happen with a stake in you.
var/cooldown_static = FALSE // Feed, Masquerade, and One-Shot powers don't improve their cooldown.
//var/not_bloodsucker = FALSE // This goes to Vassals or Hunters, but NOT bloodsuckers.
var/must_be_concious = TRUE //Can't use this ability while unconcious.
/datum/action/bloodsucker/New()
if(bloodcost > 0)
@@ -101,6 +102,11 @@
if(display_error)
to_chat(owner, "<span class='warning'>Garlic in your blood is interfering with your powers!</span>")
return FALSE
if(must_be_concious)
if(owner.stat != CONSCIOUS)
if(display_error)
to_chat(owner, "<span class='warning'>You can't do this while you are unconcious!</span>")
return FALSE
// Incap?
if(must_be_capacitated)
var/mob/living/L = owner
@@ -16,6 +16,7 @@
can_use_in_torpor = TRUE
must_be_capacitated = TRUE
can_be_immobilized = TRUE
must_be_concious = FALSE
/datum/action/bloodsucker/gohome/CheckCanUse(display_error)
. = ..()
@@ -27,6 +27,7 @@
warn_constant_cost = TRUE
can_use_in_torpor = TRUE // Masquerade is maybe the only one that can do this. It stops your healing.
cooldown_static = TRUE
must_be_concious = FALSE
// NOTE: Firing off vulgar powers disables your Masquerade!
@@ -16,7 +16,7 @@
if(user.stat != DEAD)
user.emote("deathgasp")
user.tod = STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)
user.fakedeath("changeling") //play dead
user.fakedeath("changeling", TRUE) //play dead
user.update_stat()
addtimer(CALLBACK(src, .proc/ready_to_regenerate, user), LING_FAKEDEATH_TIME, TIMER_UNIQUE)
@@ -21,6 +21,7 @@
chemical_cost = 1000
dna_cost = -1
var/recharge_slowdown = 0
var/silent = FALSE
var/weapon_type
var/weapon_name_simple
@@ -37,6 +38,8 @@
if(!silent)
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
user.visible_message("<span class='warning'>With a sickening crunch, [user] reforms [user.p_their()] [weapon_name_simple] into an arm!</span>", "<span class='notice'>We assimilate the [weapon_name_simple] back into our body.</span>", "<span class='italics>You hear organic matter ripping and tearing!</span>")
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
changeling.chem_recharge_slowdown -= recharge_slowdown
user.update_inv_hands()
return 1
@@ -57,6 +60,8 @@
user.put_in_hands(W)
if(!silent)
playsound(user, 'sound/effects/blobattack.ogg', 30, 1)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
changeling.chem_recharge_slowdown += recharge_slowdown
return W
/obj/effect/proc_holder/changeling/weapon/on_refund(mob/user)
@@ -141,10 +146,11 @@
name = "Arm Blade"
desc = "We reform one of our arms into a deadly blade."
helptext = "We may retract our armblade in the same manner as we form it. Cannot be used while in lesser form. This ability is loud, and might cause our blood to react violently to heat."
chemical_cost = 10
chemical_cost = 5
dna_cost = 2
loudness = 2
req_human = 1
recharge_slowdown = 0.6
weapon_type = /obj/item/melee/arm_blade
weapon_name_simple = "blade"
action_icon = 'icons/mob/actions/actions_changeling.dmi'
@@ -487,7 +493,7 @@
helmet_type = /obj/item/clothing/head/helmet/space/changeling
suit_name_simple = "flesh shell"
helmet_name_simple = "space helmet"
recharge_slowdown = 0.5
recharge_slowdown = 0.6
blood_on_castoff = 1
/obj/item/clothing/suit/space/changeling
@@ -532,11 +538,11 @@
name = "Chitinous Armor"
desc = "We turn our skin into tough chitin to protect us from damage."
helptext = "Upkeep of the armor requires a constant expenditure of chemicals, resulting in a reduced chemical generation. The armor is strong against brute force, but does not provide much protection from lasers. Cannot be used in lesser form. This ability is loud, and might cause our blood to react violently to heat."
chemical_cost = 20
chemical_cost = 10
dna_cost = 1
loudness = 2
req_human = 1
recharge_slowdown = 0.5
recharge_slowdown = 0.6
action_icon = 'icons/mob/actions/actions_changeling.dmi'
action_icon_state = "ling_armor"
action_background_icon_state = "bg_ling"
@@ -662,10 +668,11 @@
name = "Bone Gauntlets"
desc = "We turn our hands into solid bone and chitin, sacrificing dexterity for raw strength."
helptext = "These grotesque, bone-and-chitin gauntlets are remarkably good at beating victims senseless, and cannot be used in lesser form. This ability is loud, and might cause our blood to react violently to heat."
chemical_cost = 10 // same cost as armblade because its a sidegrade (sacrifice utility for punching people violently)
chemical_cost = 5 // same cost as armblade because its a sidegrade (sacrifice utility for punching people violently)
dna_cost = 2
loudness = 2
req_human = 1
recharge_slowdown = 0.6
action_icon = 'icons/mob/actions/actions_changeling.dmi'
action_icon_state = "ling_gauntlets"
action_background_icon_state = "bg_ling"
@@ -689,8 +696,8 @@
wound_enhancement = 6
var/fast_enhancement = 6
var/fast_wound_enhancement = 6
var/slow_enhancement = 20
var/slow_wound_enhancement = 20
var/slow_enhancement = 12
var/slow_wound_enhancement = 15
silent = TRUE
inherited_trait = TRAIT_CHUNKYFINGERS // how do you expect to shoot anyone with bone covered hands
secondary_trait = TRAIT_MAULER // just punch them idiot
+2 -2
View File
@@ -445,7 +445,7 @@
if(L.move_resist < MOVE_FORCE_STRONG)
var/atom/throw_target = get_edge_target_turf(L, user.dir)
L.throw_at(throw_target, 7, 1, user)
else if(!iscultist(L))
else if(!is_servant_of_ratvar(L))
L.DefaultCombatKnockdown(160)
L.adjustStaminaLoss(140) //Ensures hard stamcrit
L.flash_act(1,1)
@@ -465,7 +465,7 @@
C.drowsyness = max(10, C.drowsyness)
C.confused += clamp(20 - C.confused, 0, 10)
L.adjustBruteLoss(15)
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] [iscultist(L) ? "writhes in pain" : "falls to the ground!"]</span>")
to_chat(user, "<span class='cultitalic'>In an brilliant flash of red, [L] [is_servant_of_ratvar(L) ? "writhes in pain!" : "falls to the ground!"]</span>")
uses--
..()
@@ -98,7 +98,7 @@
var/pck = pick("assasinate","protect")
switch(pck)
if("assasinate")
var/datum/objective/assassinate/A = new
var/datum/objective/assassinate/once/A = new
A.owner = owner
var/list/owners = A.get_owners()
A.find_target(owners,protection)
@@ -2,8 +2,10 @@
name = "Codex Cicatrix"
desc = "Book describing the secrets of the veil."
icon = 'icons/obj/eldritch.dmi'
icon_state = "book"
item_state = "book"
icon_state = "codex"
item_state = "codex"
lefthand_file = 'icons/mob/inhands/misc/books_lefthand.dmi'
righthand_file = 'icons/mob/inhands/misc/books_righthand.dmi'
w_class = WEIGHT_CLASS_SMALL
///Last person that touched this
var/mob/living/last_user
@@ -69,7 +69,7 @@
var/mob/living/living_user = user
living_user.adjustBruteLoss(-3, FALSE)
living_user.adjustFireLoss(-3, FALSE)
living_user.adjustToxLoss(-3, FALSE)
living_user.adjustToxLoss(-3, FALSE, TRUE)
living_user.adjustOxyLoss(-1, FALSE)
living_user.adjustStaminaLoss(-6)
-4
View File
@@ -68,10 +68,6 @@
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
if(!turfing)
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1))
overlay_fullscreen("flash", /obj/screen/fullscreen/flash) // To be more true to the hentai
clear_fullscreen("flash", 20)
G.last_orgasmed = world.time
R.clear_reagents()
+51 -4
View File
@@ -34,10 +34,57 @@
/datum/supply_pack/critter/parrot/generate()
. = ..()
for(var/i in 1 to 4)
new /mob/living/simple_animal/parrot(.)
if(prob(1))
new /mob/living/simple_animal/parrot/clock_hawk(.)
for(var/i in 1 to 5)
switch(rand(1, 24))
if(1)
new /mob/living/simple_animal/parrot(.)
if(2)
new /mob/living/simple_animal/parrot/clock_hawk(.)
if(3)
new /mob/living/simple_animal/parrot/kea(.)
if(4)
new /mob/living/simple_animal/parrot/eclectus(.)
if(5)
new /mob/living/simple_animal/parrot/eclectusf(.)
if(6)
new /mob/living/simple_animal/parrot/greybird(.)
if(7)
new /mob/living/simple_animal/parrot/blue_caique(.)
if(8)
new /mob/living/simple_animal/parrot/white_caique(.)
if(9)
new /mob/living/simple_animal/parrot/green_budgerigar(.)
if(10)
new /mob/living/simple_animal/parrot/blue_Budgerigar(.)
if(11)
new /mob/living/simple_animal/parrot/bluegreen_Budgerigar(.)
if(12)
new /mob/living/simple_animal/parrot/commonblackbird(.)
if(13)
new /mob/living/simple_animal/parrot/azuretit(.)
if(14)
new /mob/living/simple_animal/parrot/europeanrobin(.)
if(15)
new /mob/living/simple_animal/parrot/goldcrest(.)
if(16)
new /mob/living/simple_animal/parrot/ringneckdove(.)
if(17)
new /mob/living/simple_animal/parrot/cockatiel(.)
if(18)
new /mob/living/simple_animal/parrot/white_cockatiel(.)
if(19)
new /mob/living/simple_animal/parrot/yellowish_cockatiel(.)
if(20)
new /mob/living/simple_animal/parrot/grey_cockatiel(.)
if(21)
new /mob/living/simple_animal/parrot/too(.)
if(22)
new /mob/living/simple_animal/parrot/hooded_too(.)
if(23)
new /mob/living/simple_animal/parrot/pink_too(.)
if(24)
new /mob/living/simple_animal/parrot/eclectusr(.)
/datum/supply_pack/critter/butterfly
name = "Butterflies Crate"
+24 -2
View File
@@ -101,6 +101,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
keyUp(keycode)
return
if(href_list["statpanel_item_target"])
handle_statpanel_click(href_list)
return
// Tgui Topic middleware
if(tgui_Topic(href_list))
return
@@ -141,6 +145,10 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
..() //redirect to hsrc.Topic()
/client/proc/handle_statpanel_click(list/href_list)
var/atom/target = locate(href_list["statpanel_item_target"])
Click(target, target.loc, null, "[href_list["statpanel_item_shiftclick"]?"shift=1;":null][href_list["statpanel_item_ctrlclick"]?"ctrl=1;":null]&alt=[href_list["statpanel_item_altclick"]?"alt=1;":null]", FALSE, "statpanel")
/client/proc/is_content_unlocked()
if(!prefs.unlock_content)
to_chat(src, "Become a BYOND member to access member-perks and features, as well as support the engine that makes this game possible. Only 10 bucks for 3 months! <a href=\"https://secure.byond.com/membership\">Click Here to find out more</a>.")
@@ -798,7 +806,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.</span>")
ip_intel = res.intel
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE)
/client/Click(atom/object, atom/location, control, params, ignore_spam = FALSE, extra_info)
if(last_click > world.time - world.tick_lag)
return
last_click = world.time
@@ -851,7 +859,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
return
if(prefs.log_clicks)
log_click(object, location, control, params, src)
log_click(object, location, control, params, src, extra_info? "clicked ([extra_info])" : null)
if (prefs.hotkeys)
// If hotkey mode is enabled, then clicking the map will automatically
@@ -921,8 +929,22 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
if (NAMEOF(src, view))
view_size.setDefault(var_value)
return TRUE
if(NAMEOF(src, computer_id))
return FALSE
if(NAMEOF(src, address))
return FALSE
. = ..()
/client/vv_get_var(var_name)
. = ..()
switch(var_name)
if(NAMEOF(src, computer_id))
if(!check_rights(R_SENSITIVE, FALSE))
return "SENSITIVE"
if(NAMEOF(src, address))
if(!check_rights(R_SENSITIVE, FALSE))
return "SENSITIVE"
/client/proc/rescale_view(change, min, max)
var/viewscale = getviewsize(view)
var/x = viewscale[1]
+20 -2
View File
@@ -12,11 +12,29 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/default_slot = 1 //Holder so it doesn't default to slot 1, rather the last one used
var/max_save_slots = 24
//non-preference stuff
var/muted = 0
// Intra-round persistence begin
/// Flags for admin mutes
var/muted = NONE
/// Last IP the person was seen on
var/last_ip
/// Last CID the person was seen on
var/last_id
/// Do we log their clicks to disk?
var/log_clicks = FALSE
/// Characters they have joined the round under - Lazylist of names
var/list/characters_joined_as
/// Slots they have joined the round under - Lazylist of numbers
var/list/slots_joined_as
/// Are we currently subject to respawn restrictions? Usually set by us using the "respawn" verb, but can be lifted by admins.
var/respawn_restrictions_active = FALSE
/// time of death we consider for respawns
var/respawn_time_of_death = -INFINITY
/// did they DNR? used to prevent respawns.
var/dnr_triggered = FALSE
/// did they cryo on their last ghost?
var/respawn_did_cryo = FALSE
// Intra-round persistence end
var/icon/custom_holoform_icon
var/list/cached_holoform_icons
+1 -1
View File
@@ -179,7 +179,7 @@ GLOBAL_VAR_INIT(normal_ooc_colour, "#002eb8")
to_chat(usr, "<span class='notice'>Sorry, that function is not enabled on this server.</span>")
return
browse_messages(null, usr.ckey, null, TRUE)
browse_messages(null, usr.ckey, null, TRUE, override = TRUE)
/client/proc/self_playtime()
set name = "View tracked playtime"
@@ -20,6 +20,7 @@
body_parts_covered = ARMS
cold_protection = ARMS
strip_delay = 300 //you can't just yank them off
obj_flags = UNIQUE_RENAME
/// did you ever get around to wearing these or no
var/wornonce = FALSE
///Extra damage through the punch.
+2 -2
View File
@@ -873,9 +873,9 @@
/obj/item/clothing/head/helmet/space/hardsuit/lavaknight
name = "cydonian helmet"
desc = "A helmet designed with both form and function in mind, it protects the user against physical trauma and hazardous conditions while also having polychromic light strips."
icon_state = "knight_cydonia"
icon_state = "hardsuit0-knight_cydonia"
item_state = "knight_yellow"
hardsuit_type = null
hardsuit_type = "knight_cydonia"
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
resistance_flags = FIRE_PROOF | LAVA_PROOF
heat_protection = HEAD
@@ -256,7 +256,7 @@ Contains:
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert
armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50)
resistance_flags = FIRE_PROOF | ACID_PROOF
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC|STYLE_PAW_TAURIC
//ERT Security
/obj/item/clothing/head/helmet/space/hardsuit/ert/alert/sec
+1 -1
View File
@@ -554,7 +554,7 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
/datum/holiday/xmas
name = CHRISTMAS
begin_day = 10
begin_day = 18
begin_month = DECEMBER
end_day = 27
drone_hat = /obj/item/clothing/head/santa
+14 -2
View File
@@ -73,6 +73,12 @@
/// Starting skill modifiers.
var/list/starting_modifiers
// These can be flags but I don't care because they're never changed
/// Can you always join as this job even while respawning (should probably only be on for assistant)
var/always_can_respawn_as = FALSE
/// Is this job considered a combat role for respawning? (usually sec/command)
var/considered_combat_role = FALSE
/**
* Checks if we should be created on a certain map
*/
@@ -118,15 +124,21 @@
//Used for a special check of whether to allow a client to latejoin as this job.
/datum/job/proc/special_check_latejoin(client/C)
var/joined = LAZYLEN(C.prefs?.characters_joined_as)
if(C.prefs?.respawn_restrictions_active && (joined || CONFIG_GET(flag/respawn_penalty_includes_observe)))
if(!CONFIG_GET(flag/allow_non_assistant_respawn) && !always_can_respawn_as)
return FALSE
if(!CONFIG_GET(flag/allow_combat_role_respawn) && considered_combat_role)
return FALSE
return TRUE
/datum/job/proc/GetAntagRep()
. = CONFIG_GET(keyed_list/antag_rep)[lowertext(title)]
. = CONFIG_GET(keyed_list/antag_rep)[ckey(title)]
if(. == null)
return antag_rep
/datum/job/proc/GetThreat()
. = CONFIG_GET(keyed_list/job_threat)[lowertext(title)]
. = CONFIG_GET(keyed_list/job_threat)[ckey(title)]
if(. == null)
return threat
+1
View File
@@ -16,6 +16,7 @@
display_order = JOB_DISPLAY_ORDER_AI
var/do_special_check = TRUE
threat = 5
considered_combat_role = TRUE
starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic)
+1
View File
@@ -18,6 +18,7 @@ Assistant
paycheck_department = ACCOUNT_CIV
display_order = JOB_DISPLAY_ORDER_ASSISTANT
dresscodecompliant = FALSE
always_can_respawn_as = TRUE
threat = 0.2
/datum/job/assistant/get_access()
+1
View File
@@ -14,6 +14,7 @@
exp_requirements = 180
exp_type = EXP_TYPE_COMMAND
exp_type_department = EXP_TYPE_COMMAND
considered_combat_role = TRUE
outfit = /datum/outfit/job/captain
@@ -15,6 +15,7 @@
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_ENGINEERING
considered_combat_role = TRUE
outfit = /datum/outfit/job/ce
plasma_outfit = /datum/outfit/plasmaman/ce
@@ -15,6 +15,7 @@
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_MEDICAL
considered_combat_role = TRUE
outfit = /datum/outfit/job/cmo
plasma_outfit = /datum/outfit/plasmaman/cmo
+1
View File
@@ -11,6 +11,7 @@
minimal_player_age = 21
exp_requirements = 120
exp_type = EXP_TYPE_CREW
considered_combat_role = TRUE
starting_modifiers = list(/datum/skill_modifier/job/level/wiring/basic)
+1
View File
@@ -15,6 +15,7 @@
outfit = /datum/outfit/job/detective
plasma_outfit = /datum/outfit/plasmaman/detective
considered_combat_role = TRUE
access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
minimal_access = list(ACCESS_SEC_DOORS, ACCESS_FORENSICS_LOCKERS, ACCESS_MORGUE, ACCESS_MAINT_TUNNELS, ACCESS_COURT, ACCESS_BRIG, ACCESS_WEAPONS, ACCESS_MINERAL_STOREROOM)
@@ -15,7 +15,7 @@
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SERVICE
considered_combat_role = TRUE
outfit = /datum/outfit/job/hop
plasma_outfit = /datum/outfit/plasmaman/hop
@@ -14,6 +14,7 @@
minimal_player_age = 10
exp_requirements = 300
exp_type = EXP_TYPE_CREW
considered_combat_role = TRUE
exp_type_department = EXP_TYPE_SECURITY
outfit = /datum/outfit/job/hos
@@ -15,6 +15,7 @@
exp_requirements = 180
exp_type = EXP_TYPE_CREW
exp_type_department = EXP_TYPE_SUPPLY
considered_combat_role = TRUE
outfit = /datum/outfit/job/quartermaster
@@ -15,6 +15,7 @@
exp_type_department = EXP_TYPE_SCIENCE
exp_requirements = 180
exp_type = EXP_TYPE_CREW
considered_combat_role = TRUE
outfit = /datum/outfit/job/rd
plasma_outfit = /datum/outfit/plasmaman/rd
@@ -12,6 +12,7 @@
minimal_player_age = 7
exp_requirements = 300
exp_type = EXP_TYPE_CREW
considered_combat_role = TRUE
outfit = /datum/outfit/job/security
plasma_outfit = /datum/outfit/plasmaman/security
+1
View File
@@ -12,6 +12,7 @@
minimal_player_age = 7
exp_requirements = 300
exp_type = EXP_TYPE_CREW
considered_combat_role = TRUE
outfit = /datum/outfit/job/warden
plasma_outfit = /datum/outfit/plasmaman/warden
+4 -2
View File
@@ -124,7 +124,8 @@
return TRUE
/datum/keybinding/living/hold_sprint
hotkey_keys = list("Shift")
hotkey_keys = list()
classic_keys = list()
name = "hold_sprint"
full_name = "Sprint (hold down)"
description = "Hold down to sprint"
@@ -144,7 +145,8 @@
return TRUE
/datum/keybinding/living/toggle_sprint
hotkey_keys = list()
hotkey_keys = list("Shift")
classic_keys = list("Shift")
name = "toggle_sprint"
full_name = "Sprint (toggle)"
description = "Press to toggle sprint"
+1 -1
View File
@@ -5,7 +5,7 @@
SHOULD_NOT_SLEEP(TRUE)
/datum/proc/keyLoop(client/user) // Called once every frame
//SHOULD_NOT_SLEEP(TRUE)
SHOULD_NOT_SLEEP(TRUE)
/client/verb/fix_macros()
set name = "Fix Keybindings"
+3 -4
View File
@@ -81,11 +81,10 @@
STOP_PROCESSING(SSmachines, src)
icon_state = "coinpress0"
/obj/machinery/mineral/mint/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/mineral/mint/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "Mint", name, ui_x, ui_y, master_ui, state)
ui = new(user, src, "Mint", name)
ui.open()
/obj/machinery/mineral/mint/ui_data()
@@ -375,7 +375,9 @@
ready = PLAYER_NOT_READY
return FALSE
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to play this round!","Player Setup","Yes","No")
var/mintime = max(CONFIG_GET(number/respawn_delay), (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time, 0)
var/this_is_like_playing_right = alert(src,"Are you sure you wish to observe? You will not be able to respawn for [round(mintime / 600, 0.1)] minutes!!","Player Setup","Yes","No")
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
ready = PLAYER_NOT_READY
@@ -397,6 +399,7 @@
stack_trace("There's no freaking observer landmark available on this map or you're making observers before the map is initialised")
transfer_ckey(observer, FALSE)
observer.client = client
observer.client.prefs?.respawn_time_of_death = world.time
observer.set_ghost_appearance()
if(observer.client && observer.client.prefs)
observer.real_name = observer.client.prefs.real_name
@@ -463,6 +466,9 @@
alert(src, "An administrator has disabled late join spawning.")
return FALSE
if(!respawn_latejoin_check(notify = TRUE))
return FALSE
var/arrivals_docked = TRUE
if(SSshuttle.arrivals)
close_spawn_windows() //In case we get held up
@@ -526,6 +532,8 @@
GLOB.joined_player_list += character.ckey
GLOB.latejoiners += character
LAZYOR(character.client.prefs.slots_joined_as, character.client.prefs.default_slot)
LAZYOR(character.client.prefs.characters_joined_as, character.real_name)
if(CONFIG_GET(flag/allow_latejoin_antagonists) && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
if(SSshuttle.emergency)
+11 -3
View File
@@ -264,7 +264,7 @@ Transfer_mind is there to check if mob is being deleted/not going to have a body
Works together with spawning an observer, noted above.
*/
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE)
/mob/proc/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE, cryo = FALSE)
var/sig_flags = SEND_SIGNAL(src, COMSIG_MOB_GHOSTIZE, can_reenter_corpse, special, penalize)
penalize = !(sig_flags & COMPONENT_DO_NOT_PENALIZE_GHOSTING) && (suiciding || penalize) // suicide squad.
voluntary_ghosted = voluntary
@@ -277,6 +277,12 @@ Works together with spawning an observer, noted above.
if (client && client.prefs && client.prefs.auto_ooc)
if (!(client.prefs.chat_toggles & CHAT_OOC))
client.prefs.chat_toggles ^= CHAT_OOC
if(ckey && penalize)
var/datum/preferences/P = GLOB.preferences_datums[ckey]
if(P)
P.respawn_restrictions_active = TRUE
P.respawn_time_of_death = world.time
P.respawn_did_cryo = cryo
transfer_ckey(ghost, FALSE)
ghost.client.init_verbs()
if(penalize)
@@ -423,12 +429,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
to_chat(usr, "<span class='warning'>You're already stuck out of your body!</span>")
return FALSE
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. ","Are you sure you want to stay dead?","Yes","No")
var/response = alert(src, "Are you sure you want to prevent (almost) all means of resuscitation? This cannot be undone. THIS WILL ALSO STOP YOU FROM RESPAWNING!!!","Are you sure you want to stay dead and never respawn?","Yes","No")
if(response != "Yes")
return
can_reenter_corpse = FALSE
to_chat(src, "You can no longer be brought back into your body.")
client.prefs?.dnr_triggered = TRUE
to_chat(src, "You can no longer be brought back into your body or respawn.")
return TRUE
/mob/dead/observer/proc/notify_cloning(var/message, var/sound, var/atom/source, flashwindow = TRUE)
+184
View File
@@ -0,0 +1,184 @@
// ADMIN VERBS BEGIN
/**
* Fully returns a player to lobby, allowing them to bypass all respawn restrictions
* Works on ghosts or new players (lobby players)
* If a lobby player is selected, their restrictions are removed.
*/
/client/proc/admin_cmd_respawn_return_to_lobby()
set name = "Respawn Player (Unrestricted)"
set desc = "Gives a player an unrestricted respawn, resetting all respawn restrictions for them."
set category = "Admin"
var/list/mob/valid = list()
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
if(!I.client)
continue
valid["[I.ckey] - Observing: [I]"] = I.ckey
for(var/mob/dead/new_player/I in GLOB.dead_mob_list)
if(!I.client || !I.client.prefs.respawn_restrictions_active)
continue
valid["[I.ckey] - IN LOBBY"] = I.ckey
if(!valid.len)
to_chat(src, "<span class='warning'>No player found that is either a ghost or is in lobby with restrictions active.</span>")
return
var/ckey = valid[input(src, "Choose a player (only showing logged in players who have restrictions)", "Unrestricted Respawn") as null|anything in valid]
var/client/player = GLOB.directory[ckey]
if(!player)
to_chat(src, "<span class='warning'>Client not found.</span>")
return
var/mob/M = player.mob
if(istype(M, /mob/dead/observer))
var/mob/dead/observer/O = M
var/confirm = alert(src, "Send [O]([ckey]) back to the lobby without respawn restrictions?", "Send to Lobby", "Yes", "No")
if(confirm != "Yes")
return
message_admins("[key_name_admin(src)] gave [key_name_admin(O)] a full respawn and sent them back to the lobby.")
log_admin("[key_name(src)] gave [key_name(O)] a full respawn and sent them back to the lobby.")
to_chat(O, "<span class='userdanger'>You have been given a full respawn.</span>")
O.do_respawn(FALSE)
O.client.prefs.dnr_triggered = FALSE
else if(istype(M, /mob/dead/new_player))
var/mob/dead/new_player/NP = M
var/confirm = alert(src, "Remove [NP]'s respawn restrictions?", "Remove Restrictions", "Yes", "No")
if(confirm != "Yes")
return
message_admins("[key_name_admin(src)] removed [ckey]'s respawn restrictions.")
log_admin("[key_name(src)] removed [ckey]'s respawn restrictions")
NP.client.prefs.respawn_restrictions_active = FALSE
NP.client.prefs.dnr_triggered = FALSE
to_chat(NP, "<span class='boldnotie'>Your respawn restrictions have been removed.")
else
CRASH("Invalid mobtype")
/**
* Allows a ghost to bypass respawn delay without lifting respawn restrictions
*/
/client/proc/admin_cmd_remove_ghost_respawn_timer()
set name = "Remove Respawn Timer for Player"
set desc = "Removes a player's respawn timer without removing their respawning restrictions."
set category = "Admin"
var/list/mob/dead/observer/valid = list()
for(var/mob/dead/observer/I in GLOB.dead_mob_list)
if(!I.client)
continue
valid["[I.ckey] - [I.name]"] = I
if(!valid.len)
to_chat(src, "<span class='warning'>No logged in ghosts found.</span>")
return
var/mob/dead/observer/O = valid[input(src, "Choose a player (only showing logged in)", "Remove Respawn Timer") as null|anything in valid]
if(!O.client)
to_chat(src, "<span class='warning'>[O] has no client.</span>")
return
var/timeleft = O.time_left_to_respawn()
if(!timeleft)
to_chat(src, "<span class='warning'>[O] can already respawn.")
return
message_admins("[key_name_admin(src)] removed [key_name_admin(O)]'s respawn timer.")
log_admin("[key_name(src)] removed [key_name(O)]'s respawn timer.")
O.client.prefs.respawn_time_of_death = -INFINITY
to_chat(O, "<span class='boldnotice'>Your respawn timer has been removed.")
// ADMIN VERBS END
/**
* Checks if we can latejoin on the currently selected slot, taking into account respawn status.
*/
/mob/dead/new_player/proc/respawn_latejoin_check(notify = FALSE)
if(!client.prefs.respawn_restrictions_active)
return TRUE
var/can_same_person = CONFIG_GET(flag/allow_same_character_respawn)
if(can_same_person)
return TRUE
var/nameless = client.prefs.nameless
var/randomname = client.prefs.be_random_name
var/randombody = client.prefs.be_random_body
if(randombody && (nameless || randomname))
return TRUE // somewhat unrecognizable
if(client.prefs.slots_joined_as && (client.prefs.default_slot in client.prefs.slots_joined_as))
if(notify)
to_chat(src, "<span class='userdanger'>You cannot respawn on the same slot. Joined slots: [english_list(client.prefs.slots_joined_as)].")
return FALSE
if((!nameless && !randomname) && (client.prefs.characters_joined_as && (client.prefs.real_name in client.prefs.characters_joined_as)))
if(notify)
to_chat(src, "<span class='userdanger'>You cannot respawn on the same character. Joined slots: [english_list(client.prefs.characters_joined_as)].")
return FALSE
return TRUE
/**
* Attempts to respawn.
*/
/mob/dead/observer/verb/respawn()
set name = "Respawn"
set category = "OOC"
if(!CONFIG_GET(flag/respawns_enabled))
to_chat(src, "<span class='warning'>Respawns are disabled in configuration.</span>")
return
if(client.prefs.dnr_triggered)
to_chat(src, "<span class='danger'>You cannot respawn as you have enabled DNR.</span>")
return
var/roundstart_timeleft = (SSticker.round_start_time + (CONFIG_GET(number/respawn_minimum_delay_roundstart) * 600)) - world.time
if(roundstart_timeleft > 0)
to_chat(src, "<span class='warning'>It's been too short of a time since the round started! Please wait [CEILING(roundstart_timeleft / 600, 0.1)] more minutes.</span>")
return
var/list/banned_modes = CONFIG_GET(keyed_list/respawn_chaos_gamemodes)
if(SSticker.mode && banned_modes[lowertext(SSticker.mode.config_tag)])
to_chat(src, "<span class='warning'>The current mode tag, [SSticker.mode.config_tag], is not eligible for respawn.</span>")
return
var/timeleft = time_left_to_respawn()
if(timeleft)
to_chat(src, "<span class='warning'>It's been too short of a time since you died/observed! Please wait [round(timeleft / 600, 0.1)] more minutes.</span>")
return
do_respawn(TRUE)
/**
* Gets time left until we can respawn. Returns 0 if we can respawn now.
*/
/mob/dead/observer/verb/time_left_to_respawn()
ASSERT(client)
return max(0, ((client.prefs.respawn_did_cryo? CONFIG_GET(number/respawn_delay_cryo) : CONFIG_GET(number/respawn_delay)) MINUTES + client.prefs.respawn_time_of_death) - world.time)
/**
* Handles respawning
*/
/mob/dead/observer/proc/do_respawn(penalize)
if(!client)
return
if(isnull(penalize))
penalize = client.prefs.respawn_restrictions_active
client.prefs.respawn_restrictions_active = penalize
message_admins("[key_name_admin(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
log_game("[key_name(src)] was respawned to lobby [penalize? "with" : "without"] restrictions.")
var/mob/dead/new_player/N = transfer_to_lobby()
to_chat(N, "<span class='userdanger'>You have been respawned to the lobby. \
Remember to take heed of rules regarding round knowledge - notably, that ALL past lives are forgotten. \
Any character you join as has NO knowledge of round events unless specified otherwise by an admin.</span>")
/**
* Actual proc that removes us and puts us back on lobby
*
* Returns the new mob.
*/
/mob/dead/observer/proc/transfer_to_lobby()
if(!client) // if no one's in us we can just be deleted
qdel(src)
return
client.screen.Cut()
client.view_size.resetToDefault()
client.generate_clickcatcher()
client.apply_clickcatcher()
client.view_size.setDefault(getScreenSize(client.prefs.widescreenpref))
client.view_size.resetToDefault()
var/mob/dead/new_player/M = new /mob/dead/new_player
M.ckey = ckey
return M
+1 -1
View File
@@ -5,7 +5,7 @@
silent = FALSE
losebreath = 0
if(!gibbed)
if(!gibbed && !HAS_TRAIT(src, TRAIT_DEATHCOMA))
emote("deathgasp")
. = ..()
@@ -190,6 +190,11 @@
message = "chimes."
sound = 'sound/machines/chime.ogg'
/datum/emote/sound/human/squeak
key = "squeak"
message = "squeaks."
sound = 'sound/effects/mousesqueek.ogg'
//rock paper scissors emote handling
/mob/living/carbon/human/proc/beginRockPaperScissors(var/chosen_move)
GLOB.rockpaperscissors_players[src] = list(chosen_move, ROCKPAPERSCISSORS_NOT_DECIDED)
@@ -43,7 +43,7 @@
AddComponent(/datum/component/mood)
AddComponent(/datum/component/combat_mode)
AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text")
AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!")
AddElement(/datum/element/flavor_text/carbon/temporary, "", "Set Pose (Temporary Flavor Text)", "This should be used only for things pertaining to the current round!", _save_key = null)
AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE)
/mob/living/carbon/human/Destroy()
@@ -14,6 +14,7 @@
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
block_parry_data = /datum/block_parry_data/unarmed/human
default_block_parry_data = /datum/block_parry_data/unarmed/human
//Hair colour and style
var/hair_color = "000"
@@ -98,20 +99,54 @@
parry_failed_clickcd_duration = 0.4
parry_data = list( // yeah it's snowflake
"HUMAN_PARRY_STAGGER" = 3 SECONDS,
"HUMAN_PARRY_PUNCH" = TRUE,
"HUMAN_PARRY_MININUM_EFFICIENCY" = 0.9
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
"UNARMED_PARRY_PUNCH" = TRUE,
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
)
/mob/living/carbon/human/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
/mob/living/on_active_parry(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, list/block_return, parry_efficiency, parry_time)
var/datum/block_parry_data/D = return_block_parry_datum(block_parry_data)
. = ..()
if(!owner.Adjacent(attacker))
return ..()
if(parry_efficiency < D.parry_data["HUMAN_PARRY_MINIMUM_EFFICIENCY"])
return ..()
return
if(parry_efficiency < D.parry_data["UNARMED_PARRY_MINIMUM_EFFICIENCY"])
return
visible_message("<span class='warning'>[src] strikes back perfectly at [attacker], staggering them!</span>")
if(D.parry_data["HUMAN_PARRY_PUNCH"])
if(D.parry_data["UNARMED_PARRY_PUNCH"])
UnarmedAttack(attacker, TRUE, INTENT_HARM, ATTACK_IS_PARRY_COUNTERATTACK | ATTACK_IGNORE_ACTION | ATTACK_IGNORE_CLICKDELAY | NO_AUTO_CLICKDELAY_HANDLING)
var/mob/living/L = attacker
if(istype(L))
L.Stagger(D.parry_data["HUMAN_PARRY_STAGGER"])
L.Stagger(D.parry_data["UNARMED_PARRY_STAGGER"])
/// Unarmed parry data for pugilists
/datum/block_parry_data/unarmed/pugilist
parry_respect_clickdelay = FALSE
parry_stamina_cost = 4
parry_attack_types = ATTACK_TYPE_UNARMED | ATTACK_TYPE_PROJECTILE | ATTACK_TYPE_TACKLE | ATTACK_TYPE_THROWN | ATTACK_TYPE_MELEE
parry_flags = PARRY_DEFAULT_HANDLE_FEEDBACK | PARRY_LOCK_ATTACKING
parry_time_windup = 0
parry_time_spindown = 0
parry_time_active = 5
parry_time_perfect = 1.5
parry_time_perfect_leeway = 1.5
parry_imperfect_falloff_percent = 20
parry_efficiency_perfect = 100
parry_efficiency_perfect_override = list(
ATTACK_TYPE_PROJECTILE_TEXT = 60,
)
parry_efficiency_considered_successful = 0.01
parry_efficiency_to_counterattack = 0.01
parry_max_attacks = INFINITY
parry_failed_cooldown_duration = 1.5 SECONDS
parry_failed_stagger_duration = 0
parry_cooldown = 0
parry_failed_clickcd_duration = 0.8
parry_data = list( // yeah it's snowflake
"UNARMED_PARRY_STAGGER" = 3 SECONDS,
"UNARMED_PARRY_PUNCH" = TRUE,
"UNARMED_PARRY_MININUM_EFFICIENCY" = 90
)
@@ -62,7 +62,6 @@
H.add_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer -= 1 //go one layer down so people go over you
ENABLE_BITFIELD(H.pass_flags, PASSMOB) //this actually lets people pass over you
squeak = H.AddComponent(/datum/component/squeak, custom_sounds = list('sound/effects/blobattack.ogg')) //blorble noise when people step on you
@@ -103,7 +102,6 @@
REMOVE_TRAIT(H, TRAIT_HUMAN_NO_RENDER, SLIMEPUDDLE_TRAIT)
H.update_disabled_bodyparts(silent = TRUE)
H.remove_movespeed_modifier(/datum/movespeed_modifier/slime_puddle)
H.layer += 1 //go one layer back above!
DISABLE_BITFIELD(H.pass_flags, PASSMOB)
is_puddle = FALSE
if(squeak)
@@ -139,6 +139,18 @@
if(E.web_ready == FALSE)
to_chat(H, "<span class='warning'>You need to wait awhile to regenerate web fluid.</span>")
return
if(!H.Adjacent(A)) //No.
return
if(!isliving(A) && A.anchored)
to_chat(H, "<span class='warning'>[A] is bolted to the floor!</span>")
return
if(istype(A, /obj/structure/arachnid))
to_chat(H, "<span class='warning'>No double wrapping.</span>")
return
if(istype(A, /obj/effect))
to_chat(H, "<span class='warning'>You cannot wrap this.</span>")
return
H.visible_message("<span class='danger'>[H] starts to wrap [A] into a cocoon!</span>","<span class='warning'>You start to wrap [A] into a cocoon.</span>")
if(!do_after(H, 10 SECONDS, 1, A))
to_chat(H, "<span class='warning'>Your web spinning was interrupted!</span>")
return
@@ -27,7 +27,7 @@
/datum/species/dullahan/check_roundstart_eligible()
if(SSevents.holidays && SSevents.holidays[HALLOWEEN])
return TRUE
return FALSE
return ..()
/datum/species/dullahan/on_species_gain(mob/living/carbon/human/H, datum/species/old_species)
. = ..()
@@ -7,7 +7,7 @@
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR,HAS_FLESH)
mutantlungs = /obj/item/organ/lungs/slime
mutant_heart = /obj/item/organ/heart/slime
mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None")
mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None", "legs" = "Plantigrade")
inherent_traits = list(TRAIT_TOXINLOVER)
meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/slime
gib_types = list(/obj/effect/gibspawner/slime, /obj/effect/gibspawner/slime/bodypartless)
@@ -406,7 +406,7 @@
default_color = "00FFFF"
species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR)
inherent_traits = list(TRAIT_TOXINLOVER)
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None")
mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_body_markings" = "Plain", "mam_snouts" = "None", "taur" = "None", "legs" = "Plantigrade")
say_mod = "says"
hair_color = "mutcolor"
hair_alpha = 160 //a notch brighter so it blends better.
+4
View File
@@ -66,6 +66,10 @@
GLOB.alive_mob_list -= src
if(!gibbed)
GLOB.dead_mob_list += src
if(ckey)
var/datum/preferences/P = GLOB.preferences_datums[ckey]
if(P)
P.respawn_time_of_death = world.time
set_drugginess(0)
set_disgust(0)
SetSleeping(0, 0)
+2 -2
View File
@@ -264,9 +264,9 @@
return FALSE
/mob/living/carbon/human/has_tail()
if(!dna || !dna.features)
if(!dna || !dna.species)
return ..()
var/list/L = dna.features // caches list because i refuse to type it out and because performance
var/list/L = dna.species.mutant_bodyparts // caches list because i refuse to type it out and because performance
return (L["mam_tail"] && (L["mam_tail"] != "None")) || (L["tail_human"] && (L["tail_human"] != "None")) || (L["tail_lizard"] && (L["tail_lizard"] != "None"))
/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE)
@@ -127,7 +127,7 @@
handle_parry_ending_effects(data, effect_text)
parrying = NOT_PARRYING
parry_start_time = 0
parry_end_time_last = world.time
parry_end_time_last = world.time + (successful? 0 : data.parry_failed_cooldown_duration)
successful_parries = null
/**
@@ -154,6 +154,8 @@ GLOBAL_LIST_EMPTY(block_parry_data)
var/parry_failed_stagger_duration = 3.5 SECONDS
/// Clickdelay duration post-parry if you fail to parry an attack
var/parry_failed_clickcd_duration = 2 SECONDS
/// Parry cooldown post-parry if failed. This is ADDED to parry_cooldown!!!
var/parry_failed_cooldown_duration = 0 SECONDS
/**
* Quirky proc to get average of flags in list that are in attack_type because why is attack_type a flag.
@@ -32,6 +32,10 @@
// Combat - Blocking/Parrying system
/// Our block_parry_data for unarmed blocks/parries. Currently only used for parrying, as unarmed block isn't implemented yet. YOU MUST RUN [get_block_parry_data(this)] INSTEAD OF DIRECTLY ACCESSING!
var/datum/block_parry_data/block_parry_data = /datum/block_parry_data // defaults to *something* because [combat_flags] dictates whether or not we can unarmed block/parry.
/// Default
var/datum/block_parry_data/default_block_parry_data = /datum/block_parry_data
/// If we're a pugilist
var/datum/block_parry_data/pugilist_block_parry_data = /datum/block_parry_data/unarmed/pugilist
// Blocking
/// The item the user is actively blocking with if any.
var/obj/item/active_block_item
@@ -1,12 +1,3 @@
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
/mob/living/ComponentInitialize()
. = ..()
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_LIVING_NO_DENSITY), .proc/update_density)
//Stuff like mobility flag updates, resting updates, etc.
+20
View File
@@ -0,0 +1,20 @@
/// IN THE FUTURE, WE WILL PROBABLY REFACTOR TO LESSEN THE NEED FOR UPDATE_MOBILITY, BUT FOR NOW.. WE CAN START DOING THIS.
/// FOR BLOCKING MOVEMENT, USE TRAIT_MOBILITY_NOMOVE AS MUCH AS POSSIBLE. IT WILL MAKE REFACTORS IN THE FUTURE EASIER.
/mob/living/ComponentInitialize()
. = ..()
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOMOVE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOPICKUP), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOUSE), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_MOBILITY_NOREST), .proc/update_mobility)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_LIVING_NO_DENSITY), .proc/update_density)
RegisterSignal(src, SIGNAL_TRAIT(TRAIT_PUGILIST), .proc/update_pugilism)
/mob/living/proc/update_pugilism()
if(HAS_TRAIT(src, TRAIT_PUGILIST))
combat_flags |= COMBAT_FLAG_UNARMED_PARRY
block_parry_data = pugilist_block_parry_data
else
var/initial_combat_flags = initial(combat_flags)
if(!(initial_combat_flags & COMBAT_FLAG_UNARMED_PARRY))
combat_flags &= ~COMBAT_FLAG_UNARMED_PARRY
block_parry_data = default_block_parry_data
@@ -1,3 +1,30 @@
/mob/living/silicon/verb/clear_custom_holoform()
set name = "Clear Custom Holoform"
set desc = "Clear your current custom holoform"
set category = "OOC"
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
return
client.prefs.custom_holoform_icon = null
client.prefs.cached_holoform_icons = null
to_chat(src, "<span class='boldnotice'>Holoform removed.</span>")
/mob/living/silicon/verb/set_custom_holoform()
set name = "Set Custom Holoform"
set desc = "Set your custom holoform using your current preferences slot and a specified set of gear."
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
return
if(client.prefs.last_custom_holoform > world.time - CUSTOM_HOLOFORM_DELAY)
to_chat(src, "<span class='warning'>You are attempting to change custom holoforms too fast!</span>")
var/icon/new_holoform = user_interface_custom_holoform(client)
if(new_holoform)
client.prefs.custom_holoform_icon = new_holoform
client.prefs.cached_holoform_icons = null
client.prefs.last_custom_holoform = world.time
to_chat(src, "<span class='boldnotice'>Holoform set.</span>")
/mob/living/silicon/proc/attempt_set_custom_holoform()
if(!client.prefs)
to_chat(src, "<span class='boldwarning'>No preferences datum on your client, contact an admin/coder!</span>")
@@ -9,6 +9,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians
real_name = "Guardian Spirit"
desc = "A mysterious being that stands by its charge, ever vigilant."
speak_emote = list("hisses")
rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS
gender = NEUTER
mob_biotypes = NONE
bubble_icon = "guardian"
@@ -1034,3 +1034,159 @@
/mob/living/simple_animal/parrot/clock_hawk/ratvar_act()
return
// Different Parrot Breeds
/mob/living/simple_animal/parrot/kea
name = "Kea"
icon_state = "kea-flap"
icon_living = "kea-flap"
icon_dead = "kea-dead"
icon_sit = "kea_sit"
/mob/living/simple_animal/parrot/eclectusr
name = "Eclectus"
icon_state = "eclectusr-flap"
icon_living = "eclectusr-flap"
icon_dead = "eclectusr-dead"
icon_sit = "electusr_sit"
/mob/living/simple_animal/parrot/eclectus
name = "Eclectus"
icon_state = "eclectus-flap"
icon_living = "eclectus-flap"
icon_dead = "eclectus-dead"
icon_sit = "electus_sit"
/mob/living/simple_animal/parrot/eclectusf
name = "Eclectus"
icon_state = "eclectusf-flap"
icon_living = "eclectusf-flap"
icon_dead = "eclectusf-dead"
icon_sit = "electusf_sit"
/mob/living/simple_animal/parrot/greybird
name = "Grey Bird"
icon_state = "agrey-flap"
icon_living = "agrey-flap"
icon_dead = "agrey-dead"
icon_sit = "agrey_sit"
/mob/living/simple_animal/parrot/blue_caique
name = "Blue Caique "
icon_state = "bcaique-flap"
icon_living = "bcaique-flap"
icon_dead = "bcaique-dead"
icon_sit = "bcaique_sit"
/mob/living/simple_animal/parrot/white_caique
name = "White caique"
icon_state = "wcaique-flap"
icon_living = "wcaique-flap"
icon_dead = "wcaique-dead"
icon_sit = "wcaique_sit"
/mob/living/simple_animal/parrot/green_budgerigar
name = "Green Budgerigar"
icon_state = "gbudge-flap"
icon_living = "gbudge-flap"
icon_dead = "gbudge-dead"
icon_sit = "gbudge_sit"
/mob/living/simple_animal/parrot/blue_Budgerigar
name = "Blue Budgerigar"
icon_state = "bbudge-flap"
icon_living = "bbudge-flap"
icon_dead = "bbudge-dead"
icon_sit = "bbudge_sit"
/mob/living/simple_animal/parrot/bluegreen_Budgerigar
name = "Bluegreen Budgerigar"
icon_state = "bgbudge-flap"
icon_living = "bgbudge-flap"
icon_dead = "bgbudge-dead"
icon_sit = "bgbudge_sit"
/mob/living/simple_animal/parrot/commonblackbird
name = "Black Bird"
icon_state = "commonblackbird"
icon_living = "commonblackbird"
icon_dead = "commonblackbird-dead"
icon_sit = "commonblackbird_sit"
/mob/living/simple_animal/parrot/azuretit
name = "Azure Tit"
icon_state = "azuretit"
icon_living = "azuretit"
icon_dead = "azuretit-dead"
icon_sit = "azuretit_sit"
/mob/living/simple_animal/parrot/europeanrobin
name = "European Robin"
icon_state = "europeanrobin"
icon_living = "europeanrobin"
icon_dead = "europeanrobin-dead"
icon_sit = "europeanrobin_sit"
/mob/living/simple_animal/parrot/goldcrest
name = "Goldcrest"
icon_state = "goldcrest"
icon_living = "goldcrest"
icon_dead = "goldcrest-dead"
icon_sit = "goldencrest_sit"
/mob/living/simple_animal/parrot/ringneckdove
name = "Ringneck Dove"
icon_state = "ringneckdove"
icon_living = "ringneckdove"
icon_dead = "ringneckdove-dead"
icon_sit = "ringneckdove_sit"
/mob/living/simple_animal/parrot/cockatiel
name = "Cockatiel"
icon_state = "tiel-flap"
icon_living = "tiel-flap"
icon_dead = "tiel-dead"
icon_sit = "tiel_sit"
/mob/living/simple_animal/parrot/white_cockatiel
name = "White Cockatiel"
icon_state = "wtiel-flap"
icon_living = "wtiel-flap"
icon_dead = "wtiel-dead"
icon_sit = "wtiel_sit"
/mob/living/simple_animal/parrot/yellowish_cockatiel
name = "Yellowish Cockatiel"
icon_state = "luttiel-flap"
icon_living = "luttiel-flap"
icon_dead = "luttiel-dead"
icon_sit = "luttiel_sit"
/mob/living/simple_animal/parrot/grey_cockatiel
name = "Grey Cockatiel"
icon_state = "blutiel-flap"
icon_living = "blutiel-flap"
icon_dead = "blutiel-dead"
icon_sit = "blutiel_sit"
/mob/living/simple_animal/parrot/too
name = "Too"
icon_state = "too-flap"
icon_living = "too-flap"
icon_dead = "too-dead"
icon_sit = "too_sit"
/mob/living/simple_animal/parrot/hooded_too
name = "Utoo"
icon_state = "utoo-flap"
icon_living = "utoo-flap"
icon_dead = "utoo-dead"
icon_sit = "utoo_sit"
/mob/living/simple_animal/parrot/pink_too
name = "Mtoo"
icon_state = "mtoo-flap"
icon_living = "mtoo-flap"
icon_dead = "mtoo-dead"
icon_sit = "mtoo_sit"
+6 -33
View File
@@ -457,39 +457,6 @@
else
to_chat(src, "You don't have a mind datum for some reason, so you can't add a note to it.")
/mob/verb/abandon_mob()
set name = "Respawn"
set category = "OOC"
if (CONFIG_GET(flag/norespawn))
return
if ((stat != DEAD || !( SSticker )))
to_chat(usr, "<span class='boldnotice'>You must be dead to use this!</span>")
return
log_game("[key_name(usr)] used abandon mob.")
to_chat(usr, "<span class='boldnotice'>Please roleplay correctly!</span>")
if(!client)
log_game("[key_name(usr)] AM failed due to disconnect.")
return
client.screen.Cut()
client.screen += client.void
if(!client)
log_game("[key_name(usr)] AM failed due to disconnect.")
return
var/mob/dead/new_player/M = new /mob/dead/new_player()
if(!client)
log_game("[key_name(usr)] AM failed due to disconnect.")
qdel(M)
return
M.key = key
// M.Login() //wat
return
/mob/proc/transfer_ckey(mob/new_mob, send_signal = TRUE)
if(!new_mob || (!ckey && new_mob.ckey))
CRASH("transfer_ckey() called [new_mob ? "on ckey-less mob with a player mob as target" : "without a valid mob target"]!")
@@ -1002,6 +969,12 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
switch(var_name)
if("logging")
return debug_variable(var_name, logging, 0, src, FALSE)
if(NAMEOF(src, lastKnownIP))
if(!check_rights(R_SENSITIVE, FALSE))
return "SENSITIVE"
if(NAMEOF(src, computer_id))
if(!check_rights(R_SENSITIVE, FALSE))
return "SENSITIVE"
. = ..()
/mob/vv_auto_rename(new_name)
+83 -9
View File
@@ -86,15 +86,6 @@ proc/get_top_level_mob(var/mob/S)
else if(!params)
var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN)
if(subtle_emote && !check_invalid(user, subtle_emote))
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
switch(type)
if("Visible")
emote_type = EMOTE_VISIBLE
if("Hearable")
emote_type = EMOTE_AUDIBLE
else
alert("Unable to use this emote, must be either hearable or visible.")
return
message = subtle_emote
else
return FALSE
@@ -111,6 +102,80 @@ proc/get_top_level_mob(var/mob/S)
user.visible_message(message = message, self_message = message, vision_distance = 1, ignored_mobs = GLOB.dead_mob_list, omni = TRUE)
///////////////// SUBTLE 3: DARE DICE
/datum/emote/living/subtler_table
key = "subtler_table"
key_third_person = "subtler_table"
message = null
mob_type_blacklist_typecache = list(/mob/living/brain)
/datum/emote/living/subtler_table/proc/check_invalid(mob/user, input)
if(stop_bad_mime.Find(input, 1, 1))
to_chat(user, "<span class='danger'>Invalid emote.</span>")
return TRUE
return FALSE
/datum/emote/living/subtler_table/run_emote(mob/user, params, type_override = null)
if(!locate(/obj/structure/table) in range(user, 1))
to_chat(user, "There are no tables around you.")
return FALSE
if(jobban_isbanned(user, "emote"))
to_chat(user, "You cannot send subtle emotes (banned).")
return FALSE
else if(user.client && user.client.prefs.muted & MUTE_IC)
to_chat(user, "You cannot send IC messages (muted).")
return FALSE
else if(!params)
var/subtle_emote = stripped_multiline_input_or_reflect(user, "Choose an emote to display.", "Subtler" , null, MAX_MESSAGE_LEN)
if(subtle_emote && !check_invalid(user, subtle_emote))
message = subtle_emote
else
return FALSE
else
message = params
if(type_override)
emote_type = type_override
. = TRUE
if(!can_run_emote(user))
return FALSE
user.log_message("[message] (TABLE-WRAPPING)", LOG_SUBTLER)
message = "<span class='emote'><b>[user]</b> <i>[user.say_emphasis(message)]</i></span>"
var/list/show_to = list()
var/list/processing = list()
var/safety = 25
for(var/obj/structure/table/T in range(user, 1))
processing |= T
for(var/i in processing)
var/obj/structure/table/T = i
if(safety-- <= 0)
to_chat(user, "Table scan aborted early, some people might have not received the message (max 25)")
break
if(get_dist(T, user) > 7)
continue // nah
processing |= T
for(var/mob/living/M in range(T, 1)) // no ghosts/cameramobs
show_to |= M
var/obj/structure/table/other
other = locate() in get_step(T, NORTH)
if(other)
processing |= other
other = locate() in get_step(T, SOUTH)
if(other)
processing |= other
other = locate() in get_step(T, WEST)
if(other)
processing |= other
other = locate() in get_step(T, EAST)
if(other)
processing |= other
for(var/i in show_to)
var/mob/M = i
M.show_message(message)
///////////////// VERB CODE
/mob/living/verb/subtle()
set name = "Subtle"
@@ -128,3 +193,12 @@ proc/get_top_level_mob(var/mob/S)
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.emote("subtler")
///////////////// VERB CODE 3
/mob/living/verb/subtler_table()
set name = "Subtler Around Table"
set category = "IC"
if(GLOB.say_disabled) //This is dumb but it's here because heehoo copypaste, who the FUCK uses this to identify lag?
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.emote("subtler_table")
+2 -1
View File
@@ -1082,11 +1082,12 @@
if("lockdown")
var/celluse = rand(20,35)
celluse = celluse /100
if(!cell.use(cell.maxcharge*celluse))
return
for (var/obj/machinery/door/D in GLOB.airlocks)
if (get_area(D) == area)
INVOKE_ASYNC(D,/obj/machinery/door.proc/hostile_lockdown,usr, FALSE)
addtimer(CALLBACK(D,/obj/machinery/door.proc/disable_lockdown, FALSE), 30 SECONDS)
cell.charge -= cell.maxcharge*celluse
var/obj/item/implant/hijack/H = usr.getImplant(/obj/item/implant/hijack)
H.stealthcooldown = world.time + 3 MINUTES
if("occupy")
+2
View File
@@ -86,6 +86,8 @@
// recharge the cell
/obj/item/stock_parts/cell/proc/give(amount)
if(amount < 0)
return
if(rigged && amount > 0)
explode()
return 0
+5
View File
@@ -100,6 +100,10 @@
var/impact_light_intensity = 3
var/impact_light_range = 2
var/impact_light_color_override
// Normal lighting effects
var/fired_light_intensity = 1
var/fired_light_range = 0
var/fired_light_color = rgb(255, 255, 255)
//Homing
var/homing = FALSE
@@ -506,6 +510,7 @@
transform = M
trajectory_ignore_forcemove = TRUE
forceMove(starting)
set_light(fired_light_range, fired_light_intensity, fired_light_color)
trajectory_ignore_forcemove = FALSE
if(isnull(pixel_increment_amount))
pixel_increment_amount = SSprojectiles.global_pixel_increment_amount
@@ -2,22 +2,22 @@
icon_state = "magjectile"
damage = 20
armour_penetration = 20
light_range = 3
fired_light_range = 3
pixels_per_second = TILES_TO_PIXELS(16.667)
range = 35
light_color = LIGHT_COLOR_RED
fired_light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/magnetic/disabler
icon_state = "magjectile-nl" //nl stands for non-lethal
damage = 2
armour_penetration = 10
stamina = 20
light_color = LIGHT_COLOR_BLUE
fired_light_color = LIGHT_COLOR_BLUE
/obj/item/projectile/bullet/magnetic/weak
damage = 15
armour_penetration = 10
light_range = 2
fired_light_range = 2
range = 25
/obj/item/projectile/bullet/magnetic/weak/disabler
@@ -30,8 +30,8 @@
stamina = 10
movement_type = FLYING | UNSTOPPABLE
range = 6
light_range = 1
light_color = LIGHT_COLOR_RED
fired_light_range = 1
fired_light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/incendiary/mag_inferno
icon_state = "magjectile-large"
@@ -40,8 +40,8 @@
movement_type = FLYING | UNSTOPPABLE
range = 20
pixels_per_second = TILES_TO_PIXELS(12.5)
light_range = 4
light_color = LIGHT_COLOR_RED
fired_light_range = 4
fired_light_color = LIGHT_COLOR_RED
/obj/item/projectile/bullet/incendiary/mag_inferno/on_hit(atom/target, blocked = FALSE)
..()
@@ -171,11 +171,13 @@
/datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L)
..()
L.ignore_slowdown(type)
ADD_TRAIT(L, TRAIT_IGNOREDAMAGESLOWDOWN, type)
L.update_movespeed()
ADD_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
/datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L)
L.unignore_slowdown(type)
REMOVE_TRAIT(L, TRAIT_IGNOREDAMAGESLOWDOWN, type)
L.update_movespeed()
REMOVE_TRAIT(L, TRAIT_TASED_RESISTANCE, type)
..()
@@ -633,7 +633,7 @@
value = REAGENT_VALUE_RARE
/datum/reagent/medicine/sal_acid
name = "Salicyclic Acid"
name = "Salicylic Acid"
description = "Stimulates the healing of severe bruises. Extremely rapidly heals severe bruising and slowly heals minor ones. Overdose will worsen existing bruising."
reagent_state = LIQUID
color = "#D2D2D2"
@@ -155,7 +155,7 @@
required_reagents = list(/datum/reagent/medicine/pen_acid = 1, /datum/reagent/toxin/slimejelly = 1)
/datum/chemical_reaction/sal_acid
name = "Salicyclic Acid"
name = "Salicylic Acid"
id = /datum/reagent/medicine/sal_acid
results = list(/datum/reagent/medicine/sal_acid = 5)
required_reagents = list(/datum/reagent/sodium = 1, /datum/reagent/phenol = 1, /datum/reagent/carbon = 1, /datum/reagent/oxygen = 1, /datum/reagent/toxin/acid = 1)
@@ -305,12 +305,6 @@
results = list(/datum/reagent/medicine/regen_jelly = 2)
required_reagents = list(/datum/reagent/medicine/tricordrazine = 1, /datum/reagent/toxin/slimejelly = 1)
/datum/chemical_reaction/jelly_convert
name = "Blood Jelly Conversion"
id = /datum/reagent/toxin/slimejelly
results = list(/datum/reagent/toxin/slimejelly = 1)
required_reagents = list(/datum/reagent/toxin = 1, /datum/reagent/blood/jellyblood = 1)
/datum/chemical_reaction/corazone
name = "Corazone"
id = /datum/reagent/medicine/corazone
@@ -81,6 +81,12 @@
var/obj/machinery/portable_atmospherics/P = item_to_retrieve.loc
P.disconnect()
P.update_icon()
else if(istype(item_to_retrieve.loc, /obj/machinery/disposal) || istype(item_to_retrieve.loc, /obj/structure/disposalpipe)) //If it's in disposals, only recall the item.
break
else if(istype(item_to_retrieve.loc, /obj/machinery/nuclearbomb)) //I feel like yandev
break //Just to be sure.
item_to_retrieve = item_to_retrieve.loc
@@ -699,6 +699,8 @@
else
if(species_id in GLOB.greyscale_limb_types) //should they have greyscales?
base_bp_icon = DEFAULT_BODYPART_ICON_ORGANIC
else
base_bp_icon = DEFAULT_BODYPART_ICON
if(base_bp_icon != DEFAULT_BODYPART_ICON)
color_src = mut_colors ? MUTCOLORS : ((H.dna.skin_tone_override && S.use_skintones == USE_SKINTONES_GRAYSCALE_CUSTOM) ? CUSTOM_SKINTONE : SKINTONE)
+5 -4
View File
@@ -98,18 +98,19 @@
return json_encode(response)
/datum/tgs_api/v5/OnTopic(T)
if(!initialized)
return FALSE //continue world/Topic
var/list/params = params2list(T)
var/json = params[DMAPI5_TOPIC_DATA]
if(!json)
return FALSE
return FALSE // continue to /world/Topic
var/list/topic_parameters = json_decode(json)
if(!topic_parameters)
return TopicResponse("Invalid topic parameters json!");
if(!initialized)
TGS_WARNING_LOG("Missed topic due to not being initialized: [T]")
return TRUE // too early to handle, but it's still our responsibility
var/their_sCK = topic_parameters[DMAPI5_PARAMETER_ACCESS_IDENTIFIER]
if(their_sCK != access_identifier)
return TopicResponse("Failed to decode [DMAPI5_PARAMETER_ACCESS_IDENTIFIER] from: [json]!");
+6 -4
View File
@@ -10,6 +10,7 @@
canmove = TRUE
density = FALSE //Thought I couldn't fix this one easily, phew
arms_required = 1
var/override_movespeed = FALSE
/obj/vehicle/ridden/wheelchair/Initialize()
. = ..()
@@ -42,10 +43,11 @@
canmove = FALSE
addtimer(VARSET_CALLBACK(src, canmove, TRUE), 20)
return FALSE
var/datum/component/riding/D = GetComponent(/datum/component/riding)
//1.5 (movespeed as of this change) multiplied by 6.7 gets ABOUT 10 (rounded), the old constant for the wheelchair that gets divided by how many arms they have
//if that made no sense this simply makes the wheelchair speed change along with movement speed delay
D.vehicle_move_delay = round((CONFIG_GET(number/movedelay/run_delay) * 4) / min(user.get_num_arms(), 2), world.tick_lag)
if(!override_movespeed)
var/datum/component/riding/D = GetComponent(/datum/component/riding)
//1.5 (movespeed as of this change) multiplied by 6.7 gets ABOUT 10 (rounded), the old constant for the wheelchair that gets divided by how many arms they have
//if that made no sense this simply makes the wheelchair speed change along with movement speed delay
D.vehicle_move_delay = round((CONFIG_GET(number/movedelay/run_delay) * 4) / min(user.get_num_arms(), 2), world.tick_lag)
return ..()
/obj/vehicle/ridden/wheelchair/Moved()
+1
View File
@@ -14,6 +14,7 @@
/obj/belly
name = "belly" // Name of this location
desc = "It's a belly! You're in it!" // Flavor text description of inside sight/sound/smells/feels.
rad_flags = RAD_NO_CONTAMINATE | RAD_PROTECT_CONTENTS
var/vore_sound = "Gulp" // Sound when ingesting someone
var/vore_verb = "ingest" // Verb for eating with this in messages
var/release_sound = "Splatter" // Sound for letting someone out.