This commit is contained in:
Seris02
2020-01-14 23:42:37 +08:00
126 changed files with 284 additions and 73 deletions

View File

@@ -341,7 +341,7 @@
if(probabilities[M.config_tag]<=0)
qdel(M)
continue
if(M.config_tag in SSvote.stored_modetier_results && SSvote.stored_modetier_results[M.config_tag] < Get(/datum/config_entry/number/dropped_modes))
if(CONFIG_GET(flag/modetier_voting) && !(M.config_tag in SSvote.stored_modetier_results))
qdel(M)
continue
if(min_pop[M.config_tag])

View File

@@ -396,7 +396,6 @@
config_entry_value = TRUE
/datum/config_entry/flag/modetier_voting
config_entry_value = TRUE
/datum/config_entry/number/dropped_modes
config_entry_value = 3

View File

@@ -188,6 +188,12 @@ SUBSYSTEM_DEF(ticker)
tipped = TRUE
if(timeLeft <= 0)
if(SSvote.mode && (SSvote.mode == "roundtype" || SSvote.mode == "dynamic" || SSvote.mode == "mode tiers"))
SSvote.result()
SSpersistence.SaveSavedVotes()
for(var/client/C in SSvote.voting)
C << browse(null, "window=vote;can_close=0")
SSvote.reset()
current_state = GAME_STATE_SETTING_UP
Master.SetRunLevel(RUNLEVEL_SETUP)
if(start_immediately)
@@ -221,12 +227,6 @@ SUBSYSTEM_DEF(ticker)
var/init_start = world.timeofday
//Create and announce mode
var/list/datum/game_mode/runnable_modes
if(SSvote.mode && (SSvote.mode == "roundtype" || SSvote.mode == "dynamic" || SSvote.mode == "mode tiers"))
SSvote.result()
SSpersistence.SaveSavedVotes()
for(var/client/C in SSvote.voting)
C << browse(null, "window=vote;can_close=0")
SSvote.reset()
if(GLOB.master_mode == "random" || GLOB.master_mode == "secret")
runnable_modes = config.get_runnable_modes()

View File

@@ -102,17 +102,18 @@ SUBSYSTEM_DEF(vote)
var/list/d[][] = new/list(choices.len,choices.len) // the basic vote matrix, how many times a beats b
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
for(var/a in 1 to choices.len)
for(var/b in a+1 to choices.len)
var/a_rank = this_vote.Find(a)
var/b_rank = this_vote.Find(b)
a_rank = a_rank ? a_rank : choices.len+1
b_rank = b_rank ? b_rank : choices.len+1
if(a_rank<b_rank)
d[a][b]++
else if(b_rank<a_rank)
d[b][a]++
//if equal, do nothing
if(islist(this_vote))
for(var/a in 1 to choices.len)
for(var/b in a+1 to choices.len)
var/a_rank = this_vote.Find(a)
var/b_rank = this_vote.Find(b)
a_rank = a_rank ? a_rank : choices.len+1
b_rank = b_rank ? b_rank : choices.len+1
if(a_rank<b_rank)
d[a][b]++
else if(b_rank<a_rank)
d[b][a]++
//if equal, do nothing
var/list/p[][] = new/list(choices.len,choices.len) //matrix of shortest path from a to b
for(var/i in 1 to choices.len)
for(var/j in 1 to choices.len)
@@ -142,15 +143,18 @@ SUBSYSTEM_DEF(vote)
// https://en.wikipedia.org/wiki/Majority_judgment
var/list/scores_by_choice = list()
for(var/choice in choices)
scores_by_choice[choice] = list()
scores_by_choice += "[choice]"
scores_by_choice["[choice]"] = list()
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
var/list/pretty_vote = list()
for(var/choice in this_vote)
sorted_insert(scores_by_choice[choice],this_vote[choice],/proc/cmp_numeric_asc)
// START BALLOT GATHERING
pretty_vote += choice
pretty_vote[choice] = GLOB.vote_score_options[this_vote[choice]]
for(var/choice in choices)
if("[choice]" in this_vote && "[choice]" in scores_by_choice)
sorted_insert(scores_by_choice["[choice]"],this_vote["[choice]"],/proc/cmp_numeric_asc)
// START BALLOT GATHERING
pretty_vote += "[choice]"
if(this_vote["[choice]"] in GLOB.vote_score_options)
pretty_vote["[choice]"] = GLOB.vote_score_options[this_vote["[choice]"]]
SSblackbox.record_feedback("associative","voting_ballots",1,pretty_vote)
// END BALLOT GATHERING
for(var/score_name in scores_by_choice)
@@ -186,11 +190,13 @@ SUBSYSTEM_DEF(vote)
/datum/controller/subsystem/vote/proc/calculate_scores(var/blackbox_text)
var/list/scores_by_choice = list()
for(var/choice in choices)
scores_by_choice[choice] = list()
scores_by_choice += "[choice]"
scores_by_choice["[choice]"] = list()
for(var/ckey in voted)
var/list/this_vote = voted[ckey]
for(var/choice in this_vote)
sorted_insert(scores_by_choice[choice],this_vote[choice],/proc/cmp_numeric_asc)
for(var/choice in choices)
if("[choice]" in this_vote && "[choice]" in scores_by_choice)
sorted_insert(scores_by_choice["[choice]"],this_vote["[choice]"],/proc/cmp_numeric_asc)
var/middle_score = round(GLOB.vote_score_options.len/2,1)
for(var/score_name in scores_by_choice)
var/list/score = scores_by_choice[score_name]
@@ -212,6 +218,7 @@ SUBSYSTEM_DEF(vote)
calculate_condorcet_votes(vote_title_text)
if(vote_system == SCORE_VOTING)
calculate_majority_judgement_vote(vote_title_text)
calculate_scores(vote_title_text)
var/list/winners = get_result()
var/was_roundtype_vote = mode == "roundtype" || mode == "dynamic"
if(winners.len > 0)
@@ -219,13 +226,20 @@ SUBSYSTEM_DEF(vote)
stored_gamemode_votes = list()
if(!obfuscated && vote_system == RANKED_CHOICE_VOTING)
text += "\nIt should be noted that this is not a raw tally of votes (impossible in ranked choice) but the score determined by the schulze method of voting, so the numbers will look weird!"
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
if(was_roundtype_vote)
stored_gamemode_votes[choices[i]] = votes
text += "\n<b>[choices[i]]:</b> [obfuscated ? "???" : votes]" //CIT CHANGE - adds obfuscated votes
if(mode == "mode tiers")
for(var/score_name in scores)
var/score = scores[score_name]
if(!score)
score = 0
text = "\n<b>[score_name]:</b> [obfuscated ? "???" : score]"
else
for(var/i=1,i<=choices.len,i++)
var/votes = choices[choices[i]]
if(!votes)
votes = 0
if(was_roundtype_vote)
stored_gamemode_votes[choices[i]] = votes
text += "\n<b>[choices[i]]:</b> [obfuscated ? "???" : votes]" //CIT CHANGE - adds obfuscated votes
if(mode != "custom")
if(winners.len > 1 && !obfuscated) //CIT CHANGE - adds obfuscated votes
text = "\n<b>Vote Tied Between:</b>"
@@ -247,8 +261,9 @@ SUBSYSTEM_DEF(vote)
if(RANKED_CHOICE_VOTING)
for(var/i=1,i<=voted.len,i++)
var/list/myvote = voted[voted[i]]
for(var/j=1,j<=myvote.len,j++)
SSblackbox.record_feedback("nested tally","voting",1,list(vote_title_text,"[j]\th",choices[myvote[j]]))
if(islist(myvote))
for(var/j=1,j<=myvote.len,j++)
SSblackbox.record_feedback("nested tally","voting",1,list(vote_title_text,"[j]\th",choices[myvote[j]]))
if(obfuscated) //CIT CHANGE - adds obfuscated votes. this messages admins with the vote's true results
var/admintext = "Obfuscated results"
if(vote_system == RANKED_CHOICE_VOTING)
@@ -276,7 +291,7 @@ SUBSYSTEM_DEF(vote)
if(CONFIG_GET(flag/modetier_voting))
reset()
started_time = 0
initiate_vote("mode tiers","server",hideresults=FALSE,votesystem=RANKED_CHOICE_VOTING,forced=TRUE, vote_time = 30 MINUTES)
initiate_vote("mode tiers","server",hideresults=FALSE,votesystem=SCORE_VOTING,forced=TRUE, vote_time = 30 MINUTES)
to_chat(world,"<b>The vote will end right as the round starts.</b>")
return .
if("restart")
@@ -290,7 +305,14 @@ SUBSYSTEM_DEF(vote)
else
GLOB.master_mode = .
if("mode tiers")
stored_modetier_results = choices.Copy()
var/list/raw_score_numbers = list()
for(var/score_name in scores)
sorted_insert(raw_score_numbers,scores[score_name],/proc/cmp_numeric_asc)
stored_modetier_results = scores.Copy()
for(var/score_name in stored_modetier_results)
if(stored_modetier_results[score_name] <= raw_score_numbers[CONFIG_GET(number/dropped_modes)])
stored_modetier_results -= score_name
stored_modetier_results += "traitor"
if("dynamic")
if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started.
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
@@ -417,6 +439,7 @@ SUBSYSTEM_DEF(vote)
for(var/tag in modes_to_add)
if(probabilities[tag] <= 0)
modes_to_add -= tag
modes_to_add -= "traitor" // makes it so that traitor is always available
choices.Add(modes_to_add)
if("dynamic")
for(var/T in config.storyteller_cache)
@@ -516,7 +539,7 @@ SUBSYSTEM_DEF(vote)
if(RANKED_CHOICE_VOTING)
var/list/myvote = voted[C.ckey]
for(var/i=1,i<=choices.len,i++)
var/vote = (myvote ? (myvote.Find(i)) : 0)
var/vote = (islist(myvote) ? (myvote.Find(i)) : 0)
if(vote)
. += "<li><b><a href='?src=[REF(src)];vote=[i]'>[choices[i]]</a> ([vote])</b></li>"
else
@@ -615,8 +638,12 @@ SUBSYSTEM_DEF(vote)
if(usr.ckey in voted)
if(!(usr.ckey in SSpersistence.saved_votes))
SSpersistence.saved_votes[usr.ckey] = list()
SSpersistence.saved_votes[usr.ckey][mode] = voted[usr.ckey]
saved += usr.ckey
if(islist(voted[usr.ckey]))
SSpersistence.saved_votes[usr.ckey][mode] = voted[usr.ckey]
saved += usr.ckey
else
voted[usr.ckey] = list()
to_chat(usr,"Your vote was malformed! Start over!")
if("load")
if(!(usr.ckey in SSpersistence.saved_votes))
SSpersistence.LoadSavedVote(usr.ckey)
@@ -627,7 +654,21 @@ SUBSYSTEM_DEF(vote)
else
SSpersistence.saved_votes[usr.ckey][mode] = list()
voted[usr.ckey] = SSpersistence.saved_votes[usr.ckey][mode]
saved += usr.ckey
if(islist(voted[usr.ckey]))
var/malformed = FALSE
if(vote_system == SCORE_VOTING)
for(var/thing in voted[usr.ckey])
if(!(thing in choices))
malformed = TRUE
if(!malformed)
saved += usr.ckey
else
to_chat(usr,"Your saved vote was malformed! Start over!")
SSpersistence.saved_votes[usr.ckey] -= mode
voted -= usr.ckey
else
to_chat(usr,"Your saved vote was malformed! Start over!")
voted -= usr.ckey
else
if(vote_system == SCORE_VOTING)
submit_vote(round(text2num(href_list["vote"])),round(text2num(href_list["score"])))

View File

@@ -380,9 +380,14 @@
/datum/map_template/shuttle/emergency/gorilla
suffix = "gorilla"
name = "Gorilla Cargo Freighter"
description = "A rustic, barely excuseable shuttle transporting important cargo. Not for crew who are about to go ape."
description = "(Emag only) A rustic, barely excuseable shuttle transporting important cargo. Not for crew who are about to go ape."
credit_cost = 2000
/datum/map_template/shuttle/emergency/gorilla/prerequisites_met()
if("emagged" in SSshuttle.shuttle_purchase_requirements_met)
return TRUE
return FALSE
/datum/map_template/shuttle/ferry/base
suffix = "base"
name = "transport ferry"

View File

@@ -99,10 +99,12 @@
id = "Mesmerize"
alert_type = /obj/screen/alert/status_effect/mesmerized
/datum/status_effect/no_combat_mode/mesmerize/on_apply()
/datum/status_effect/no_combat_mode/mesmerize/on_creation(mob/living/new_owner, set_duration)
. = ..()
ADD_TRAIT(owner, TRAIT_MUTE, "mesmerize")
/datum/status_effect/no_combat_mode/mesmerize/on_remove()
. = ..()
REMOVE_TRAIT(owner, TRAIT_MUTE, "mesmerize")
/obj/screen/alert/status_effect/mesmerized

View File

@@ -139,9 +139,9 @@
/datum/world_topic/status/Run(list/input, addr)
if(!key_valid) //If we have a key, then it's safe to trust that this isn't a malicious packet. Also prevents the extra info from leaking
if(GLOB.topic_status_lastcache <= world.time + 5)
if(GLOB.topic_status_lastcache >= world.time)
return GLOB.topic_status_cache
GLOB.topic_status_lastcache = world.time
GLOB.topic_status_lastcache = world.time + 5
. = list()
.["version"] = GLOB.game_version
.["mode"] = "hidden" //CIT CHANGE - hides the gamemode in topic() calls to prevent meta'ing the gamemode

View File

@@ -101,13 +101,23 @@
item_state = "synth"
instrumentId = "piano"
instrumentExt = "ogg"
var/static/list/insTypes = list("accordion" = "mid", "bikehorn" = "ogg", "glockenspiel" = "mid", "guitar" = "ogg", "harmonica" = "mid", "piano" = "ogg", "recorder" = "mid", "saxophone" = "mid", "trombone" = "mid", "violin" = "mid", "xylophone" = "mid") //No eguitar you ear-rapey fuckers.
var/static/list/insTypes = list("accordion" = "mid", "bikehorn" = "ogg", "glockenspiel" = "mid", "banjo" = "ogg", "guitar" = "ogg", "harmonica" = "mid", "piano" = "ogg", "recorder" = "mid", "saxophone" = "mid", "trombone" = "mid", "violin" = "mid", "xylophone" = "mid") //No eguitar you ear-rapey fuckers.
actions_types = list(/datum/action/item_action/synthswitch)
/obj/item/instrument/piano_synth/proc/changeInstrument(name = "piano")
song.instrumentDir = name
song.instrumentExt = insTypes[name]
/obj/item/instrument/banjo
name = "banjo"
desc = "A 'Mura' brand banjo. It's pretty much just a drum with a neck and strings."
icon_state = "banjo"
item_state = "banjo"
instrumentExt = "ogg"
attack_verb = list("scruggs-styled", "hum-diggitied", "shin-digged", "clawhammered")
hitsound = 'sound/weapons/banjoslap.ogg'
instrumentId = "banjo"
/obj/item/instrument/guitar
name = "guitar"
desc = "It's made of wood and has bronze strings."
@@ -263,8 +273,6 @@
throw_range = 15
hitsound = 'sound/items/bikehorn.ogg'
///
/obj/item/musicaltuner
name = "musical tuner"
desc = "A device for tuning musical instruments both manual and electronic alike."

View File

@@ -469,7 +469,7 @@ SLIME SCANNER
msg += "<span class='notice'>Subject is not addicted to any reagents.</span>\n"
var/datum/reagent/impure/fermiTox/F = M.reagents.has_reagent(/datum/reagent/impure/fermiTox)
if(istype(F))
if(istype(F,/datum/reagent/impure/fermiTox))
switch(F.volume)
if(5 to 10)
msg += "<span class='notice'>Subject contains a low amount of toxic isomers.</span>\n"

View File

@@ -29,7 +29,6 @@
new /obj/item/radio/headset/heads/captain(src)
new /obj/item/clothing/glasses/sunglasses/gar/supergar(src)
new /obj/item/clothing/gloves/color/captain(src)
new /obj/item/restraints/handcuffs/cable/zipties(src)
new /obj/item/storage/belt/sabre(src)
new /obj/item/gun/energy/e_gun(src)
new /obj/item/door_remote/captain(src)

View File

@@ -7,22 +7,33 @@
#define STICKYBAN_MAX_ADMIN_MATCHES 2
/world/IsBanned(key,address,computer_id,type,real_bans_only=FALSE)
var/static/key_cache = list()
if(!real_bans_only)
if(key_cache[key])
return list("reason"="concurrent connection attempts", "desc"="You are attempting to connect too fast. Try again.")
key_cache[key] = 1
if (!key || !address || !computer_id)
if(real_bans_only)
key_cache[key] = 0
return FALSE
log_access("Failed Login (invalid data): [key] [address]-[computer_id]")
key_cache[key] = 0
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided invalid or blank information to the server on connection (byond username, IP, and Computer ID.) Provided information for reference: Username:'[key]' IP:'[address]' Computer ID:'[computer_id]'. (If you continue to get this error, please restart byond or contact byond support.)")
if (text2num(computer_id) == 2147483647) //this cid causes stickybans to go haywire
log_access("Failed Login (invalid cid): [key] [address]-[computer_id]")
key_cache[key] = 0
return list("reason"="invalid login data", "desc"="Error: Could not check ban status, Please try again. Error message: Your computer provided an invalid Computer ID.)")
if (type == "world")
key_cache[key] = 0
return ..() //shunt world topic banchecks to purely to byond's internal ban system
var/ckey = ckey(key)
var/client/C = GLOB.directory[ckey]
if (C && ckey == C.ckey && computer_id == C.computer_id && address == C.address)
key_cache[key] = 0
return //don't recheck connected clients.
var/admin = FALSE
@@ -38,21 +49,25 @@
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass the whitelist</span>")
else
log_access("Failed Login: [key] - Not on whitelist")
key_cache[key] = 0
return list("reason"="whitelist", "desc" = "\nReason: You are not on the white list for this server")
//Guest Checking
if(!real_bans_only && IsGuestKey(key))
if (CONFIG_GET(flag/guest_ban))
log_access("Failed Login: [key] - Guests not allowed")
key_cache[key] = 0
return list("reason"="guest", "desc"="\nReason: Guests not allowed. Please sign in with a byond account.")
if (CONFIG_GET(flag/panic_bunker) && SSdbcore.Connect())
log_access("Failed Login: [key] - Guests not allowed during panic bunker")
key_cache[key] = 0
return list("reason"="guest", "desc"="\nReason: Sorry but the server is currently not accepting connections from never before seen players or guests. If you have played on this server with a byond account before, please log in to the byond account you have played from.")
//Population Cap Checking
var/extreme_popcap = CONFIG_GET(number/extreme_popcap)
if(!real_bans_only && extreme_popcap && living_player_count() >= extreme_popcap && !admin)
log_access("Failed Login: [key] - Population cap reached")
key_cache[key] = 0
return list("reason"="popcap", "desc"= "\nReason: [CONFIG_GET(string/extreme_popcap_message)]")
if(CONFIG_GET(flag/ban_legacy_system))
@@ -66,6 +81,7 @@
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass a matching ban on [.["key"]]</span>")
else
log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]")
key_cache[key] = 0
return .
else
@@ -73,6 +89,7 @@
var/msg = "Ban database connection failure. Key [ckey] not checked"
log_world(msg)
message_admins(msg)
key_cache[key] = 0
return
var/ipquery = ""
@@ -86,6 +103,7 @@
var/datum/DBQuery/query_ban_check = SSdbcore.NewQuery("SELECT IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].ckey), ckey), IFNULL((SELECT byond_key FROM [format_table_name("player")] WHERE [format_table_name("player")].ckey = [format_table_name("ban")].a_ckey), a_ckey), reason, expiration_time, duration, bantime, bantype, id, round_id FROM [format_table_name("ban")] WHERE (ckey = '[ckey]' [ipquery] [cidquery]) AND (bantype = 'PERMABAN' OR bantype = 'ADMIN_PERMABAN' OR ((bantype = 'TEMPBAN' OR bantype = 'ADMIN_TEMPBAN') AND expiration_time > Now())) AND isnull(unbanned)")
if(!query_ban_check.Execute(async = TRUE))
qdel(query_ban_check)
key_cache[key] = 0
return
while(query_ban_check.NextRow())
var/pkey = query_ban_check.item[1]
@@ -124,6 +142,7 @@
log_access("Failed Login: [key] [computer_id] [address] - Banned (#[banid]) [.["reason"]]")
qdel(query_ban_check)
key_cache[key] = 0
return .
qdel(query_ban_check)
@@ -138,6 +157,7 @@
//rogue ban in the process of being reverted.
if (cachedban && cachedban["reverting"])
key_cache[key] = 0
return null
if (cachedban && ckey != bannedckey)
@@ -165,6 +185,7 @@
newmatches_admin.len > STICKYBAN_MAX_ADMIN_MATCHES \
)
if (cachedban["reverting"])
key_cache[key] = 0
return null
cachedban["reverting"] = TRUE
@@ -182,6 +203,7 @@
cachedban["admin_matches_this_round"] = list()
cachedban -= "reverting"
world.SetConfig("ban", bannedckey, list2stickyban(cachedban))
key_cache[key] = 0
return null
//byond will not trigger isbanned() for "global" host bans,
@@ -191,6 +213,7 @@
log_admin("The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]")
message_admins("<span class='adminnotice'>The admin [key] has been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
addclientmessage(ckey,"<span class='adminnotice'>You have been allowed to bypass a matching host/sticky ban on [bannedckey]</span>")
key_cache[key] = 0
return null
if (C) //user is already connected!.
@@ -200,6 +223,7 @@
. = list("reason" = "Stickyban", "desc" = desc)
log_access("Failed Login: [key] [computer_id] [address] - StickyBanned [ban["message"]] Target Username: [bannedckey] Placed by [ban["admin"]]")
key_cache[key] = 0
return .

View File

@@ -91,7 +91,7 @@
target.Stun(40) //Utterly useless without this, its okay since there are so many checks to go through
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, 45) //So you cant rotate with combat mode, plus fancy status alert
if(do_mob(user, target, 40, 0, TRUE, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
if(do_mob(user, target, 40, 0, TRUE, extra_checks = CALLBACK(src, .proc/ContinueActive, user, target)))
PowerActivatedSuccessfully() // PAY COST! BEGIN COOLDOWN!
var/power_time = 90 + level_current * 12
target.apply_status_effect(STATUS_EFFECT_MESMERIZE, power_time + 80)

View File

@@ -319,9 +319,9 @@
L.dust()
else
if(!GLOB.ratvar_awakens && L.stat == CONSCIOUS)
vitality_drained = L.adjustToxLoss(1)
vitality_drained = L.adjustToxLoss(1, forced = TRUE)
else
vitality_drained = L.adjustToxLoss(1.5)
vitality_drained = L.adjustToxLoss(1.5, forced = TRUE)
if(vitality_drained)
GLOB.clockwork_vitality += vitality_drained
else

View File

@@ -2,8 +2,9 @@ GLOBAL_LIST_EMPTY(clientmessages)
/proc/addclientmessage(var/ckey, var/message)
ckey = ckey(ckey)
if (!ckey || !message)
if(!ckey || !message)
return
if (!(ckey in GLOB.clientmessages))
GLOB.clientmessages[ckey] = list()
GLOB.clientmessages[ckey] += message
var/list/L = GLOB.clientmessages[ckey]
if(!L)
GLOB.clientmessages[ckey] = L = list()
L += message

View File

@@ -826,6 +826,22 @@
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
real = FALSE
/obj/item/clothing/suit/hooded/wintercoat/durathread
name = "durathread winter coat"
desc = "The one coat to rule them all. Extremely durable while providing the utmost comfort."
icon_state = "coatdurathread"
item_state = "coatdurathread"
armor = list("melee" = 15, "bullet" = 8, "laser" = 25, "energy" = 5, "bomb" = 12, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 50)
hoodtype = /obj/item/clothing/head/hooded/winterhood/durathread
/obj/item/clothing/suit/hooded/wintercoat/durathread/Initialize()
. = ..()
allowed = GLOB.security_wintercoat_allowed
/obj/item/clothing/head/hooded/winterhood/durathread
icon_state = "winterhood_durathread"
armor = list("melee" = 20, "bullet" = 8, "laser" = 15, "energy" = 8, "bomb" = 25, "bio" = 10, "rad" = 15, "fire" = 75, "acid" = 37)
/obj/item/clothing/suit/spookyghost
name = "spooky ghost"

View File

@@ -159,6 +159,14 @@
always_availible = TRUE
category = CAT_CLOTHING
/datum/crafting_recipe/durathread_wintercoat
name = "Durathread Winter Coat"
result = /obj/item/clothing/suit/hooded/wintercoat/durathread
reqs = list(/obj/item/stack/sheet/durathread = 12,
/obj/item/stack/sheet/leather = 10)
time = 70
category = CAT_CLOTHING
/datum/crafting_recipe/wintercoat_cosmic
name = "Cosmic Winter Coat"
result = /obj/item/clothing/suit/hooded/wintercoat/cosmic

View File

@@ -25,7 +25,7 @@
else
log_admin("Client [ckey] was just autokicked for flooding keysends; likely abuse but potentially lagspike.")
message_admins("Client [ckey] was just autokicked for flooding keysends; likely abuse but potentially lagspike.")
QDEL_IN(src, 1)
qdel(src)
return
///Check if the key is short enough to even be a real key

View File

@@ -244,6 +244,10 @@
name = "Shark"
icon_state = "shark"
/datum/sprite_accessory/mam_snouts/hshark
name = "hShark"
icon_state = "hshark"
/datum/sprite_accessory/mam_snouts/toucan
name = "Toucan"
icon_state = "toucan"

View File

@@ -434,11 +434,11 @@
state = "Gas"
var/const/P = 3 //The number of seconds between life ticks
var/T = initial(R.metabolization_rate) * (60 / P)
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.type)
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R)
if(Rcr && Rcr.FermiChem)
fermianalyze = TRUE
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
var/datum/reagent/targetReagent = beaker.reagents.has_reagent(R.type)
var/datum/reagent/targetReagent = beaker.reagents.has_reagent(R)
if(!targetReagent)
CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
@@ -463,9 +463,9 @@
var/T = initial(R.metabolization_rate) * (60 / P)
if(istype(R, /datum/reagent/fermi))
fermianalyze = TRUE
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.type)
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R)
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
var/datum/reagent/targetReagent = reagents.has_reagent(R.type)
var/datum/reagent/targetReagent = reagents.has_reagent(R)
if(!targetReagent)
CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
@@ -483,7 +483,7 @@
/obj/machinery/chem_master/proc/end_fermi_reaction()//Ends any reactions upon moving.
if(beaker.reagents.fermiIsReacting)
if(beaker && beaker.reagents.fermiIsReacting)
beaker.reagents.fermiEnd()
/obj/machinery/chem_master/proc/isgoodnumber(num)

View File

@@ -60,7 +60,7 @@
B = new(T)
if(data["blood_DNA"])
B.blood_DNA[data["blood_DNA"]] = data["blood_type"]
if(!B.reagents)
if(B.reagents)
B.reagents.add_reagent(type, reac_volume)
B.update_icon()

View File

@@ -128,8 +128,7 @@
target.visible_message("<span class='danger'>[M] has been splashed with something!</span>", \
"<span class='userdanger'>[M] has been splashed with something!</span>")
for(var/datum/reagent/A in reagents.reagent_list)
R += A.type + " ("
R += num2text(A.volume) + "),"
R += "[A.type] ([A.volume]),"
if(thrownby)
log_combat(thrownby, M, "splashed", R)

View File

@@ -833,8 +833,8 @@ Nothing else in the console has ID requirements.
for(var/i in 1 to length(ui))
if(!findtextEx(ui[i], RDSCREEN_NOBREAK))
ui[i] += "<br>"
ui[i] = replacetextEx(ui[i], RDSCREEN_NOBREAK, "")
return ui.Join("")
. = ui.Join("")
return replacetextEx(., RDSCREEN_NOBREAK, "")
/obj/machinery/computer/rdconsole/Topic(raw, ls)
if(..())

View File

@@ -131,6 +131,12 @@
/obj/item/clothing/suit/drfreeze_coat = 1,
/obj/item/clothing/suit/gothcoat = 2,
/obj/item/clothing/under/draculass = 1,
/obj/item/clothing/under/christmas/christmasmaler = 3,
/obj/item/clothing/under/christmas/christmasmaleg = 3,
/obj/item/clothing/under/christmas/christmasfemaler = 3,
/obj/item/clothing/under/christmas/christmasfemaleg = 3,
/obj/item/clothing/head/christmashat = 3,
/obj/item/clothing/head/christmashatg = 3,
/obj/item/clothing/under/drfreeze = 1) //End of Cit Changes
refill_canister = /obj/item/vending_refill/autodrobe

View File

@@ -123,15 +123,19 @@
/obj/item/clothing/ears/headphones = 10,
/obj/item/clothing/suit/apron/purple_bartender = 4,
/obj/item/clothing/under/rank/bartender/purple = 4,
/* Commenting out until next Christmas or made automatic
/obj/item/clothing/under/christmas/christmasmaler = 3,
/obj/item/clothing/under/christmas/christmasmaleg = 3,
/obj/item/clothing/under/christmas/christmasfemaler = 3,
/obj/item/clothing/under/christmas/christmasfemaleg = 3,
*/
/obj/item/clothing/suit/hooded/wintercoat/christmascoatr = 3,
/obj/item/clothing/suit/hooded/wintercoat/christmascoatg = 3,
/obj/item/clothing/suit/hooded/wintercoat/christmascoatrg = 3,
/*Commenting out until next Christmas or made automatic
/obj/item/clothing/head/christmashat = 3,
/obj/item/clothing/head/christmashatg = 3,
*/
/obj/item/clothing/shoes/winterboots/christmasbootsr = 3,
/obj/item/clothing/shoes/winterboots/christmasbootsg = 3,
/obj/item/clothing/shoes/winterboots/santaboots = 3,