Merge branch 'master' into update-smooth-movement
This commit is contained in:
@@ -539,7 +539,7 @@
|
||||
#define COMSIG_MECHA_EQUIPMENT_CLICK "mecha_action_equipment_click"
|
||||
/// Prevents click from happening.
|
||||
#define COMPONENT_CANCEL_EQUIPMENT_CLICK (1<<0)
|
||||
|
||||
|
||||
// /mob/living/carbon/human signals
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target)
|
||||
#define COMSIG_HUMAN_MELEE_UNARMED_ATTACKBY "human_melee_unarmed_attackby" //from mob/living/carbon/human/UnarmedAttack(): (mob/living/carbon/human/attacker)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Subsystem signals. Format:
|
||||
// When the signal is called: (signal arguments)
|
||||
// All signals send the source datum of the signal as the first argument
|
||||
|
||||
///Subsystem signals
|
||||
///From base of datum/controller/subsystem/Initialize: (start_timeofday)
|
||||
#define COMSIG_SUBSYSTEM_POST_INITIALIZE "subsystem_post_initialize"
|
||||
|
||||
///Called when the ticker enters the pre-game phase
|
||||
#define COMSIG_TICKER_ENTER_PREGAME "comsig_ticker_enter_pregame"
|
||||
|
||||
///Called when the ticker sets up the game for start
|
||||
#define COMSIG_TICKER_ENTER_SETTING_UP "comsig_ticker_enter_setting_up"
|
||||
|
||||
///Called when the ticker fails to set up the game for start
|
||||
#define COMSIG_TICKER_ERROR_SETTING_UP "comsig_ticker_error_setting_up"
|
||||
|
||||
/// Called when the round has started, but before GAME_STATE_PLAYING
|
||||
#define COMSIG_TICKER_ROUND_STARTING "comsig_ticker_round_starting"
|
||||
|
||||
// Point of interest signals
|
||||
/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_added : (atom/new_poi)
|
||||
#define COMSIG_ADDED_POINT_OF_INTEREST "added_point_of_interest"
|
||||
/// Sent from base of /datum/controller/subsystem/points_of_interest/proc/on_poi_element_removed : (atom/old_poi)
|
||||
#define COMSIG_REMOVED_POINT_OF_INTEREST "removed_point_of_interest"
|
||||
@@ -187,6 +187,9 @@
|
||||
#define ABOVE_HUD_LAYER 30
|
||||
#define ABOVE_HUD_RENDER_TARGET "ABOVE_HUD_PLANE"
|
||||
|
||||
#define LOBBY_BACKGROUND_LAYER 3
|
||||
#define LOBBY_BUTTON_LAYER 4
|
||||
|
||||
#define SPLASHSCREEN_LAYER 90
|
||||
#define SPLASHSCREEN_PLANE 90
|
||||
#define SPLASHSCREEN_RENDER_TARGET "SPLASHSCREEN_PLANE"
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#define LOG_MECHA (1 << 17)
|
||||
#define LOG_SHUTTLE (1 << 18)
|
||||
#define LOG_VICTIM (1 << 19)
|
||||
#define LOG_ECON (1 << 20)
|
||||
|
||||
//Individual logging panel pages
|
||||
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK | LOG_VICTIM)
|
||||
@@ -50,7 +51,7 @@
|
||||
#define INDIVIDUAL_COMMS_LOG (LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS)
|
||||
#define INDIVIDUAL_OOC_LOG (LOG_OOC | LOG_ADMIN)
|
||||
#define INDIVIDUAL_OWNERSHIP_LOG (LOG_OWNERSHIP)
|
||||
#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME | LOG_VICTIM)
|
||||
#define INDIVIDUAL_SHOW_ALL_LOG (LOG_ATTACK | LOG_SAY | LOG_WHISPER | LOG_EMOTE | LOG_DSAY | LOG_PDA | LOG_CHAT | LOG_COMMENT | LOG_TELECOMMS | LOG_OOC | LOG_ADMIN | LOG_OWNERSHIP | LOG_GAME | LOG_VICTIM | LOG_ECON)
|
||||
|
||||
#define LOGSRC_CLIENT "Client"
|
||||
#define LOGSRC_MOB "Mob"
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
// Ready states at roundstart for mob/dead/new_player
|
||||
#define PLAYER_NOT_READY 0
|
||||
#define PLAYER_READY_TO_PLAY 1
|
||||
#define PLAYER_READY_TO_OBSERVE 2
|
||||
|
||||
// movement intent defines for the m_intent var
|
||||
#define MOVE_INTENT_WALK "walk"
|
||||
|
||||
@@ -8,5 +8,6 @@
|
||||
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
|
||||
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
|
||||
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
|
||||
/datum/reagent/consumable/semen //NO.
|
||||
/datum/reagent/consumable/semen, //NO.
|
||||
/datum/reagent/consumable/milk
|
||||
))
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
//ambition end
|
||||
#define MAX_MESSAGE_LEN 4096 //Citadel edit: What's the WORST that could happen?
|
||||
#define MAX_FLAVOR_LEN 4096
|
||||
#define MAX_FLAVOR_PREVIEW_LEN 40
|
||||
#define MAX_TASTE_LEN 40 //lick... vore... ew...
|
||||
#define MAX_NAME_LEN 42
|
||||
#define MAX_BROADCAST_LEN 512
|
||||
|
||||
@@ -233,6 +233,8 @@
|
||||
#define TRAIT_TRASHCAN "trashcan"
|
||||
///Used for fireman carry to have mobe not be dropped when passing by a prone individual.
|
||||
#define TRAIT_BEING_CARRIED "being_carried"
|
||||
#define TRAIT_GLASS_BONES "glass_bones"
|
||||
#define TRAIT_PAPER_SKIN "paper_skin"
|
||||
|
||||
// mobility flag traits
|
||||
// IN THE FUTURE, IT WOULD BE NICE TO DO SOMETHING SIMILAR TO https://github.com/tgstation/tgstation/pull/48923/files (ofcourse not nearly the same because I have my.. thoughts on it)
|
||||
|
||||
@@ -161,6 +161,10 @@
|
||||
if (CONFIG_GET(flag/log_telecomms))
|
||||
WRITE_LOG(GLOB.world_telecomms_log, "TCOMMS: [text]")
|
||||
|
||||
/proc/log_econ(text)
|
||||
if (CONFIG_GET(flag/log_econ))
|
||||
WRITE_LOG(GLOB.world_econ_log, "MONEY: [text]")
|
||||
|
||||
/proc/log_chat(text)
|
||||
if (CONFIG_GET(flag/log_pda))
|
||||
//same thing here
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
///Returns whether or not a player is a guest using their ckey as an input
|
||||
/proc/is_guest_key(key)
|
||||
if(findtext(key, "Guest-", 1, 7) != 1) //was findtextEx
|
||||
return FALSE
|
||||
|
||||
var/i, ch, len = length(key)
|
||||
|
||||
for(i = 7, i <= len, ++i) //we know the first 6 chars are Guest-
|
||||
ch = text2ascii(key, i)
|
||||
if (ch < 48 || ch > 57) //0-9
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -258,15 +258,24 @@
|
||||
|
||||
send2adminchat("Server", "A round of [mode.name] just ended[mode_result == "undefined" ? "." : " with a [mode_result]."] Survival rate: [survival_rate]")
|
||||
|
||||
if(LAZYLEN(GLOB.round_end_notifiees))
|
||||
world.TgsTargetedChatBroadcast("[GLOB.round_end_notifiees.Join(", ")] the round has ended.", FALSE)
|
||||
|
||||
if(length(CONFIG_GET(keyed_list/cross_server)))
|
||||
send_news_report()
|
||||
|
||||
//tell the nice people on discord what went on before the salt cannon happens.
|
||||
world.TgsTargetedChatBroadcast("The current round has ended. Please standby for your shift interlude Nanotrasen News Network's report!", FALSE)
|
||||
world.TgsTargetedChatBroadcast(send_news_report(), FALSE)
|
||||
if(CONFIG_GET(string/chat_roundend_notice_tag))
|
||||
var/broadcastmessage = ""
|
||||
|
||||
if(LAZYLEN(GLOB.round_end_notifiees))
|
||||
broadcastmessage += "[GLOB.round_end_notifiees.Join(", ")], "
|
||||
|
||||
|
||||
broadcastmessage += "[((broadcastmessage == "") ? "the" : "The")] current round has ended. Please standby for your shift interlude Nanotrasen News Network's report!\n"
|
||||
broadcastmessage += "```\n[send_news_report()]\n```"
|
||||
|
||||
if(CONFIG_GET(string/chat_reboot_role))
|
||||
broadcastmessage += "\n\n<@&[CONFIG_GET(string/chat_reboot_role)]>, the server will reboot shortly!"
|
||||
|
||||
send2chat(broadcastmessage, CONFIG_GET(string/chat_roundend_notice_tag))
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
@@ -548,7 +557,7 @@
|
||||
parts += "There were [station_vault] credits collected by crew this shift.<br>"
|
||||
if(total_players > 0)
|
||||
parts += "An average of [station_vault/total_players] credits were collected.<br>"
|
||||
// log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]")
|
||||
log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]")
|
||||
if(mr_moneybags)
|
||||
parts += "The most affluent crew member at shift end was <b>[mr_moneybags.account_holder] with [mr_moneybags.account_balance]</b> cr!</div>"
|
||||
else
|
||||
|
||||
@@ -49,6 +49,8 @@ GLOBAL_VAR(tgui_log)
|
||||
GLOBAL_PROTECT(tgui_log)
|
||||
GLOBAL_VAR(world_shuttle_log)
|
||||
GLOBAL_PROTECT(world_shuttle_log)
|
||||
GLOBAL_VAR(world_econ_log)
|
||||
GLOBAL_PROTECT(world_econ_log)
|
||||
|
||||
GLOBAL_VAR(perf_log)
|
||||
GLOBAL_PROTECT(perf_log)
|
||||
|
||||
@@ -101,14 +101,6 @@
|
||||
..()
|
||||
|
||||
/client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params)
|
||||
var/list/L = params2list(params)
|
||||
if (L["middle"])
|
||||
if (src_object && src_location != over_location)
|
||||
middragtime = world.time
|
||||
middragatom = src_object
|
||||
else
|
||||
middragtime = 0
|
||||
middragatom = null
|
||||
mouseParams = params
|
||||
mouseLocation = over_location
|
||||
mouseObject = over_object
|
||||
@@ -121,9 +113,3 @@
|
||||
|
||||
/obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob)
|
||||
return
|
||||
|
||||
/client/MouseDrop(src_object, over_object, src_location, over_location, src_control, over_control, params)
|
||||
if (middragatom == src_object)
|
||||
middragtime = 0
|
||||
middragatom = null
|
||||
..()
|
||||
|
||||
@@ -0,0 +1,333 @@
|
||||
/datum/hud/new_player
|
||||
|
||||
/datum/hud/new_player/proc/populate_buttons(mob/dead/new_player/owner)
|
||||
var/list/buttons = subtypesof(/atom/movable/screen/lobby)
|
||||
for(var/button_type in buttons)
|
||||
var/atom/movable/screen/lobby/lobbyscreen = new button_type()
|
||||
lobbyscreen.SlowInit()
|
||||
lobbyscreen.hud = src
|
||||
static_inventory += lobbyscreen
|
||||
if(istype(lobbyscreen, /atom/movable/screen/lobby/button))
|
||||
var/atom/movable/screen/lobby/button/lobby_button = lobbyscreen
|
||||
lobby_button.owner = REF(owner)
|
||||
show_hud(hud_version)
|
||||
|
||||
/atom/movable/screen/lobby
|
||||
plane = SPLASHSCREEN_PLANE
|
||||
layer = LOBBY_BUTTON_LAYER
|
||||
screen_loc = "TOP,CENTER"
|
||||
|
||||
/// Run sleeping actions after initialize
|
||||
/atom/movable/screen/lobby/proc/SlowInit()
|
||||
return
|
||||
|
||||
/atom/movable/screen/lobby/background
|
||||
layer = LOBBY_BACKGROUND_LAYER
|
||||
icon = 'icons/hud/lobby/background.dmi'
|
||||
icon_state = "background"
|
||||
screen_loc = "TOP,CENTER:-61"
|
||||
|
||||
/atom/movable/screen/lobby/button
|
||||
///Is the button currently enabled?
|
||||
var/enabled = TRUE
|
||||
///Is the button currently being hovered over with the mouse?
|
||||
var/highlighted = FALSE
|
||||
/// The ref of the mob that owns this button. Only the owner can click on it.
|
||||
var/owner
|
||||
|
||||
/atom/movable/screen/lobby/button/Click(location, control, params)
|
||||
if(owner != REF(usr))
|
||||
return
|
||||
|
||||
. = ..()
|
||||
|
||||
if(!enabled)
|
||||
return
|
||||
flick("[base_icon_state]_pressed", src)
|
||||
update_appearance(UPDATE_ICON)
|
||||
return TRUE
|
||||
|
||||
/atom/movable/screen/lobby/button/MouseEntered(location,control,params)
|
||||
if(owner != REF(usr))
|
||||
return
|
||||
|
||||
. = ..()
|
||||
highlighted = TRUE
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
/atom/movable/screen/lobby/button/MouseExited()
|
||||
if(owner != REF(usr))
|
||||
return
|
||||
|
||||
. = ..()
|
||||
highlighted = FALSE
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
/atom/movable/screen/lobby/button/update_icon(updates)
|
||||
. = ..()
|
||||
if(!enabled)
|
||||
icon_state = "[base_icon_state]_disabled"
|
||||
return
|
||||
else if(highlighted)
|
||||
icon_state = "[base_icon_state]_highlighted"
|
||||
return
|
||||
icon_state = base_icon_state
|
||||
|
||||
/atom/movable/screen/lobby/button/proc/set_button_status(status)
|
||||
if(status == enabled)
|
||||
return FALSE
|
||||
enabled = status
|
||||
update_appearance(UPDATE_ICON)
|
||||
return TRUE
|
||||
|
||||
///Prefs menu
|
||||
/atom/movable/screen/lobby/button/character_setup
|
||||
screen_loc = "TOP:-70,CENTER:-54"
|
||||
icon = 'icons/hud/lobby/character_setup.dmi'
|
||||
icon_state = "character_setup"
|
||||
base_icon_state = "character_setup"
|
||||
|
||||
/atom/movable/screen/lobby/button/character_setup/Click(location, control, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
hud.mymob.client.prefs.current_tab = SETTINGS_TAB
|
||||
hud.mymob.client.prefs.ShowChoices(hud.mymob)
|
||||
|
||||
///Button that appears before the game has started
|
||||
/atom/movable/screen/lobby/button/ready
|
||||
screen_loc = "TOP:-8,CENTER:-65"
|
||||
icon = 'icons/hud/lobby/ready.dmi'
|
||||
icon_state = "not_ready"
|
||||
base_icon_state = "not_ready"
|
||||
var/ready = FALSE
|
||||
|
||||
/atom/movable/screen/lobby/button/ready/Initialize(mapload)
|
||||
. = ..()
|
||||
switch(SSticker.current_state)
|
||||
if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/hide_ready_button)
|
||||
if(GAME_STATE_SETTING_UP)
|
||||
set_button_status(FALSE)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/show_ready_button)
|
||||
else
|
||||
set_button_status(FALSE)
|
||||
|
||||
/atom/movable/screen/lobby/button/ready/proc/hide_ready_button()
|
||||
SIGNAL_HANDLER
|
||||
set_button_status(FALSE)
|
||||
UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/show_ready_button)
|
||||
|
||||
/atom/movable/screen/lobby/button/ready/proc/show_ready_button()
|
||||
SIGNAL_HANDLER
|
||||
set_button_status(TRUE)
|
||||
UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/hide_ready_button)
|
||||
|
||||
/atom/movable/screen/lobby/button/ready/Click(location, control, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/mob/dead/new_player/new_player = hud.mymob
|
||||
ready = !ready
|
||||
if(ready)
|
||||
new_player.ready = PLAYER_READY_TO_PLAY
|
||||
base_icon_state = "ready"
|
||||
else
|
||||
new_player.ready = PLAYER_NOT_READY
|
||||
base_icon_state = "not_ready"
|
||||
update_appearance(UPDATE_ICON)
|
||||
|
||||
///Shown when the game has started
|
||||
/atom/movable/screen/lobby/button/join
|
||||
screen_loc = "TOP:-13,CENTER:-58"
|
||||
icon = 'icons/hud/lobby/join.dmi'
|
||||
icon_state = "" //Default to not visible
|
||||
base_icon_state = "join_game"
|
||||
enabled = FALSE
|
||||
|
||||
/atom/movable/screen/lobby/button/join/Initialize(mapload)
|
||||
. = ..()
|
||||
switch(SSticker.current_state)
|
||||
if(GAME_STATE_PREGAME, GAME_STATE_STARTUP)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/show_join_button)
|
||||
if(GAME_STATE_SETTING_UP)
|
||||
set_button_status(TRUE)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/hide_join_button)
|
||||
else
|
||||
set_button_status(TRUE)
|
||||
|
||||
/atom/movable/screen/lobby/button/join/Click(location, control, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!SSticker?.IsRoundInProgress())
|
||||
to_chat(hud.mymob, span_boldwarning("The round is either not ready, or has already finished..."))
|
||||
return
|
||||
|
||||
//Determines Relevent Population Cap
|
||||
var/relevant_cap
|
||||
var/hpc = CONFIG_GET(number/hard_popcap)
|
||||
var/epc = CONFIG_GET(number/extreme_popcap)
|
||||
if(hpc && epc)
|
||||
relevant_cap = min(hpc, epc)
|
||||
else
|
||||
relevant_cap = max(hpc, epc)
|
||||
|
||||
var/mob/dead/new_player/new_player = hud.mymob
|
||||
|
||||
if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(new_player.key) in GLOB.admin_datums)))
|
||||
to_chat(new_player, span_danger("[CONFIG_GET(string/hard_popcap_message)]"))
|
||||
|
||||
var/queue_position = SSticker.queued_players.Find(new_player)
|
||||
if(queue_position == 1)
|
||||
to_chat(new_player, span_notice("You are next in line to join the game. You will be notified when a slot opens up."))
|
||||
else if(queue_position)
|
||||
to_chat(new_player, span_notice("There are [queue_position-1] players in front of you in the queue to join the game."))
|
||||
else
|
||||
SSticker.queued_players += new_player
|
||||
to_chat(new_player, span_notice("You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len]."))
|
||||
return
|
||||
new_player.LateChoices()
|
||||
|
||||
/atom/movable/screen/lobby/button/join/proc/show_join_button()
|
||||
SIGNAL_HANDLER
|
||||
set_button_status(TRUE)
|
||||
UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP, .proc/hide_join_button)
|
||||
|
||||
/atom/movable/screen/lobby/button/join/proc/hide_join_button()
|
||||
SIGNAL_HANDLER
|
||||
set_button_status(FALSE)
|
||||
UnregisterSignal(SSticker, COMSIG_TICKER_ERROR_SETTING_UP)
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_SETTING_UP, .proc/show_join_button)
|
||||
|
||||
/atom/movable/screen/lobby/button/observe
|
||||
screen_loc = "TOP:-40,CENTER:-54"
|
||||
icon = 'icons/hud/lobby/observe.dmi'
|
||||
icon_state = "observe_disabled"
|
||||
base_icon_state = "observe"
|
||||
enabled = FALSE
|
||||
|
||||
/atom/movable/screen/lobby/button/observe/Initialize(mapload)
|
||||
. = ..()
|
||||
if(SSticker.current_state > GAME_STATE_STARTUP)
|
||||
set_button_status(TRUE)
|
||||
else
|
||||
RegisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, .proc/enable_observing)
|
||||
|
||||
/atom/movable/screen/lobby/button/observe/Click(location, control, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/mob/dead/new_player/new_player = hud.mymob
|
||||
new_player.make_me_an_observer()
|
||||
|
||||
/atom/movable/screen/lobby/button/observe/proc/enable_observing()
|
||||
SIGNAL_HANDLER
|
||||
flick("[base_icon_state]_enabled", src)
|
||||
set_button_status(TRUE)
|
||||
UnregisterSignal(SSticker, COMSIG_TICKER_ENTER_PREGAME, .proc/enable_observing)
|
||||
|
||||
/atom/movable/screen/lobby/button/settings
|
||||
icon = 'icons/hud/lobby/bottom_buttons.dmi'
|
||||
icon_state = "settings"
|
||||
base_icon_state = "settings"
|
||||
screen_loc = "TOP:-122,CENTER:+30"
|
||||
|
||||
/atom/movable/screen/lobby/button/settings/Click(location, control, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
hud.mymob.client.prefs.current_tab = GAME_PREFERENCES_TAB
|
||||
hud.mymob.client.prefs.ShowChoices(hud.mymob)
|
||||
|
||||
/atom/movable/screen/lobby/button/changelog_button
|
||||
icon = 'icons/hud/lobby/bottom_buttons.dmi'
|
||||
icon_state = "changelog"
|
||||
base_icon_state = "changelog"
|
||||
screen_loc ="TOP:-122,CENTER:+58"
|
||||
|
||||
|
||||
/atom/movable/screen/lobby/button/crew_manifest
|
||||
icon = 'icons/hud/lobby/bottom_buttons.dmi'
|
||||
icon_state = "crew_manifest"
|
||||
base_icon_state = "crew_manifest"
|
||||
screen_loc = "TOP:-122,CENTER:+2"
|
||||
|
||||
/atom/movable/screen/lobby/button/crew_manifest/Click(location, control, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/mob/dead/new_player/new_player = hud.mymob
|
||||
new_player.ViewManifest()
|
||||
|
||||
/atom/movable/screen/lobby/button/changelog_button/Click(location, control, params)
|
||||
. = ..()
|
||||
usr.client?.changelog()
|
||||
|
||||
/atom/movable/screen/lobby/button/poll
|
||||
icon = 'icons/hud/lobby/bottom_buttons.dmi'
|
||||
icon_state = "poll"
|
||||
base_icon_state = "poll"
|
||||
screen_loc = "TOP:-122,CENTER:-26"
|
||||
|
||||
var/new_poll = FALSE
|
||||
|
||||
/atom/movable/screen/lobby/button/poll/SlowInit(mapload)
|
||||
. = ..()
|
||||
if(!usr)
|
||||
return
|
||||
var/mob/dead/new_player/new_player = usr
|
||||
if(is_guest_key(new_player.key))
|
||||
set_button_status(FALSE)
|
||||
return
|
||||
if(!SSdbcore.Connect())
|
||||
set_button_status(FALSE)
|
||||
return
|
||||
var/isadmin = FALSE
|
||||
if(new_player.client?.holder)
|
||||
isadmin = TRUE
|
||||
var/datum/db_query/query_get_new_polls = SSdbcore.NewQuery({"
|
||||
SELECT id FROM [format_table_name("poll_question")]
|
||||
WHERE (adminonly = 0 OR :isadmin = 1)
|
||||
AND Now() BETWEEN starttime AND endtime
|
||||
AND deleted = 0
|
||||
AND id NOT IN (
|
||||
SELECT pollid FROM [format_table_name("poll_vote")]
|
||||
WHERE ckey = :ckey
|
||||
AND deleted = 0
|
||||
)
|
||||
AND id NOT IN (
|
||||
SELECT pollid FROM [format_table_name("poll_textreply")]
|
||||
WHERE ckey = :ckey
|
||||
AND deleted = 0
|
||||
)
|
||||
"}, list("isadmin" = isadmin, "ckey" = new_player.ckey))
|
||||
if(!query_get_new_polls.Execute())
|
||||
qdel(query_get_new_polls)
|
||||
set_button_status(FALSE)
|
||||
return
|
||||
if(query_get_new_polls.NextRow())
|
||||
new_poll = TRUE
|
||||
else
|
||||
new_poll = FALSE
|
||||
update_appearance(UPDATE_OVERLAYS)
|
||||
qdel(query_get_new_polls)
|
||||
if(QDELETED(new_player))
|
||||
set_button_status(FALSE)
|
||||
return
|
||||
|
||||
/atom/movable/screen/lobby/button/poll/update_overlays()
|
||||
. = ..()
|
||||
if(new_poll)
|
||||
. += mutable_appearance('icons/hud/lobby/poll_overlay.dmi', "new_poll")
|
||||
|
||||
/atom/movable/screen/lobby/button/poll/Click(location, control, params)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/mob/dead/new_player/new_player = hud.mymob
|
||||
new_player.handle_player_polling()
|
||||
@@ -0,0 +1,14 @@
|
||||
/datum/config_entry/flag/irc_announce_new_game
|
||||
deprecated_by = /datum/config_entry/string/chat_announce_new_game
|
||||
|
||||
/datum/config_entry/flag/irc_announce_new_game/DeprecationUpdate(value)
|
||||
return "" //default broadcast
|
||||
|
||||
/datum/config_entry/string/chat_announce_new_game
|
||||
config_entry_value = null
|
||||
|
||||
/datum/config_entry/string/chat_reboot_role
|
||||
|
||||
/datum/config_entry/string/chat_roundend_notice_tag
|
||||
|
||||
/datum/config_entry/string/chat_squawk_tag
|
||||
@@ -39,16 +39,6 @@
|
||||
|
||||
/datum/config_entry/flag/show_irc_name
|
||||
|
||||
/datum/config_entry/flag/irc_announce_new_game
|
||||
deprecated_by = /datum/config_entry/string/chat_announce_new_game
|
||||
|
||||
/datum/config_entry/flag/irc_announce_new_game/DeprecationUpdate(value)
|
||||
return "" //default broadcast
|
||||
|
||||
/datum/config_entry/string/chat_announce_new_game
|
||||
|
||||
config_entry_value = null
|
||||
|
||||
/datum/config_entry/string/default_view
|
||||
config_entry_value = "15x15"
|
||||
|
||||
|
||||
@@ -79,6 +79,10 @@
|
||||
/datum/config_entry/flag/log_telecomms
|
||||
config_entry_value = TRUE
|
||||
|
||||
/// log economy
|
||||
/datum/config_entry/flag/log_econ
|
||||
config_entry_value = TRUE
|
||||
|
||||
/// log certain expliotable parrots and other such fun things in a JSON file of twitter valid phrases.
|
||||
/datum/config_entry/flag/log_twitter
|
||||
config_entry_value = TRUE
|
||||
|
||||
@@ -31,7 +31,7 @@ SUBSYSTEM_DEF(autotransfer)
|
||||
if(world.time < targettime)
|
||||
return
|
||||
if(maxvotes == NO_MAXVOTES_CAP || maxvotes > curvotes)
|
||||
SSvote.initiate_vote("transfer","server")
|
||||
SSvote.initiate_vote("transfer","server", votesystem=APPROVAL_VOTING)
|
||||
targettime = targettime + voteinterval
|
||||
curvotes++
|
||||
else
|
||||
|
||||
@@ -367,9 +367,14 @@ SUBSYSTEM_DEF(job)
|
||||
JobDebug("DO, Handling unrejectable unassigned")
|
||||
//Mop up people who can't leave.
|
||||
for(var/mob/dead/new_player/player in unassigned) //Players that wanted to back out but couldn't because they're antags (can you feel the edge case?)
|
||||
if(!GiveRandomJob(player))
|
||||
if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them an assistant
|
||||
return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll
|
||||
if(player.client.prefs.joblessrole == BERANDOMJOB) //Gives the player a random role if their preferences are set to it
|
||||
if(!GiveRandomJob(player))
|
||||
if(!AssignRole(player, SSjob.overflow_role)) //If everything is already filled, make them the overflow role
|
||||
return FALSE //Living on the edge, the forced antagonist couldn't be assigned to overflow role (bans, client age) - just reroll
|
||||
else //If the player prefers to return to lobby or be an assistant, give them assistant
|
||||
if(!AssignRole(player, SSjob.overflow_role))
|
||||
if(!GiveRandomJob(player)) //The forced antagonist couldn't be assigned to overflow role (bans, client age) - give a random role
|
||||
return FALSE //Somehow the forced antagonist couldn't be assigned to the overflow role or the a random role - reroll
|
||||
|
||||
return validate_required_jobs(required_jobs)
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
//As a brief warning to all those who dare tread upon these grounds:
|
||||
//The bulk of this code here was written years ago, back in the days of 512.
|
||||
//We were incredibly drunk back then. And nowadays, we've found that being drunk is a hard requirement for working with this code.
|
||||
//So if you're here to make changes? Brandish a glass. There are many sins here, but it's exactly as engineered as it needs to be.
|
||||
//We physically won't be able to tell you what half of this code does. The only thing that'll help you here is the ballmer peak.
|
||||
//Bottoms up, friend. And be sure to drink responsibly. Be sure to fetch some water, too; it eases the hangover. - Bhijn & Myr
|
||||
|
||||
|
||||
// Jukelist indices
|
||||
#define JUKE_TRACK 1
|
||||
#define JUKE_CHANNEL 2
|
||||
#define JUKE_BOX 3
|
||||
#define JUKE_FALLOFF 4
|
||||
#define JUKE_SOUND 5
|
||||
|
||||
|
||||
SUBSYSTEM_DEF(jukeboxes)
|
||||
name = "Jukeboxes"
|
||||
wait = 5
|
||||
@@ -25,27 +41,41 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
var/channeltoreserve = pick(freejukeboxchannels)
|
||||
if(!channeltoreserve)
|
||||
return FALSE
|
||||
var/sound/song_to_init = sound(T.song_path)
|
||||
freejukeboxchannels -= channeltoreserve
|
||||
var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff)
|
||||
var/list/youvegotafreejukebox = list(T, channeltoreserve, jukebox, jukefalloff, song_to_init)
|
||||
|
||||
song_to_init.status = SOUND_MUTE
|
||||
song_to_init.environment = 7
|
||||
song_to_init.channel = channeltoreserve
|
||||
song_to_init.volume = 1
|
||||
song_to_init.falloff = jukefalloff
|
||||
song_to_init.echo = list(0, null, -10000, null, null, null, null, null, null, null, null, null, null, 1, 1, 1, null, null)
|
||||
|
||||
activejukeboxes.len++
|
||||
activejukeboxes[activejukeboxes.len] = youvegotafreejukebox
|
||||
|
||||
//Due to changes in later versions of 512, SOUND_UPDATE no longer properly plays audio when a file is defined in the sound datum. As such, we are now required to init the audio before we can actually do anything with it.
|
||||
//Downsides to this? This means that you can *only* hear the jukebox audio if you were present on the server when it started playing, and it means that it's now impossible to add loops to the jukebox track list.
|
||||
var/sound/song_to_init = sound(T.song_path)
|
||||
song_to_init.status = SOUND_MUTE
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(!M.client)
|
||||
continue
|
||||
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
|
||||
continue
|
||||
|
||||
M.playsound_local(M, null, 100, channel = youvegotafreejukebox[2], S = song_to_init)
|
||||
SEND_SOUND(M, song_to_init)
|
||||
return activejukeboxes.len
|
||||
|
||||
|
||||
//Updates jukebox by transferring to different object or modifying falloff.
|
||||
/datum/controller/subsystem/jukeboxes/proc/updatejukebox(IDtoupdate, obj/jukebox, jukefalloff)
|
||||
if(islist(activejukeboxes[IDtoupdate]))
|
||||
if(istype(jukebox))
|
||||
activejukeboxes[IDtoupdate][JUKE_BOX] = jukebox
|
||||
if(!isnull(jukefalloff))
|
||||
activejukeboxes[IDtoupdate][JUKE_FALLOFF] = jukefalloff
|
||||
|
||||
/datum/controller/subsystem/jukeboxes/proc/removejukebox(IDtoremove)
|
||||
if(islist(activejukeboxes[IDtoremove]))
|
||||
var/jukechannel = activejukeboxes[IDtoremove][2]
|
||||
var/jukechannel = activejukeboxes[IDtoremove][JUKE_CHANNEL]
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(!M.client)
|
||||
continue
|
||||
@@ -85,37 +115,74 @@ SUBSYSTEM_DEF(jukeboxes)
|
||||
if(!jukeinfo.len)
|
||||
stack_trace("Active jukebox without any associated metadata.")
|
||||
continue
|
||||
var/datum/track/juketrack = jukeinfo[1]
|
||||
var/datum/track/juketrack = jukeinfo[JUKE_TRACK]
|
||||
if(!istype(juketrack))
|
||||
stack_trace("Invalid jukebox track datum.")
|
||||
continue
|
||||
var/obj/jukebox = jukeinfo[3]
|
||||
var/obj/jukebox = jukeinfo[JUKE_BOX]
|
||||
if(!istype(jukebox))
|
||||
stack_trace("Nonexistant or invalid object associated with jukebox.")
|
||||
continue
|
||||
var/sound/song_played = sound(juketrack.song_path)
|
||||
|
||||
var/list/audible_zlevels = get_multiz_accessible_levels(jukebox.z) //TODO - for multiz refresh, this should use the cached zlevel connections var in SSMapping. For now this is fine!
|
||||
|
||||
var/sound/song_played = jukeinfo[JUKE_SOUND]
|
||||
var/turf/currentturf = get_turf(jukebox)
|
||||
var/area/currentarea = get_area(jukebox)
|
||||
var/list/hearerscache = hearers(7, jukebox)
|
||||
var/targetfalloff = jukeinfo[JUKE_FALLOFF]
|
||||
var/mixes = ((targetfalloff*250)-750)
|
||||
var/inrange
|
||||
var/pressure_factor
|
||||
|
||||
song_played.falloff = jukeinfo[4]
|
||||
|
||||
var/datum/gas_mixture/source_env = (istype(currentturf) ? currentturf.return_air() : null)
|
||||
var/datum/gas_mixture/hearer_env //We init this var outside of the mob loop for the sake of performance
|
||||
var/turf/hearerturf //ditto
|
||||
|
||||
var/source_pressure = (istype(source_env) ? source_env.return_pressure() : 0)
|
||||
|
||||
song_played.falloff = targetfalloff
|
||||
song_played.volume = min((targetfalloff * 50), 100)
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(!M.client)
|
||||
continue
|
||||
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS) || !M.can_hear())
|
||||
M.stop_sound_channel(jukeinfo[2])
|
||||
if(!(M.client.prefs.toggles & SOUND_INSTRUMENTS))
|
||||
M.stop_sound_channel(jukeinfo[JUKE_CHANNEL])
|
||||
continue
|
||||
|
||||
var/inrange = FALSE
|
||||
if(jukebox.z == M.z) //todo - expand this to work with mining planet z-levels when robust jukebox audio gets merged to master
|
||||
song_played.status = SOUND_UPDATE
|
||||
if(get_area(M) == currentarea)
|
||||
inrange = TRUE
|
||||
else if(M in hearerscache)
|
||||
inrange = TRUE
|
||||
else
|
||||
song_played.status = SOUND_MUTE | SOUND_UPDATE //Setting volume = 0 doesn't let the sound properties update at all, which is lame.
|
||||
M.playsound_local(currentturf, null, 100, channel = jukeinfo[2], S = song_played, envwet = (inrange ? -250 : 0), envdry = (inrange ? 0 : -10000))
|
||||
inrange = FALSE
|
||||
song_played.status = SOUND_MUTE | SOUND_UPDATE
|
||||
|
||||
if(source_pressure)
|
||||
hearerturf = get_turf(M)
|
||||
hearer_env = (istype(hearerturf) ? hearerturf.return_air() : null)
|
||||
if(istype(hearer_env))
|
||||
pressure_factor = min(source_pressure, hearer_env.return_pressure())
|
||||
|
||||
if(pressure_factor && targetfalloff && M.can_hear() && (M.z in audible_zlevels))
|
||||
if(get_area(M) == currentarea)
|
||||
inrange = TRUE
|
||||
else if(M in hearerscache)
|
||||
inrange = TRUE
|
||||
|
||||
song_played.x = (currentturf.x - M.x) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
|
||||
song_played.z = (currentturf.y - M.y) * SOUND_DEFAULT_DISTANCE_MULTIPLIER
|
||||
song_played.y = (((currentturf.z - M.z) * 10 * SOUND_DEFAULT_DISTANCE_MULTIPLIER) + ((currentturf.z < M.z) ? -5 : 5))
|
||||
|
||||
if(pressure_factor < ONE_ATMOSPHERE)
|
||||
song_played.volume = (min((targetfalloff * 50), 100) * max((pressure_factor - SOUND_MINIMUM_PRESSURE)/(ONE_ATMOSPHERE - SOUND_MINIMUM_PRESSURE), 1))
|
||||
|
||||
song_played.echo[1] = (inrange ? 0 : -10000)
|
||||
song_played.echo[3] = (inrange ? mixes : max(mixes, 0))
|
||||
song_played.status = SOUND_UPDATE
|
||||
SEND_SOUND(M, song_played)
|
||||
CHECK_TICK
|
||||
return
|
||||
|
||||
#undef JUKE_TRACK
|
||||
#undef JUKE_CHANNEL
|
||||
#undef JUKE_BOX
|
||||
#undef JUKE_FALLOFF
|
||||
#undef JUKE_SOUND
|
||||
|
||||
@@ -164,8 +164,8 @@ SUBSYSTEM_DEF(ticker)
|
||||
to_chat(world, "<span class='boldnotice'>Welcome to [station_name()]!</span>")
|
||||
send2chat("New round starting on [SSmapping.config.map_name]!", CONFIG_GET(string/chat_announce_new_game))
|
||||
current_state = GAME_STATE_PREGAME
|
||||
//Everyone who wants to be an observer is now spawned
|
||||
create_observers()
|
||||
SEND_SIGNAL(src, COMSIG_TICKER_ENTER_PREGAME)
|
||||
|
||||
fire()
|
||||
if(GAME_STATE_PREGAME)
|
||||
//lobby stats for statpanels
|
||||
@@ -203,6 +203,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
for(var/client/C in SSvote.voting)
|
||||
C << browse(null, "window=vote;can_close=0")
|
||||
SSvote.reset()
|
||||
SEND_SIGNAL(src, COMSIG_TICKER_ENTER_SETTING_UP)
|
||||
current_state = GAME_STATE_SETTING_UP
|
||||
Master.SetRunLevel(RUNLEVEL_SETUP)
|
||||
if(start_immediately)
|
||||
@@ -215,6 +216,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
start_at = world.time + (CONFIG_GET(number/lobby_countdown) * 10)
|
||||
timeLeft = null
|
||||
Master.SetRunLevel(RUNLEVEL_LOBBY)
|
||||
SEND_SIGNAL(src, COMSIG_TICKER_ERROR_SETTING_UP)
|
||||
|
||||
if(GAME_STATE_PLAYING)
|
||||
mode.process(wait * 0.1)
|
||||
@@ -378,8 +380,6 @@ SUBSYSTEM_DEF(ticker)
|
||||
LAZYOR(player.client.prefs.characters_joined_as, player.new_character.real_name)
|
||||
else
|
||||
stack_trace("WARNING: Either a player did not have a new_character, did not have a client, or did not have preferences. This is VERY bad.")
|
||||
else
|
||||
player.new_player_panel()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/collect_minds()
|
||||
@@ -612,7 +612,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
var/list/ded = SSblackbox.first_death
|
||||
if(ded.len)
|
||||
var/last_words = ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""
|
||||
news_message += "\nNT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
|
||||
news_message += "\nNT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died.\nTheir name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]"
|
||||
else
|
||||
news_message += "\nNT Sanctioned Psykers proudly confirm reports that nobody died this shift!"
|
||||
|
||||
@@ -633,13 +633,6 @@ SUBSYSTEM_DEF(ticker)
|
||||
else
|
||||
timeLeft = newtime
|
||||
|
||||
//Everyone who wanted to be an observer gets made one now
|
||||
/datum/controller/subsystem/ticker/proc/create_observers()
|
||||
for(var/mob/dead/new_player/player in GLOB.player_list)
|
||||
if(player.ready == PLAYER_READY_TO_OBSERVE && player.mind)
|
||||
//Break chain since this has a sleep input in it
|
||||
addtimer(CALLBACK(player, /mob/dead/new_player.proc/make_me_an_observer), 1)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/load_mode()
|
||||
var/mode = trim(file2text("data/mode.txt"))
|
||||
if(mode)
|
||||
|
||||
@@ -10,7 +10,7 @@ SUBSYSTEM_DEF(title)
|
||||
|
||||
/datum/controller/subsystem/title/Initialize()
|
||||
if(file_path && icon)
|
||||
return ..()
|
||||
return
|
||||
|
||||
if(fexists("data/previous_title.dat"))
|
||||
var/previous_path = file2text("data/previous_title.dat")
|
||||
@@ -31,13 +31,16 @@ SUBSYSTEM_DEF(title)
|
||||
if(length(title_screens))
|
||||
file_path = "[global.config.directory]/title_screens/images/[pick(title_screens)]"
|
||||
|
||||
if(!file_path || !fexists(file_path))
|
||||
file_path = "icons/default_title.dmi"
|
||||
if(!file_path)
|
||||
file_path = "icons/runtime/default_title.dmi"
|
||||
|
||||
if(fexists(file_path))
|
||||
icon = new(fcopy_rsc(file_path))
|
||||
if(splash_turf)
|
||||
splash_turf.icon = icon
|
||||
ASSERT(fexists(file_path))
|
||||
|
||||
icon = new(fcopy_rsc(file_path))
|
||||
|
||||
if(splash_turf)
|
||||
splash_turf.icon = icon
|
||||
splash_turf.handle_generic_titlescreen_sizes()
|
||||
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
new_dna.species = new species.type
|
||||
new_dna.species.say_mod = species.say_mod
|
||||
new_dna.species.exotic_blood_color = species.exotic_blood_color //it can change from the default value
|
||||
new_dna.species.exotic_blood_blend_mode = species.exotic_blood_blend_mode
|
||||
new_dna.species.eye_type = species.eye_type
|
||||
new_dna.species.limbs_id = species.limbs_id || species.id
|
||||
new_dna.real_name = real_name
|
||||
|
||||
@@ -76,10 +76,10 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
if(examine_full_view)
|
||||
examine_list += "[msg]"
|
||||
return
|
||||
if(length_char(msg) <= 40)
|
||||
if(length_char(msg) <= MAX_FLAVOR_PREVIEW_LEN)
|
||||
examine_list += "<span class='notice'>[msg]</span>"
|
||||
else
|
||||
examine_list += "<span class='notice'>[copytext_char(msg, 1, 37)]... <a href='?src=[REF(src)];show_flavor=[REF(target)]'>More...</span></a>"
|
||||
examine_list += "<span class='notice'>[copytext_char(msg, 1, (MAX_FLAVOR_PREVIEW_LEN - 3))]... <a href='?src=[REF(src)];show_flavor=[REF(target)]'>More...</span></a>"
|
||||
|
||||
/datum/element/flavor_text/Topic(href, href_list)
|
||||
. = ..()
|
||||
@@ -199,7 +199,7 @@ GLOBAL_LIST_EMPTY(mobs_with_editable_flavor_text) //et tu, hacky code
|
||||
if(ismob(target))
|
||||
add_verb(target, /mob/proc/set_pose)
|
||||
|
||||
/datum/element/flavor_Text/carbon/temporary/Detach(datum/source, force)
|
||||
/datum/element/flavor_text/carbon/temporary/Detach(datum/source, force)
|
||||
. = ..()
|
||||
if(ismob(source))
|
||||
remove_verb(source, /mob/proc/set_pose)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// And yes this does have to be in the constructor, BYOND ignores it if you set it as a normal var
|
||||
|
||||
// Helper similar to image()
|
||||
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE, color = "#FFFFFF")
|
||||
/proc/mutable_appearance(icon, icon_state = "", layer = FLOAT_LAYER, plane = FLOAT_PLANE, alpha = 255, appearance_flags = NONE, color = "#FFFFFF", blend_mode = BLEND_DEFAULT)
|
||||
var/mutable_appearance/MA = new()
|
||||
MA.icon = icon
|
||||
MA.icon_state = icon_state
|
||||
@@ -19,5 +19,6 @@
|
||||
MA.alpha = alpha
|
||||
MA.appearance_flags |= appearance_flags
|
||||
MA.color = color
|
||||
MA.blend_mode = blend_mode
|
||||
return MA
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
/// should we immediately call on_spawn or add a timer to trigger
|
||||
var/on_spawn_immediate = TRUE
|
||||
var/mob/living/quirk_holder
|
||||
var/processing_quirk = FALSE
|
||||
|
||||
/datum/quirk/New(mob/living/quirk_mob, spawn_effects)
|
||||
if(!quirk_mob || (human_only && !ishuman(quirk_mob)) || quirk_mob.has_quirk(type))
|
||||
@@ -25,7 +26,8 @@
|
||||
quirk_holder.roundstart_quirks += src
|
||||
if(mob_trait)
|
||||
ADD_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
|
||||
START_PROCESSING(SSquirks, src)
|
||||
if(processing_quirk)
|
||||
START_PROCESSING(SSquirks, src)
|
||||
add()
|
||||
if(spawn_effects)
|
||||
if(on_spawn_immediate)
|
||||
@@ -35,7 +37,8 @@
|
||||
addtimer(CALLBACK(src, .proc/post_add), 30)
|
||||
|
||||
/datum/quirk/Destroy()
|
||||
STOP_PROCESSING(SSquirks, src)
|
||||
if(processing_quirk)
|
||||
STOP_PROCESSING(SSquirks, src)
|
||||
remove()
|
||||
if(quirk_holder)
|
||||
to_chat(quirk_holder, lose_text)
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
mob_trait = TRAIT_JOLLY
|
||||
mood_quirk = TRUE
|
||||
medical_record_text = "Patient demonstrates constant euthymia irregular for environment. It's a bit much, to be honest."
|
||||
processing_quirk = TRUE
|
||||
|
||||
/datum/quirk/jolly/on_process()
|
||||
if(prob(0.05))
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
lose_text = "<span class='notice'>You no longer feel depressed.</span>" //if only it were that easy!
|
||||
medical_record_text = "Patient has a severe mood disorder, causing them to experience acute episodes of depression."
|
||||
mood_quirk = TRUE
|
||||
processing_quirk = TRUE
|
||||
|
||||
/datum/quirk/depression/on_process()
|
||||
if(prob(0.05))
|
||||
@@ -38,6 +39,7 @@
|
||||
medical_record_text = "Patient demonstrates an unnatural attachment to a family heirloom."
|
||||
var/obj/item/heirloom
|
||||
var/where
|
||||
processing_quirk = TRUE
|
||||
|
||||
GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
|
||||
@@ -102,6 +104,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
gain_text = "<span class='danger'>You feel smooth.</span>"
|
||||
lose_text = "<span class='notice'>You feel wrinkled again.</span>"
|
||||
medical_record_text = "Patient has a tumor in their brain that is slowly driving them to brain death."
|
||||
processing_quirk = TRUE
|
||||
|
||||
/datum/quirk/brainproblems/on_process()
|
||||
quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)
|
||||
@@ -129,25 +132,38 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
value = -1
|
||||
medical_record_text = "Patient demonstrates a fear of the dark. (Seriously?)"
|
||||
|
||||
/datum/quirk/nyctophobia/on_process()
|
||||
var/mob/living/carbon/human/H = quirk_holder
|
||||
if(H.dna.species.id in list("shadow", "nightmare"))
|
||||
return //we're tied with the dark, so we don't get scared of it; don't cleanse outright to avoid cheese
|
||||
var/turf/T = get_turf(quirk_holder)
|
||||
var/lums = T.get_lumcount()
|
||||
if(lums <= 0.2)
|
||||
if(quirk_holder.m_intent == MOVE_INTENT_RUN)
|
||||
addtimer(CALLBACK(src, .proc/recheck),2) //0.2 seconds of being in the dark
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
|
||||
else
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
|
||||
/datum/quirk/nyctophobia/add()
|
||||
RegisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
|
||||
|
||||
/datum/quirk/nyctophobia/proc/recheck()
|
||||
var/turf/T = get_turf(quirk_holder)
|
||||
var/lums = T.get_lumcount()
|
||||
if(lums <= 0.2) //check again, did they remain in the dark for 0.2 seconds?
|
||||
to_chat(quirk_holder, "<span class='warning'>Easy, easy, take it slow... you're in the dark...</span>")
|
||||
/datum/quirk/nyctophobia/remove()
|
||||
UnregisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED)
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
|
||||
|
||||
/// Called when the quirk holder moves. Updates the quirk holder's mood.
|
||||
/datum/quirk/nyctophobia/proc/on_holder_moved(mob/living/source, atom/old_loc, dir, forced)
|
||||
if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious())
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_holder = quirk_holder
|
||||
|
||||
if(human_holder.dna?.species.id in list(SPECIES_SHADOW, SPECIES_NIGHTMARE))
|
||||
return
|
||||
|
||||
if((human_holder.sight & SEE_TURFS) == SEE_TURFS)
|
||||
return
|
||||
|
||||
var/turf/holder_turf = get_turf(quirk_holder)
|
||||
|
||||
var/lums = holder_turf.get_lumcount()
|
||||
|
||||
if(lums > 0.2)
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
|
||||
return
|
||||
|
||||
if(quirk_holder.m_intent == MOVE_INTENT_RUN)
|
||||
to_chat(quirk_holder, span_warning("Easy, easy, take it slow... you're in the dark..."))
|
||||
quirk_holder.toggle_move_intent()
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
|
||||
|
||||
/datum/quirk/lightless
|
||||
name = "Light Sensitivity"
|
||||
@@ -157,6 +173,36 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
lose_text = "<span class='notice'>Enlightening.</span>"
|
||||
medical_record_text = "Despite my warnings, the patient refuses turn on the lights, only to end up rolling down a full flight of stairs and into the cellar."
|
||||
|
||||
/datum/quirk/lightless/add()
|
||||
RegisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
|
||||
|
||||
/datum/quirk/lightless/remove()
|
||||
UnregisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED)
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "brightlight")
|
||||
|
||||
/datum/quirk/lightless/proc/on_holder_moved(mob/living/source, atom/old_loc, dir, forced)
|
||||
if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious())
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/human_holder = quirk_holder
|
||||
|
||||
if(human_holder.dna?.species.id in list(SPECIES_SHADOW, SPECIES_NIGHTMARE))
|
||||
return
|
||||
|
||||
if((human_holder.sight & SEE_TURFS) == SEE_TURFS)
|
||||
return
|
||||
|
||||
var/turf/holder_turf = get_turf(quirk_holder)
|
||||
|
||||
var/lums = holder_turf.get_lumcount()
|
||||
|
||||
if(lums < 0.8)
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "brightlight")
|
||||
return
|
||||
|
||||
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "brightlight", /datum/mood_event/brightlight)
|
||||
|
||||
|
||||
/datum/quirk/lightless/on_process()
|
||||
var/turf/T = get_turf(quirk_holder)
|
||||
var/lums = T.get_lumcount()
|
||||
@@ -236,6 +282,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
gain_text = "<span class='userdanger'>...</span>"
|
||||
lose_text = "<span class='notice'>You feel in tune with the world again.</span>"
|
||||
medical_record_text = "Patient suffers from acute Reality Dissociation Syndrome and experiences vivid hallucinations."
|
||||
processing_quirk = TRUE
|
||||
|
||||
/datum/quirk/insanity/on_process()
|
||||
if(quirk_holder.reagents.has_reagent(/datum/reagent/toxin/mindbreaker))
|
||||
@@ -261,6 +308,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
lose_text = "<span class='notice'>You feel easier about talking again.</span>" //if only it were that easy!
|
||||
medical_record_text = "Patient is usually anxious in social encounters and prefers to avoid them."
|
||||
var/dumb_thing = TRUE
|
||||
processing_quirk = TRUE
|
||||
|
||||
/datum/quirk/social_anxiety/add()
|
||||
RegisterSignal(quirk_holder, COMSIG_MOB_EYECONTACT, .proc/eye_contact)
|
||||
@@ -425,3 +473,21 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
gain_text = "<span class='notice'>You can't smell anything!</span>"
|
||||
lose_text = "<span class='notice'>You can smell again!</span>"
|
||||
medical_record_text = "Patient suffers from anosmia and is incapable of smelling gases or particulates."
|
||||
|
||||
/datum/quirk/paper_skin
|
||||
name = "Paper Skin"
|
||||
desc = "Your flesh is weaker, resulting in receiving cuts more easily."
|
||||
value = -1
|
||||
mob_trait = TRAIT_PAPER_SKIN
|
||||
gain_text = "<span class='notice'>Your flesh feels weak!</span>"
|
||||
lose_text = "<span class='notice'>Your flesh feels more durable!</span>"
|
||||
medical_record_text = "Patient suffers from weak flesh, resulting in them receiving cuts far more easily."
|
||||
|
||||
/datum/quirk/glass_bones
|
||||
name = "Glass Bones"
|
||||
desc = "Your bones are far more brittle, and more vulnerable to breakage."
|
||||
value = -1
|
||||
mob_trait = TRAIT_GLASS_BONES
|
||||
gain_text = "<span class='notice'>Your bones feels weak!</span>"
|
||||
lose_text = "<span class='notice'>Your bones feels more durable!</span>"
|
||||
medical_record_text = "Patient suffers from brittle bones, resulting in them receiving breakages far more easily."
|
||||
|
||||
+13
-2
@@ -702,7 +702,7 @@
|
||||
var/blood_id = get_blood_id()
|
||||
if(!(blood_id in GLOB.blood_reagent_types))
|
||||
return
|
||||
return list("color" = BLOOD_COLOR_HUMAN, "ANIMAL DNA" = "Y-")
|
||||
return list("color" = BLOOD_COLOR_HUMAN, "blendmode" = BLEND_MULTIPLY, "ANIMAL DNA" = "Y-")
|
||||
|
||||
/mob/living/carbon/get_blood_dna_list()
|
||||
var/blood_id = get_blood_id()
|
||||
@@ -711,14 +711,16 @@
|
||||
var/list/blood_dna = list()
|
||||
if(dna)
|
||||
blood_dna["color"] = dna.species.exotic_blood_color //so when combined, the list grows with the number of colors
|
||||
blood_dna["blendmode"] = dna.species.exotic_blood_blend_mode
|
||||
blood_dna[dna.unique_enzymes] = dna.blood_type
|
||||
else
|
||||
blood_dna["color"] = BLOOD_COLOR_HUMAN
|
||||
blood_dna["blendmode"] = BLEND_MULTIPLY
|
||||
blood_dna["UNKNOWN DNA"] = "X*"
|
||||
return blood_dna
|
||||
|
||||
/mob/living/carbon/alien/get_blood_dna_list()
|
||||
return list("color" = BLOOD_COLOR_XENO, "UNKNOWN DNA" = "X*")
|
||||
return list("color" = BLOOD_COLOR_XENO, "blendmode" = BLEND_MULTIPLY, "UNKNOWN DNA" = "X*")
|
||||
|
||||
//to add a mob's dna info into an object's blood_DNA list.
|
||||
/atom/proc/transfer_mob_blood_dna(mob/living/L)
|
||||
@@ -737,6 +739,7 @@
|
||||
var/old = blood_DNA["color"]
|
||||
blood_DNA["color"] = BlendRGB(blood_DNA["color"], new_blood_dna["color"])
|
||||
changed = old != blood_DNA["color"]
|
||||
blood_DNA["blendmode"] = new_blood_dna["blendmode"]
|
||||
if(blood_DNA.len == old_length)
|
||||
return FALSE
|
||||
return changed
|
||||
@@ -756,6 +759,7 @@
|
||||
blood_DNA["color"] = blood_dna["color"]
|
||||
else
|
||||
blood_DNA["color"] = BlendRGB(blood_DNA["color"], blood_dna["color"])
|
||||
blood_DNA["blendmode"] = blood_dna["blendmode"]
|
||||
|
||||
//to add blood from a mob onto something, and transfer their dna info
|
||||
/atom/proc/add_mob_blood(mob/living/M)
|
||||
@@ -826,6 +830,11 @@
|
||||
/atom/proc/blood_DNA_to_color()
|
||||
return (blood_DNA && blood_DNA["color"]) || BLOOD_COLOR_HUMAN
|
||||
|
||||
/atom/proc/blood_DNA_to_blend()
|
||||
if(blood_DNA && !isnull(blood_DNA["blendmode"]))
|
||||
return blood_DNA["blendmode"]
|
||||
return BLEND_MULTIPLY
|
||||
|
||||
/atom/proc/clean_blood()
|
||||
. = blood_DNA? TRUE : FALSE
|
||||
blood_DNA = null
|
||||
@@ -1192,6 +1201,8 @@
|
||||
log_mecha(log_text)
|
||||
if(LOG_SHUTTLE)
|
||||
log_shuttle(log_text)
|
||||
if(LOG_ECON)
|
||||
log_econ(log_text)
|
||||
else
|
||||
stack_trace("Invalid individual logging type: [message_type]. Defaulting to [LOG_GAME] (LOG_GAME).")
|
||||
log_game(log_text)
|
||||
|
||||
@@ -312,6 +312,36 @@ Class Procs:
|
||||
|
||||
return TRUE // If we passed all of those checks, woohoo! We can interact with this machine.
|
||||
|
||||
/obj/machinery/proc/can_transact(obj/item/card/id/thecard, allowdepartment, silent)
|
||||
if(!istype(thecard))
|
||||
if(!silent)
|
||||
say("No card found.")
|
||||
return FALSE
|
||||
else if (!thecard.registered_account)
|
||||
if(!silent)
|
||||
say("No account found.")
|
||||
return FALSE
|
||||
else if(!allowdepartment && !thecard.registered_account.account_job)
|
||||
if(!silent)
|
||||
say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/proc/attempt_transact(obj/item/card/id/thecard, transaction_cost)
|
||||
if(!istype(thecard))
|
||||
return FALSE
|
||||
var/datum/bank_account/account = thecard.registered_account
|
||||
if(!istype(account))
|
||||
return FALSE
|
||||
|
||||
if(transaction_cost)
|
||||
if(!account.adjust_money(-transaction_cost))
|
||||
return FALSE
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
|
||||
if(D)
|
||||
D.adjust_money(transaction_cost)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/proc/check_nap_violations()
|
||||
if(!SSeconomy.full_ancap)
|
||||
return TRUE
|
||||
|
||||
@@ -6,17 +6,22 @@
|
||||
verb_say = "states"
|
||||
density = TRUE
|
||||
req_one_access = list(ACCESS_BAR, ACCESS_KITCHEN, ACCESS_HYDROPONICS, ACCESS_ENGINE, ACCESS_CARGO, ACCESS_THEATRE)
|
||||
payment_department = ACCOUNT_SRV
|
||||
var/active = FALSE
|
||||
var/list/rangers = list()
|
||||
var/stop = 0
|
||||
var/volume = 70
|
||||
var/datum/track/selection = null
|
||||
var/queuecost = PRICE_CHEAP //Set to -1 to make this jukebox require access for queueing
|
||||
var/datum/track/playing = null
|
||||
var/datum/track/selectedtrack = null
|
||||
var/list/queuedplaylist = list()
|
||||
var/queuecooldown //This var exists solely to prevent accidental repeats of John Mulaney's 'What's New Pussycat?' incident. Intentional, however......
|
||||
|
||||
/obj/machinery/jukebox/disco
|
||||
name = "radiant dance machine mark IV"
|
||||
desc = "The first three prototypes were discontinued after mass casualty incidents."
|
||||
icon_state = "disco"
|
||||
req_access = list(ACCESS_ENGINE)
|
||||
req_one_access = list(ACCESS_ENGINE)
|
||||
anchored = FALSE
|
||||
var/list/spotlights = list()
|
||||
var/list/sparkles = list()
|
||||
@@ -24,7 +29,7 @@
|
||||
/obj/machinery/jukebox/disco/indestructible
|
||||
name = "radiant dance machine mark V"
|
||||
desc = "Now redesigned with data gathered from the extensive disco and plasma research."
|
||||
req_access = null
|
||||
req_one_access = null
|
||||
anchored = TRUE
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
@@ -46,6 +51,16 @@
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/machinery/jukebox/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
queuecost = PRICE_FREE
|
||||
req_one_access = null
|
||||
to_chat(user, "<span class='notice'>You've bypassed [src]'s audio volume limiter, and enabled free play.</span>")
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/jukebox/update_icon_state()
|
||||
if(active)
|
||||
icon_state = "[initial(icon_state)]-active"
|
||||
@@ -56,7 +71,7 @@
|
||||
if(!anchored)
|
||||
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
|
||||
return UI_CLOSE
|
||||
if(!allowed(user) && !isobserver(user))
|
||||
if((queuecost < 0 && !allowed(user)) && !isobserver(user))
|
||||
to_chat(user,"<span class='warning'>Error: Access Denied.</span>")
|
||||
user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return UI_CLOSE
|
||||
@@ -77,18 +92,21 @@
|
||||
data["active"] = active
|
||||
data["songs"] = list()
|
||||
for(var/datum/track/S in SSjukeboxes.songs)
|
||||
var/list/track_data = list(
|
||||
name = S.song_name
|
||||
)
|
||||
var/list/track_data = list(name = S.song_name)
|
||||
data["songs"] += list(track_data)
|
||||
data["queued_tracks"] = list()
|
||||
for(var/datum/track/S in queuedplaylist)
|
||||
var/list/track_data = list(name = S.song_name)
|
||||
data["queued_tracks"] += list(track_data)
|
||||
data["track_selected"] = null
|
||||
data["track_length"] = null
|
||||
data["track_beat"] = null
|
||||
if(selection)
|
||||
data["track_selected"] = selection.song_name
|
||||
data["track_length"] = DisplayTimeText(selection.song_length)
|
||||
data["track_beat"] = selection.song_beat
|
||||
if(playing)
|
||||
data["track_selected"] = playing.song_name
|
||||
data["track_length"] = DisplayTimeText(playing.song_length)
|
||||
data["volume"] = volume
|
||||
data["is_emagged"] = (obj_flags & EMAGGED)
|
||||
data["cost_for_play"] = queuecost
|
||||
data["has_access"] = allowed(user)
|
||||
return data
|
||||
|
||||
/obj/machinery/jukebox/ui_act(action, list/params)
|
||||
@@ -100,57 +118,91 @@
|
||||
if("toggle")
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!active)
|
||||
if(stop > world.time)
|
||||
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
|
||||
return
|
||||
if(!allowed(usr))
|
||||
return
|
||||
if(!active && !playing)
|
||||
activate_music()
|
||||
START_PROCESSING(SSobj, src)
|
||||
return TRUE
|
||||
else
|
||||
stop = 0
|
||||
return TRUE
|
||||
if("select_track")
|
||||
if(active)
|
||||
to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>")
|
||||
return TRUE
|
||||
if("add_to_queue")
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(world.time < queuecooldown)
|
||||
return
|
||||
if(!istype(selectedtrack, /datum/track))
|
||||
return
|
||||
if(!allowed(usr) && queuecost)
|
||||
var/obj/item/card/id/C
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
C = L.get_idcard(TRUE)
|
||||
if(!can_transact(C))
|
||||
queuecooldown = world.time + (1 SECONDS)
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return
|
||||
if(!attempt_transact(C, queuecost))
|
||||
say("Insufficient funds.")
|
||||
queuecooldown = world.time + (1 SECONDS)
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return
|
||||
to_chat(usr, "<span class='notice'>You spend [queuecost] credits to queue [selectedtrack.song_name].</span>")
|
||||
log_econ("[queuecost] credits were inserted into [src] by [key_name(usr)] (ID: [C.registered_name]) to queue [selectedtrack.song_name].")
|
||||
queuedplaylist += selectedtrack
|
||||
if(active)
|
||||
say("[selectedtrack.song_name] has been added to the queue.")
|
||||
else if(!playing)
|
||||
activate_music()
|
||||
playsound(src, 'sound/machines/ping.ogg', 50, TRUE)
|
||||
queuecooldown = world.time + (3 SECONDS)
|
||||
return TRUE
|
||||
if("select_track")
|
||||
var/list/available = list()
|
||||
for(var/datum/track/S in SSjukeboxes.songs)
|
||||
available[S.song_name] = S
|
||||
var/selected = params["track"]
|
||||
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
|
||||
return
|
||||
selection = available[selected]
|
||||
selectedtrack = available[selected]
|
||||
return TRUE
|
||||
if("set_volume")
|
||||
if(!allowed(usr))
|
||||
return
|
||||
var/new_volume = params["volume"]
|
||||
if(new_volume == "reset")
|
||||
volume = initial(volume)
|
||||
return TRUE
|
||||
else if(new_volume == "min")
|
||||
volume = 0
|
||||
return TRUE
|
||||
else if(new_volume == "max")
|
||||
volume = 100
|
||||
return TRUE
|
||||
volume = ((obj_flags & EMAGGED) ? 210 : 100)
|
||||
else if(text2num(new_volume) != null)
|
||||
volume = text2num(new_volume)
|
||||
return TRUE
|
||||
volume = clamp(0, text2num(new_volume), ((obj_flags & EMAGGED) ? 210 : 100))
|
||||
var/wherejuke = SSjukeboxes.findjukeboxindex(src)
|
||||
if(wherejuke)
|
||||
SSjukeboxes.updatejukebox(wherejuke, jukefalloff = volume/35)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/jukebox/proc/activate_music()
|
||||
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
|
||||
if(playing || !queuedplaylist.len)
|
||||
return FALSE
|
||||
playing = queuedplaylist[1]
|
||||
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, playing, volume/35)
|
||||
if(jukeboxslottotake)
|
||||
active = TRUE
|
||||
update_icon()
|
||||
START_PROCESSING(SSobj, src)
|
||||
stop = world.time + selection.song_length
|
||||
stop = world.time + playing.song_length
|
||||
queuedplaylist.Cut(1, 2)
|
||||
say("Now playing: [playing.song_name]")
|
||||
playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, TRUE)
|
||||
return TRUE
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/machinery/jukebox/disco/activate_music()
|
||||
..()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
dance_setup()
|
||||
lights_spin()
|
||||
|
||||
@@ -243,7 +295,7 @@
|
||||
S.pixel_y = 7
|
||||
S.forceMove(get_turf(src))
|
||||
sleep(7)
|
||||
if(selection.song_name == "Engineering's Ultimate High-Energy Hustle")
|
||||
if(playing.song_name == "Engineering's Ultimate High-Energy Hustle")
|
||||
sleep(280)
|
||||
for(var/obj/reveal in sparkles)
|
||||
reveal.alpha = 255
|
||||
@@ -299,7 +351,7 @@
|
||||
continue
|
||||
if(prob(2)) // Unique effects for the dance floor that show up randomly to mix things up
|
||||
INVOKE_ASYNC(src, .proc/hierofunk)
|
||||
sleep(selection.song_beat)
|
||||
sleep(playing.song_beat)
|
||||
|
||||
#undef DISCO_INFENO_RANGE
|
||||
|
||||
@@ -431,6 +483,7 @@
|
||||
return
|
||||
SSjukeboxes.removejukebox(position)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
playing = null
|
||||
rangers = list()
|
||||
|
||||
/obj/machinery/jukebox/disco/dance_over()
|
||||
@@ -439,12 +492,21 @@
|
||||
QDEL_LIST(sparkles)
|
||||
|
||||
/obj/machinery/jukebox/process()
|
||||
if(active && world.time >= stop)
|
||||
active = FALSE
|
||||
dance_over()
|
||||
playsound(src,'sound/machines/terminal_off.ogg',50,1)
|
||||
update_icon()
|
||||
stop = world.time + 100
|
||||
if(active)
|
||||
if(world.time >= stop)
|
||||
active = FALSE
|
||||
dance_over()
|
||||
if(stop && queuedplaylist.len)
|
||||
activate_music()
|
||||
else
|
||||
playsound(src,'sound/machines/terminal_off.ogg',50,1)
|
||||
update_icon()
|
||||
playing = null
|
||||
stop = 0
|
||||
else if(volume > 140) // BOOM BOOM BOOM BOOM
|
||||
for(var/mob/living/carbon/C in hearers(round(volume/35), src)) // I WANT YOU IN MY ROOM
|
||||
if(istype(C)) // LETS SPEND THE NIGHT TOGETHER
|
||||
C.adjustEarDamage(max((((volume/35) - sqrt(get_dist(C, src) * 4)) - C.get_ear_protection())*0.1, 0)) // FROM NOW UNTIL FOREVER
|
||||
|
||||
|
||||
/obj/machinery/jukebox/disco/process()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "They look bloody and gruesome."
|
||||
icon_state = "gibbl5"
|
||||
layer = LOW_OBJ_LAYER
|
||||
blend_mode = BLEND_DEFAULT
|
||||
random_icon_states = list("gib1", "gib2", "gib3", "gib4", "gib5", "gib6")
|
||||
mergeable_decal = FALSE
|
||||
bloodiness = 0 //This isn't supposed to be bloody.
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "It's gooey. Perhaps it's the chef's cooking?"
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "floor1"
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7")
|
||||
blood_state = BLOOD_STATE_BLOOD
|
||||
bloodiness = BLOOD_AMOUNT_PER_DECAL
|
||||
@@ -33,16 +34,20 @@
|
||||
. = ..()
|
||||
if(!fixed_color)
|
||||
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
|
||||
blend_mode = blood_DNA_to_blend()
|
||||
|
||||
/obj/effect/decal/cleanable/blood/PersistenceSave(list/data)
|
||||
. = ..()
|
||||
data["color"] = color
|
||||
data["blendmode"] = blend_mode
|
||||
|
||||
/obj/effect/decal/cleanable/blood/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
if(data["color"])
|
||||
fixed_color = TRUE
|
||||
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
|
||||
if(data["blendmode"])
|
||||
blend_mode = data["blendmode"]
|
||||
name = "dried blood"
|
||||
desc = "Looks like it's been here a while. Eew"
|
||||
bloodiness = 0
|
||||
@@ -82,8 +87,8 @@
|
||||
/obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose
|
||||
name = "blood"
|
||||
icon = 'icons/effects/blood.dmi'
|
||||
icon_state = "ltrails_1"
|
||||
desc = "Your instincts say you shouldn't be following these."
|
||||
blend_mode = BLEND_MULTIPLY
|
||||
random_icon_states = null
|
||||
beauty = -50
|
||||
persistent = TRUE
|
||||
@@ -95,6 +100,7 @@
|
||||
. = ..()
|
||||
data["dir"] = dir
|
||||
data["color"] = color
|
||||
data["blendmode"] = blend_mode
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/PersistenceLoad(list/data)
|
||||
. = ..()
|
||||
@@ -103,11 +109,14 @@
|
||||
if(data["color"])
|
||||
fixed_color = TRUE
|
||||
add_atom_colour(data["color"], FIXED_COLOUR_PRIORITY)
|
||||
if(data["blendmode"])
|
||||
blend_mode = data["blendmode"]
|
||||
|
||||
/obj/effect/decal/cleanable/trail_holder/update_icon()
|
||||
. = ..()
|
||||
if(!fixed_color)
|
||||
add_atom_colour(blood_DNA_to_color(), FIXED_COLOUR_PRIORITY)
|
||||
blend_mode = blood_DNA_to_blend()
|
||||
|
||||
/obj/effect/cleanable/trail_holder/Initialize(mapload)
|
||||
. = ..()
|
||||
|
||||
+5
-2
@@ -111,12 +111,15 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
|
||||
|
||||
/mob/proc/playsound_local(turf/turf_source, soundin, vol as num, vary, frequency, falloff_exponent = SOUND_FALLOFF_EXPONENT, channel = 0, pressure_affected = TRUE, sound/S, max_distance,
|
||||
falloff_distance = SOUND_DEFAULT_FALLOFF_DISTANCE, distance_multiplier = SOUND_DEFAULT_DISTANCE_MULTIPLIER, envwet = -10000, envdry = 0)
|
||||
if(!client || !can_hear())
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(!S)
|
||||
S = sound(get_sfx(soundin))
|
||||
|
||||
if(!can_hear() && !(S.status & SOUND_UPDATE)) //This is primarily to make sure sound updates still go through when a spaceman's deaf
|
||||
return
|
||||
|
||||
S.wait = 0 //No queue
|
||||
S.channel = channel || SSsounds.random_available_channel()
|
||||
S.volume = vol
|
||||
@@ -173,7 +176,7 @@ distance_multiplier - Can be used to multiply the distance at which the sound is
|
||||
var/dz = turf_source.y - T.y // Hearing from infront/behind
|
||||
S.z = dz * distance_multiplier
|
||||
var/dy = (turf_source.z - T.z) * 5 * distance_multiplier // Hearing from above / below, multiplied by 5 because we assume height is further along coords.
|
||||
S.y = dy + 1
|
||||
S.y = dy + distance_multiplier
|
||||
|
||||
S.falloff = isnull(max_distance)? FALLOFF_SOUNDS : max_distance //use max_distance, else just use 1 as we are a direct sound so falloff isnt relevant.
|
||||
|
||||
|
||||
@@ -73,16 +73,26 @@
|
||||
|
||||
/turf/closed/indestructible/splashscreen
|
||||
name = "Space Station 13"
|
||||
icon = 'icons/blank_title.png'
|
||||
desc = null
|
||||
icon = 'icons/blanks/blank_title.png'
|
||||
icon_state = ""
|
||||
layer = FLY_LAYER
|
||||
plane = SPLASHSCREEN_PLANE
|
||||
bullet_bounce_sound = null
|
||||
|
||||
/turf/closed/indestructible/splashscreen/New()
|
||||
INITIALIZE_IMMEDIATE(/turf/closed/indestructible/splashscreen)
|
||||
|
||||
/turf/closed/indestructible/splashscreen/Initialize(mapload)
|
||||
. = ..()
|
||||
SStitle.splash_turf = src
|
||||
if(SStitle.icon)
|
||||
icon = SStitle.icon
|
||||
..()
|
||||
handle_generic_titlescreen_sizes()
|
||||
|
||||
///helper proc that will center the screen if the icon is changed to a generic width, to make admins have to fudge around with pixel_x less. returns null
|
||||
/turf/closed/indestructible/splashscreen/proc/handle_generic_titlescreen_sizes()
|
||||
var/icon/size_check = icon(SStitle.icon, icon_state)
|
||||
var/width = size_check.Width()
|
||||
pixel_x = (672 - width) * 0.5 //The title screen is mapped with the expectation that it's 672x480. Should probably turn the title screen size into a define some time!
|
||||
|
||||
/turf/closed/indestructible/splashscreen/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
@@ -90,7 +100,13 @@
|
||||
switch(var_name)
|
||||
if(NAMEOF(src, icon))
|
||||
SStitle.icon = icon
|
||||
handle_generic_titlescreen_sizes()
|
||||
|
||||
/turf/closed/indestructible/start_area
|
||||
name = null
|
||||
desc = null
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
|
||||
/turf/closed/indestructible/riveted
|
||||
icon = 'icons/turf/walls/riveted.dmi'
|
||||
icon_state = "riveted"
|
||||
|
||||
@@ -117,6 +117,7 @@ GLOBAL_LIST(topic_status_cache)
|
||||
GLOB.world_asset_log = "[GLOB.log_directory]/asset.log"
|
||||
GLOB.world_attack_log = "[GLOB.log_directory]/attack.log"
|
||||
GLOB.world_victim_log = "[GLOB.log_directory]/victim.log"
|
||||
GLOB.world_econ_log = "[GLOB.log_directory]/econ.log"
|
||||
GLOB.world_pda_log = "[GLOB.log_directory]/pda.log"
|
||||
GLOB.world_telecomms_log = "[GLOB.log_directory]/telecomms.log"
|
||||
GLOB.world_manifest_log = "[GLOB.log_directory]/manifest.log"
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
linked_organ = null
|
||||
. = ..()
|
||||
|
||||
/obj/item/organ/genital/on_life()
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/proc/set_aroused_state(new_state,cause = "manual toggle")
|
||||
if(!(genital_flags & GENITAL_CAN_AROUSE))
|
||||
return FALSE
|
||||
|
||||
@@ -15,12 +15,6 @@
|
||||
var/prev_size //former size value, to allow update_size() to early return should be there no significant changes.
|
||||
layer_index = BUTT_LAYER_INDEX
|
||||
|
||||
/obj/item/organ/genital/butt/on_life()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/butt/modify_size(modifier, min = -INFINITY, max = BUTT_SIZE_MAX)
|
||||
var/new_value = clamp(size_cached + modifier, min, max)
|
||||
if(new_value == size_cached)
|
||||
|
||||
@@ -69,6 +69,19 @@
|
||||
fire_products = FIRE_PRODUCT_PLASMA
|
||||
enthalpy = FIRE_PLASMA_ENERGY_RELEASED // 3000000, 3 megajoules, 3000 kj
|
||||
|
||||
/datum/gas/nitrous_oxide
|
||||
id = GAS_NITROUS
|
||||
specific_heat = 40
|
||||
name = "Nitrous Oxide"
|
||||
gas_overlay = "nitrous_oxide"
|
||||
moles_visible = MOLES_GAS_VISIBLE * 2
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fire_products = list(GAS_N2 = 1)
|
||||
oxidation_rate = 0.5
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST + 100
|
||||
enthalpy = 81600
|
||||
heat_resistance = 6
|
||||
|
||||
/datum/gas/water_vapor
|
||||
id = GAS_H2O
|
||||
specific_heat = 40
|
||||
@@ -82,18 +95,23 @@
|
||||
powermix = 1
|
||||
breath_reagent = /datum/reagent/water
|
||||
|
||||
/datum/gas/nitrous_oxide
|
||||
id = GAS_NITROUS
|
||||
specific_heat = 40
|
||||
name = "Nitrous Oxide"
|
||||
gas_overlay = "nitrous_oxide"
|
||||
moles_visible = MOLES_GAS_VISIBLE * 2
|
||||
flags = GAS_FLAG_DANGEROUS
|
||||
fire_products = list(GAS_N2 = 1)
|
||||
oxidation_rate = 0.5
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST + 100
|
||||
enthalpy = 81600
|
||||
heat_resistance = 6
|
||||
|
||||
/datum/gas/pluoxium
|
||||
id = GAS_PLUOXIUM
|
||||
specific_heat = 80
|
||||
name = "Pluoxium"
|
||||
fusion_power = 10
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 25 // it is VERY stable
|
||||
oxidation_rate = 8 // when it can oxidize, it can oxidize a LOT
|
||||
enthalpy = -2000000 // but it reduces the heat output a great deal (plasma fires add 3000000 per mole)
|
||||
powermix = -1
|
||||
heat_penalty = -1
|
||||
transmit_modifier = -5
|
||||
heat_resistance = 3
|
||||
price = 6
|
||||
|
||||
/datum/gas/pluoxium/generate_TLV()
|
||||
return new/datum/tlv(-1, -1, 5, 6)
|
||||
|
||||
/datum/gas/tritium
|
||||
id = GAS_TRITIUM
|
||||
@@ -111,6 +129,7 @@
|
||||
fire_burn_rate = 2
|
||||
fire_radiation_released = 50 // arbitrary number, basically 60 moles of trit burning will just barely start to harm you
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
|
||||
price = 7
|
||||
|
||||
/datum/gas/nitric_oxide
|
||||
id = GAS_NITRIC
|
||||
@@ -134,6 +153,7 @@
|
||||
fire_products = list(GAS_N2 = 0.5)
|
||||
enthalpy = 33200
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST - 50
|
||||
price = 3
|
||||
|
||||
/datum/gas/hypernoblium
|
||||
id = GAS_HYPERNOB
|
||||
@@ -141,6 +161,7 @@
|
||||
name = "Hyper-noblium"
|
||||
gas_overlay = "freon"
|
||||
moles_visible = MOLES_GAS_VISIBLE
|
||||
price = 50
|
||||
|
||||
/datum/gas/hydrogen
|
||||
id = GAS_HYDROGEN
|
||||
@@ -168,6 +189,7 @@
|
||||
enthalpy = FIRE_CARBON_ENERGY_RELEASED // it is a mystery
|
||||
transmit_modifier = -2
|
||||
radioactivity_modifier = 5
|
||||
price = 3
|
||||
|
||||
/datum/gas/stimulum
|
||||
id = GAS_STIMULUM
|
||||
@@ -176,22 +198,7 @@
|
||||
odor_strength = 10
|
||||
name = "Stimulum"
|
||||
fusion_power = 7
|
||||
|
||||
/datum/gas/pluoxium
|
||||
id = GAS_PLUOXIUM
|
||||
specific_heat = 80
|
||||
name = "Pluoxium"
|
||||
fusion_power = 10
|
||||
oxidation_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST * 25 // it is VERY stable
|
||||
oxidation_rate = 8 // when it can oxidize, it can oxidize a LOT
|
||||
enthalpy = -2000000 // but it reduces the heat output a great deal (plasma fires add 3000000 per mole)
|
||||
powermix = -1
|
||||
heat_penalty = -1
|
||||
transmit_modifier = -5
|
||||
heat_resistance = 3
|
||||
|
||||
/datum/gas/pluoxium/generate_TLV()
|
||||
return new/datum/tlv(-1, -1, 5, 6)
|
||||
price = 25
|
||||
|
||||
/datum/gas/miasma
|
||||
id = GAS_MIASMA
|
||||
@@ -202,6 +209,7 @@
|
||||
name = "Miasma"
|
||||
gas_overlay = "miasma"
|
||||
moles_visible = MOLES_GAS_VISIBLE * 60
|
||||
price = 2
|
||||
|
||||
/datum/gas/methane
|
||||
id = GAS_METHANE
|
||||
@@ -227,6 +235,7 @@
|
||||
)
|
||||
enthalpy = -74600
|
||||
fire_temperature = FIRE_MINIMUM_TEMPERATURE_TO_EXIST
|
||||
price = 1
|
||||
|
||||
/datum/gas/methyl_bromide
|
||||
id = GAS_METHYL_BROMIDE
|
||||
@@ -249,6 +258,7 @@
|
||||
enthalpy = -35400
|
||||
fire_burn_rate = 4 / 7 // oh no
|
||||
fire_temperature = 808 // its autoignition; it apparently doesn't spark readily, so i don't put it lower
|
||||
price = 2
|
||||
|
||||
/datum/gas/bromine
|
||||
id = GAS_BROMINE
|
||||
@@ -285,3 +295,4 @@
|
||||
powermix = -1
|
||||
transmit_modifier = -10
|
||||
heat_penalty = -10
|
||||
price = 10
|
||||
|
||||
@@ -43,6 +43,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
|
||||
var/list/TLVs = list()
|
||||
var/list/odors = list()
|
||||
var/list/odor_strengths = list()
|
||||
var/list/prices = list()
|
||||
|
||||
/datum/gas
|
||||
var/id = ""
|
||||
@@ -60,6 +61,7 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
|
||||
var/datum/reagent/breath_reagent = null // what breathing this adds to your reagents
|
||||
var/datum/reagent/breath_reagent_dangerous = null // what breathing this adds to your reagents IF it's above a danger threshold
|
||||
var/list/breath_alert_info = null // list for alerts that pop up when you have too much/not enough of something
|
||||
var/price = 0 // How much this gas is worth when sold, per mole.
|
||||
var/oxidation_temperature = null // temperature above which this gas is an oxidizer; null for none
|
||||
var/oxidation_rate = 1 // how many moles of this can oxidize how many moles of material
|
||||
var/fire_temperature = null // temperature above which gas may catch fire; null for none
|
||||
@@ -135,6 +137,8 @@ GLOBAL_LIST_INIT(nonreactive_gases, typecacheof(list(GAS_O2, GAS_N2, GAS_CO2, GA
|
||||
if(gas.odor)
|
||||
odor_strengths[g] = gas.odor_strength
|
||||
odors[g] = gas.odor
|
||||
if(gas.price)
|
||||
prices[g] = gas.price
|
||||
add_supermatter_properties(gas)
|
||||
_auxtools_register_gas(gas)
|
||||
if(done_initializing)
|
||||
|
||||
@@ -169,13 +169,9 @@
|
||||
/datum/export/large/gas_canister/get_cost(obj/O)
|
||||
var/obj/machinery/portable_atmospherics/canister/C = O
|
||||
var/worth = 10
|
||||
worth += C.air_contents.get_moles(GAS_BZ)*3
|
||||
worth += C.air_contents.get_moles(GAS_STIMULUM)*25
|
||||
worth += C.air_contents.get_moles(GAS_HYPERNOB)*20
|
||||
worth += C.air_contents.get_moles(GAS_MIASMA)*2
|
||||
worth += C.air_contents.get_moles(GAS_TRITIUM)*7
|
||||
worth += C.air_contents.get_moles(GAS_PLUOXIUM)*6
|
||||
worth += C.air_contents.get_moles(GAS_NITRYL)*10
|
||||
var/list/gas_prices = GLOB.gas_data.prices
|
||||
for(var/gas in C.air_contents.get_gases())
|
||||
worth += C.air_contents.get_moles(gas)*gas_prices[gas]
|
||||
return worth
|
||||
|
||||
|
||||
|
||||
@@ -135,10 +135,6 @@
|
||||
///Used in MouseDrag to preserve the last mouse-entered object.
|
||||
var/mouseObject = null
|
||||
var/mouseControlObject = null
|
||||
//Middle-mouse-button click dragtime control for aimbot exploit detection.
|
||||
var/middragtime = 0
|
||||
//Middle-mouse-button clicked object control for aimbot exploit detection.
|
||||
var/atom/middragatom
|
||||
|
||||
/// Messages currently seen by this client
|
||||
var/list/seen_messages
|
||||
|
||||
@@ -867,10 +867,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
return
|
||||
last_activity = world.time
|
||||
last_click = world.time
|
||||
var/ab = FALSE
|
||||
var/list/L = params2list(params)
|
||||
if (object && object == middragatom && L["left"])
|
||||
ab = max(0, 5 SECONDS-(world.time-middragtime)*0.1)
|
||||
|
||||
if(L["drag"])
|
||||
return
|
||||
|
||||
var/mcl = CONFIG_GET(number/minute_click_limit)
|
||||
if (!holder && !ignore_spam && mcl)
|
||||
var/minute = round(world.time, 600)
|
||||
@@ -879,20 +880,14 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if (minute != clicklimiter[CURRENT_MINUTE])
|
||||
clicklimiter[CURRENT_MINUTE] = minute
|
||||
clicklimiter[MINUTE_COUNT] = 0
|
||||
clicklimiter[MINUTE_COUNT] += 1+(ab)
|
||||
clicklimiter[MINUTE_COUNT] += 1
|
||||
if (clicklimiter[MINUTE_COUNT] > mcl)
|
||||
var/msg = "Your previous click was ignored because you've done too many in a minute."
|
||||
if (minute != clicklimiter[ADMINSWARNED_AT]) //only one admin message per-minute. (if they spam the admins can just boot/ban them)
|
||||
clicklimiter[ADMINSWARNED_AT] = minute
|
||||
|
||||
msg += " Administrators have been informed."
|
||||
if (ab)
|
||||
log_game("[key_name(src)] is using the middle click aimbot exploit")
|
||||
message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] is using the middle click aimbot exploit</span>")
|
||||
add_system_note("aimbot", "Is using the middle click aimbot exploit")
|
||||
log_click(object, location, control, params, src, "lockout (spam - minute ab c [ab] s [middragtime])", TRUE)
|
||||
else
|
||||
log_click(object, location, control, params, src, "lockout (spam - minute)", TRUE)
|
||||
log_click(object, location, control, params, src, "lockout (spam - minute)", TRUE)
|
||||
log_game("[key_name(src)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
|
||||
message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute click limit of [mcl] clicks in a given game minute")
|
||||
to_chat(src, "<span class='danger'>[msg]</span>")
|
||||
@@ -906,15 +901,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
|
||||
if (second != clicklimiter[CURRENT_SECOND])
|
||||
clicklimiter[CURRENT_SECOND] = second
|
||||
clicklimiter[SECOND_COUNT] = 0
|
||||
clicklimiter[SECOND_COUNT] += 1+(!!ab)
|
||||
clicklimiter[SECOND_COUNT] += 1
|
||||
if (clicklimiter[SECOND_COUNT] > scl)
|
||||
to_chat(src, "<span class='danger'>Your previous click was ignored because you've done too many in a second</span>")
|
||||
return
|
||||
|
||||
if(ab) //Citadel edit, things with stuff.
|
||||
log_click(object, location, control, params, src, "dropped (ab c [ab] s [middragtime])", TRUE)
|
||||
return
|
||||
|
||||
if(prefs.log_clicks)
|
||||
log_click(object, location, control, params, src, extra_info? "clicked ([extra_info])" : null)
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<table><tr><td width='340px' height='300px' valign='top'>"
|
||||
dat += "<h2>Flavor Text</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=flavor_text;task=input'><b>Set Examine Text</b></a><br>"
|
||||
if(length(features["flavor_text"]) <= 40)
|
||||
if(length(features["flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN)
|
||||
if(!length(features["flavor_text"]))
|
||||
dat += "\[...\]"
|
||||
else
|
||||
@@ -413,7 +413,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "[TextPreview(features["flavor_text"])]...<BR>"
|
||||
dat += "<h2>Silicon Flavor Text</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=silicon_flavor_text;task=input'><b>Set Silicon Examine Text</b></a><br>"
|
||||
if(length(features["silicon_flavor_text"]) <= 40)
|
||||
if(length(features["silicon_flavor_text"]) <= MAX_FLAVOR_PREVIEW_LEN)
|
||||
if(!length(features["silicon_flavor_text"]))
|
||||
dat += "\[...\]"
|
||||
else
|
||||
@@ -423,7 +423,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<h2>OOC notes</h2>"
|
||||
dat += "<a href='?_src_=prefs;preference=ooc_notes;task=input'><b>Set OOC notes</b></a><br>"
|
||||
var/ooc_notes_len = length(features["ooc_notes"])
|
||||
if(ooc_notes_len <= 40)
|
||||
if(ooc_notes_len <= MAX_FLAVOR_PREVIEW_LEN)
|
||||
if(!ooc_notes_len)
|
||||
dat += "\[...\]"
|
||||
else
|
||||
@@ -1714,7 +1714,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if("name")
|
||||
var/new_name = input(user, "Choose your character's name:", "Character Preference") as text|null
|
||||
if(new_name)
|
||||
new_name = reject_bad_name(new_name)
|
||||
new_name = reject_bad_name(new_name, allow_numbers = TRUE)
|
||||
if(new_name)
|
||||
real_name = new_name
|
||||
else
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// You do not need to raise this if you are adding new values that have sane defaults.
|
||||
// Only raise this value when changing the meaning/format/name/layout of an existing value
|
||||
// where you would want the updater procs below to run
|
||||
#define SAVEFILE_VERSION_MAX 53
|
||||
#define SAVEFILE_VERSION_MAX 54
|
||||
|
||||
/*
|
||||
SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn
|
||||
@@ -72,15 +72,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
var/job_engsec_med = 0
|
||||
var/job_engsec_low = 0
|
||||
|
||||
S["job_civilian_high"] >> job_civilian_high
|
||||
S["job_civilian_med"] >> job_civilian_med
|
||||
S["job_civilian_low"] >> job_civilian_low
|
||||
S["job_medsci_high"] >> job_medsci_high
|
||||
S["job_medsci_med"] >> job_medsci_med
|
||||
S["job_medsci_low"] >> job_medsci_low
|
||||
S["job_engsec_high"] >> job_engsec_high
|
||||
S["job_engsec_med"] >> job_engsec_med
|
||||
S["job_engsec_low"] >> job_engsec_low
|
||||
S["job_civilian_high"] >> job_civilian_high
|
||||
S["job_civilian_med"] >> job_civilian_med
|
||||
S["job_civilian_low"] >> job_civilian_low
|
||||
S["job_medsci_high"] >> job_medsci_high
|
||||
S["job_medsci_med"] >> job_medsci_med
|
||||
S["job_medsci_low"] >> job_medsci_low
|
||||
S["job_engsec_high"] >> job_engsec_high
|
||||
S["job_engsec_med"] >> job_engsec_med
|
||||
S["job_engsec_low"] >> job_engsec_low
|
||||
|
||||
//Can't use SSjob here since this happens right away on login
|
||||
for(var/job in subtypesof(/datum/job))
|
||||
@@ -173,10 +173,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
var/devourable
|
||||
var/feeding
|
||||
var/lickable
|
||||
S["digestable"] >> digestable
|
||||
S["devourable"] >> devourable
|
||||
S["feeding"] >> feeding
|
||||
S["lickable"] >> lickable
|
||||
S["digestable"] >> digestable
|
||||
S["devourable"] >> devourable
|
||||
S["feeding"] >> feeding
|
||||
S["lickable"] >> lickable
|
||||
if(digestable)
|
||||
vore_flags |= DIGESTABLE
|
||||
if(devourable)
|
||||
@@ -196,8 +196,8 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
features["taur"] = "Cow (Spotted)"
|
||||
|
||||
if(current_version < 31)
|
||||
S["wing_color"] >> features["wings_color"]
|
||||
S["horn_color"] >> features["horns_color"]
|
||||
S["wing_color"] >> features["wings_color"]
|
||||
S["horn_color"] >> features["horns_color"]
|
||||
|
||||
if(current_version < 33)
|
||||
features["flavor_text"] = html_encode(features["flavor_text"])
|
||||
@@ -346,6 +346,16 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
if(current_version < 53)
|
||||
parallax = PARALLAX_INSANE
|
||||
|
||||
// Some genius decided to make features update on the loading part, go figure.
|
||||
if(current_version < 54)
|
||||
var/old_silicon_flavor = S["silicon_feature_flavor_text"]
|
||||
if(length(old_silicon_flavor))
|
||||
features["feature_silicon_flavor_text"] = old_silicon_flavor
|
||||
var/old_flavor_text = S["flavor_text"]
|
||||
// If they have the old flavor text but also have the new one, i suppose the new one is more important.
|
||||
if(length(old_flavor_text) && !length(features["feature_flavor_text"]))
|
||||
features["feature_flavor_text"] = old_flavor_text
|
||||
|
||||
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
|
||||
if(!ckey)
|
||||
return
|
||||
@@ -380,70 +390,70 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
. = TRUE
|
||||
|
||||
//general preferences
|
||||
S["ooccolor"] >> ooccolor
|
||||
S["lastchangelog"] >> lastchangelog
|
||||
S["UI_style"] >> UI_style
|
||||
S["outline_color"] >> outline_color
|
||||
S["outline_enabled"] >> outline_enabled
|
||||
S["screentip_pref"] >> screentip_pref
|
||||
S["screentip_color"] >> screentip_color
|
||||
S["hotkeys"] >> hotkeys
|
||||
S["chat_on_map"] >> chat_on_map
|
||||
S["max_chat_length"] >> max_chat_length
|
||||
S["ooccolor"] >> ooccolor
|
||||
S["lastchangelog"] >> lastchangelog
|
||||
S["UI_style"] >> UI_style
|
||||
S["outline_color"] >> outline_color
|
||||
S["outline_enabled"] >> outline_enabled
|
||||
S["screentip_pref"] >> screentip_pref
|
||||
S["screentip_color"] >> screentip_color
|
||||
S["hotkeys"] >> hotkeys
|
||||
S["chat_on_map"] >> chat_on_map
|
||||
S["max_chat_length"] >> max_chat_length
|
||||
S["see_chat_non_mob"] >> see_chat_non_mob
|
||||
S["tgui_fancy"] >> tgui_fancy
|
||||
S["tgui_lock"] >> tgui_lock
|
||||
S["buttons_locked"] >> buttons_locked
|
||||
S["windowflash"] >> windowflashing
|
||||
S["tgui_fancy"] >> tgui_fancy
|
||||
S["tgui_lock"] >> tgui_lock
|
||||
S["buttons_locked"] >> buttons_locked
|
||||
S["windowflash"] >> windowflashing
|
||||
S["be_special"] >> be_special
|
||||
|
||||
|
||||
S["default_slot"] >> default_slot
|
||||
S["chat_toggles"] >> chat_toggles
|
||||
S["toggles"] >> toggles
|
||||
S["deadmin"] >> deadmin
|
||||
S["ghost_form"] >> ghost_form
|
||||
S["ghost_orbit"] >> ghost_orbit
|
||||
S["ghost_accs"] >> ghost_accs
|
||||
S["ghost_others"] >> ghost_others
|
||||
S["preferred_map"] >> preferred_map
|
||||
S["ignoring"] >> ignoring
|
||||
S["ghost_hud"] >> ghost_hud
|
||||
S["inquisitive_ghost"] >> inquisitive_ghost
|
||||
S["default_slot"] >> default_slot
|
||||
S["chat_toggles"] >> chat_toggles
|
||||
S["toggles"] >> toggles
|
||||
S["deadmin"] >> deadmin
|
||||
S["ghost_form"] >> ghost_form
|
||||
S["ghost_orbit"] >> ghost_orbit
|
||||
S["ghost_accs"] >> ghost_accs
|
||||
S["ghost_others"] >> ghost_others
|
||||
S["preferred_map"] >> preferred_map
|
||||
S["ignoring"] >> ignoring
|
||||
S["ghost_hud"] >> ghost_hud
|
||||
S["inquisitive_ghost"] >> inquisitive_ghost
|
||||
S["uses_glasses_colour"]>> uses_glasses_colour
|
||||
S["clientfps"] >> clientfps
|
||||
S["parallax"] >> parallax
|
||||
S["ambientocclusion"] >> ambientocclusion
|
||||
S["auto_fit_viewport"] >> auto_fit_viewport
|
||||
S["widescreenpref"] >> widescreenpref
|
||||
S["long_strip_menu"] >> long_strip_menu
|
||||
S["clientfps"] >> clientfps
|
||||
S["parallax"] >> parallax
|
||||
S["ambientocclusion"] >> ambientocclusion
|
||||
S["auto_fit_viewport"] >> auto_fit_viewport
|
||||
S["widescreenpref"] >> widescreenpref
|
||||
S["long_strip_menu"] >> long_strip_menu
|
||||
S["pixel_size"] >> pixel_size
|
||||
S["scaling_method"] >> scaling_method
|
||||
S["hud_toggle_flash"] >> hud_toggle_flash
|
||||
S["hud_toggle_color"] >> hud_toggle_color
|
||||
S["menuoptions"] >> menuoptions
|
||||
S["enable_tips"] >> enable_tips
|
||||
S["tip_delay"] >> tip_delay
|
||||
S["pda_style"] >> pda_style
|
||||
S["pda_color"] >> pda_color
|
||||
S["pda_skin"] >> pda_skin
|
||||
S["hud_toggle_flash"] >> hud_toggle_flash
|
||||
S["hud_toggle_color"] >> hud_toggle_color
|
||||
S["menuoptions"] >> menuoptions
|
||||
S["enable_tips"] >> enable_tips
|
||||
S["tip_delay"] >> tip_delay
|
||||
S["pda_style"] >> pda_style
|
||||
S["pda_color"] >> pda_color
|
||||
S["pda_skin"] >> pda_skin
|
||||
|
||||
// Custom hotkeys
|
||||
S["key_bindings"] >> key_bindings
|
||||
S["modless_key_bindings"] >> modless_key_bindings
|
||||
S["key_bindings"] >> key_bindings
|
||||
S["modless_key_bindings"] >> modless_key_bindings
|
||||
|
||||
//citadel code
|
||||
S["arousable"] >> arousable
|
||||
S["screenshake"] >> screenshake
|
||||
S["damagescreenshake"] >> damagescreenshake
|
||||
S["autostand"] >> autostand
|
||||
S["cit_toggles"] >> cit_toggles
|
||||
S["preferred_chaos"] >> preferred_chaos
|
||||
S["auto_ooc"] >> auto_ooc
|
||||
S["no_tetris_storage"] >> no_tetris_storage
|
||||
S["arousable"] >> arousable
|
||||
S["screenshake"] >> screenshake
|
||||
S["damagescreenshake"] >> damagescreenshake
|
||||
S["autostand"] >> autostand
|
||||
S["cit_toggles"] >> cit_toggles
|
||||
S["preferred_chaos"] >> preferred_chaos
|
||||
S["auto_ooc"] >> auto_ooc
|
||||
S["no_tetris_storage"] >> no_tetris_storage
|
||||
|
||||
//favorite outfits
|
||||
S["favorite_outfits"] >> favorite_outfits
|
||||
S["favorite_outfits"] >> favorite_outfits
|
||||
|
||||
var/list/parsed_favs = list()
|
||||
for(var/typetext in favorite_outfits)
|
||||
@@ -461,47 +471,47 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
update_preferences(needs_update, S) //needs_update = savefile_version if we need an update (positive integer)
|
||||
|
||||
//Sanitize
|
||||
ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor)))
|
||||
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
||||
UI_style = sanitize_inlist(UI_style, GLOB.available_ui_styles, GLOB.available_ui_styles[1])
|
||||
hotkeys = sanitize_integer(hotkeys, 0, 1, initial(hotkeys))
|
||||
chat_on_map = sanitize_integer(chat_on_map, 0, 1, initial(chat_on_map))
|
||||
ooccolor = sanitize_ooccolor(sanitize_hexcolor(ooccolor, 6, 1, initial(ooccolor)))
|
||||
lastchangelog = sanitize_text(lastchangelog, initial(lastchangelog))
|
||||
UI_style = sanitize_inlist(UI_style, GLOB.available_ui_styles, GLOB.available_ui_styles[1])
|
||||
hotkeys = sanitize_integer(hotkeys, 0, 1, initial(hotkeys))
|
||||
chat_on_map = sanitize_integer(chat_on_map, 0, 1, initial(chat_on_map))
|
||||
max_chat_length = sanitize_integer(max_chat_length, 1, CHAT_MESSAGE_MAX_LENGTH, initial(max_chat_length))
|
||||
see_chat_non_mob = sanitize_integer(see_chat_non_mob, 0, 1, initial(see_chat_non_mob))
|
||||
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
|
||||
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
|
||||
buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked))
|
||||
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
|
||||
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
|
||||
toggles = sanitize_integer(toggles, 0, 16777215, initial(toggles))
|
||||
deadmin = sanitize_integer(deadmin, 0, 16777215, initial(deadmin))
|
||||
clientfps = sanitize_integer(clientfps, 0, 1000, 0)
|
||||
parallax = sanitize_integer(parallax, PARALLAX_DISABLE, PARALLAX_INSANE, null)
|
||||
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
|
||||
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
|
||||
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
|
||||
long_strip_menu = sanitize_integer(long_strip_menu, 0, 1, initial(long_strip_menu))
|
||||
pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size))
|
||||
scaling_method = sanitize_text(scaling_method, initial(scaling_method))
|
||||
see_chat_non_mob = sanitize_integer(see_chat_non_mob, 0, 1, initial(see_chat_non_mob))
|
||||
tgui_fancy = sanitize_integer(tgui_fancy, 0, 1, initial(tgui_fancy))
|
||||
tgui_lock = sanitize_integer(tgui_lock, 0, 1, initial(tgui_lock))
|
||||
buttons_locked = sanitize_integer(buttons_locked, 0, 1, initial(buttons_locked))
|
||||
windowflashing = sanitize_integer(windowflashing, 0, 1, initial(windowflashing))
|
||||
default_slot = sanitize_integer(default_slot, 1, max_save_slots, initial(default_slot))
|
||||
toggles = sanitize_integer(toggles, 0, 16777215, initial(toggles))
|
||||
deadmin = sanitize_integer(deadmin, 0, 16777215, initial(deadmin))
|
||||
clientfps = sanitize_integer(clientfps, 0, 1000, 0)
|
||||
parallax = sanitize_integer(parallax, PARALLAX_DISABLE, PARALLAX_INSANE, null)
|
||||
ambientocclusion = sanitize_integer(ambientocclusion, 0, 1, initial(ambientocclusion))
|
||||
auto_fit_viewport = sanitize_integer(auto_fit_viewport, 0, 1, initial(auto_fit_viewport))
|
||||
widescreenpref = sanitize_integer(widescreenpref, 0, 1, initial(widescreenpref))
|
||||
long_strip_menu = sanitize_integer(long_strip_menu, 0, 1, initial(long_strip_menu))
|
||||
pixel_size = sanitize_integer(pixel_size, PIXEL_SCALING_AUTO, PIXEL_SCALING_3X, initial(pixel_size))
|
||||
scaling_method = sanitize_text(scaling_method, initial(scaling_method))
|
||||
hud_toggle_flash = sanitize_integer(hud_toggle_flash, 0, 1, initial(hud_toggle_flash))
|
||||
hud_toggle_color = sanitize_hexcolor(hud_toggle_color, 6, 1, initial(hud_toggle_color))
|
||||
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
|
||||
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
|
||||
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
|
||||
ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION)
|
||||
menuoptions = SANITIZE_LIST(menuoptions)
|
||||
be_special = SANITIZE_LIST(be_special)
|
||||
pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style))
|
||||
pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color))
|
||||
pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT)
|
||||
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
|
||||
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
|
||||
autostand = sanitize_integer(autostand, 0, 1, initial(autostand))
|
||||
cit_toggles = sanitize_integer(cit_toggles, 0, 16777215, initial(cit_toggles))
|
||||
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
|
||||
no_tetris_storage = sanitize_integer(no_tetris_storage, 0, 1, initial(no_tetris_storage))
|
||||
key_bindings = sanitize_islist(key_bindings, list())
|
||||
modless_key_bindings = sanitize_islist(modless_key_bindings, list())
|
||||
ghost_form = sanitize_inlist(ghost_form, GLOB.ghost_forms, initial(ghost_form))
|
||||
ghost_orbit = sanitize_inlist(ghost_orbit, GLOB.ghost_orbits, initial(ghost_orbit))
|
||||
ghost_accs = sanitize_inlist(ghost_accs, GLOB.ghost_accs_options, GHOST_ACCS_DEFAULT_OPTION)
|
||||
ghost_others = sanitize_inlist(ghost_others, GLOB.ghost_others_options, GHOST_OTHERS_DEFAULT_OPTION)
|
||||
menuoptions = SANITIZE_LIST(menuoptions)
|
||||
be_special = SANITIZE_LIST(be_special)
|
||||
pda_style = sanitize_inlist(pda_style, GLOB.pda_styles, initial(pda_style))
|
||||
pda_color = sanitize_hexcolor(pda_color, 6, 1, initial(pda_color))
|
||||
pda_skin = sanitize_inlist(pda_skin, GLOB.pda_reskins, PDA_SKIN_ALT)
|
||||
screenshake = sanitize_integer(screenshake, 0, 800, initial(screenshake))
|
||||
damagescreenshake = sanitize_integer(damagescreenshake, 0, 2, initial(damagescreenshake))
|
||||
autostand = sanitize_integer(autostand, 0, 1, initial(autostand))
|
||||
cit_toggles = sanitize_integer(cit_toggles, 0, 16777215, initial(cit_toggles))
|
||||
auto_ooc = sanitize_integer(auto_ooc, 0, 1, initial(auto_ooc))
|
||||
no_tetris_storage = sanitize_integer(no_tetris_storage, 0, 1, initial(no_tetris_storage))
|
||||
key_bindings = sanitize_islist(key_bindings, list())
|
||||
modless_key_bindings = sanitize_islist(modless_key_bindings, list())
|
||||
favorite_outfits = SANITIZE_LIST(favorite_outfits)
|
||||
|
||||
verify_keybindings_valid() // one of these days this will runtime and you'll be glad that i put it in a different proc so no one gets their saves wiped
|
||||
@@ -663,7 +673,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
//Species
|
||||
var/species_id
|
||||
S["species"] >> species_id
|
||||
S["species"] >> species_id
|
||||
if(species_id)
|
||||
if(species_id == "avian" || species_id == "aquatic")
|
||||
species_id = "mammal"
|
||||
@@ -678,63 +688,63 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
scars_index = rand(1,5) // WHY
|
||||
|
||||
//Character
|
||||
S["real_name"] >> real_name
|
||||
S["nameless"] >> nameless
|
||||
S["custom_species"] >> custom_species
|
||||
S["name_is_always_random"] >> be_random_name
|
||||
S["body_is_always_random"] >> be_random_body
|
||||
S["gender"] >> gender
|
||||
S["body_model"] >> features["body_model"]
|
||||
S["body_size"] >> features["body_size"]
|
||||
S["age"] >> age
|
||||
S["hair_color"] >> hair_color
|
||||
S["facial_hair_color"] >> facial_hair_color
|
||||
S["eye_type"] >> eye_type
|
||||
S["left_eye_color"] >> left_eye_color
|
||||
S["right_eye_color"] >> right_eye_color
|
||||
S["use_custom_skin_tone"] >> use_custom_skin_tone
|
||||
S["skin_tone"] >> skin_tone
|
||||
S["hair_style_name"] >> hair_style
|
||||
S["facial_style_name"] >> facial_hair_style
|
||||
S["grad_style"] >> grad_style
|
||||
S["grad_color"] >> grad_color
|
||||
S["underwear"] >> underwear
|
||||
S["undie_color"] >> undie_color
|
||||
S["undershirt"] >> undershirt
|
||||
S["shirt_color"] >> shirt_color
|
||||
S["socks"] >> socks
|
||||
S["socks_color"] >> socks_color
|
||||
S["backbag"] >> backbag
|
||||
S["jumpsuit_style"] >> jumpsuit_style
|
||||
S["uplink_loc"] >> uplink_spawn_loc
|
||||
S["custom_speech_verb"] >> custom_speech_verb
|
||||
S["custom_tongue"] >> custom_tongue
|
||||
S["additional_language"] >> additional_language
|
||||
S["feature_mcolor"] >> features["mcolor"]
|
||||
S["feature_lizard_tail"] >> features["tail_lizard"]
|
||||
S["feature_lizard_snout"] >> features["snout"]
|
||||
S["feature_lizard_horns"] >> features["horns"]
|
||||
S["feature_lizard_frills"] >> features["frills"]
|
||||
S["feature_lizard_spines"] >> features["spines"]
|
||||
S["feature_lizard_legs"] >> features["legs"]
|
||||
S["feature_human_tail"] >> features["tail_human"]
|
||||
S["feature_human_ears"] >> features["ears"]
|
||||
S["feature_deco_wings"] >> features["deco_wings"]
|
||||
S["feature_insect_wings"] >> features["insect_wings"]
|
||||
S["feature_insect_fluff"] >> features["insect_fluff"]
|
||||
S["feature_insect_markings"] >> features["insect_markings"]
|
||||
S["feature_arachnid_legs"] >> features["arachnid_legs"]
|
||||
S["feature_arachnid_spinneret"] >> features["arachnid_spinneret"]
|
||||
S["feature_arachnid_mandibles"] >> features["arachnid_mandibles"]
|
||||
S["feature_horns_color"] >> features["horns_color"]
|
||||
S["feature_wings_color"] >> features["wings_color"]
|
||||
S["feature_color_scheme"] >> features["color_scheme"]
|
||||
S["real_name"] >> real_name
|
||||
S["nameless"] >> nameless
|
||||
S["custom_species"] >> custom_species
|
||||
S["name_is_always_random"] >> be_random_name
|
||||
S["body_is_always_random"] >> be_random_body
|
||||
S["gender"] >> gender
|
||||
S["body_model"] >> features["body_model"]
|
||||
S["body_size"] >> features["body_size"]
|
||||
S["age"] >> age
|
||||
S["hair_color"] >> hair_color
|
||||
S["facial_hair_color"] >> facial_hair_color
|
||||
S["eye_type"] >> eye_type
|
||||
S["left_eye_color"] >> left_eye_color
|
||||
S["right_eye_color"] >> right_eye_color
|
||||
S["use_custom_skin_tone"] >> use_custom_skin_tone
|
||||
S["skin_tone"] >> skin_tone
|
||||
S["hair_style_name"] >> hair_style
|
||||
S["facial_style_name"] >> facial_hair_style
|
||||
S["grad_style"] >> grad_style
|
||||
S["grad_color"] >> grad_color
|
||||
S["underwear"] >> underwear
|
||||
S["undie_color"] >> undie_color
|
||||
S["undershirt"] >> undershirt
|
||||
S["shirt_color"] >> shirt_color
|
||||
S["socks"] >> socks
|
||||
S["socks_color"] >> socks_color
|
||||
S["backbag"] >> backbag
|
||||
S["jumpsuit_style"] >> jumpsuit_style
|
||||
S["uplink_loc"] >> uplink_spawn_loc
|
||||
S["custom_speech_verb"] >> custom_speech_verb
|
||||
S["custom_tongue"] >> custom_tongue
|
||||
S["additional_language"] >> additional_language
|
||||
S["feature_mcolor"] >> features["mcolor"]
|
||||
S["feature_lizard_tail"] >> features["tail_lizard"]
|
||||
S["feature_lizard_snout"] >> features["snout"]
|
||||
S["feature_lizard_horns"] >> features["horns"]
|
||||
S["feature_lizard_frills"] >> features["frills"]
|
||||
S["feature_lizard_spines"] >> features["spines"]
|
||||
S["feature_lizard_legs"] >> features["legs"]
|
||||
S["feature_human_tail"] >> features["tail_human"]
|
||||
S["feature_human_ears"] >> features["ears"]
|
||||
S["feature_deco_wings"] >> features["deco_wings"]
|
||||
S["feature_insect_wings"] >> features["insect_wings"]
|
||||
S["feature_insect_fluff"] >> features["insect_fluff"]
|
||||
S["feature_insect_markings"] >> features["insect_markings"]
|
||||
S["feature_arachnid_legs"] >> features["arachnid_legs"]
|
||||
S["feature_arachnid_spinneret"] >> features["arachnid_spinneret"]
|
||||
S["feature_arachnid_mandibles"] >> features["arachnid_mandibles"]
|
||||
S["feature_horns_color"] >> features["horns_color"]
|
||||
S["feature_wings_color"] >> features["wings_color"]
|
||||
S["feature_color_scheme"] >> features["color_scheme"]
|
||||
S["persistent_scars"] >> persistent_scars
|
||||
S["scars1"] >> scars_list["1"]
|
||||
S["scars2"] >> scars_list["2"]
|
||||
S["scars3"] >> scars_list["3"]
|
||||
S["scars4"] >> scars_list["4"]
|
||||
S["scars5"] >> scars_list["5"]
|
||||
S["scars1"] >> scars_list["1"]
|
||||
S["scars2"] >> scars_list["2"]
|
||||
S["scars3"] >> scars_list["3"]
|
||||
S["scars4"] >> scars_list["4"]
|
||||
S["scars5"] >> scars_list["5"]
|
||||
var/limbmodstr
|
||||
S["modified_limbs"] >> limbmodstr
|
||||
if(length(limbmodstr))
|
||||
@@ -756,100 +766,88 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
else
|
||||
tcg_decks = list()
|
||||
|
||||
S["chosen_limb_id"] >> chosen_limb_id
|
||||
S["hide_ckey"] >> hide_ckey //saved per-character
|
||||
S["chosen_limb_id"] >> chosen_limb_id
|
||||
S["hide_ckey"] >> hide_ckey //saved per-character
|
||||
|
||||
//Custom names
|
||||
for(var/custom_name_id in GLOB.preferences_custom_names)
|
||||
var/savefile_slot_name = custom_name_id + "_name" //TODO remove this
|
||||
S[savefile_slot_name] >> custom_names[custom_name_id]
|
||||
|
||||
S["preferred_ai_core_display"] >> preferred_ai_core_display
|
||||
S["prefered_security_department"] >> prefered_security_department
|
||||
S["preferred_ai_core_display"] >> preferred_ai_core_display
|
||||
S["prefered_security_department"] >> prefered_security_department
|
||||
|
||||
//Jobs
|
||||
S["joblessrole"] >> joblessrole
|
||||
S["joblessrole"] >> joblessrole
|
||||
|
||||
//Load prefs
|
||||
S["job_preferences"] >> job_preferences
|
||||
S["job_preferences"] >> job_preferences
|
||||
|
||||
//Quirks
|
||||
S["all_quirks"] >> all_quirks
|
||||
S["all_quirks"] >> all_quirks
|
||||
|
||||
//Records
|
||||
S["security_records"] >> security_records
|
||||
S["medical_records"] >> medical_records
|
||||
S["security_records"] >> security_records
|
||||
S["medical_records"] >> medical_records
|
||||
|
||||
//Citadel code
|
||||
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
|
||||
S["feature_mcolor2"] >> features["mcolor2"]
|
||||
S["feature_mcolor3"] >> features["mcolor3"]
|
||||
S["feature_genitals_use_skintone"] >> features["genitals_use_skintone"]
|
||||
S["feature_mcolor2"] >> features["mcolor2"]
|
||||
S["feature_mcolor3"] >> features["mcolor3"]
|
||||
// note safe json decode will runtime the first time it migrates but this is fine and it solves itself don't worry about it if you see it error
|
||||
features["mam_body_markings"] = safe_json_decode(S["feature_mam_body_markings"])
|
||||
S["feature_mam_tail"] >> features["mam_tail"]
|
||||
S["feature_mam_ears"] >> features["mam_ears"]
|
||||
S["feature_mam_tail_animated"] >> features["mam_tail_animated"]
|
||||
S["feature_taur"] >> features["taur"]
|
||||
S["feature_mam_snouts"] >> features["mam_snouts"]
|
||||
S["feature_meat"] >> features["meat_type"]
|
||||
S["feature_mam_tail"] >> features["mam_tail"]
|
||||
S["feature_mam_ears"] >> features["mam_ears"]
|
||||
S["feature_mam_tail_animated"] >> features["mam_tail_animated"]
|
||||
S["feature_taur"] >> features["taur"]
|
||||
S["feature_mam_snouts"] >> features["mam_snouts"]
|
||||
S["feature_meat"] >> features["meat_type"]
|
||||
//Xeno features
|
||||
S["feature_xeno_tail"] >> features["xenotail"]
|
||||
S["feature_xeno_dors"] >> features["xenodorsal"]
|
||||
S["feature_xeno_head"] >> features["xenohead"]
|
||||
S["feature_xeno_tail"] >> features["xenotail"]
|
||||
S["feature_xeno_dors"] >> features["xenodorsal"]
|
||||
S["feature_xeno_head"] >> features["xenohead"]
|
||||
//cock features
|
||||
S["feature_has_cock"] >> features["has_cock"]
|
||||
S["feature_cock_shape"] >> features["cock_shape"]
|
||||
S["feature_cock_color"] >> features["cock_color"]
|
||||
S["feature_cock_length"] >> features["cock_length"]
|
||||
S["feature_cock_diameter"] >> features["cock_diameter"]
|
||||
S["feature_cock_taur"] >> features["cock_taur"]
|
||||
S["feature_cock_visibility"] >> features["cock_visibility"]
|
||||
S["feature_has_cock"] >> features["has_cock"]
|
||||
S["feature_cock_shape"] >> features["cock_shape"]
|
||||
S["feature_cock_color"] >> features["cock_color"]
|
||||
S["feature_cock_length"] >> features["cock_length"]
|
||||
S["feature_cock_diameter"] >> features["cock_diameter"]
|
||||
S["feature_cock_taur"] >> features["cock_taur"]
|
||||
S["feature_cock_visibility"] >> features["cock_visibility"]
|
||||
//balls features
|
||||
S["feature_has_balls"] >> features["has_balls"]
|
||||
S["feature_balls_color"] >> features["balls_color"]
|
||||
S["feature_balls_shape"] >> features["balls_shape"]
|
||||
S["feature_balls_size"] >> features["balls_size"]
|
||||
S["feature_balls_visibility"] >> features["balls_visibility"]
|
||||
S["feature_has_balls"] >> features["has_balls"]
|
||||
S["feature_balls_color"] >> features["balls_color"]
|
||||
S["feature_balls_shape"] >> features["balls_shape"]
|
||||
S["feature_balls_size"] >> features["balls_size"]
|
||||
S["feature_balls_visibility"] >> features["balls_visibility"]
|
||||
//breasts features
|
||||
S["feature_has_breasts"] >> features["has_breasts"]
|
||||
S["feature_breasts_size"] >> features["breasts_size"]
|
||||
S["feature_breasts_shape"] >> features["breasts_shape"]
|
||||
S["feature_breasts_color"] >> features["breasts_color"]
|
||||
S["feature_breasts_producing"] >> features["breasts_producing"]
|
||||
S["feature_breasts_visibility"] >> features["breasts_visibility"]
|
||||
S["feature_has_breasts"] >> features["has_breasts"]
|
||||
S["feature_breasts_size"] >> features["breasts_size"]
|
||||
S["feature_breasts_shape"] >> features["breasts_shape"]
|
||||
S["feature_breasts_color"] >> features["breasts_color"]
|
||||
S["feature_breasts_producing"] >> features["breasts_producing"]
|
||||
S["feature_breasts_visibility"] >> features["breasts_visibility"]
|
||||
//vagina features
|
||||
S["feature_has_vag"] >> features["has_vag"]
|
||||
S["feature_vag_shape"] >> features["vag_shape"]
|
||||
S["feature_vag_color"] >> features["vag_color"]
|
||||
S["feature_vag_visibility"] >> features["vag_visibility"]
|
||||
S["feature_has_vag"] >> features["has_vag"]
|
||||
S["feature_vag_shape"] >> features["vag_shape"]
|
||||
S["feature_vag_color"] >> features["vag_color"]
|
||||
S["feature_vag_visibility"] >> features["vag_visibility"]
|
||||
//womb features
|
||||
S["feature_has_womb"] >> features["has_womb"]
|
||||
S["feature_has_womb"] >> features["has_womb"]
|
||||
//butt features
|
||||
S["feature_has_butt"] >> features["has_butt"]
|
||||
S["feature_butt_color"] >> features["butt_color"]
|
||||
S["feature_butt_size"] >> features["butt_size"]
|
||||
S["feature_butt_visibility"] >> features["butt_visibility"]
|
||||
S["feature_has_butt"] >> features["has_butt"]
|
||||
S["feature_butt_color"] >> features["butt_color"]
|
||||
S["feature_butt_size"] >> features["butt_size"]
|
||||
S["feature_butt_visibility"] >> features["butt_visibility"]
|
||||
|
||||
//flavor text
|
||||
//Let's make our players NOT cry desperately as we wipe their savefiles of their special snowflake texts:
|
||||
if((S["flavor_text"] != "") && (S["flavor_text"] != null) && S["flavor_text"]) //If old text isn't null and isn't "" but still exists.
|
||||
S["flavor_text"] >> features["flavor_text"] //Load old flavortext as current dna-based flavortext
|
||||
// Flavor texts, Made into a standard.
|
||||
S["feature_flavor_text"] >> features["flavor_text"]
|
||||
S["feature_silicon_flavor_text"] >> features["silicon_flavor_text"]
|
||||
S["feature_ooc_notes"] >> features["ooc_notes"]
|
||||
|
||||
WRITE_FILE(S["feature_flavor_text"], features["flavor_text"]) //Save it in our new type of flavor-text
|
||||
WRITE_FILE(S["flavor_text"] , "") //Remove old flavortext, completing the cut-and-paste into the new format.
|
||||
|
||||
else //We have no old flavortext, default to new
|
||||
S["feature_flavor_text"] >> features["flavor_text"]
|
||||
|
||||
|
||||
S["silicon_feature_flavor_text"] >> features["silicon_flavor_text"]
|
||||
|
||||
S["feature_ooc_notes"] >> features["ooc_notes"]
|
||||
S["silicon_flavor_text"] >> features["silicon_flavor_text"]
|
||||
|
||||
S["vore_flags"] >> vore_flags
|
||||
S["vore_taste"] >> vore_taste
|
||||
S["vore_smell"] >> vore_smell
|
||||
S["vore_flags"] >> vore_flags
|
||||
S["vore_taste"] >> vore_taste
|
||||
S["vore_smell"] >> vore_smell
|
||||
var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json"
|
||||
if(fexists(char_vr_path))
|
||||
var/list/json_from_file = json_decode(file2text(char_vr_path))
|
||||
@@ -869,69 +867,69 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
//Sanitize
|
||||
|
||||
real_name = reject_bad_name(real_name)
|
||||
gender = sanitize_gender(gender, TRUE, TRUE)
|
||||
real_name = reject_bad_name(real_name)
|
||||
gender = sanitize_gender(gender, TRUE, TRUE)
|
||||
features["body_model"] = sanitize_gender(features["body_model"], FALSE, FALSE, gender == FEMALE ? FEMALE : MALE)
|
||||
if(!real_name)
|
||||
real_name = random_unique_name(gender)
|
||||
custom_species = reject_bad_name(custom_species)
|
||||
real_name = random_unique_name(gender)
|
||||
custom_species = reject_bad_name(custom_species)
|
||||
for(var/custom_name_id in GLOB.preferences_custom_names)
|
||||
var/namedata = GLOB.preferences_custom_names[custom_name_id]
|
||||
custom_names[custom_name_id] = reject_bad_name(custom_names[custom_name_id],namedata["allow_numbers"])
|
||||
if(!custom_names[custom_name_id])
|
||||
custom_names[custom_name_id] = get_default_name(custom_name_id)
|
||||
|
||||
nameless = sanitize_integer(nameless, 0, 1, initial(nameless))
|
||||
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
|
||||
be_random_body = sanitize_integer(be_random_body, 0, 1, initial(be_random_body))
|
||||
nameless = sanitize_integer(nameless, 0, 1, initial(nameless))
|
||||
be_random_name = sanitize_integer(be_random_name, 0, 1, initial(be_random_name))
|
||||
be_random_body = sanitize_integer(be_random_body, 0, 1, initial(be_random_body))
|
||||
|
||||
hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_list)
|
||||
facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
underwear = sanitize_inlist(underwear, GLOB.underwear_list)
|
||||
undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list)
|
||||
undie_color = sanitize_hexcolor(undie_color, 6, FALSE, initial(undie_color))
|
||||
shirt_color = sanitize_hexcolor(shirt_color, 6, FALSE, initial(shirt_color))
|
||||
socks = sanitize_inlist(socks, GLOB.socks_list)
|
||||
socks_color = sanitize_hexcolor(socks_color, 6, FALSE, initial(socks_color))
|
||||
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
|
||||
hair_color = sanitize_hexcolor(hair_color, 6, FALSE)
|
||||
facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE)
|
||||
grad_style = sanitize_inlist(grad_style, GLOB.hair_gradients_list, "None")
|
||||
grad_color = sanitize_hexcolor(grad_color, 6, FALSE)
|
||||
eye_type = sanitize_inlist(eye_type, GLOB.eye_types, DEFAULT_EYES_TYPE)
|
||||
left_eye_color = sanitize_hexcolor(left_eye_color, 6, FALSE)
|
||||
right_eye_color = sanitize_hexcolor(right_eye_color, 6, FALSE)
|
||||
hair_style = sanitize_inlist(hair_style, GLOB.hair_styles_list)
|
||||
facial_hair_style = sanitize_inlist(facial_hair_style, GLOB.facial_hair_styles_list)
|
||||
underwear = sanitize_inlist(underwear, GLOB.underwear_list)
|
||||
undershirt = sanitize_inlist(undershirt, GLOB.undershirt_list)
|
||||
undie_color = sanitize_hexcolor(undie_color, 6, FALSE, initial(undie_color))
|
||||
shirt_color = sanitize_hexcolor(shirt_color, 6, FALSE, initial(shirt_color))
|
||||
socks = sanitize_inlist(socks, GLOB.socks_list)
|
||||
socks_color = sanitize_hexcolor(socks_color, 6, FALSE, initial(socks_color))
|
||||
age = sanitize_integer(age, AGE_MIN, AGE_MAX, initial(age))
|
||||
hair_color = sanitize_hexcolor(hair_color, 6, FALSE)
|
||||
facial_hair_color = sanitize_hexcolor(facial_hair_color, 6, FALSE)
|
||||
grad_style = sanitize_inlist(grad_style, GLOB.hair_gradients_list, "None")
|
||||
grad_color = sanitize_hexcolor(grad_color, 6, FALSE)
|
||||
eye_type = sanitize_inlist(eye_type, GLOB.eye_types, DEFAULT_EYES_TYPE)
|
||||
left_eye_color = sanitize_hexcolor(left_eye_color, 6, FALSE)
|
||||
right_eye_color = sanitize_hexcolor(right_eye_color, 6, FALSE)
|
||||
|
||||
var/static/allow_custom_skintones
|
||||
if(isnull(allow_custom_skintones))
|
||||
allow_custom_skintones = CONFIG_GET(flag/allow_custom_skintones)
|
||||
use_custom_skin_tone = allow_custom_skintones ? sanitize_integer(use_custom_skin_tone, FALSE, TRUE, initial(use_custom_skin_tone)) : FALSE
|
||||
use_custom_skin_tone = allow_custom_skintones ? sanitize_integer(use_custom_skin_tone, FALSE, TRUE, initial(use_custom_skin_tone)) : FALSE
|
||||
if(use_custom_skin_tone)
|
||||
skin_tone = sanitize_hexcolor(skin_tone, 6, TRUE, "#FFFFFF")
|
||||
skin_tone = sanitize_hexcolor(skin_tone, 6, TRUE, "#FFFFFF")
|
||||
else
|
||||
skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones - GLOB.nonstandard_skin_tones, initial(skin_tone))
|
||||
skin_tone = sanitize_inlist(skin_tone, GLOB.skin_tones - GLOB.nonstandard_skin_tones, initial(skin_tone))
|
||||
|
||||
features["horns_color"] = sanitize_hexcolor(features["horns_color"], 6, FALSE, "85615a")
|
||||
features["wings_color"] = sanitize_hexcolor(features["wings_color"], 6, FALSE, "FFFFFF")
|
||||
backbag = sanitize_inlist(backbag, GLOB.backbaglist, initial(backbag))
|
||||
jumpsuit_style = sanitize_inlist(jumpsuit_style, GLOB.jumpsuitlist, initial(jumpsuit_style))
|
||||
uplink_spawn_loc = sanitize_inlist(uplink_spawn_loc, GLOB.uplink_spawn_loc_list, initial(uplink_spawn_loc))
|
||||
features["mcolor"] = sanitize_hexcolor(features["mcolor"], 6, FALSE)
|
||||
features["tail_lizard"] = sanitize_inlist(features["tail_lizard"], GLOB.tails_list_lizard)
|
||||
features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human)
|
||||
features["snout"] = sanitize_inlist(features["snout"], GLOB.snouts_list)
|
||||
features["horns"] = sanitize_inlist(features["horns"], GLOB.horns_list)
|
||||
features["ears"] = sanitize_inlist(features["ears"], GLOB.ears_list)
|
||||
features["frills"] = sanitize_inlist(features["frills"], GLOB.frills_list)
|
||||
features["spines"] = sanitize_inlist(features["spines"], GLOB.spines_list)
|
||||
features["legs"] = sanitize_inlist(features["legs"], GLOB.legs_list, "Plantigrade")
|
||||
features["deco_wings"] = sanitize_inlist(features["deco_wings"], GLOB.deco_wings_list, "None")
|
||||
features["insect_fluff"] = sanitize_inlist(features["insect_fluff"], GLOB.insect_fluffs_list)
|
||||
features["insect_markings"] = sanitize_inlist(features["insect_markings"], GLOB.insect_markings_list, "None")
|
||||
features["insect_wings"] = sanitize_inlist(features["insect_wings"], GLOB.insect_wings_list)
|
||||
features["arachnid_legs"] = sanitize_inlist(features["arachnid_legs"], GLOB.arachnid_legs_list, "Plain")
|
||||
features["arachnid_spinneret"] = sanitize_inlist(features["arachnid_spinneret"], GLOB.arachnid_spinneret_list, "Plain")
|
||||
features["arachnid_mandibles"] = sanitize_inlist(features["arachnid_mandibles"], GLOB.arachnid_mandibles_list, "Plain")
|
||||
features["horns_color"] = sanitize_hexcolor(features["horns_color"], 6, FALSE, "85615a")
|
||||
features["wings_color"] = sanitize_hexcolor(features["wings_color"], 6, FALSE, "FFFFFF")
|
||||
backbag = sanitize_inlist(backbag, GLOB.backbaglist, initial(backbag))
|
||||
jumpsuit_style = sanitize_inlist(jumpsuit_style, GLOB.jumpsuitlist, initial(jumpsuit_style))
|
||||
uplink_spawn_loc = sanitize_inlist(uplink_spawn_loc, GLOB.uplink_spawn_loc_list, initial(uplink_spawn_loc))
|
||||
features["mcolor"] = sanitize_hexcolor(features["mcolor"], 6, FALSE)
|
||||
features["tail_lizard"] = sanitize_inlist(features["tail_lizard"], GLOB.tails_list_lizard)
|
||||
features["tail_human"] = sanitize_inlist(features["tail_human"], GLOB.tails_list_human)
|
||||
features["snout"] = sanitize_inlist(features["snout"], GLOB.snouts_list)
|
||||
features["horns"] = sanitize_inlist(features["horns"], GLOB.horns_list)
|
||||
features["ears"] = sanitize_inlist(features["ears"], GLOB.ears_list)
|
||||
features["frills"] = sanitize_inlist(features["frills"], GLOB.frills_list)
|
||||
features["spines"] = sanitize_inlist(features["spines"], GLOB.spines_list)
|
||||
features["legs"] = sanitize_inlist(features["legs"], GLOB.legs_list, "Plantigrade")
|
||||
features["deco_wings"] = sanitize_inlist(features["deco_wings"], GLOB.deco_wings_list, "None")
|
||||
features["insect_fluff"] = sanitize_inlist(features["insect_fluff"], GLOB.insect_fluffs_list)
|
||||
features["insect_markings"] = sanitize_inlist(features["insect_markings"], GLOB.insect_markings_list, "None")
|
||||
features["insect_wings"] = sanitize_inlist(features["insect_wings"], GLOB.insect_wings_list)
|
||||
features["arachnid_legs"] = sanitize_inlist(features["arachnid_legs"], GLOB.arachnid_legs_list, "Plain")
|
||||
features["arachnid_spinneret"] = sanitize_inlist(features["arachnid_spinneret"], GLOB.arachnid_spinneret_list, "Plain")
|
||||
features["arachnid_mandibles"] = sanitize_inlist(features["arachnid_mandibles"], GLOB.arachnid_mandibles_list, "Plain")
|
||||
|
||||
var/static/size_min
|
||||
if(!size_min)
|
||||
@@ -939,7 +937,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
var/static/size_max
|
||||
if(!size_max)
|
||||
size_max = CONFIG_GET(number/body_size_max)
|
||||
features["body_size"] = sanitize_num_clamp(features["body_size"], size_min, size_max, RESIZE_DEFAULT_SIZE, 0.01)
|
||||
features["body_size"] = sanitize_num_clamp(features["body_size"], size_min, size_max, RESIZE_DEFAULT_SIZE, 0.01)
|
||||
|
||||
var/static/list/B_sizes
|
||||
if(!B_sizes)
|
||||
@@ -963,33 +961,33 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
var/list/L = CONFIG_GET(keyed_list/safe_visibility_toggles)
|
||||
safe_visibilities = L.Copy()
|
||||
|
||||
features["breasts_size"] = sanitize_inlist(features["breasts_size"], B_sizes, BREASTS_SIZE_DEF)
|
||||
features["cock_length"] = sanitize_integer(features["cock_length"], min_D, max_D, COCK_SIZE_DEF)
|
||||
features["butt_size"] = sanitize_integer(features["butt_size"], min_B, max_B, BUTT_SIZE_DEF)
|
||||
features["breasts_shape"] = sanitize_inlist(features["breasts_shape"], GLOB.breasts_shapes_list, DEF_BREASTS_SHAPE)
|
||||
features["cock_shape"] = sanitize_inlist(features["cock_shape"], GLOB.cock_shapes_list, DEF_COCK_SHAPE)
|
||||
features["balls_shape"] = sanitize_inlist(features["balls_shape"], GLOB.balls_shapes_list, DEF_BALLS_SHAPE)
|
||||
features["vag_shape"] = sanitize_inlist(features["vag_shape"], GLOB.vagina_shapes_list, DEF_VAGINA_SHAPE)
|
||||
features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 6, FALSE, "FFFFFF")
|
||||
features["cock_color"] = sanitize_hexcolor(features["cock_color"], 6, FALSE, "FFFFFF")
|
||||
features["balls_color"] = sanitize_hexcolor(features["balls_color"], 6, FALSE, "FFFFFF")
|
||||
features["vag_color"] = sanitize_hexcolor(features["vag_color"], 6, FALSE, "FFFFFF")
|
||||
features["breasts_visibility"] = sanitize_inlist(features["breasts_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["cock_visibility"] = sanitize_inlist(features["cock_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["balls_visibility"] = sanitize_inlist(features["balls_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["vag_visibility"] = sanitize_inlist(features["vag_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["butt_visibility"] = sanitize_inlist(features["butt_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["breasts_size"] = sanitize_inlist(features["breasts_size"], B_sizes, BREASTS_SIZE_DEF)
|
||||
features["cock_length"] = sanitize_integer(features["cock_length"], min_D, max_D, COCK_SIZE_DEF)
|
||||
features["butt_size"] = sanitize_integer(features["butt_size"], min_B, max_B, BUTT_SIZE_DEF)
|
||||
features["breasts_shape"] = sanitize_inlist(features["breasts_shape"], GLOB.breasts_shapes_list, DEF_BREASTS_SHAPE)
|
||||
features["cock_shape"] = sanitize_inlist(features["cock_shape"], GLOB.cock_shapes_list, DEF_COCK_SHAPE)
|
||||
features["balls_shape"] = sanitize_inlist(features["balls_shape"], GLOB.balls_shapes_list, DEF_BALLS_SHAPE)
|
||||
features["vag_shape"] = sanitize_inlist(features["vag_shape"], GLOB.vagina_shapes_list, DEF_VAGINA_SHAPE)
|
||||
features["breasts_color"] = sanitize_hexcolor(features["breasts_color"], 6, FALSE, "FFFFFF")
|
||||
features["cock_color"] = sanitize_hexcolor(features["cock_color"], 6, FALSE, "FFFFFF")
|
||||
features["balls_color"] = sanitize_hexcolor(features["balls_color"], 6, FALSE, "FFFFFF")
|
||||
features["vag_color"] = sanitize_hexcolor(features["vag_color"], 6, FALSE, "FFFFFF")
|
||||
features["breasts_visibility"] = sanitize_inlist(features["breasts_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["cock_visibility"] = sanitize_inlist(features["cock_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["balls_visibility"] = sanitize_inlist(features["balls_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["vag_visibility"] = sanitize_inlist(features["vag_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
features["butt_visibility"] = sanitize_inlist(features["butt_visibility"], safe_visibilities, GEN_VISIBLE_NO_UNDIES)
|
||||
|
||||
custom_speech_verb = sanitize_inlist(custom_speech_verb, GLOB.speech_verbs, "default")
|
||||
custom_tongue = sanitize_inlist(custom_tongue, GLOB.roundstart_tongues, "default")
|
||||
additional_language = sanitize_inlist(additional_language, GLOB.roundstart_languages, "None")
|
||||
custom_speech_verb = sanitize_inlist(custom_speech_verb, GLOB.speech_verbs, "default")
|
||||
custom_tongue = sanitize_inlist(custom_tongue, GLOB.roundstart_tongues, "default")
|
||||
additional_language = sanitize_inlist(additional_language, GLOB.roundstart_languages, "None")
|
||||
|
||||
security_records = copytext(security_records, 1, MAX_FLAVOR_LEN)
|
||||
medical_records = copytext(medical_records, 1, MAX_FLAVOR_LEN)
|
||||
security_records = copytext(security_records, 1, MAX_FLAVOR_LEN)
|
||||
medical_records = copytext(medical_records, 1, MAX_FLAVOR_LEN)
|
||||
|
||||
features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["ooc_notes"] = copytext(features["ooc_notes"], 1, MAX_FLAVOR_LEN)
|
||||
features["flavor_text"] = copytext(features["flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["silicon_flavor_text"] = copytext(features["silicon_flavor_text"], 1, MAX_FLAVOR_LEN)
|
||||
features["ooc_notes"] = copytext(features["ooc_notes"], 1, MAX_FLAVOR_LEN)
|
||||
|
||||
//load every advanced coloring mode thing in one go
|
||||
//THIS MUST BE DONE AFTER ALL FEATURE SAVES OR IT WILL NOT WORK
|
||||
@@ -1011,11 +1009,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
message_admins("Sprite Accessory Failure (loading data): Accessory [accessory.type] is a matrixed item without any matrixed sections set!")
|
||||
continue
|
||||
if(S["feature_[primary_string]"])
|
||||
S["feature_[primary_string]"] >> features[primary_string]
|
||||
S["feature_[primary_string]"] >> features[primary_string]
|
||||
if(S["feature_[secondary_string]"])
|
||||
S["feature_[secondary_string]"] >> features[secondary_string]
|
||||
S["feature_[secondary_string]"] >> features[secondary_string]
|
||||
if(S["feature_[tertiary_string]"])
|
||||
S["feature_[tertiary_string]"] >> features[tertiary_string]
|
||||
S["feature_[tertiary_string]"] >> features[tertiary_string]
|
||||
|
||||
persistent_scars = sanitize_integer(persistent_scars)
|
||||
scars_list["1"] = sanitize_text(scars_list["1"])
|
||||
@@ -1024,7 +1022,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
scars_list["4"] = sanitize_text(scars_list["4"])
|
||||
scars_list["5"] = sanitize_text(scars_list["5"])
|
||||
|
||||
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
|
||||
joblessrole = sanitize_integer(joblessrole, 1, 3, initial(joblessrole))
|
||||
//Validate job prefs
|
||||
for(var/j in job_preferences)
|
||||
if(job_preferences["[j]"] != JP_LOW && job_preferences["[j]"] != JP_MEDIUM && job_preferences["[j]"] != JP_HIGH)
|
||||
@@ -1032,10 +1030,10 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
all_quirks = SANITIZE_LIST(all_quirks)
|
||||
|
||||
vore_flags = sanitize_integer(vore_flags, 0, MAX_VORE_FLAG, 0)
|
||||
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
|
||||
vore_smell = copytext(vore_smell, 1, MAX_TASTE_LEN)
|
||||
belly_prefs = SANITIZE_LIST(belly_prefs)
|
||||
vore_flags = sanitize_integer(vore_flags, 0, MAX_VORE_FLAG, 0)
|
||||
vore_taste = copytext(vore_taste, 1, MAX_TASTE_LEN)
|
||||
vore_smell = copytext(vore_smell, 1, MAX_TASTE_LEN)
|
||||
belly_prefs = SANITIZE_LIST(belly_prefs)
|
||||
|
||||
cit_character_pref_load(S)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
if(damaged_clothes)
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedgloves")
|
||||
if(blood_DNA)
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", color = blood_DNA_to_color())
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "bloodyhands", color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
|
||||
/obj/item/clothing/gloves/update_clothes_damaged_state()
|
||||
..()
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
if(damaged_clothes)
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedhelmet")
|
||||
if(blood_DNA)
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "helmetblood", color = blood_DNA_to_color())
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "helmetblood", color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
|
||||
/obj/item/clothing/head/update_clothes_damaged_state()
|
||||
..()
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
if(damaged_clothes)
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
|
||||
if(blood_DNA)
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color())
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
|
||||
/obj/item/clothing/mask/update_clothes_damaged_state()
|
||||
..()
|
||||
|
||||
@@ -113,6 +113,50 @@
|
||||
to_chat(user, "<span class='notice'>Your Joy mask now has a [choice] Emotion!</span>")
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/mask/kitsuneblk
|
||||
name = "Black Kitsune Mask"
|
||||
desc = "An oriental styled porcelain mask, this one is black and gold."
|
||||
icon_state = "blackkitsunemask"
|
||||
item_state = "blackkitsunemask"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
flags_cover = MASKCOVERSMOUTH
|
||||
flags_inv = HIDEFACE|HIDEFACIALHAIR
|
||||
visor_flags_inv = HIDEFACE|HIDEFACIALHAIR
|
||||
visor_flags_cover = MASKCOVERSMOUTH
|
||||
slot_flags = ITEM_SLOT_MASK
|
||||
|
||||
/obj/item/clothing/mask/kitsuneblk/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
|
||||
/obj/item/clothing/mask/kitsuneblk/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
adjustmask(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/mask/kitsunewhi
|
||||
name = "White Kitsune Mask"
|
||||
desc = "An oriental styled porcelain mask, this one is white and red."
|
||||
icon_state = "whitekitsunemask"
|
||||
item_state = "whitekitsunemask"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
flags_cover = MASKCOVERSMOUTH
|
||||
flags_inv = HIDEFACE|HIDEFACIALHAIR
|
||||
visor_flags_inv = HIDEFACE|HIDEFACIALHAIR
|
||||
visor_flags_cover = MASKCOVERSMOUTH
|
||||
slot_flags = ITEM_SLOT_MASK
|
||||
|
||||
/obj/item/clothing/mask/kitsunewhi/attack_self(mob/user)
|
||||
adjustmask(user)
|
||||
|
||||
/obj/item/clothing/mask/kitsunewhi/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
return
|
||||
adjustmask(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/clothing/mask/pig
|
||||
name = "pig mask"
|
||||
desc = "A rubber pig mask with a builtin voice modulator."
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
if(damaged_clothes)
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedmask")
|
||||
if(blood_DNA)
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color())
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "maskblood", color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
|
||||
/obj/item/clothing/neck/tie
|
||||
name = "tie"
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
var/last_bloodtype = "" //used to track the last bloodtype to have graced these shoes; makes for better performing footprint shenanigans
|
||||
var/last_blood_DNA = "" //same as last one
|
||||
var/last_blood_color = ""
|
||||
var/last_blood_blend = null
|
||||
|
||||
///Whether these shoes have laces that can be tied/untied
|
||||
var/can_be_tied = TRUE
|
||||
@@ -68,6 +69,7 @@
|
||||
last_bloodtype = blood_dna[blood_dna[blood_dna.len]]//trust me this works
|
||||
last_blood_DNA = blood_dna[blood_dna.len]
|
||||
last_blood_color = blood_dna["color"]
|
||||
last_blood_blend = blood_dna["blendmode"]
|
||||
|
||||
/obj/item/clothing/shoes/worn_overlays(isinhands = FALSE, icon_file, used_state, style_flags = NONE)
|
||||
. = ..()
|
||||
@@ -82,7 +84,7 @@
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damagedshoe")
|
||||
if(bloody)
|
||||
var/file2use = style_flags & STYLE_DIGITIGRADE ? 'icons/mob/clothing/feet_digi.dmi' : 'icons/effects/blood.dmi'
|
||||
. += mutable_appearance(file2use, "shoeblood", color = blood_DNA_to_color())
|
||||
. += mutable_appearance(file2use, "shoeblood", color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
|
||||
/obj/item/clothing/shoes/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damaged[blood_overlay_type]")
|
||||
if(blood_DNA)
|
||||
var/file2use = (style_flags & STYLE_ALL_TAURIC) ? 'modular_citadel/icons/mob/64x32_effects.dmi' : 'icons/effects/blood.dmi'
|
||||
. += mutable_appearance(file2use, "[blood_overlay_type]blood", color = blood_DNA_to_color())
|
||||
. += mutable_appearance(file2use, "[blood_overlay_type]blood", color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
var/mob/living/carbon/human/M = loc
|
||||
if(ishuman(M) && M.w_uniform)
|
||||
var/obj/item/clothing/under/U = M.w_uniform
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
if(damaged_clothes)
|
||||
. += mutable_appearance('icons/effects/item_damage.dmi', "damageduniform")
|
||||
if(blood_DNA)
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "uniformblood", color = blood_DNA_to_color())
|
||||
. += mutable_appearance('icons/effects/blood.dmi', "uniformblood", color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
if(accessory_overlay)
|
||||
. += accessory_overlay
|
||||
|
||||
|
||||
@@ -311,6 +311,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/pizza/donkpocket = 0.3,
|
||||
/obj/item/reagent_containers/food/snacks/pizza/dank = 0.1) //pizzas here are weighted by chance to be someone's favorite
|
||||
var/static/list/pizza_preferences
|
||||
COOLDOWN_DECLARE(next_pizza_attunement)
|
||||
|
||||
/obj/item/pizzabox/infinite/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -323,11 +324,18 @@
|
||||
. += "<span class='deadsay'>This pizza box is anomalous, and will produce infinite pizza.</span>"
|
||||
|
||||
/obj/item/pizzabox/infinite/attack_self(mob/living/user)
|
||||
QDEL_NULL(pizza)
|
||||
if(ishuman(user))
|
||||
attune_pizza(user)
|
||||
if(COOLDOWN_FINISHED(src, next_pizza_attunement))
|
||||
QDEL_NULL(pizza)
|
||||
if(ishuman(user))
|
||||
attune_pizza(user)
|
||||
. = ..()
|
||||
|
||||
/obj/item/pizzabox/infinite/on_attack_hand(mob/user, act_intent, unarmed_attack_flags)
|
||||
var/had_pizza = (pizza ? TRUE : FALSE)
|
||||
. = ..()
|
||||
if(had_pizza && !pizza)
|
||||
COOLDOWN_START(src, next_pizza_attunement, (3 SECONDS))
|
||||
|
||||
/obj/item/pizzabox/infinite/proc/attune_pizza(mob/living/carbon/human/noms) //tonight on "proc names I never thought I'd type"
|
||||
if(!pizza_preferences[noms.ckey])
|
||||
pizza_preferences[noms.ckey] = pickweight(pizza_types)
|
||||
|
||||
@@ -9,6 +9,12 @@
|
||||
|
||||
..()
|
||||
|
||||
if(!age_verify())
|
||||
return
|
||||
|
||||
if(!client) //client can end up null as a result of age_verify() kicking those who fail
|
||||
return
|
||||
|
||||
var/motd = global.config.motd
|
||||
if(motd)
|
||||
to_chat(src, "<div class=\"motd\">[motd]</div>", handle_whitespace=FALSE)
|
||||
@@ -22,8 +28,11 @@
|
||||
|
||||
sight |= SEE_TURFS
|
||||
|
||||
new_player_panel()
|
||||
client.playtitlemusic()
|
||||
|
||||
var/datum/asset/asset_datum = get_asset_datum(/datum/asset/simple/lobby)
|
||||
asset_datum.send(client)
|
||||
|
||||
if(SSticker.current_state < GAME_STATE_SETTING_UP)
|
||||
var/tl = SSticker.GetTimeLeft()
|
||||
var/postfix
|
||||
@@ -32,3 +41,7 @@
|
||||
else
|
||||
postfix = "soon"
|
||||
to_chat(src, "Please set up your character and select \"Ready\". The game will start [postfix].")
|
||||
|
||||
var/datum/hud/new_player/NH = hud_used
|
||||
if(istype(NH))
|
||||
NH.populate_buttons(src)
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#define LINKIFY_READY(string, value) "<a href='byond://?src=[REF(src)];ready=[value]'>[string]</a>"
|
||||
|
||||
/mob/dead/new_player
|
||||
var/ready = 0
|
||||
var/spawning = 0//Referenced when you want to delete the new_player later on in the code.
|
||||
@@ -10,6 +8,8 @@
|
||||
|
||||
density = FALSE
|
||||
stat = DEAD
|
||||
hud_type = /datum/hud/new_player
|
||||
hud_possible = list()
|
||||
|
||||
var/mob/living/new_character //for instant transfer once the round is set up
|
||||
|
||||
@@ -43,69 +43,6 @@
|
||||
/mob/dead/new_player/prepare_huds()
|
||||
return
|
||||
|
||||
/mob/dead/new_player/proc/new_player_panel()
|
||||
var/output = "<center><p>Welcome, <b>[client ? client.prefs.real_name : "Unknown User"]</b></p>"
|
||||
output += "<center><p><a href='byond://?src=[REF(src)];show_preferences=1'>Setup Character</a></p>"
|
||||
|
||||
if(SSticker.current_state <= GAME_STATE_PREGAME)
|
||||
switch(ready)
|
||||
if(PLAYER_NOT_READY)
|
||||
output += "<p>\[ [LINKIFY_READY("Ready", PLAYER_READY_TO_PLAY)] | <b>Not Ready</b> | [LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)] \]</p>"
|
||||
if(PLAYER_READY_TO_PLAY)
|
||||
output += "<p>\[ <b>Ready</b> | [LINKIFY_READY("Not Ready", PLAYER_NOT_READY)] | [LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)] \]</p>"
|
||||
if(PLAYER_READY_TO_OBSERVE)
|
||||
output += "<p>\[ [LINKIFY_READY("Ready", PLAYER_READY_TO_PLAY)] | [LINKIFY_READY("Not Ready", PLAYER_NOT_READY)] | <b> Observe </b> \]</p>"
|
||||
else
|
||||
output += "<p><a href='byond://?src=[REF(src)];manifest=1'>View the Crew Manifest</a></p>"
|
||||
output += "<p><a href='byond://?src=[REF(src)];late_join=1'>Join Game!</a></p>"
|
||||
output += "<p>[LINKIFY_READY("Observe", PLAYER_READY_TO_OBSERVE)]</p>"
|
||||
|
||||
if(!IsGuestKey(src.key))
|
||||
output += playerpolls()
|
||||
|
||||
output += "</center>"
|
||||
|
||||
//src << browse(output,"window=playersetup;size=210x240;can_close=0")
|
||||
var/datum/browser/popup = new(src, "playersetup", "<div align='center'>New Player Options</div>", 250, 265)
|
||||
popup.set_window_options("can_close=0")
|
||||
popup.set_content(output)
|
||||
popup.open(FALSE)
|
||||
|
||||
/mob/dead/new_player/proc/playerpolls()
|
||||
var/output = "" //hey tg why is this a list?
|
||||
if (SSdbcore.Connect())
|
||||
var/isadmin = FALSE
|
||||
if(client?.holder)
|
||||
isadmin = TRUE
|
||||
var/datum/db_query/query_get_new_polls = SSdbcore.NewQuery({"
|
||||
SELECT id FROM [format_table_name("poll_question")]
|
||||
WHERE (adminonly = 0 OR :isadmin = 1)
|
||||
AND Now() BETWEEN starttime AND endtime
|
||||
AND deleted = 0
|
||||
AND id NOT IN (
|
||||
SELECT pollid FROM [format_table_name("poll_vote")]
|
||||
WHERE ckey = :ckey
|
||||
AND deleted = 0
|
||||
)
|
||||
AND id NOT IN (
|
||||
SELECT pollid FROM [format_table_name("poll_textreply")]
|
||||
WHERE ckey = :ckey
|
||||
AND deleted = 0
|
||||
)
|
||||
"}, list("isadmin" = isadmin, "ckey" = ckey))
|
||||
var/rs = REF(src)
|
||||
if(!query_get_new_polls.Execute())
|
||||
qdel(query_get_new_polls)
|
||||
return
|
||||
if(query_get_new_polls.NextRow())
|
||||
output += "<p><b><a href='byond://?src=[rs];showpoll=1'>Show Player Polls</A> (NEW!)</b></p>"
|
||||
else
|
||||
output += "<p><a href='byond://?src=[rs];showpoll=1'>Show Player Polls</A></p>"
|
||||
qdel(query_get_new_polls)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
return output
|
||||
|
||||
/mob/dead/new_player/proc/age_gate()
|
||||
var/list/dat = list("<center>")
|
||||
dat += "Enter your date of birth here, to confirm that you are over 18.<BR>"
|
||||
@@ -152,6 +89,9 @@
|
||||
if(!(client.prefs.db_flags & DB_FLAG_AGE_CONFIRMATION_INCOMPLETE)) //completed? Skip
|
||||
return TRUE
|
||||
|
||||
if(!client)
|
||||
return FALSE
|
||||
|
||||
var/age_verification = age_gate()
|
||||
//ban them and kick them
|
||||
if(age_verification != 1)
|
||||
@@ -269,61 +209,12 @@
|
||||
if(!age_verify())
|
||||
return
|
||||
|
||||
//Determines Relevent Population Cap
|
||||
var/relevant_cap
|
||||
var/hpc = CONFIG_GET(number/hard_popcap)
|
||||
var/epc = CONFIG_GET(number/extreme_popcap)
|
||||
if(hpc && epc)
|
||||
relevant_cap = min(hpc, epc)
|
||||
else
|
||||
relevant_cap = max(hpc, epc)
|
||||
|
||||
if(href_list["show_preferences"])
|
||||
client.prefs.ShowChoices(src)
|
||||
return 1
|
||||
|
||||
if(href_list["ready"])
|
||||
var/tready = text2num(href_list["ready"])
|
||||
//Avoid updating ready if we're after PREGAME (they should use latejoin instead)
|
||||
//This is likely not an actual issue but I don't have time to prove that this
|
||||
//no longer is required
|
||||
if(SSticker.current_state <= GAME_STATE_PREGAME)
|
||||
ready = tready
|
||||
//if it's post initialisation and they're trying to observe we do the needful
|
||||
if(!SSticker.current_state < GAME_STATE_PREGAME && tready == PLAYER_READY_TO_OBSERVE)
|
||||
ready = tready
|
||||
make_me_an_observer()
|
||||
return
|
||||
|
||||
if(href_list["refresh"])
|
||||
src << browse(null, "window=playersetup") //closes the player setup window
|
||||
new_player_panel()
|
||||
|
||||
if(href_list["late_join"])
|
||||
if(!SSticker || !SSticker.IsRoundInProgress())
|
||||
to_chat(usr, "<span class='danger'>The round is either not ready, or has already finished...</span>")
|
||||
return
|
||||
|
||||
if(href_list["late_join"] == "override")
|
||||
LateChoices()
|
||||
return
|
||||
|
||||
if(SSticker.queued_players.len || (relevant_cap && living_player_count() >= relevant_cap && !(ckey(key) in GLOB.admin_datums)))
|
||||
to_chat(usr, "<span class='danger'>[CONFIG_GET(string/hard_popcap_message)]</span>")
|
||||
|
||||
var/queue_position = SSticker.queued_players.Find(usr)
|
||||
if(queue_position == 1)
|
||||
to_chat(usr, "<span class='notice'>You are next in line to join the game. You will be notified when a slot opens up.</span>")
|
||||
else if(queue_position)
|
||||
to_chat(usr, "<span class='notice'>There are [queue_position-1] players in front of you in the queue to join the game.</span>")
|
||||
else
|
||||
SSticker.queued_players += usr
|
||||
to_chat(usr, "<span class='notice'>You have been added to the queue to join the game. Your position in queue is [SSticker.queued_players.len].</span>")
|
||||
return
|
||||
LateChoices()
|
||||
|
||||
if(href_list["manifest"])
|
||||
ViewManifest()
|
||||
return
|
||||
|
||||
if(href_list["SelectedJob"])
|
||||
if(!SSticker || !SSticker.IsRoundInProgress())
|
||||
@@ -337,6 +228,17 @@
|
||||
to_chat(usr, "<span class='notice'>There is an administrative lock on entering the game!</span>")
|
||||
return
|
||||
|
||||
//Determines Relevent Population Cap
|
||||
var/relevant_cap
|
||||
var/hpc = CONFIG_GET(number/hard_popcap)
|
||||
var/epc = CONFIG_GET(number/extreme_popcap)
|
||||
if(hpc && epc)
|
||||
relevant_cap = min(hpc, epc)
|
||||
else
|
||||
relevant_cap = max(hpc, epc)
|
||||
|
||||
|
||||
|
||||
if(SSticker.queued_players.len && !(ckey(key) in GLOB.admin_datums))
|
||||
if((living_player_count() >= relevant_cap) || (src != SSticker.queued_players[1]))
|
||||
to_chat(usr, "<span class='warning'>Server is full.</span>")
|
||||
@@ -349,6 +251,15 @@
|
||||
if(!GLOB.enter_allowed)
|
||||
to_chat(usr, "<span class='notice'> There is an administrative lock on entering the game!</span>")
|
||||
|
||||
//Determines Relevent Population Cap
|
||||
var/relevant_cap
|
||||
var/hpc = CONFIG_GET(number/hard_popcap)
|
||||
var/epc = CONFIG_GET(number/extreme_popcap)
|
||||
if(hpc && epc)
|
||||
relevant_cap = min(hpc, epc)
|
||||
else
|
||||
relevant_cap = max(hpc, epc)
|
||||
|
||||
if(SSticker.queued_players.len && !(ckey(key) in GLOB.admin_datums))
|
||||
if((living_player_count() >= relevant_cap) || (src != SSticker.queued_players[1]))
|
||||
to_chat(usr, "<span class='warning'>Server is full.</span>")
|
||||
@@ -360,13 +271,6 @@
|
||||
SSticker.queue_delay = 4
|
||||
qdel(src)
|
||||
|
||||
else if(!href_list["late_join"])
|
||||
new_player_panel()
|
||||
|
||||
if(href_list["showpoll"])
|
||||
handle_player_polling()
|
||||
return
|
||||
|
||||
if(href_list["pollid"])
|
||||
var/pollid = href_list["pollid"]
|
||||
if(istext(pollid))
|
||||
@@ -460,7 +364,6 @@
|
||||
if(QDELETED(src) || !src.client || this_is_like_playing_right != "Yes")
|
||||
ready = PLAYER_NOT_READY
|
||||
src << browse(null, "window=playersetup") //closes the player setup window
|
||||
new_player_panel()
|
||||
return FALSE
|
||||
|
||||
var/mob/dead/observer/observer = new()
|
||||
|
||||
@@ -193,6 +193,7 @@
|
||||
|
||||
blood_data["blood_DNA"] = dna.unique_enzymes
|
||||
blood_data["bloodcolor"] = dna.species.exotic_blood_color
|
||||
blood_data["bloodblend"] = dna.species.exotic_blood_blend_mode
|
||||
if(disease_resistances && disease_resistances.len)
|
||||
blood_data["resistances"] = disease_resistances.Copy()
|
||||
var/list/temp_chem = list()
|
||||
@@ -264,7 +265,7 @@
|
||||
"O-" = list("O-","SY"),
|
||||
"O+" = list("O-", "O+","SY"),
|
||||
"L" = list("L","SY"),
|
||||
"U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U","SY"),
|
||||
"U" = list("A-", "A+", "B-", "B+", "O-", "O+", "AB-", "AB+", "L", "U","SY", "BUG"),
|
||||
"HF" = list("HF", "SY"),
|
||||
"X*" = list("X*", "SY"),
|
||||
"SY" = list("SY"),
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
FP.blood_DNA["color"] = S.last_blood_color
|
||||
else
|
||||
FP.blood_DNA["color"] = BlendRGB(FP.blood_DNA["color"], S.last_blood_color)
|
||||
FP.blood_DNA["blendmode"] = S.last_blood_blend
|
||||
FP.update_icon()
|
||||
update_inv_shoes()
|
||||
//End bloody footprints
|
||||
|
||||
@@ -65,6 +65,8 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/exotic_bloodtype = ""
|
||||
/// Assume human as the default blood colour, override this default by species subtypes
|
||||
var/exotic_blood_color = BLOOD_COLOR_HUMAN
|
||||
/// Which blend mode should this species blood use?
|
||||
var/exotic_blood_blend_mode = BLEND_MULTIPLY
|
||||
///What the species drops when gibbed by a gibber machine.
|
||||
var/meat = /obj/item/reagent_containers/food/snacks/meat/slab/human //What the species drops on gibbing
|
||||
var/list/gib_types = list(/obj/effect/gibspawner/human, /obj/effect/gibspawner/human/bodypartless)
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
exotic_blood = /datum/reagent/blood/jellyblood
|
||||
exotic_bloodtype = "GEL"
|
||||
exotic_blood_color = "BLOOD_COLOR_SLIME"
|
||||
exotic_blood_blend_mode = BLEND_DEFAULT
|
||||
damage_overlay_type = ""
|
||||
liked_food = TOXIC | MEAT
|
||||
disliked_food = null
|
||||
@@ -31,6 +32,7 @@
|
||||
species_category = SPECIES_CATEGORY_JELLY
|
||||
wings_icons = SPECIES_WINGS_JELLY
|
||||
ass_image = 'icons/ass/assslime.png'
|
||||
blacklisted_quirks = list(/datum/quirk/glass_bones)
|
||||
|
||||
/datum/species/jelly/on_species_loss(mob/living/carbon/C)
|
||||
C.faction -= "slime"
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
wings_icons = SPECIES_WINGS_SKELETAL
|
||||
|
||||
ass_image = 'icons/ass/assplasma.png'
|
||||
blacklisted_quirks = list(/datum/quirk/paper_skin)
|
||||
|
||||
/datum/species/plasmaman/spec_life(mob/living/carbon/human/H)
|
||||
var/datum/gas_mixture/environment = H.loc.return_air()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
species_category = SPECIES_CATEGORY_SKELETON //they have their own category that's disassociated from undead, paired with plasmapeople
|
||||
wings_icons = SPECIES_WINGS_SKELETAL
|
||||
blacklisted_quirks = list(/datum/quirk/paper_skin)
|
||||
|
||||
/datum/species/skeleton/New()
|
||||
if(SSevents.holidays && SSevents.holidays[HALLOWEEN]) //skeletons are stronger during the spooky season!
|
||||
|
||||
@@ -209,7 +209,7 @@ There are several things that need to be remembered:
|
||||
inv.update_icon()
|
||||
|
||||
if(!gloves && bloody_hands)
|
||||
var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color())
|
||||
var/mutable_appearance/bloody_overlay = mutable_appearance('icons/effects/blood.dmi', "bloodyhands", -GLOVES_LAYER, color = blood_DNA_to_color(), blend_mode = blood_DNA_to_blend())
|
||||
if(get_num_arms(FALSE) < 2)
|
||||
if(has_left_hand(FALSE))
|
||||
bloody_overlay.icon_state = "bloodyhands_left"
|
||||
|
||||
@@ -925,8 +925,8 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list(
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
|
||||
. = ..()
|
||||
if(. && !client && prob(1) && prob(1)) //Only the one true bird may speak across dimensions.
|
||||
world.TgsTargetedChatBroadcast("A stray squawk is heard... \"[message]\"", FALSE)
|
||||
if(. && !client && prob(1) && prob(1) && CONFIG_GET(string/chat_squawk_tag)) //Only the one true bird may speak across dimensions.
|
||||
send2chat("A stray squawk is heard... \"[message]\"", CONFIG_GET(string/chat_squawk_tag))
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/BiologicalLife(seconds, times_fired)
|
||||
if(!(. = ..()))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/datum/reagent/blood
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "bloodblend" = BLEND_MULTIPLY, "blood_type"= null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null)
|
||||
name = "Blood"
|
||||
chemical_flags = REAGENT_ALL_PROCESS
|
||||
value = REAGENT_VALUE_UNCOMMON // $$$ blood ""donations"" $$$
|
||||
@@ -81,6 +81,7 @@
|
||||
B.blood_DNA["color"] = data["bloodcolor"]
|
||||
else
|
||||
B.blood_DNA["color"] = BlendRGB(B.blood_DNA["color"], data["bloodcolor"])
|
||||
B.blood_DNA["blendmode"] = data["bloodblend"]
|
||||
if(B.reagents)
|
||||
B.reagents.add_reagent(type, reac_volume)
|
||||
B.update_icon()
|
||||
@@ -148,7 +149,7 @@
|
||||
. += D
|
||||
|
||||
/datum/reagent/blood/synthetics
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"="REPLICATED", "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"="REPLICATED", "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "bloodblend" = BLEND_MULTIPLY, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Synthetic Blood"
|
||||
description = "A synthetically produced imitation of blood."
|
||||
taste_description = "oil"
|
||||
@@ -156,7 +157,7 @@
|
||||
value = REAGENT_VALUE_NONE
|
||||
|
||||
/datum/reagent/blood/jellyblood
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "bloodblend" = BLEND_DEFAULT, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Slime Jelly Blood"
|
||||
description = "A gooey semi-liquid produced from one of the deadliest lifeforms in existence. SO REAL."
|
||||
color = BLOOD_COLOR_SLIME
|
||||
@@ -165,7 +166,7 @@
|
||||
pH = 4
|
||||
|
||||
/datum/reagent/blood/tomato
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "bloodblend" = BLEND_MULTIPLY, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
name = "Tomato Blood"
|
||||
description = "This highly resembles blood, but it doesnt actually function like it, resembling more ketchup, with a more blood-like consistency."
|
||||
taste_description = "sap" //Like tree sap?
|
||||
@@ -189,7 +190,7 @@
|
||||
description = "You don't even want to think about what's in here."
|
||||
taste_description = "gross iron"
|
||||
shot_glass_icon_state = "shotglassred"
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "blood_type"= "O+","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_HUMAN, "bloodblend" = BLEND_MULTIPLY, "blood_type"= "O+","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
pH = 7.45
|
||||
|
||||
/datum/reagent/liquidgibs/xeno
|
||||
@@ -197,7 +198,7 @@
|
||||
color = BLOOD_COLOR_XENO
|
||||
taste_description = "blended heresy"
|
||||
shot_glass_icon_state = "shotglassgreen"
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_XENO, "bloodblend" = BLEND_MULTIPLY, "blood_type"="X*","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
pH = 2.5
|
||||
|
||||
/datum/reagent/liquidgibs/slime
|
||||
@@ -205,20 +206,20 @@
|
||||
color = BLOOD_COLOR_SLIME
|
||||
taste_description = "slime"
|
||||
shot_glass_icon_state = "shotglassgreen"
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SLIME, "bloodblend" = BLEND_DEFAULT, "blood_type"="GEL","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
pH = 4
|
||||
|
||||
/datum/reagent/liquidgibs/synth
|
||||
name = "Synthetic sludge"
|
||||
color = BLOOD_COLOR_SYNTHETIC
|
||||
taste_description = "jellied plastic"
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_SYNTHETIC, "bloodblend" = BLEND_MULTIPLY, "blood_type"="SY","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
|
||||
/datum/reagent/liquidgibs/oil
|
||||
name = "Hydraulic sludge"
|
||||
color = BLOOD_COLOR_OIL
|
||||
taste_description = "chunky burnt oil"
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
data = list("donor"=null,"viruses"=null,"blood_DNA"=null, "bloodcolor" = BLOOD_COLOR_OIL, "bloodblend" = BLEND_MULTIPLY, "blood_type"="HF","resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null)
|
||||
pH = 9.75
|
||||
|
||||
/datum/reagent/vaccine
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
/obj/item/reagent_containers/blood/Initialize(mapload)
|
||||
. = ..()
|
||||
if(blood_type != null)
|
||||
reagents.add_reagent(/datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"bloodcolor"=bloodtype_to_color(blood_type), "blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
|
||||
reagents.add_reagent(/datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"bloodcolor"=bloodtype_to_color(blood_type), "bloodblend" = BLEND_MULTIPLY, "blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
|
||||
update_icon()
|
||||
|
||||
/obj/item/reagent_containers/blood/on_reagent_change(changetype)
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
return
|
||||
account.adjust_money(-deposit_value) //The money vanishes, not paid to any accounts.
|
||||
SSblackbox.record_feedback("amount", "BEPIS_credits_spent", deposit_value)
|
||||
//log_econ("[deposit_value] credits were inserted into [src] by [account.account_holder]")
|
||||
log_econ("[deposit_value] credits were inserted into [src] by [key_name(usr)] (account: [account.account_holder])")
|
||||
banked_cash += deposit_value
|
||||
use_power(1000 * power_saver)
|
||||
say("Cash deposit successful. There is [banked_cash] in the chamber.")
|
||||
|
||||
@@ -228,6 +228,8 @@
|
||||
var/mangled_state = get_mangled_state()
|
||||
var/bio_state = owner.get_biological_state()
|
||||
var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%)
|
||||
var/glass_bones = HAS_TRAIT(owner, TRAIT_GLASS_BONES)
|
||||
var/paper_skin = HAS_TRAIT(owner, TRAIT_PAPER_SKIN)
|
||||
|
||||
if(wounding_type == WOUND_BLUNT)
|
||||
if(sharpness == SHARP_EDGED)
|
||||
@@ -242,22 +244,29 @@
|
||||
if(wounding_type == WOUND_SLASH)
|
||||
wounding_type = WOUND_BLUNT
|
||||
wounding_dmg *= (easy_dismember ? 1 : 0.5)
|
||||
wounding_dmg *= (glass_bones ? 1.5 : 1)
|
||||
else if(wounding_type == WOUND_PIERCE)
|
||||
wounding_type = WOUND_BLUNT
|
||||
wounding_dmg *= (easy_dismember ? 1 : 0.75)
|
||||
wounding_dmg *= (glass_bones ? 1.5 : 1)
|
||||
if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
|
||||
return
|
||||
// if we're flesh only, all blunt attacks become weakened slashes in terms of wound damage
|
||||
if(BIO_JUST_FLESH)
|
||||
if(wounding_type == WOUND_BLUNT)
|
||||
wounding_type = WOUND_SLASH
|
||||
wounding_dmg *= (easy_dismember ? 1 : 0.3)
|
||||
wounding_dmg *= (easy_dismember ? 1 : 0.5)
|
||||
wounding_dmg *= (paper_skin ? 1.5 : 1)
|
||||
if((mangled_state & BODYPART_MANGLED_FLESH) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus))
|
||||
return
|
||||
// standard humanoids
|
||||
if(BIO_FLESH_BONE)
|
||||
// if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate
|
||||
// So a big sharp weapon is still all you need to destroy a limb
|
||||
if(wounding_type == WOUND_SLASH || wounding_type == WOUND_PIERCE)
|
||||
wounding_dmg *= (paper_skin ? 1.5 : 1)
|
||||
else
|
||||
wounding_dmg *= (glass_bones ? 1.5 : 1)
|
||||
if(mangled_state == BODYPART_MANGLED_FLESH && sharpness)
|
||||
playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100)
|
||||
if(wounding_type == WOUND_SLASH && !easy_dismember)
|
||||
|
||||
@@ -18,10 +18,9 @@
|
||||
// to hear anything.
|
||||
var/deaf = 0
|
||||
|
||||
// `ear_damage` measures long term damage to the ears, if too high,
|
||||
// `damage` in this case measures long term damage to the ears, if too high,
|
||||
// the person will not have either `deaf` or `ear_damage` decrease
|
||||
// without external aid (earmuffs, drugs)
|
||||
var/ear_damage = 0
|
||||
|
||||
//Resistance against loud noises
|
||||
var/bang_protect = 0
|
||||
@@ -44,16 +43,22 @@
|
||||
|
||||
/obj/item/organ/ears/proc/restoreEars()
|
||||
deaf = 0
|
||||
ear_damage = 0
|
||||
damage = 0
|
||||
prev_damage = 0
|
||||
organ_flags &= ~ORGAN_FAILING
|
||||
|
||||
var/mob/living/carbon/C = owner
|
||||
|
||||
if(iscarbon(owner) && HAS_TRAIT(C, TRAIT_DEAF))
|
||||
deaf = 1
|
||||
var/mess = check_damage_thresholds()
|
||||
if(mess && owner)
|
||||
to_chat(owner, mess)
|
||||
|
||||
/obj/item/organ/ears/proc/adjustEarDamage(ddmg, ddeaf)
|
||||
ear_damage = max(ear_damage + (ddmg*damage_multiplier), 0)
|
||||
if(owner.status_flags & GODMODE)
|
||||
return
|
||||
setOrganDamage(max(damage + (ddmg*damage_multiplier), 0))
|
||||
deaf = max(deaf + (ddeaf*damage_multiplier), 0)
|
||||
|
||||
/obj/item/organ/ears/proc/minimumDeafTicks(value)
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
to_chat(H, "<span class='alert'>Your throat closes up!</span>")
|
||||
H.silent = max(H.silent, 3)
|
||||
else
|
||||
H.adjustFireLoss(nitryl_pp/4)
|
||||
H.adjustFireLoss(nitryl_pp/2)
|
||||
gas_breathed = breath.get_moles(GAS_NITRYL)
|
||||
if (gas_breathed > gas_stimulation_min)
|
||||
H.reagents.add_reagent(/datum/reagent/nitryl,1)
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
owner.dna.species.stop_wagging_tail(owner)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/tail/on_life()
|
||||
return
|
||||
|
||||
/obj/item/organ/tail/cat
|
||||
name = "cat tail"
|
||||
desc = "A severed cat tail. Who's wagging now?"
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
#define UNIT_TEST_SAVING_FLAVOR_TEXT "Space"
|
||||
#define UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT "Station"
|
||||
#define UNIT_TEST_SAVING_OOC_NOTES "Thirteen"
|
||||
|
||||
/datum/unit_test/character_saving/Run()
|
||||
try
|
||||
var/datum/preferences/P = new
|
||||
P.load_path("test")
|
||||
P.features["flavor_text"] = "Foo"
|
||||
P.features["ooc_notes"] = "Bar"
|
||||
P.features["flavor_text"] = UNIT_TEST_SAVING_FLAVOR_TEXT
|
||||
P.features["silicon_flavor_text"] = UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT
|
||||
P.features["ooc_notes"] = UNIT_TEST_SAVING_OOC_NOTES
|
||||
P.save_character()
|
||||
P.load_character()
|
||||
if(P.features["flavor_text"] != "Foo")
|
||||
if(P.features["flavor_text"] != UNIT_TEST_SAVING_FLAVOR_TEXT)
|
||||
Fail("Flavor text is failing to save.")
|
||||
if(P.features["ooc_notes"] != "Bar")
|
||||
if(P.features["silicon_flavor_text"] != UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT)
|
||||
Fail("Silicon flavor text is failing to save.")
|
||||
if(P.features["ooc_notes"] != UNIT_TEST_SAVING_OOC_NOTES)
|
||||
Fail("OOC text is failing to save.")
|
||||
P.save_character()
|
||||
P.load_character()
|
||||
if(P.features["flavor_text"] != "Foo")
|
||||
if((P.features["flavor_text"] != UNIT_TEST_SAVING_FLAVOR_TEXT) || (P.features["silicon_flavor_text"] != UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT) || (P.features["ooc_notes"] != UNIT_TEST_SAVING_OOC_NOTES))
|
||||
Fail("Repeated saving and loading possibly causing save deletion.")
|
||||
catch(var/exception/e)
|
||||
Fail("Failed to save and load character due to exception [e.file]:[e.line], [e.name]")
|
||||
|
||||
#undef UNIT_TEST_SAVING_FLAVOR_TEXT
|
||||
#undef UNIT_TEST_SAVING_SILICON_FLAVOR_TEXT
|
||||
#undef UNIT_TEST_SAVING_OOC_NOTES
|
||||
|
||||
@@ -272,7 +272,7 @@
|
||||
|
||||
/obj/vehicle/sealed/mecha/proc/update_part_values() ///Updates the values given by scanning module and capacitor tier, called when a part is removed or inserted.
|
||||
if(scanmod)
|
||||
normal_step_energy_drain = 20 - (5 * scanmod.rating) //10 is normal, so on lowest part its worse, on second its ok and on higher its real good up to 0 on best
|
||||
normal_step_energy_drain = initial(normal_step_energy_drain) * (1.5 / (scanmod.rating - 0.5)) //movement power cost is 3x of default at T1, 1x at T2, 0.6x at T3 and 0.4x at T4
|
||||
step_energy_drain = normal_step_energy_drain
|
||||
else
|
||||
normal_step_energy_drain = 500
|
||||
@@ -641,6 +641,9 @@
|
||||
if(!Process_Spacemove(direction))
|
||||
return FALSE
|
||||
if(!has_charge(step_energy_drain))
|
||||
if(TIMER_COOLDOWN_CHECK(src, COOLDOWN_MECHA_MESSAGE))
|
||||
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>Insufficient power to move!</span>")
|
||||
TIMER_COOLDOWN_START(src, COOLDOWN_MECHA_MESSAGE, 2 SECONDS)
|
||||
return FALSE
|
||||
if(zoom_mode)
|
||||
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>Unable to move while in zoom mode!</span>")
|
||||
@@ -651,7 +654,7 @@
|
||||
if(!scanmod || !capacitor)
|
||||
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>Missing [scanmod? "capacitor" : "scanning module"].</span>")
|
||||
return FALSE
|
||||
if(lavaland_only && is_mining_level(z))
|
||||
if(lavaland_only && !is_mining_level(z))
|
||||
to_chat(occupants, "[icon2html(src, occupants)]<span class='warning'>Invalid Environment.</span>")
|
||||
return FALSE
|
||||
|
||||
@@ -683,6 +686,7 @@
|
||||
return TRUE
|
||||
|
||||
set_glide_size(DELAY_TO_GLIDE_SIZE(movedelay))
|
||||
use_power(step_energy_drain)
|
||||
//Otherwise just walk normally
|
||||
. = step(src,direction, dir)
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
deflect_chance = 5
|
||||
armor = list(MELEE = 25, BULLET = 20, LASER = 30, ENERGY = 15, BOMB = 0, BIO = 0, RAD = 0, FIRE = 100, ACID = 100)
|
||||
max_temperature = 25000
|
||||
leg_overload_coeff = 80
|
||||
leg_overload_coeff = 300
|
||||
overload_step_energy_drain_min = 300
|
||||
force = 25
|
||||
wreckage = /obj/structure/mecha_wreckage/gygax
|
||||
internal_damage_threshold = 35
|
||||
max_equip = 3
|
||||
step_energy_drain = 3
|
||||
normal_step_energy_drain = 3
|
||||
|
||||
/obj/vehicle/sealed/mecha/combat/gygax/dark
|
||||
desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
|
||||
@@ -24,7 +25,8 @@
|
||||
deflect_chance = 20
|
||||
armor = list(MELEE = 40, BULLET = 40, LASER = 50, ENERGY = 35, BOMB = 20, BIO = 0, RAD =20, FIRE = 100, ACID = 100)
|
||||
max_temperature = 35000
|
||||
leg_overload_coeff = 70
|
||||
leg_overload_coeff = 100
|
||||
overload_step_energy_drain_min = 100
|
||||
force = 30
|
||||
operation_req_access = list(ACCESS_SYNDICATE)
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
max_temperature = 25000
|
||||
wreckage = /obj/structure/mecha_wreckage/odysseus
|
||||
internal_damage_threshold = 35
|
||||
step_energy_drain = 6
|
||||
normal_step_energy_drain = 6
|
||||
infra_luminosity = 6
|
||||
internals_req_access = list(ACCESS_ROBOTICS, ACCESS_MEDICAL)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
icon_state = "phazon"
|
||||
movedelay = 2
|
||||
dir_in = 2 //Facing South.
|
||||
step_energy_drain = 3
|
||||
normal_step_energy_drain = 3
|
||||
max_integrity = 200
|
||||
deflect_chance = 30
|
||||
armor = list(MELEE = 30, BULLET = 30, LASER = 30, ENERGY = 30, BOMB = 30, BIO = 0, RAD = 50, FIRE = 100, ACID = 100)
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
mecha_flags = CANSTRAFE | IS_ENCLOSED | HAS_LIGHTS
|
||||
internal_damage_threshold = 25
|
||||
max_equip = 2
|
||||
step_energy_drain = 3
|
||||
normal_step_energy_drain = 3
|
||||
color = "#87878715"
|
||||
stepsound = null
|
||||
turnsound = null
|
||||
|
||||
@@ -118,7 +118,12 @@
|
||||
return ..()
|
||||
|
||||
/obj/item/mecha_parts/mecha_tracking/try_attach_part(mob/user, obj/vehicle/sealed/mecha/M)
|
||||
if(!..())
|
||||
for(var/obj/item/I in M.contents)
|
||||
if(istype(I, src))
|
||||
to_chat(user, "<span class='warning'>[M] already has a tracking beacon!</span>")
|
||||
return
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
M.trackers += src
|
||||
M.diag_hud_set_mechtracking()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
wreckage = /obj/structure/mecha_wreckage/odysseus
|
||||
internal_damage_threshold = 35
|
||||
deflect_chance = 15
|
||||
step_energy_drain = 6
|
||||
normal_step_energy_drain = 6
|
||||
internals_req_access = list(ACCESS_ROBOTICS, ACCESS_MEDICAL)
|
||||
|
||||
/obj/vehicle/sealed/mecha/medical/odysseus/moved_inside(mob/living/carbon/human/H)
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
movedelay = 4
|
||||
lights_power = 7
|
||||
wreckage = /obj/structure/mecha_wreckage/ripley/deathripley
|
||||
step_energy_drain = 0
|
||||
normal_step_energy_drain = 0
|
||||
enclosed = TRUE
|
||||
enter_delay = 40
|
||||
silicon_icon_state = null
|
||||
|
||||
@@ -864,21 +864,10 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
if(isliving(usr))
|
||||
var/mob/living/L = usr
|
||||
C = L.get_idcard(TRUE)
|
||||
if(!C)
|
||||
say("No card found.")
|
||||
if(!can_transact(C))
|
||||
flick(icon_deny,src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
else if (!C.registered_account)
|
||||
say("No account found.")
|
||||
flick(icon_deny,src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
else if(!C.registered_account.account_job)
|
||||
say("Departmental accounts have been blacklisted from personal expenses due to embezzlement.")
|
||||
flick(icon_deny, src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
// else if(age_restrictions && R.age_restricted && (!C.registered_age || C.registered_age < AGE_MINOR))
|
||||
// say("You are not of legal age to purchase [R.name].")
|
||||
// if(!(usr in GLOB.narcd_underages))
|
||||
@@ -901,16 +890,13 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
price_to_use = 0 // it's free shut up
|
||||
if(coin_records.Find(R) || hidden_records.Find(R))
|
||||
price_to_use = R.custom_premium_price ? R.custom_premium_price : extra_price
|
||||
if(price_to_use && !account.adjust_money(-price_to_use))
|
||||
if(price_to_use && !attempt_transact(C, price_to_use))
|
||||
say("You do not possess the funds to purchase [R.name].")
|
||||
flick(icon_deny,src)
|
||||
vend_ready = TRUE
|
||||
return
|
||||
var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department)
|
||||
if(D)
|
||||
D.adjust_money(price_to_use)
|
||||
SSblackbox.record_feedback("amount", "vending_spent", price_to_use)
|
||||
// log_econ("[price_to_use] credits were inserted into [src] by [D.account_holder] to buy [R].")
|
||||
SSblackbox.record_feedback("amount", "vending_spent", price_to_use)
|
||||
log_econ("[price_to_use] credits were inserted into [src] by [key_name(usr)] (account: [account.account_holder]) to buy [R].")
|
||||
if(last_shopper != REF(usr) || purchase_message_cooldown < world.time)
|
||||
say("Thank you for shopping with [src]!")
|
||||
purchase_message_cooldown = world.time + 5 SECONDS
|
||||
@@ -1169,7 +1155,7 @@ GLOBAL_LIST_EMPTY(vending_products)
|
||||
if(owner)
|
||||
owner.adjust_money(S.custom_price)
|
||||
SSblackbox.record_feedback("amount", "vending_spent", S.custom_price)
|
||||
// log_econ("[S.custom_price] credits were spent on [src] buying a [S] by [owner.account_holder], owned by [private_a.account_holder].")
|
||||
log_econ("[S.custom_price] credits were spent on [src] buying a [S] by [key_name(usr)] (account: [owner.account_holder]), owned by [private_a.account_holder].")
|
||||
vending_machine_input[N] = max(vending_machine_input[N] - 1, 0)
|
||||
S.forceMove(drop_location())
|
||||
loaded_items--
|
||||
|
||||
Reference in New Issue
Block a user