Merge branch 'master' into ProteanNerf

This commit is contained in:
Razgriz
2021-03-24 17:24:15 -07:00
committed by GitHub
1002 changed files with 339579 additions and 13883 deletions

View File

@@ -96,15 +96,6 @@
"You hear a ratchet.")
deconstruct()
/obj/machinery/atmospherics/omni/can_unwrench()
var/int_pressure = 0
for(var/datum/omni_port/P in ports)
int_pressure += P.air.return_pressure()
var/datum/gas_mixture/env_air = loc.return_air()
if((int_pressure - env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
return 0
return 1
/obj/machinery/atmospherics/omni/attack_hand(user as mob)
if(..())
return

View File

@@ -173,6 +173,5 @@ What is the naming convention for planes or layers?
plane = initial(plane)
layer = initial(layer)
// Check if a mob can "logically" see an atom plane
#define MOB_CAN_SEE_PLANE(M, P) (P <= PLANE_WORLD || (P in M.planes_visible))

View File

@@ -19,6 +19,7 @@
#define DM_FLAG_STRIPPING 0x2
#define DM_FLAG_LEAVEREMAINS 0x4
#define DM_FLAG_THICKBELLY 0x8
#define DM_FLAG_AFFECTWORN 0x10
//Item related modes
#define IM_HOLD "Hold"

View File

@@ -61,4 +61,8 @@
#define INFECTION_LEVEL_ONE 100
#define INFECTION_LEVEL_TWO 500
#define INFECTION_LEVEL_THREE 1000
#define INFECTION_LEVEL_MAX 1500
#define INFECTION_LEVEL_MAX 1500
#define MODULAR_BODYPART_INVALID 0 // Cannot be detached or reattached.
#define MODULAR_BODYPART_PROSTHETIC 1 // Can be detached or reattached freely.
#define MODULAR_BODYPART_CYBERNETIC 2 // Can be detached or reattached to compatible parent organs.

View File

@@ -157,6 +157,16 @@
#define MAT_GRAPHITE "graphite"
#define MAT_LEATHER "leather"
#define MAT_CHITIN "chitin"
#define MAT_CLOTH "cloth"
#define MAT_SYNCLOTH "syncloth"
#define MAT_COPPER "copper"
#define MAT_QUARTZ "quartz"
#define MAT_TIN "tin"
#define MAT_VOPAL "void opal"
#define MAT_ALUMINIUM "aluminium"
#define MAT_BRONZE "bronze"
#define MAT_PAINITE "painite"
#define MAT_BOROSILICATE "borosilicate glass"
#define SHARD_SHARD "shard"
#define SHARD_SHRAPNEL "shrapnel"

View File

@@ -160,12 +160,6 @@
#define FLASH_PROTECTION_MODERATE 1
#define FLASH_PROTECTION_MAJOR 2
#define ANIMAL_SPAWN_DELAY round(config.respawn_delay / 6)
#define DRONE_SPAWN_DELAY round(config.respawn_delay / 3)
#define ANIMAL_SPAWN_DELAY round(config.respawn_delay / 6)
#define DRONE_SPAWN_DELAY round(config.respawn_delay / 3)
// Incapacitation flags, used by the mob/proc/incapacitated() proc
#define INCAPACITATION_RESTRAINED 1
#define INCAPACITATION_BUCKLED_PARTIALLY 2

View File

@@ -24,6 +24,30 @@
#define EMP_TOX_DMG 0x80 // EMPs inflict toxin damage
#define EMP_OXY_DMG 0x100 // EMPs inflict oxy damage
// Species allergens
#define MEAT 0x1 // Skrell won't like this.
#define FISH 0x2 // Seperate for completion's sake. Still bad for skrell.
#define FRUIT 0x4 // An apple a day only keeps the doctor away if they're allergic.
#define VEGETABLE 0x8 // Taters 'n' carrots. Potato allergy is a thing, apparently.
#define GRAINS 0x10 // Wheat, oats, etc.
#define BEANS 0x20 // The musical fruit! Includes soy.
#define SEEDS 0x40 // Hope you don't have a nut allergy.
#define DAIRY 0x80 // Lactose intolerance, ho! Also bad for skrell.
#define FUNGI 0x100 // Delicious shrooms.
#define COFFEE 0x200 // Mostly here for tajara.
#define GENERIC 0x400 // Catchall for stuff that doesn't fall into the groups above. You shouldn't be allergic to this type, ever.
#define SUGARS 0x800 // For unathi-like reactions
#define EGGS 0x1000 // For Skrell eggs allergy
// Allergen reactions
#define AG_TOX_DMG 0x1 // the classic
#define AG_OXY_DMG 0x2 // intense airway reactions
#define AG_EMOTE 0x4 // general emote reactions based on affect type
#define AG_PAIN 0x8 // short-lived hurt
#define AG_WEAKEN 0x10 // too weak to move, oof
#define AG_BLURRY 0x20 // blurred vision!
#define AG_SLEEPY 0x40 // fatigue/exhaustion
// Species spawn flags
#define SPECIES_IS_WHITELISTED 0x1 // Must be whitelisted to play.
#define SPECIES_IS_RESTRICTED 0x2 // Is not a core/normally playable species. (castes, mutantraces)

View File

@@ -10,6 +10,7 @@
#define LANGUAGE_ENOCHIAN "Enochian"
#define LANGUAGE_VESPINAE "Vespinae"
#define LANGUAGE_SPACER "Spacer"
#define LANGUAGE_CLOWNISH "Coulrian"
#define LANGUAGE_CHIMPANZEE "Chimpanzee"
#define LANGUAGE_NEAERA "Neaera"

View File

@@ -52,6 +52,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
// Subsystem init_order, from highest priority to lowest priority
// Subsystems shutdown in the reverse of the order they initialize in
// The numbers just define the ordering, they are meaningless otherwise.
#define INIT_ORDER_DBCORE 41 //CHOMPEdit
#define INIT_ORDER_SQLITE 40
#define INIT_ORDER_CHEMISTRY 35
#define INIT_ORDER_SKYBOX 30

View File

@@ -1,254 +1,351 @@
//tgstation-server DMAPI
// tgstation-server DMAPI
#define TGS_DMAPI_VERSION "5.1.1"
#define TGS_DMAPI_VERSION "6.0.3"
//All functions and datums outside this document are subject to change with any version and should not be relied on
// All functions and datums outside this document are subject to change with any version and should not be relied on.
//CONFIGURATION
// CONFIGURATION
//create this define if you want to do configuration outside of this file
/// Create this define if you want to do TGS configuration outside of this file.
#ifndef TGS_EXTERNAL_CONFIGURATION
//Comment this out once you've filled in the below
// Comment this out once you've filled in the below.
#error TGS API unconfigured
//Uncomment this if you wish to allow the game to interact with TGS 3
//This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()()
#define TGS_V3_API
// Uncomment this if you wish to allow the game to interact with TGS 3.
// This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()()
//#define TGS_V3_API
//Required interfaces (fill in with your codebase equivalent):
// Required interfaces (fill in with your codebase equivalent):
//create a global variable named `Name` and set it to `Value`
/// Create a global variable named `Name` and set it to `Value`.
#define TGS_DEFINE_AND_SET_GLOBAL(Name, Value)
//Read the value in the global variable `Name`
/// Read the value in the global variable `Name`.
#define TGS_READ_GLOBAL(Name)
//Set the value in the global variable `Name` to `Value`
/// Set the value in the global variable `Name` to `Value`.
#define TGS_WRITE_GLOBAL(Name, Value)
//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities
/// Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities.
#define TGS_PROTECT_DATUM(Path)
//Display an announcement `message` from the server to all players
/// Display an announcement `message` from the server to all players.
#define TGS_WORLD_ANNOUNCE(message)
//Notify current in-game administrators of a string `event`
/// Notify current in-game administrators of a string `event`.
#define TGS_NOTIFY_ADMINS(event)
//Write an info `message` to a server log
/// Write an info `message` to a server log.
#define TGS_INFO_LOG(message)
//Write an warning `message` to a server log
/// Write an warning `message` to a server log.
#define TGS_WARNING_LOG(message)
//Write an error `message` to a server log
/// Write an error `message` to a server log.
#define TGS_ERROR_LOG(message)
//Get the number of connected /clients
/// Get the number of connected /clients.
#define TGS_CLIENT_COUNT
#endif
//EVENT CODES
// EVENT CODES
#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //Before a reboot mode change, extras parameters are the current and new reboot mode enums
#define TGS_EVENT_PORT_SWAP -2 //Before a port change is about to happen, extra parameters is new port
#define TGS_EVENT_INSTANCE_RENAMED -3 //Before the instance is renamed, extra parameter is the new name
#define TGS_EVENT_WATCHDOG_REATTACH -4 //After the watchdog reattaches to DD, extra parameter is the new /datum/tgs_version of the server
/// Before a reboot mode change, extras parameters are the current and new reboot mode enums
#define TGS_EVENT_REBOOT_MODE_CHANGE -1
/// Before a port change is about to happen, extra parameters is new port
#define TGS_EVENT_PORT_SWAP -2
/// Before the instance is renamed, extra parameter is the new name
#define TGS_EVENT_INSTANCE_RENAMED -3
/// After the watchdog reattaches to DD, extra parameter is the new [/datum/tgs_version] of the server
#define TGS_EVENT_WATCHDOG_REATTACH -4
//See the descriptions for the parameters of these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs
/// When the repository is reset to its origin reference. Parameters: Reference name, Commit SHA
#define TGS_EVENT_REPO_RESET_ORIGIN 0
/// When the repository performs a checkout. Parameters: Checkout git object
#define TGS_EVENT_REPO_CHECKOUT 1
/// When the repository performs a fetch operation. No parameters
#define TGS_EVENT_REPO_FETCH 2
/// When the repository test merges. Parameters: PR Number, PR Sha, (Nullable) Comment made by TGS user
#define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3
/// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path
#define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4
/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND
#define TGS_EVENT_BYOND_INSTALL_START 5
/// When a BYOND install operation fails. Parameters: Error message
#define TGS_EVENT_BYOND_INSTALL_FAIL 6
/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND
#define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7
/// When the compiler starts running. Parameters: Game directory path, origin commit SHA
#define TGS_EVENT_COMPILE_START 8
/// When a compile is cancelled. No parameters
#define TGS_EVENT_COMPILE_CANCELLED 9
/// When a compile fails. Parameters: Game directory path, [TRUE]/[FALSE] based on if the cause for failure was DMAPI validation
#define TGS_EVENT_COMPILE_FAILURE 10
#define TGS_EVENT_COMPILE_COMPLETE 11 // Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the TGS_EVENT_DEPLOYMENT_COMPLETE instead
/// When a compile operation completes. Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the [TGS_EVENT_DEPLOYMENT_COMPLETE] instead. Parameters: Game directory path
#define TGS_EVENT_COMPILE_COMPLETE 11
/// When an automatic update for the current instance begins. No parameters
#define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12
/// When the repository encounters a merge conflict: Parameters: Base SHA, target SHA, base reference, target reference
#define TGS_EVENT_REPO_MERGE_CONFLICT 13
/// When a deployment completes. No Parameters
#define TGS_EVENT_DEPLOYMENT_COMPLETE 14
/// Before the watchdog shuts down. Not sent for graceful shutdowns. No parameters.
#define TGS_EVENT_WATCHDOG_SHUTDOWN 15
/// Before the watchdog detaches for a TGS update/restart. No parameters.
#define TGS_EVENT_WATCHDOG_DETACH 16
// We don't actually implement these 4 events as the DMAPI can never receive them.
// #define TGS_EVENT_WATCHDOG_LAUNCH 17
// #define TGS_EVENT_WATCHDOG_CRASH 18
// #define TGS_EVENT_WORLD_END_PROCESS 19
// #define TGS_EVENT_WORLD_REBOOT 20
/// Watchdog event when TgsInitializationComplete() is called. No parameters.
#define TGS_EVENT_WORLD_PRIME 21
//OTHER ENUMS
// OTHER ENUMS
/// The server will reboot normally.
#define TGS_REBOOT_MODE_NORMAL 0
/// The server will stop running on reboot.
#define TGS_REBOOT_MODE_SHUTDOWN 1
/// The watchdog will restart on reboot.
#define TGS_REBOOT_MODE_RESTART 2
/// DreamDaemon Trusted security level.
#define TGS_SECURITY_TRUSTED 0
/// DreamDaemon Safe security level.
#define TGS_SECURITY_SAFE 1
/// DreamDaemon Ultrasafe security level.
#define TGS_SECURITY_ULTRASAFE 2
//REQUIRED HOOKS
//Call this somewhere in /world/New() that is always run
//IMPORTANT: This function may sleep!
//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels
//minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated
/**
* Call this somewhere in [/world/proc/New] that is always run. This function may sleep!
*
* * event_handler - Optional user defined [/datum/tgs_event_handler].
* * minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated. Can be one of [TGS_SECURITY_ULTRASAFE], [TGS_SECURITY_SAFE], or [TGS_SECURITY_TRUSTED].
*/
/world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE)
return
//Call this when your initializations are complete and your game is ready to play before any player interactions happen
//This may use world.sleep_offline to make this happen so ensure no changes are made to it while this call is running
//Most importantly, before this point, note that any static files or directories may be in use by another server. Your code should account for this
//This function should not be called before ..() in /world/New()
/**
* Call this when your initializations are complete and your game is ready to play before any player interactions happen.
*
* This may use [/world/var/sleep_offline] to make this happen so ensure no changes are made to it while this call is running.
* Afterwards, consider explicitly setting it to what you want to avoid this BYOND bug: http://www.byond.com/forum/post/2575184
* This function should not be called before ..() in [/world/proc/New].
*/
/world/proc/TgsInitializationComplete()
return
//Put this at the start of /world/Topic()
/// Put this at the start of [/world/proc/Topic].
#define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return
#define VGS_TOPIC var/vgs_topic_return = VgsTopic(args[1]); if(vgs_topic_return) return vgs_topic_return // VOREStation Edit - VGS
//Call this at the beginning of world/Reboot(reason)
/**
* Call this as late as possible in [world/proc/Reboot].
*/
/world/proc/TgsReboot()
return
//DATUM DEFINITIONS
//unless otherwise specified all datums defined here should be considered read-only, warranty void if written
// DATUM DEFINITIONS
// All datums defined here should be considered read-only
//represents git revision information about the current world build
/// Represents git revision information.
/datum/tgs_revision_information
var/commit //full sha of compiled commit
var/origin_commit //full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch
/// Full SHA of the commit.
var/commit
/// ISO 8601 timestamp of when the commit was created
var/timestamp
/// Full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch.
var/origin_commit
//represents a version of tgstation-server
/// Represents a version.
/datum/tgs_version
var/suite //The suite/major version, can be >=3
/// The suite/major version number
var/suite
//this group of variables can be null to represent a wild card
var/minor //The minor version
var/patch //The patch version
var/deprecated_patch //The legacy version
// This group of variables can be null to represent a wild card
/// The minor version number. null for wildcards
var/minor
/// The patch version number. null for wildcards
var/patch
var/raw_parameter //The unparsed parameter
var/deprefixed_parameter //The version only bit of raw_parameter
/// Legacy version number. Generally null
var/deprecated_patch
//if the tgs_version is a wildcard version
/// Unparsed string value
var/raw_parameter
/// String value minus prefix
var/deprefixed_parameter
/**
* Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] contains wildcards.
*/
/datum/tgs_version/proc/Wildcard()
return
//if the tgs_version equals some other_version
/**
* Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] equals some other version.
*
* other_version - The [/datum/tgs_version] to compare against.
*/
/datum/tgs_version/proc/Equals(datum/tgs_version/other_version)
return
//represents a merge of a GitHub pull request
/// Represents a merge of a GitHub pull request.
/datum/tgs_revision_information/test_merge
var/number //pull request number
var/title //pull request title
var/body //pull request body
var/author //pull request github author
var/url //link to pull request html
var/pull_request_commit //commit of the pull request when it was merged
var/time_merged //timestamp of when the merge commit for the pull request was created
var/comment //optional comment left by the one who initiated the test merge
/// The test merge number.
var/number
/// The test merge source's title when it was merged.
var/title
/// The test merge source's body when it was merged.
var/body
/// The Username of the test merge source's author.
var/author
/// An http URL to the test merge source.
var/url
/// The SHA of the test merge when that was merged.
var/head_commit
/// Optional comment left by the TGS user who initiated the merge.
var/comment
//represents a connected chat channel
/// Represents a connected chat channel.
/datum/tgs_chat_channel
var/id //internal channel representation
var/friendly_name //user friendly channel name
var/connection_name //the name of the configured chat connection
var/is_admin_channel //if the server operator has marked this channel for game admins only
var/is_private_channel //if this is a private chat channel
var/custom_tag //user defined string associated with channel
/// TGS internal channel ID.
var/id
/// User friendly name of the channel.
var/friendly_name
/// Name of the chat connection. This is the IRC server address or the Discord guild.
var/connection_name
/// [TRUE]/[FALSE] based on if the server operator has marked this channel for game admins only.
var/is_admin_channel
/// [TRUE]/[FALSE] if the channel is a private message channel for a [/datum/tgs_chat_user].
var/is_private_channel
/// Tag string associated with the channel in TGS
var/custom_tag
//represents a chat user
// Represents a chat user
/datum/tgs_chat_user
var/id //Internal user representation, requires channel to be unique
var/friendly_name //The user's public name
var/mention //The text to use to ping this user in a message
var/datum/tgs_chat_channel/channel //The /datum/tgs_chat_channel this user was from
/// TGS internal user ID.
var/id
// The user's display name.
var/friendly_name
// The string to use to ping this user in a message.
var/mention
/// The [/datum/tgs_chat_channel] the user was from
var/datum/tgs_chat_channel/channel
//user definable callback for handling events
//extra parameters may be specified depending on the event
/**
* User definable callback for handling TGS events.
*
* event_code - One of the TGS_EVENT_ defines. Extra parameters will be documented in each
*/
/datum/tgs_event_handler/proc/HandleEvent(event_code, ...)
set waitfor = FALSE
return
//user definable chat command
/// User definable chat command
/datum/tgs_chat_command
var/name = "" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command
var/help_text = "" //help text for this command
var/admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins
/// The string to trigger this command on a chat bot. e.g `@bot name ...` or `!tgs name ...`
var/name = ""
/// The help text displayed for this command
var/help_text = ""
/// If this command should be available to game administrators only
var/admin_only = FALSE
//override to implement command
//sender: The tgs_chat_user who send to command
//params: The trimmed string following the command name
//The return value will be stringified and sent to the appropriate chat
/**
* Process command activation. Should return a string to respond to the issuer with.
*
* sender - The [/datum/tgs_chat_user] who issued the command.
* params - The trimmed string following the command `/datum/tgs_chat_command/var/name].
*/
/datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params)
CRASH("[type] has no implementation for Run()")
//FUNCTIONS
// API FUNCTIONS
//Returns the respective supported /datum/tgs_version of the API
/world/proc/TgsMaximumAPIVersion()
/// Returns the maximum supported [/datum/tgs_version] of the DMAPI.
/world/proc/TgsMaximumApiVersion()
return
/world/proc/TgsMinimumAPIVersion()
/// Returns the minimum supported [/datum/tgs_version] of the DMAPI.
/world/proc/TgsMinimumApiVersion()
return
//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise
//No function below this succeeds if it returns FALSE or if TgsNew() has yet to be called
/**
* Returns [TRUE] if DreamDaemon was launched under TGS, the API matches, and was properly initialized. [FALSE] will be returned otherwise.
*/
/world/proc/TgsAvailable()
return
//Forces a hard reboot of BYOND by ending the process
//unlike del(world) clients will try to reconnect
//If the service has not requested a shutdown, the next server will take over
// No function below this succeeds if it TgsAvailable() returns FALSE or if TgsNew() has yet to be called.
/**
* Forces a hard reboot of DreamDaemon by ending the process.
*
* Unlike del(world) clients will try to reconnect.
* If TGS has not requested a [TGS_REBOOT_MODE_SHUTDOWN] DreamDaemon will be launched again
*/
/world/proc/TgsEndProcess()
return
//Send a message to non-admin connected chats
//message: The message to send
//admin_only: If TRUE, message will instead be sent to only admin connected chats
/world/proc/TgsTargetedChatBroadcast(message, admin_only)
/**
* Send a message to connected chats.
*
* message - The string to send.
* admin_only: If [TRUE], message will be sent to admin connected chats. Vice-versa applies.
*/
/world/proc/TgsTargetedChatBroadcast(message, admin_only = FALSE)
return
//Send a private message to a specific user
//message: The message to send
//user: The /datum/tgs_chat_user to send to
/**
* Send a private message to a specific user.
*
* message - The string to send.
* user: The [/datum/tgs_chat_user] to PM.
*/
/world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user)
return
//The following functions will sleep if a call to TgsNew() is sleeping
// The following functions will sleep if a call to TgsNew() is sleeping
//Sends a message to connected game chats
//message: The message to send
//channels: optional channels to limit the broadcast to
/world/proc/TgsChatBroadcast(message, list/channels)
/**
* Send a message to connected chats that are flagged as game-related in TGS.
*
* message - The string to send.
* channels - Optional list of [/datum/tgs_chat_channel]s to restrict the message to.
*/
/world/proc/TgsChatBroadcast(message, list/channels = null)
return
//Gets the current /datum/tgs_version of the server tools running the server
/// Returns the current [/datum/tgs_version] of TGS if it is running the server, null otherwise.
/world/proc/TgsVersion()
return
//Gets the current /datum/tgs_version of the DMAPI being used
/// Returns the current [/datum/tgs_version] of the DMAPI being used if it was activated, null otherwise.
/world/proc/TgsApiVersion()
return
//Gets the name of the TGS instance running the game
/// Returns the name of the TGS instance running the game if TGS is present, null otherwise.
/world/proc/TgsInstanceName()
return
//Get the current `/datum/tgs_revision_information`
/// Return the current [/datum/tgs_revision_information] of the running server if TGS is present, null otherwise.
/world/proc/TgsRevision()
return
//Get the current BYOND security level
/// Returns the current BYOND security level as a TGS_SECURITY_ define if TGS is present, null otherwise.
/world/proc/TgsSecurityLevel()
return
//Gets a list of active `/datum/tgs_revision_information/test_merge`s
/// Returns a list of active [/datum/tgs_revision_information/test_merge]s if TGS is present, null otherwise.
/world/proc/TgsTestMerges()
return
//Gets a list of connected tgs_chat_channel
/// Returns a list of connected [/datum/tgs_chat_channel]s if TGS is present, null otherwise.
/world/proc/TgsChatChannelInfo()
return

View File

@@ -5,4 +5,7 @@ GLOBAL_LIST_EMPTY(meteor_list)
GLOBAL_LIST_EMPTY(wire_color_directory) // This is an associative list with the `holder_type` as the key, and a list of colors as the value.
// Reference list for disposal sort junctions. Filled up by sorting junction's New()
GLOBAL_LIST_EMPTY(tagger_locations)
GLOBAL_LIST_EMPTY(tagger_locations)
GLOBAL_LIST_INIT(char_directory_tags, list("Pred", "Prey", "Switch", "Non-Vore", "Unset"))
GLOBAL_LIST_INIT(char_directory_erptags, list("Top", "Bottom", "Switch", "No ERP", "Unset"))

View File

@@ -6,4 +6,3 @@ GLOBAL_LIST_EMPTY(directory) //all ckeys with associated client
GLOBAL_LIST_EMPTY(clients)
GLOBAL_LIST_EMPTY(players_by_zlevel)
GLOBAL_LIST_EMPTY(round_text_log)
GLOBAL_LIST_EMPTY(ghost_mob_list) //CHOMPedit List of all ghosts, including clientless. Excludes /mob/new_player

View File

@@ -1 +1,2 @@
var/datum/gear_tweak/color/gear_tweak_free_color_choice = new()
var/datum/gear_tweak/color/gear_tweak_free_color_choice = new()
var/datum/gear_tweak/implant_location/gear_tweak_implant_location = new()

View File

@@ -43,6 +43,11 @@ var/global/list/facial_hair_styles_male_list = list()
var/global/list/facial_hair_styles_female_list = list()
var/global/list/skin_styles_female_list = list() //unused
var/global/list/body_marking_styles_list = list() //stores /datum/sprite_accessory/marking indexed by name
var/global/list/ear_styles_list = list() // Stores /datum/sprite_accessory/ears indexed by type
var/global/list/tail_styles_list = list() // Stores /datum/sprite_accessory/tail indexed by type
var/global/list/wing_styles_list = list() // Stores /datum/sprite_accessory/wing indexed by type
GLOBAL_LIST_INIT(custom_species_bases, new) // Species that can be used for a Custom Species icon base
//Underwear
var/datum/category_collection/underwear/global_underwear = new()
@@ -94,13 +99,13 @@ var/global/list/string_slot_flags = list(
"holster" = SLOT_HOLSTER
)
/proc/get_mannequin(var/ckey)
if(!mannequins_)
mannequins_ = new()
. = mannequins_[ckey]
if(!.)
. = new/mob/living/carbon/human/dummy/mannequin()
mannequins_[ckey] = .
GLOBAL_LIST_EMPTY(mannequins)
/proc/get_mannequin(var/ckey = "NULL")
var/mob/living/carbon/human/dummy/mannequin/M = GLOB.mannequins[ckey]
if(!istype(M))
GLOB.mannequins[ckey] = new /mob/living/carbon/human/dummy/mannequin(null)
M = GLOB.mannequins[ckey]
return M
//////////////////////////
/////Initial Building/////
@@ -214,6 +219,23 @@ var/global/list/string_slot_flags = list(
var/decl/closet_appearance/app = new T()
GLOB.closet_appearances[T] = app
paths = typesof(/datum/sprite_accessory/ears) - /datum/sprite_accessory/ears
for(var/path in paths)
var/obj/item/clothing/head/instance = new path()
ear_styles_list[path] = instance
// Custom Tails
paths = typesof(/datum/sprite_accessory/tail) - /datum/sprite_accessory/tail - /datum/sprite_accessory/tail/taur
for(var/path in paths)
var/datum/sprite_accessory/tail/instance = new path()
tail_styles_list[path] = instance
// Custom Wings
paths = typesof(/datum/sprite_accessory/wing) - /datum/sprite_accessory/wing
for(var/path in paths)
var/datum/sprite_accessory/wing/instance = new path()
wing_styles_list[path] = instance
// VOREStation Add - Vore Modes!
paths = typesof(/datum/digest_mode)
for(var/T in paths)
@@ -221,6 +243,41 @@ var/global/list/string_slot_flags = list(
GLOB.digest_modes[DM.id] = DM
// VOREStation Add End
/*
// Custom species traits
paths = typesof(/datum/trait) - /datum/trait
for(var/path in paths)
var/datum/trait/instance = new path()
if(!instance.name)
continue //A prototype or something
var/cost = instance.cost
traits_costs[path] = cost
all_traits[path] = instance
switch(cost)
if(-INFINITY to -0.1)
negative_traits[path] = instance
if(0)
neutral_traits[path] = instance
if(0.1 to INFINITY)
positive_traits[path] = instance
*/
// Custom species icon bases
var/list/blacklisted_icons = list(SPECIES_CUSTOM,SPECIES_PROMETHEAN) //VOREStation Edit
var/list/whitelisted_icons = list(SPECIES_FENNEC,SPECIES_XENOHYBRID) //VOREStation Edit
for(var/species_name in GLOB.playable_species)
if(species_name in blacklisted_icons)
continue
var/datum/species/S = GLOB.all_species[species_name]
if(S.spawn_flags & SPECIES_IS_WHITELISTED)
continue
GLOB.custom_species_bases += species_name
for(var/species_name in whitelisted_icons)
GLOB.custom_species_bases += species_name
return 1 // Hooks must return 1
return 1
/* // Uncomment to debug chemical reaction list.

View File

@@ -13,4 +13,12 @@ var/global/list/vore_reagent_sounds = list(
'sound/vore/walkslosh10.ogg',
"None" = null)
/var/global/list/existing_metroids = list() //Global variable for tracking metroids for the event announcement. Needs to go here for load order.
/var/global/list/existing_metroids = list() //Global variable for tracking metroids for the event announcement. Needs to go here for load order.
//stuff that only synths can eat
var/global/list/edible_tech = list(/obj/item/weapon/cell,
/obj/item/weapon/circuitboard,
/obj/item/integrated_circuit,
/obj/item/broken_device,
/obj/item/brokenbug,
)

View File

@@ -2,20 +2,17 @@
* VOREStation global lists
*/
var/global/list/ear_styles_list = list() // Stores /datum/sprite_accessory/ears indexed by type
var/global/list/hair_accesories_list= list()// Stores /datum/sprite_accessory/hair_accessory indexed by type
var/global/list/tail_styles_list = list() // Stores /datum/sprite_accessory/tail indexed by type
var/global/list/wing_styles_list = list() // Stores /datum/sprite_accessory/wing indexed by type
var/global/list/negative_traits = list() // Negative custom species traits, indexed by path
var/global/list/neutral_traits = list() // Neutral custom species traits, indexed by path
var/global/list/everyone_traits = list() // Neutral traits available to all species, indexed by path
var/global/list/positive_traits = list() // Positive custom species traits, indexed by path
var/global/list/traits_costs = list() // Just path = cost list, saves time in char setup
var/global/list/all_traits = list() // All of 'em at once (same instances)
var/global/list/active_ghost_pods = list()
var/global/list/sensorpreflist = list("Off", "Binary", "Vitals", "Tracking", "No Preference") //TFF 5/8/19 - Suit Sensors global list
var/global/list/custom_species_bases = list() // Species that can be used for a Custom Species icon base
//stores numeric player size options indexed by name
var/global/list/player_sizes_list = list(
"Macro" = RESIZE_HUGE,
@@ -106,30 +103,74 @@ var/global/list/fancy_release_sounds = list(
)
var/global/list/global_vore_egg_types = list(
"Unathi" = UNATHI_EGG,
"Tajaran" = TAJARAN_EGG,
"Akula" = AKULA_EGG,
"Skrell" = SKRELL_EGG,
"Nevrean" = NEVREAN_EGG,
"Sergal" = SERGAL_EGG,
"Human" = HUMAN_EGG,
"Slime" = SLIME_EGG,
"Egg" = EGG_EGG,
"Xenochimera" = XENOCHIMERA_EGG,
"Xenomorph" = XENOMORPH_EGG)
"Unathi",
"Tajara",
"Akula",
"Skrell",
"Sergal",
"Nevrean",
"Human",
"Slime",
"Egg",
"Xenochimera",
"Xenomorph",
"Chocolate",
"Boney",
"Slime glob",
"Chicken",
"Synthetic",
"Bluespace Floppy",
"Bluespace Compressed File",
"Bluespace CD",
"Escape pod",
"Cooking error",
"Web cocoon",
"Honeycomb",
"Bug cocoon",
"Rock",
"Yellow",
"Blue",
"Green",
"Orange",
"Purple",
"Red",
"Rainbow",
"Spotted pink")
var/global/list/tf_vore_egg_types = list(
"Unathi" = /obj/structure/closet/secure_closet/egg/unathi,
"Tajara" = /obj/structure/closet/secure_closet/egg/tajaran,
"Akula" = /obj/structure/closet/secure_closet/egg/shark,
"Skrell" = /obj/structure/closet/secure_closet/egg/skrell,
"Sergal" = /obj/structure/closet/secure_closet/egg/sergal,
"Nevrean" = /obj/structure/closet/secure_closet/egg/nevrean,
"Human" = /obj/structure/closet/secure_closet/egg/human,
"Slime" = /obj/structure/closet/secure_closet/egg/slime,
"Egg" = /obj/structure/closet/secure_closet/egg,
"Xenochimera" = /obj/structure/closet/secure_closet/egg/scree,
"Xenomorph" = /obj/structure/closet/secure_closet/egg/xenomorph)
"Unathi" = /obj/item/weapon/storage/vore_egg/unathi,
"Tajara" = /obj/item/weapon/storage/vore_egg/tajaran,
"Akula" = /obj/item/weapon/storage/vore_egg/shark,
"Skrell" = /obj/item/weapon/storage/vore_egg/skrell,
"Sergal" = /obj/item/weapon/storage/vore_egg/sergal,
"Nevrean" = /obj/item/weapon/storage/vore_egg/nevrean,
"Human" = /obj/item/weapon/storage/vore_egg/human,
"Slime" = /obj/item/weapon/storage/vore_egg/slime,
"Egg" = /obj/item/weapon/storage/vore_egg,
"Xenochimera" = /obj/item/weapon/storage/vore_egg/scree,
"Xenomorph" = /obj/item/weapon/storage/vore_egg/xenomorph,
"Chocolate" = /obj/item/weapon/storage/vore_egg/chocolate,
"Boney" = /obj/item/weapon/storage/vore_egg/owlpellet,
"Slime glob" = /obj/item/weapon/storage/vore_egg/slimeglob,
"Chicken" = /obj/item/weapon/storage/vore_egg/chicken,
"Synthetic" = /obj/item/weapon/storage/vore_egg/synthetic,
"Bluespace Floppy" = /obj/item/weapon/storage/vore_egg/floppy,
"Bluespace Compressed File" = /obj/item/weapon/storage/vore_egg/file,
"Bluespace CD" = /obj/item/weapon/storage/vore_egg/cd,
"Escape pod" = /obj/item/weapon/storage/vore_egg/escapepod,
"Cooking error" = /obj/item/weapon/storage/vore_egg/badrecipe,
"Web cocoon" = /obj/item/weapon/storage/vore_egg/cocoon,
"Honeycomb" = /obj/item/weapon/storage/vore_egg/honeycomb,
"Bug cocoon" = /obj/item/weapon/storage/vore_egg/bugcocoon,
"Rock" = /obj/item/weapon/storage/vore_egg/rock,
"Yellow" = /obj/item/weapon/storage/vore_egg/yellow,
"Blue" = /obj/item/weapon/storage/vore_egg/blue,
"Green" = /obj/item/weapon/storage/vore_egg/green,
"Orange" = /obj/item/weapon/storage/vore_egg/orange,
"Purple" = /obj/item/weapon/storage/vore_egg/purple,
"Red" = /obj/item/weapon/storage/vore_egg/red,
"Rainbow" = /obj/item/weapon/storage/vore_egg/rainbow,
"Spotted pink" = /obj/item/weapon/storage/vore_egg/pinkspots)
var/global/list/edible_trash = list(/obj/item/broken_device,
/obj/item/clothing/accessory/collar, //TFF 10/7/19 - add option to nom collars,
@@ -145,6 +186,7 @@ var/global/list/edible_trash = list(/obj/item/broken_device,
/obj/item/device/paicard,
/obj/item/device/pda,
/obj/item/device/radio/headset,
/obj/item/device/starcaster_news, //chompstation addition
/obj/item/inflatable/torn,
/obj/item/organ,
/obj/item/stack/material/cardboard,
@@ -180,7 +222,9 @@ var/global/list/edible_trash = list(/obj/item/broken_device,
/obj/item/weapon/storage/fancy/cigarettes,
/obj/item/weapon/storage/fancy/crayons,
/obj/item/weapon/storage/fancy/egg_box,
/obj/item/weapon/storage/wallet)
/obj/item/weapon/storage/wallet,
/obj/item/weapon/storage/vore_egg,
/obj/item/weapon/material/kitchen) //chompstation addition
var/global/list/contamination_flavors = list(
"Generic" = contamination_flavors_generic,
@@ -434,30 +478,12 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
/hook/startup/proc/init_vore_datum_ref_lists()
var/paths
// Custom Ears
paths = typesof(/datum/sprite_accessory/ears) - /datum/sprite_accessory/ears
for(var/path in paths)
var/obj/item/clothing/head/instance = new path()
ear_styles_list[path] = instance
// Custom Tails
paths = typesof(/datum/sprite_accessory/tail) - /datum/sprite_accessory/tail - /datum/sprite_accessory/tail/taur
for(var/path in paths)
var/datum/sprite_accessory/tail/instance = new path()
tail_styles_list[path] = instance
// Custom Wings
paths = typesof(/datum/sprite_accessory/wing) - /datum/sprite_accessory/wing
for(var/path in paths)
var/datum/sprite_accessory/wing/instance = new path()
wing_styles_list[path] = instance
// Custom Hair Accessories
paths = typesof(/datum/sprite_accessory/hair_accessory) - /datum/sprite_accessory/hair_accessory
for(var/path in paths)
var/datum/sprite_accessory/hair_accessory/instance = new path()
hair_accesories_list[path] = instance
// Custom species traits
paths = typesof(/datum/trait) - /datum/trait
for(var/path in paths)
@@ -472,20 +498,27 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
negative_traits[path] = instance
if(0)
neutral_traits[path] = instance
if(!(instance.custom_only))
everyone_traits[path] = instance
if(0.1 to INFINITY)
positive_traits[path] = instance
// Custom species icon bases
var/list/blacklisted_icons = list(SPECIES_CUSTOM,SPECIES_PROMETHEAN) //Just ones that won't work well.
var/list/whitelisted_icons = list(SPECIES_FENNEC,SPECIES_XENOHYBRID) //Include these anyway
for(var/species_name in GLOB.playable_species)
if(species_name in blacklisted_icons)
continue
var/datum/species/S = GLOB.all_species[species_name]
if(S.spawn_flags & SPECIES_IS_WHITELISTED)
continue
custom_species_bases += species_name
for(var/species_name in whitelisted_icons)
custom_species_bases += species_name
// Weaver recipe stuff
paths = typesof(/datum/weaver_recipe/structure) - /datum/weaver_recipe/structure
for(var/path in paths)
var/datum/weaver_recipe/instance = new path()
if(!instance.title)
continue //A prototype or something
weavable_structures[instance.title] = instance
paths = typesof(/datum/weaver_recipe/item) - /datum/weaver_recipe/item
for(var/path in paths)
var/datum/weaver_recipe/instance = new path()
if(!instance.title)
continue //A prototype or something
weavable_items[instance.title] = instance
return 1 // Hooks must return 1
var/global/list/weavable_structures = list()
var/global/list/weavable_items = list()

View File

@@ -65,45 +65,110 @@
if (config.log_say)
WRITE_LOG(diary, "SAY: [speaker.simple_info_line()]: [html_decode(text)]")
//Log the message to in-game dialogue logs, as well.
//Log the message to in-game dialogue logs, as well. //CHOMPEdit Begin
if(speaker.client)
speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:#32cd32\">[text]</span>"
GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:#32cd32\">[text]</span>"
//speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:#32cd32\">[text]</span>"
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "say", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:#32cd32\">[text]</span>"
//CHOMPEdit End
/proc/log_ooc(text, client/user)
if (config.log_ooc)
WRITE_LOG(diary, "OOC: [user.simple_info_line()]: [html_decode(text)]")
GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[user]</b>) <u>OOC:</u> - <span style=\"color:blue\"><b>[text]</b></span>"
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = user.ckey, "sender_mob" = user.mob.real_name, "message_type" = "ooc", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[user]</b>) <u>OOC:</u> - <span style=\"color:blue\"><b>[text]</b></span>"
/proc/log_aooc(text, client/user)
if (config.log_ooc)
WRITE_LOG(diary, "AOOC: [user.simple_info_line()]: [html_decode(text)]")
GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[user]</b>) <u>AOOC:</u> - <span style=\"color:red\"><b>[text]</b></span>"
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = user.ckey, "sender_mob" = user.mob.real_name, "message_type" = "aooc", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[user]</b>) <u>AOOC:</u> - <span style=\"color:red\"><b>[text]</b></span>"
/proc/log_looc(text, client/user)
if (config.log_ooc)
WRITE_LOG(diary, "LOOC: [user.simple_info_line()]: [html_decode(text)]")
GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[user]</b>) <u>LOOC:</u> - <span style=\"color:orange\"><b>[text]</b></span>"
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = user.ckey, "sender_mob" = user.mob.real_name, "message_type" = "looc", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[user]</b>) <u>LOOC:</u> - <span style=\"color:orange\"><b>[text]</b></span>"
/proc/log_whisper(text, mob/speaker)
if (config.log_whisper)
WRITE_LOG(diary, "WHISPER: [speaker.simple_info_line()]: [html_decode(text)]")
if(speaker.client)
speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:gray\"><i>[text]</i></span>"
GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:gray\"><i>[text]</i></span>"
//speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:gray\"><i>[text]</i></span>"
//GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>SAY:</u> - <span style=\"color:gray\"><i>[text]</i></span>"
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "whisper", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
/proc/log_emote(text, mob/speaker)
if (config.log_emote)
WRITE_LOG(diary, "EMOTE: [speaker.simple_info_line()]: [html_decode(text)]")
//CHOMPEdit Begin
if(speaker.client)
speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>EMOTE:</u> - <span style=\"color:#CCBADC\">[text]</span>"
GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>EMOTE:</u> - <span style=\"color:#CCBADC\">[text]</span>"
//speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>EMOTE:</u> - <span style=\"color:#CCBADC\">[text]</span>"
//GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>EMOTE:</u> - <span style=\"color:#CCBADC\">[text]</span>"
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "emote", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//CHOMPEdit End
/proc/log_attack(attacker, defender, message)
if (config.log_attack)
@@ -124,14 +189,40 @@
/proc/log_ghostsay(text, mob/speaker)
if (config.log_say)
WRITE_LOG(diary, "DEADCHAT: [speaker.simple_info_line()]: [html_decode(text)]")
speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>DEADSAY:</u> - <span style=\"color:green\">[text]</span>"
GLOB.round_text_log += "<font size=1><span style=\"color:#7e668c\"><b>([time_stamp()])</b> (<b>[src]/[speaker.client]</b>) <u>DEADSAY:</u> - [text]</span></font>"
//CHOMPEdit Begin
if(speaker.client)
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "deadsay", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>DEADSAY:</u> - <span style=\"color:green\">[text]</span>"
//GLOB.round_text_log += "<font size=1><span style=\"color:#7e668c\"><b>([time_stamp()])</b> (<b>[src]/[speaker.client]</b>) <u>DEADSAY:</u> - [text]</span></font>"
//CHOMPEdit End
/proc/log_ghostemote(text, mob/speaker)
if (config.log_emote)
WRITE_LOG(diary, "DEADEMOTE: [speaker.simple_info_line()]: [html_decode(text)]")
//CHOMPEdit Begin
if(speaker.client)
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "deademote", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//CHOMPEdit End
/proc/log_adminwarn(text)
if (config.log_adminwarn)
@@ -140,10 +231,23 @@
/proc/log_pda(text, mob/speaker)
if (config.log_pda)
WRITE_LOG(diary, "PDA: [speaker.simple_info_line()]: [html_decode(text)]")
//CHOMPEdit Begin
if(speaker.client)
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "pda", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>MSG:</u> - <span style=\"color:[COLOR_GREEN]\">[text]</span>"
GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>MSG:</u> - <span style=\"color:[COLOR_GREEN]\">[text]</span>"
//speaker.dialogue_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>MSG:</u> - <span style=\"color:[COLOR_GREEN]\">[text]</span>"
//GLOB.round_text_log += "<b>([time_stamp()])</b> (<b>[speaker]/[speaker.client]</b>) <u>MSG:</u> - <span style=\"color:[COLOR_GREEN]\">[text]</span>"
//CHOMPEdit End
/proc/log_to_dd(text)
to_world_log(text) //this comes before the config check because it can't possibly runtime

View File

@@ -1,11 +1,53 @@
/proc/log_nsay(text, inside, mob/speaker)
if (config.log_say)
WRITE_LOG(diary, "NSAY (NIF:[inside]): [speaker.simple_info_line()]: [html_decode(text)]")
//CHOMPEdit Begin
if(speaker.client)
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "nsay", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//CHOMPEdit End
/proc/log_nme(text, inside, mob/speaker)
if (config.log_emote)
WRITE_LOG(diary, "NME (NIF:[inside]): [speaker.simple_info_line()]: [html_decode(text)]")
//CHOMPEdit Begin
if(speaker.client)
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "nme", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//CHOMPEdit End
/proc/log_subtle(text, mob/speaker)
if (config.log_emote)
WRITE_LOG(diary, "SUBTLE: [speaker.simple_info_line()]: [html_decode(text)]")
//CHOMPEdit Begin
if(speaker.client)
if(!SSdbcore.IsConnected())
establish_db_connection()
if(!SSdbcore.IsConnected())
return null
var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_dialog (mid, time, ckey, mob, type, message) VALUES (null, NOW(), :sender_ckey, :sender_mob, :message_type, :message_content)", \
list("sender_ckey" = speaker.ckey, "sender_mob" = speaker.real_name, "message_type" = "subtle", "message_content" = text))
if(!query_insert.Execute())
log_debug("Error during logging: "+query_insert.ErrorMsg())
qdel(query_insert)
return
qdel(query_insert)
//CHOMPEdit End

View File

@@ -110,7 +110,7 @@ Proc for attack log creation, because really why not
6 is additional information, anything that needs to be added
*/
/proc/add_attack_logs(mob/user, mob/target, what_done, var/admin_notify = TRUE)
/proc/add_attack_logs(mob/user, mob/target, what_done, var/admin_notify = TRUE, var/use_async = TRUE) //CHOMPEdit
if(islist(target)) //Multi-victim adding
var/list/targets = target
for(var/mob/M in targets)
@@ -120,10 +120,21 @@ Proc for attack log creation, because really why not
var/user_str = key_name(user)
var/target_str = key_name(target)
if(ismob(user))
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Attacked [target_str]: [what_done]</font>")
if(ismob(user)) //CHOMPEdit Begin
//user.attack_log += text("\[[time_stamp()]\] <font color='red'>Attacked [target_str]: [what_done]</font>")
//var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_attacklog (id, time, ckey, mob, message) VALUES (null, NOW(), :t_ckey, :t_mob, :t_content)", list("t_ckey" = user.ckey, "t_mob" = user.real_name, "t_content" = "<font color='red'>Attacked [target_str]: [what_done]</font>"))
//query_insert.Execute(async=use_async)
//qdel(query_insert)
if(SSdbcore.Connect())
rustg_sql_query_async(SSdbcore.connection, "INSERT INTO erro_attacklog (id, time, ckey, mob, message) VALUES (null, NOW(), :t_ckey, :t_mob, :t_content)", json_encode(list("t_ckey" = user.ckey, "t_mob" = user.real_name, "t_content" = "<font color='red'>Attacked [target_str]: [what_done]</font>")))
if(ismob(target))
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Attacked by [user_str]: [what_done]</font>")
//target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Attacked by [user_str]: [what_done]</font>")
//var/DBQuery/query_insert = SSdbcore.NewQuery("INSERT INTO erro_attacklog (id, time, ckey, mob, message) VALUES (null, NOW(), :t_ckey, :t_mob, :t_content)", list("t_ckey" = target.ckey, "t_mob" = target.real_name, "t_content" = "<font color='orange'>Attacked by [user_str]: [what_done]</font>"))
//query_insert.Execute(async=use_async)
//qdel(query_insert)
if(SSdbcore.Connect())
rustg_sql_query_async(SSdbcore.connection, "INSERT INTO erro_attacklog (id, time, ckey, mob, message) VALUES (null, NOW(), :t_ckey, :t_mob, :t_content)", json_encode(list("t_ckey" = target.ckey, "t_mob" = target.real_name, "t_content" = "<font color='orange'>Attacked by [user_str]: [what_done]</font>")))
//CHOMPEdit End
log_attack(user_str,target_str,what_done)
if(admin_notify)
msg_admin_attack("[key_name_admin(user)] vs [target_str]: [what_done]")

View File

@@ -14,9 +14,11 @@
*/
// Run all strings to be used in an SQL query through this proc first to properly escape out injection attempts.
/proc/sanitizeSQL(var/t as text)
var/sqltext = dbcon.Quote(t);
return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that
/proc/sanitizeSQL(var/t as text)
//var/sqltext = dbcon.Quote(t); //CHOMPEdit Begin
//return copytext(sqltext, 2, length(sqltext));//Quote() adds quotes around input, we already do that
return t
//CHOMPEdit End
/*
* Text sanitization
@@ -402,9 +404,9 @@ proc/TextPreview(var/string,var/len=40)
t = replacetext(t, "\[/grid\]", "</td></tr></table>")
t = replacetext(t, "\[row\]", "</td><tr>")
t = replacetext(t, "\[cell\]", "<td>")
t = replacetext(t, "\[logo\]", "<img src = ntlogo.png>")
t = replacetext(t, "\[redlogo\]", "<img src = redntlogo.png>")
t = replacetext(t, "\[sglogo\]", "<img src = sglogo.png>")
t = replacetext(t, "\[logo\]", "<img src = https://raw.githubusercontent.com/CHOMPStation2/CHOMPStation2/master/html/images/ntlogo.png>") //CHOMPEdit
t = replacetext(t, "\[redlogo\]", "<img src = https://raw.githubusercontent.com/CHOMPStation2/CHOMPStation2/master/html/images/redntlogo.png>") //CHOMPEdit
t = replacetext(t, "\[sglogo\]", "<img src = https://raw.githubusercontent.com/CHOMPStation2/CHOMPStation2/master/html/images/sglogo.png>") //CHOMPEdit
t = replacetext(t, "\[editorbr\]", "")
return t

View File

@@ -1277,6 +1277,10 @@ var/list/WALLITEMS = list(
colour += temp_col
return colour
/proc/color_square(red, green, blue, hex)
var/color = hex ? hex : "#[num2hex(red, 2)][num2hex(green, 2)][num2hex(blue, 2)]"
return "<span style='font-face: fixedsys; font-size: 14px; background-color: [color]; color: [color]'>___</span>"
var/mob/dview/dview_mob = new
//Version of view() which ignores darkness, because BYOND doesn't have it.
@@ -1609,6 +1613,46 @@ GLOBAL_REAL_VAR(list/stack_trace_storage)
/proc/href(href_src, list/href_params, href_text)
return "<a href='?src=\ref[href_src];[list2params(href_params)]'>[href_text]</a>"
// This is a helper for anything that wants to render the map in TGUI
/proc/get_tgui_plane_masters()
. = list()
// 'Utility' planes
. += new /obj/screen/plane_master/fullbright //Lighting system (lighting_overlay objects)
. += new /obj/screen/plane_master/lighting //Lighting system (but different!)
. += new /obj/screen/plane_master/ghosts //Ghosts!
. += new /obj/screen/plane_master{plane = PLANE_AI_EYE} //AI Eye!
. += new /obj/screen/plane_master{plane = PLANE_CH_STATUS} //Status is the synth/human icon left side of medhuds
. += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH} //Health bar
. += new /obj/screen/plane_master{plane = PLANE_CH_LIFE} //Alive-or-not icon
. += new /obj/screen/plane_master{plane = PLANE_CH_ID} //Job ID icon
. += new /obj/screen/plane_master{plane = PLANE_CH_WANTED} //Wanted status
. += new /obj/screen/plane_master{plane = PLANE_CH_IMPLOYAL} //Loyalty implants
. += new /obj/screen/plane_master{plane = PLANE_CH_IMPTRACK} //Tracking implants
. += new /obj/screen/plane_master{plane = PLANE_CH_IMPCHEM} //Chemical implants
. += new /obj/screen/plane_master{plane = PLANE_CH_SPECIAL} //"Special" role stuff
. += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_OOC} //OOC status HUD
. += new /obj/screen/plane_master{plane = PLANE_ADMIN1} //For admin use
. += new /obj/screen/plane_master{plane = PLANE_ADMIN2} //For admin use
. += new /obj/screen/plane_master{plane = PLANE_ADMIN3} //For admin use
. += new /obj/screen/plane_master{plane = PLANE_MESONS} //Meson-specific things like open ceilings.
. += new /obj/screen/plane_master{plane = PLANE_BUILDMODE} //Things that only show up while in build mode
// Real tangible stuff planes
. += new /obj/screen/plane_master/main{plane = TURF_PLANE}
. += new /obj/screen/plane_master/main{plane = OBJ_PLANE}
. += new /obj/screen/plane_master/main{plane = MOB_PLANE}
. += new /obj/screen/plane_master/cloaked //Cloaked atoms!
//VOREStation Add - Random other plane masters
. += new /obj/screen/plane_master{plane = PLANE_CH_STATUS_R} //Right-side status icon
. += new /obj/screen/plane_master{plane = PLANE_CH_HEALTH_VR} //Health bar but transparent at 100
. += new /obj/screen/plane_master{plane = PLANE_CH_BACKUP} //Backup implant status
. += new /obj/screen/plane_master{plane = PLANE_CH_VANTAG} //Vore Antags
. += new /obj/screen/plane_master{plane = PLANE_AUGMENTED} //Augmented reality
//VOREStation Add End
/proc/CallAsync(datum/source, proctype, list/arguments)
set waitfor = FALSE
return call(source, proctype)(arglist(arguments))
return call(source, proctype)(arglist(arguments))

View File

@@ -10,3 +10,7 @@
viewX = text2num(viewrangelist[1])
viewY = text2num(viewrangelist[2])
return list(viewX, viewY)
// Used to get `atom/O as obj|mob|turf in view()` to match against strings containing apostrophes immediately after substrings that match to other objects. Somehow. - Ater
/proc/_validate_atom(atom/A)
return view()

View File

@@ -0,0 +1,25 @@
GLOBAL_LIST_EMPTY(widelists)
/proc/widelist(var/list/input_list)
var/list_hash = gen_hash_list(input_list)
if(!(list_hash in GLOB.widelists))
GLOB.widelists[list_hash] = input_list
return GLOB.widelists[list_hash]
/proc/gen_hash_list(var/list/input_list)
var/string = ""
for(var/item in input_list)
var/p1 = ""
if(islist(item))
p1 = ">>>::-;[gen_hash_list(item)];-::<<<"
else
p1 = "[item]"
var/p2 = ""
if(islist(input_list[item]))
p2 = ">>>::-;[gen_hash_list(input_list[item])];-::<<<"
else
p2 = "[input_list[item]]"
string += "[p1]::--::[p2]::;;;"
return md5(string)

View File

@@ -37,4 +37,7 @@
#define random_id(key,min_id,max_id) uniqueness_repository.Generate(/datum/uniqueness_generator/id_random, key, min_id, max_id)
#define ARGS_DEBUG log_debug("[__FILE__] - [__LINE__]") ; for(var/arg in args) { log_debug("\t[log_info_line(arg)]") }
#define ARGS_DEBUG log_debug("[__FILE__] - [__LINE__]") ; for(var/arg in args) { log_debug("\t[log_info_line(arg)]") }
#define isitem(A) istype(A, /obj/item)
#define isTaurTail(A) istype(A, /datum/sprite_accessory/tail/taur)

View File

@@ -1,3 +1 @@
#define isbelly(A) istype(A, /obj/belly)
#define isitem(A) istype(A, /obj/item)
#define isTaurTail(A) istype(A, /datum/sprite_accessory/tail/taur)

View File

@@ -354,19 +354,13 @@
facedir(direction)
/obj/screen/click_catcher
name = "Darkness"
icon = 'icons/mob/screen_gen.dmi'
icon_state = "click_catcher"
plane = CLICKCATCHER_PLANE
layer = LAYER_HUD_UNDER
mouse_opacity = 2
screen_loc = "CENTER-7,CENTER-7"
/obj/screen/click_catcher/proc/MakeGreed()
. = list()
for(var/i = 0, i<15, i++)
for(var/j = 0, j<15, j++)
var/obj/screen/click_catcher/CC = new()
CC.screen_loc = "NORTH-[i],EAST-[j]"
. += CC
screen_loc = "SOUTHWEST to NORTHEAST"
/obj/screen/click_catcher/Click(location, control, params)
var/list/modifiers = params2list(params)
@@ -374,7 +368,11 @@
var/mob/living/carbon/C = usr
C.swap_hand()
else
var/turf/T = screen_loc2turf(screen_loc, get_turf(usr))
var/list/P = params2list(params)
var/turf/T = screen_loc2turf(P["screen-loc"], get_turf(usr))
if(T)
if(modifiers["shift"])
usr.face_atom(T)
return 1
T.Click(location, control, params)
. = 1
return 1

View File

@@ -60,6 +60,8 @@
// Cyborgs have no range-checking unless there is item use
if(!W)
if(bolt && !bolt.malfunction && A.loc != module)
return
A.add_hiddenprint(src)
A.attack_robot(src)
return
@@ -119,35 +121,56 @@
/atom/proc/BorgCtrlShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlShiftClick(user)
/obj/machinery/door/airlock/BorgCtrlShiftClick(mob/user)
/obj/machinery/door/airlock/BorgCtrlShiftClick(var/mob/living/silicon/robot/user)
if(user.bolt && !user.bolt.malfunction)
return
AICtrlShiftClick(user)
/atom/proc/BorgShiftClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
ShiftClick(user)
/obj/machinery/door/airlock/BorgShiftClick(mob/user) // Opens and closes doors! Forwards to AI code.
/obj/machinery/door/airlock/BorgShiftClick(var/mob/living/silicon/robot/user) // Opens and closes doors! Forwards to AI code.
if(user.bolt && !user.bolt.malfunction)
return
AIShiftClick(user)
/atom/proc/BorgCtrlClick(var/mob/living/silicon/robot/user) //forward to human click if not overriden
CtrlClick(user)
/obj/machinery/door/airlock/BorgCtrlClick(mob/user) // Bolts doors. Forwards to AI code.
/obj/machinery/door/airlock/BorgCtrlClick(var/mob/living/silicon/robot/user) // Bolts doors. Forwards to AI code.
if(user.bolt && !user.bolt.malfunction)
return
AICtrlClick(user)
/obj/machinery/power/apc/BorgCtrlClick(mob/user) // turns off/on APCs. Forwards to AI code.
/obj/machinery/power/apc/BorgCtrlClick(var/mob/living/silicon/robot/user) // turns off/on APCs. Forwards to AI code.
if(user.bolt && !user.bolt.malfunction)
return
AICtrlClick(user)
/obj/machinery/turretid/BorgCtrlClick(mob/user) //turret control on/off. Forwards to AI code.
/obj/machinery/turretid/BorgCtrlClick(var/mob/living/silicon/robot/user) //turret control on/off. Forwards to AI code.
if(user.bolt && !user.bolt.malfunction)
return
AICtrlClick(user)
/atom/proc/BorgAltClick(var/mob/living/silicon/robot/user)
AltClick(user)
return
/obj/machinery/door/airlock/BorgAltClick(mob/user) // Eletrifies doors. Forwards to AI code.
/obj/machinery/door/airlock/BorgAltClick(var/mob/living/silicon/robot/user) // Eletrifies doors. Forwards to AI code.
if(user.bolt && !user.bolt.malfunction)
return
AIAltClick(user)
/obj/machinery/turretid/BorgAltClick(mob/user) //turret lethal on/off. Forwards to AI code.
/obj/machinery/turretid/BorgAltClick(var/mob/living/silicon/robot/user) //turret lethal on/off. Forwards to AI code.
if(user.bolt && !user.bolt.malfunction)
return
AIAltClick(user)
/*

View File

@@ -161,6 +161,13 @@
#define ui_ghost_pai "SOUTH: 6,CENTER+2:24"
#define ui_ghost_updown "SOUTH: 6,CENTER+3:24"
// NIF Soulcatcher guest ones
#define ui_nifsc_reenter "SOUTH:6,CENTER-3:24"
#define ui_nifsc_arproj "SOUTH:6,CENTER-2:24"
#define ui_nifsc_jumptoowner "SOUTH:6,CENTER-1:24"
#define ui_nifsc_nme "SOUTH:6,CENTER:24"
#define ui_nifsc_nsay "SOUTH:6,CENTER+1:24"
// Rig panel
#define ui_rig_deco1 "WEST:-7, SOUTH+5"
#define ui_rig_deco2 "WEST:-7, SOUTH+6"

View File

@@ -0,0 +1,30 @@
//Invesitgating a runtime made me discover that all simplemobs have HUD on hands set to themselves
//Which cause this original code to die because the mob does not have a mymob var...
//So yeah this is why we now check if it is type of mob first...
//Is this pretty? Fuck no, but its how i know to fix it -shark
//Oh also the swap button on simple mob hands has hud set to null so we also need to catch that.
/obj/screen/inventory/add_overlays()
if(!hud) //Simplemob swap hands button has this set to null :)
return
var/mob/user
if(istype(hud,/mob )) //Simplemob hands directly reference the mob in hud, dont ask me.
user = hud
else
user = hud.mymob //original intended behaviour
if(hud && user && slot_id)
var/obj/item/holding = user.get_active_hand()
if(!holding || user.get_equipped_item(slot_id))
return
var/image/item_overlay = image(holding)
item_overlay.alpha = 92
if(!holding.mob_can_equip(user, slot_id, disable_warning = TRUE))
item_overlay.color = "#ff0000"
else
item_overlay.color = "#00ff00"
object_overlays += item_overlay
add_overlay(object_overlays)

View File

@@ -0,0 +1,102 @@
/obj/screen/nifsc
icon = 'icons/mob/screen_nifsc.dmi'
/obj/screen/nifsc/MouseEntered(location,control,params)
flick(icon_state + "_anim", src)
openToolTip(usr, src, params, title = name, content = desc)
/obj/screen/nifsc/MouseExited()
closeToolTip(usr)
/obj/screen/nifsc/Click()
closeToolTip(usr)
/obj/screen/nifsc/reenter
name = "Re-enter NIF"
desc = "Return into the NIF"
icon_state = "reenter"
/obj/screen/nifsc/reenter/Click()
..()
var/mob/living/carbon/brain/caught_soul/CS = usr
CS.reenter_soulcatcher()
/obj/screen/nifsc/arproj
name = "AR project"
desc = "Project your form into Augmented Reality for those around your predator with the appearance of your loaded character."
icon_state = "arproj"
/obj/screen/nifsc/arproj/Click()
..()
var/mob/living/carbon/brain/caught_soul/CS = usr
CS.ar_project()
/obj/screen/nifsc/jumptoowner
name = "Jump back to host"
desc = "Jumb back to the Soulcather host"
icon_state = "jump"
/obj/screen/nifsc/jumptoowner/Click()
..()
var/mob/living/carbon/brain/caught_soul/CS = usr
CS.jump_to_owner()
/obj/screen/nifsc/nme
name = "Emote into Soulcatcher"
desc = "Emote into the NIF's Soulcatcher (circumventing AR emoting)"
icon_state = "nme"
/obj/screen/nifsc/nme/Click()
..()
var/mob/living/carbon/brain/caught_soul/CS = usr
CS.nme()
/obj/screen/nifsc/nsay
name = "Speak into Soulcatcher"
desc = "Speak into the NIF's Soulcatcher (circumventing AR speaking)"
icon_state = "nsay"
/obj/screen/nifsc/nsay/Click()
..()
var/mob/living/carbon/brain/caught_soul/CS = usr
CS.nsay()
/mob/living/carbon/brain/caught_soul/create_mob_hud(datum/hud/HUD, apply_to_client = TRUE)
..()
var/list/adding = list()
HUD.adding = adding
var/obj/screen/using
using = new /obj/screen/nifsc/reenter()
using.screen_loc = ui_nifsc_reenter
using.hud = src
adding += using
using = new /obj/screen/nifsc/arproj()
using.screen_loc = ui_nifsc_arproj
using.hud = src
adding += using
using = new /obj/screen/nifsc/jumptoowner()
using.screen_loc = ui_nifsc_jumptoowner
using.hud = src
adding += using
using = new /obj/screen/nifsc/nme()
using.screen_loc = ui_nifsc_nme
using.hud = src
adding += using
using = new /obj/screen/nifsc/nsay()
using.screen_loc = ui_nifsc_nsay
using.hud = src
adding += using
if(client && apply_to_client)
client.screen = list()
client.screen += HUD.adding
client.screen += client.void

View File

@@ -9,6 +9,14 @@
var/vorefootstep_volume = 75 //In future see about making a function to adjust volume serverside in config.txt, easy to do with reenable values. - Jack
var/nodebot_enabled = 0 //So, nodebot is a supplement to the TGS discord bot pretty much. For things likes faxes and the manifest it's very helpful because it's able to render html into an image and post it.
var/nodebot_location //We need to print the manifest to this location so nodebot can render it to chat. //NOTE: TO BE REPLACED BY BETTER CODE FOR FETCHING MANIFEST
var/ahelp_channel_tag //This is for tgs4 channels, if you're not running on tgs4, this won't work anyways. If it's not set, it will default to the admin channel.
var/discord_faxes_autoprint = 0 //Only turn this on if you're not using the nodebot.
var/discord_faxes_disabled = 0 //Turn this off if you don't want the TGS bot sending you messages whenever a fax is sent to central.
var/discord_ahelps_disabled = 0 //Turn this off if you don't want the TGS bot sending you messages whenever an ahelp ticket is created.
var/discord_ahelps_all = 0 //Turn this on if you want all admin-PMs to go to be sent to discord, and not only the first message of a ticket.
/hook/startup/proc/read_ch_config()
var/list/Lines = file2list("config/config.txt")
for(var/t in Lines)
@@ -22,11 +30,11 @@
var/pos = findtext(t, " ")
var/name = null
// var/value = null //Commenting out because config doesn't contain any values at the moment. - Jonathan
var/value = null
if (pos)
name = lowertext(copytext(t, 1, pos))
// value = copytext(t, pos + 1) //Commenting out because config doesn't contain any values at the moment. - Jonathan
value = copytext(t, pos + 1)
else
name = lowertext(t)
@@ -40,4 +48,18 @@
config.use_jobwhitelist = 1
if ("disable_emojis")
config.emojis = 0
if ("nodebot_enabled")
config.nodebot_enabled = 1
if ("discord_faxes_autoprint")
config.discord_faxes_autoprint = 1
if ("discord_faxes_disabled")
config.discord_faxes_disabled = 1
if ("discord_ahelps_disabled")
config.discord_ahelps_disabled = 1
if ("discord_ahelps_all")
config.discord_ahelps_all = 1
if ("nodebot_location")
config.nodebot_location = value
if ("ahelp_channel_tag")
config.ahelp_channel_tag = value
return 1

View File

@@ -0,0 +1,370 @@
SUBSYSTEM_DEF(dbcore)
name = "Database"
flags = SS_BACKGROUND
wait = 1 MINUTES
init_order = INIT_ORDER_DBCORE
var/failed_connection_timeout = 0
var/schema_mismatch = 0
var/db_minor = 0
var/db_major = 0
var/failed_connections = 0
var/last_error
var/list/active_queries = list()
var/connection // Arbitrary handle returned from rust_g.
/datum/controller/subsystem/dbcore/Initialize()
return ..()
/datum/controller/subsystem/dbcore/fire()
for(var/I in active_queries)
var/DBQuery/Q = I
if(world.time - Q.last_activity_time > (5 MINUTES))
message_admins("Found undeleted query, please check the server logs and notify coders.")
log_debug("Undeleted query: \"[Q.sql]\" LA: [Q.last_activity] LAT: [Q.last_activity_time]")
qdel(Q)
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/dbcore/Recover()
connection = SSdbcore.connection
/datum/controller/subsystem/dbcore/Shutdown()
//This is as close as we can get to the true round end before Disconnect() without changing where it's called, defeating the reason this is a subsystem
if(IsConnected())
Disconnect()
//nu
/datum/controller/subsystem/dbcore/can_vv_get(var_name)
return var_name != NAMEOF(src, connection) && var_name != NAMEOF(src, active_queries) && ..()
/datum/controller/subsystem/dbcore/vv_edit_var(var_name, var_value)
if(var_name == NAMEOF(src, connection))
return FALSE
return ..()
/datum/controller/subsystem/dbcore/proc/Connect()
if(IsConnected())
return TRUE
if(failed_connection_timeout <= world.time) //it's been more than 5 seconds since we failed to connect, reset the counter
failed_connections = 0
if(failed_connections > 5) //If it failed to establish a connection more than 5 times in a row, don't bother attempting to connect for 5 seconds.
failed_connection_timeout = world.time + 50
return FALSE
if(!config.sql_enabled)
return FALSE
var/user = sqlfdbklogin
var/pass = sqlfdbkpass
var/db = sqlfdbkdb
var/address = sqladdress
var/port = text2num(sqlport)
var/timeout = 10
var/thread_limit = 50
var/result = json_decode(rustg_sql_connect_pool(json_encode(list(
"host" = address,
"port" = port,
"user" = user,
"pass" = pass,
"db_name" = db,
"read_timeout" = timeout,
"write_timeout" = timeout,
"max_threads" = thread_limit,
))))
. = (result["status"] == "ok")
if (.)
connection = result["handle"]
else
connection = null
last_error = result["data"]
log_world("Connect() failed | [last_error]")
++failed_connections
/datum/controller/subsystem/dbcore/proc/CheckSchemaVersion()
if(config.sql_enabled)
if(Connect())
log_world("Database connection established.")
else
log_debug("Your server failed to establish a connection with the database.")
else
log_debug("Database is not enabled in configuration.")
/*/datum/controller/subsystem/dbcore/proc/SetRoundID()
if(!Connect())
return
var/DBQuery/query_round_initialize = SSdbcore.NewQuery(
"INSERT INTO [format_table_name("round")] (initialize_datetime, server_ip, server_port) VALUES (Now(), INET_ATON(:internet_address), :port)",
list("internet_address" = world.internet_address || "0", "port" = "[world.port]")
)
query_round_initialize.Execute(async = FALSE)
GLOB.round_id = "[query_round_initialize.last_insert_id]"
qdel(query_round_initialize)
/datum/controller/subsystem/dbcore/proc/SetRoundStart()
if(!Connect())
return
var/DBQuery/query_round_start = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET start_datetime = Now() WHERE id = :round_id",
list("round_id" = GLOB.round_id)
)
query_round_start.Execute()
qdel(query_round_start)
/datum/controller/subsystem/dbcore/proc/SetRoundEnd()
if(!Connect())
return
var/DBQuery/query_round_end = SSdbcore.NewQuery(
"UPDATE [format_table_name("round")] SET end_datetime = Now(), game_mode_result = :game_mode_result, station_name = :station_name WHERE id = :round_id",
list("game_mode_result" = SSticker.mode_result, "station_name" = station_name(), "round_id" = GLOB.round_id)
)
query_round_end.Execute()
qdel(query_round_end)*/
/datum/controller/subsystem/dbcore/proc/Disconnect()
failed_connections = 0
if (connection)
rustg_sql_disconnect_pool(connection)
connection = null
/datum/controller/subsystem/dbcore/proc/IsConnected()
if (!config.sql_enabled)
return FALSE
if (!connection)
return FALSE
return json_decode(rustg_sql_connected(connection))["status"] == "online"
/datum/controller/subsystem/dbcore/proc/ErrorMsg()
if(!config.sql_enabled)
return "Database disabled by configuration"
return last_error
/datum/controller/subsystem/dbcore/proc/ReportError(error)
last_error = error
/datum/controller/subsystem/dbcore/proc/NewQuery(sql_query, arguments)
if(IsAdminAdvancedProcCall())
message_admins("ERROR: Advanced admin proc call led to sql query. Query has been blocked")
return FALSE
return new /DBQuery(connection, sql_query, arguments)
/datum/controller/subsystem/dbcore/proc/QuerySelect(list/querys, warn = FALSE, qdel = FALSE)
if (!islist(querys))
if (!istype(querys, /DBQuery))
CRASH("Invalid query passed to QuerySelect: [querys]")
querys = list(querys)
for (var/thing in querys)
var/DBQuery/query = thing
if (warn)
INVOKE_ASYNC(query, /DBQuery.proc/warn_execute)
else
INVOKE_ASYNC(query, /DBQuery.proc/Execute)
for (var/thing in querys)
var/DBQuery/query = thing
UNTIL(!query.in_progress)
if (qdel)
qdel(query)
/*
Takes a list of rows (each row being an associated list of column => value) and inserts them via a single mass query.
Rows missing columns present in other rows will resolve to SQL NULL
You are expected to do your own escaping of the data, and expected to provide your own quotes for strings.
The duplicate_key arg can be true to automatically generate this part of the query
or set to a string that is appended to the end of the query
Ignore_errors instructes mysql to continue inserting rows if some of them have errors.
the erroneous row(s) aren't inserted and there isn't really any way to know why or why errored
Delayed insert mode was removed in mysql 7 and only works with MyISAM type tables,
It was included because it is still supported in mariadb.
It does not work with duplicate_key and the mysql server ignores it in those cases
*/
/datum/controller/subsystem/dbcore/proc/MassInsert(table, list/rows, duplicate_key = FALSE, ignore_errors = FALSE, delayed = FALSE, warn = FALSE, async = TRUE, special_columns = null)
if (!table || !rows || !istype(rows))
return
// Prepare column list
var/list/columns = list()
var/list/has_question_mark = list()
for (var/list/row in rows)
for (var/column in row)
columns[column] = "?"
has_question_mark[column] = TRUE
for (var/column in special_columns)
columns[column] = special_columns[column]
has_question_mark[column] = findtext(special_columns[column], "?")
// Prepare SQL query full of placeholders
var/list/query_parts = list("INSERT")
if (delayed)
query_parts += " DELAYED"
if (ignore_errors)
query_parts += " IGNORE"
query_parts += " INTO "
query_parts += table
query_parts += "\n([columns.Join(", ")])\nVALUES"
var/list/arguments = list()
var/has_row = FALSE
for (var/list/row in rows)
if (has_row)
query_parts += ","
query_parts += "\n ("
var/has_col = FALSE
for (var/column in columns)
if (has_col)
query_parts += ", "
if (has_question_mark[column])
var/name = "p[arguments.len]"
query_parts += replacetext(columns[column], "?", ":[name]")
arguments[name] = row[column]
else
query_parts += columns[column]
has_col = TRUE
query_parts += ")"
has_row = TRUE
if (duplicate_key == TRUE)
var/list/column_list = list()
for (var/column in columns)
column_list += "[column] = VALUES([column])"
query_parts += "\nON DUPLICATE KEY UPDATE [column_list.Join(", ")]"
else if (duplicate_key != FALSE)
query_parts += duplicate_key
var/DBQuery/Query = NewQuery(query_parts.Join(), arguments)
if (warn)
. = Query.warn_execute(async)
else
. = Query.Execute(async)
qdel(Query)
/DBQuery
// Inputs
var/connection
var/sql
var/arguments
// Status information
var/in_progress
var/last_error
var/last_activity
var/last_activity_time
// Output
var/list/list/rows
var/next_row_to_take = 1
var/affected
var/last_insert_id
var/list/item //list of data values populated by NextRow()
/DBQuery/New(connection, sql, arguments)
SSdbcore.active_queries[src] = TRUE
Activity("Created")
item = list()
src.connection = connection
src.sql = sql
src.arguments = arguments
/DBQuery/Destroy()
Close()
SSdbcore.active_queries -= src
return ..()
/DBQuery/CanProcCall(proc_name)
//fuck off kevinz
return FALSE
/DBQuery/proc/Activity(activity)
last_activity = activity
last_activity_time = world.time
/DBQuery/proc/warn_execute(async = TRUE)
. = Execute(async)
if(!.)
to_chat(usr, "<span class='danger'>A SQL error occurred during this operation, check the server logs.</span>")
/DBQuery/proc/Execute(async = TRUE, log_error = TRUE)
Activity("Execute")
if(in_progress)
CRASH("Attempted to start a new query while waiting on the old one")
if(!SSdbcore.IsConnected())
last_error = "No connection!"
return FALSE
var/start_time
if(!async)
start_time = REALTIMEOFDAY
Close()
. = run_query(async)
var/timed_out = !. && findtext(last_error, "Operation timed out")
if(!. && log_error)
log_debug("[last_error] | Query used: [sql] | Arguments: [json_encode(arguments)]")
if(!async && timed_out)
log_debug("Query execution started at [start_time]")
log_debug("Query execution ended at [REALTIMEOFDAY]")
log_debug("Slow query timeout detected.")
log_debug("Query used: [sql]")
slow_query_check()
/DBQuery/proc/run_query(async)
var/job_result_str
if (async)
var/job_id = rustg_sql_query_async(connection, sql, json_encode(arguments))
in_progress = TRUE
UNTIL((job_result_str = rustg_sql_check_query(job_id)) != RUSTG_JOB_NO_RESULTS_YET)
in_progress = FALSE
if (job_result_str == RUSTG_JOB_ERROR)
last_error = job_result_str
return FALSE
else
job_result_str = rustg_sql_query_blocking(connection, sql, json_encode(arguments))
var/result = json_decode(job_result_str)
switch (result["status"])
if ("ok")
rows = result["rows"]
affected = result["affected"]
last_insert_id = result["last_insert_id"]
return TRUE
if ("err")
last_error = result["data"]
return FALSE
if ("offline")
last_error = "offline"
return FALSE
/DBQuery/proc/RowCount()
return rows.len
/DBQuery/proc/slow_query_check()
message_admins("HEY! A database query timed out.")
/DBQuery/proc/NextRow(async = TRUE)
Activity("NextRow")
if (rows && next_row_to_take <= rows.len)
item = rows[next_row_to_take]
next_row_to_take++
return !!item
else
return FALSE
/DBQuery/proc/ErrorMsg()
return last_error
/DBQuery/proc/Close()
rows = null
item = null

View File

@@ -5,7 +5,6 @@ SUBSYSTEM_DEF(overlays)
priority = FIRE_PRIORITY_OVERLAYS
init_order = INIT_ORDER_OVERLAY
var/initialized = FALSE
var/list/queue // Queue of atoms needing overlay compiling (TODO-VERIFY!)
var/list/stats
var/list/overlay_icon_state_caches // Cache thing
@@ -22,7 +21,6 @@ var/global/image/appearance_bro = new() // Temporarily super-global because of B
stats = list()
/datum/controller/subsystem/overlays/Initialize()
initialized = TRUE
fire(mc_check = FALSE)
..()

View File

@@ -20,7 +20,7 @@ SUBSYSTEM_DEF(persist)
return
establish_db_connection()
if(!dbcon.IsConnected())
if(!SSdbcore.IsConnected()) //CHOMPEdit TGSQL
src.currentrun.Cut()
return
if(!resumed)
@@ -84,10 +84,11 @@ SUBSYSTEM_DEF(persist)
var/sql_dpt = sql_sanitize_text(department_earning)
var/sql_bal = text2num("[C.department_hours[department_earning]]")
var/sql_total = text2num("[C.play_hours[department_earning]]")
var/DBQuery/query = dbcon.NewQuery("INSERT INTO vr_player_hours (ckey, department, hours, total_hours) VALUES ('[sql_ckey]', '[sql_dpt]', [sql_bal], [sql_total]) ON DUPLICATE KEY UPDATE hours = VALUES(hours), total_hours = VALUES(total_hours)")
var/list/sqlargs = list("t_ckey" = sql_ckey, "t_department" = sql_dpt) //CHOMPEdit TGSQL
var/DBQuery/query = SSdbcore.NewQuery("INSERT INTO vr_player_hours (ckey, department, hours, total_hours) VALUES (:t_ckey, :t_department, [sql_bal], [sql_total]) ON DUPLICATE KEY UPDATE hours = VALUES(hours), total_hours = VALUES(total_hours)", sqlargs) //CHOMPEdit TGSQL
if(!query.Execute()) //CHOMPEdit
log_admin(query.ErrorMsg()) //CHOMPEdit
qdel(query) //CHOMPEdit TGSQL
if (MC_TICK_CHECK)
return

View File

@@ -22,6 +22,7 @@ PROCESSING_SUBSYSTEM_DEF(chemistry)
/datum/controller/subsystem/processing/chemistry/Initialize()
initialize_chemical_reactions()
initialize_chemical_reagents()
..()
//Chemical Reactions - Initialises all /datum/chemical_reaction into a list
// It is filtered into multiple lists within a list.

View File

@@ -4,9 +4,6 @@
// Also handles initialization and processing of overmap sectors.
//
// This global variable exists for legacy support so we don't have to rename every shuttle_controller to SSshuttles yet.
var/global/datum/controller/subsystem/shuttles/shuttle_controller
SUBSYSTEM_DEF(shuttles)
name = "Shuttles"
wait = 2 SECONDS
@@ -35,9 +32,6 @@ SUBSYSTEM_DEF(shuttles)
var/tmp/list/current_run // Shuttles remaining to process this fire() tick
/datum/controller/subsystem/shuttles/PreInit()
global.shuttle_controller = src // TODO - Remove this! Change everything to point at SSshuttles intead
/datum/controller/subsystem/shuttles/Initialize(timeofday)
last_landmark_registration_time = world.time
// Find all declared shuttle datums and initailize them. (Okay, queue them for initialization a few lines further down)

View File

@@ -49,10 +49,7 @@ var/global/datum/controller/subsystem/ticker/ticker
/datum/controller/subsystem/ticker/Initialize()
pregame_timeleft = config.pregame_time
send2mainirc("Server lobby is loaded and open at byond://[config.serverurl ? config.serverurl : (config.server ? config.server : "[world.address]:[world.port]")]")
// Set up the global announcer
GLOB.autospeaker = new (null, null, null, 1)
GLOB.autospeaker = new (null, null, null, 1) //Set up Global Announcer
return ..()
/datum/controller/subsystem/ticker/fire(resumed = FALSE)
@@ -186,11 +183,6 @@ var/global/datum/controller/subsystem/ticker/ticker
if(adm["total"] == 0)
send2adminirc("A round has started with no admins online.")
/* supply_controller.process() //Start the supply shuttle regenerating points -- TLE // handled in scheduler
master_controller.process() //Start master_controller.process()
lighting_controller.process() //Start processing DynamicAreaLighting updates
*/
current_state = GAME_STATE_PLAYING
Master.SetRunLevel(RUNLEVEL_GAME)

View File

@@ -326,6 +326,15 @@
category = list("Arms and Ammunition")
hidden = 1*/
/*
* High Caliber
*/
/datum/category_item/autolathe/arms/rifle_145
name = "14.5mm round (sabot)"
path = /obj/item/ammo_casing/a145/highvel
hidden = 1
///////////////////////////////
/*Ammo clips and Speedloaders*/
///////////////////////////////

View File

@@ -1,6 +1,13 @@
/datum/category_item/autolathe/New()
..()
var/obj/item/I = new path()
var/obj/item/I
if(path)
I = new path()
if(!I) // Something has gone horribly wrong, or right.
log_debug("[name] created an Autolathe design without an assigned path. This is expected for only the Material Sheet generation.")
return
if(I.matter && !resources)
resources = list()
for(var/material in I.matter)
@@ -57,6 +64,42 @@
name = "Tools"
category_item_type = /datum/category_item/autolathe/tools
/datum/category_group/autolathe/materials
name = "Materials"
category_item_type = /datum/category_item/autolathe/materials
/datum/category_group/autolathe/materials/New()
..()
for(var/Name in name_to_material)
var/datum/material/M = name_to_material[Name]
if(!M.stack_type) // Shouldn't happen, but might. Never know.
continue
if(istype(M, /datum/material/alienalloy))
continue
var/obj/item/stack/material/Mat = new M.stack_type()
if(Mat.name in items_by_name)
qdel(Mat)
continue
var/datum/category_item/autolathe/materials/WorkDat = new(src)
WorkDat.name = "[Mat.name]"
WorkDat.resources = Mat.matter.Copy()
WorkDat.is_stack = TRUE
WorkDat.no_scale = TRUE
WorkDat.max_stack = Mat.max_amount
WorkDat.path = M.stack_type
qdel(Mat)
items |= WorkDat
items_by_name[WorkDat.name] = WorkDat
/*******************
* Category entries *
*******************/

View File

@@ -26,6 +26,12 @@
name = "mechanical trap"
path =/obj/item/weapon/beartrap
/datum/category_item/autolathe/devices/barbedwire
name = "barbed wire"
path = /obj/item/weapon/material/barbedwire
hidden = 1
resources = list(DEFAULT_WALL_MATERIAL = 10000)
/datum/category_item/autolathe/devices/electropack
name = "electropack"
path =/obj/item/device/radio/electropack

View File

@@ -4,4 +4,24 @@
/datum/category_item/autolathe/engineering/id_restorer
name = "ID restoration console electronics"
path =/obj/item/weapon/circuitboard/id_restorer
path =/obj/item/weapon/circuitboard/id_restorer
/datum/category_item/autolathe/engineering/oven
name = "oven electronics"
path =/obj/item/weapon/circuitboard/oven
/datum/category_item/autolathe/engineering/fryer
name = "fryer electronics"
path =/obj/item/weapon/circuitboard/fryer
/datum/category_item/autolathe/engineering/grill
name = "grill electronics"
path =/obj/item/weapon/circuitboard/grill
/datum/category_item/autolathe/engineering/cerealmaker
name = "cereal maker electronics"
path =/obj/item/weapon/circuitboard/cerealmaker
/datum/category_item/autolathe/engineering/candymachine
name = "candy machine electronics"
path =/obj/item/weapon/circuitboard/candymachine

View File

@@ -85,44 +85,6 @@
name = "welding mask"
path =/obj/item/clothing/head/welding
/datum/category_item/autolathe/general/metal
name = "steel sheets"
path =/obj/item/stack/material/steel
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/general/glass
name = "glass sheets"
path =/obj/item/stack/material/glass
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/general/rglass
name = "reinforced glass sheets"
path =/obj/item/stack/material/glass/reinforced
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/general/rods
name = "metal rods"
path =/obj/item/stack/rods
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/general/plasteel
name = "plasteel sheets"
path =/obj/item/stack/material/plasteel
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
resources = list(MAT_PLASTEEL = 2000)
/datum/category_item/autolathe/general/plastic
name = "plastic sheets"
path =/obj/item/stack/material/plastic
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
resources = list(MAT_PLASTIC = 2000)
//TFF 24/12/19 - Let people print more spray bottles if needed.
/datum/category_item/autolathe/general/spraybottle
name = "spray bottle"

View File

@@ -0,0 +1,38 @@
/datum/category_item/autolathe/materials/metal
name = "steel sheets"
path =/obj/item/stack/material/steel
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/materials/glass
name = "glass sheets"
path =/obj/item/stack/material/glass
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/materials/rglass
name = "reinforced glass sheets"
path =/obj/item/stack/material/glass/reinforced
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/materials/rods
name = "metal rods"
path =/obj/item/stack/rods
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
/datum/category_item/autolathe/materials/plasteel
name = "plasteel sheets"
path =/obj/item/stack/material/plasteel
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
resources = list(MAT_PLASTEEL = 2000)
/datum/category_item/autolathe/materials/plastic
name = "plastic sheets"
path =/obj/item/stack/material/plastic
is_stack = TRUE
no_scale = TRUE //prevents material duplication exploits
resources = list(MAT_PLASTIC = 2000)

View File

@@ -48,6 +48,11 @@
path = /obj/item/weapon/reagent_containers/spray
resources = list(MAT_PLASTIC = 2000)
/datum/category_item/autolathe/devices/slowwire
name = "snare wire"
path = /obj/item/weapon/material/barbedwire/plastic
resources = list(MAT_PLASTIC = 10000)
/datum/category_item/autolathe/tools/spraynozzle
name = "spray nozzle"
path = /obj/item/weapon/reagent_containers/spray

View File

@@ -17,7 +17,7 @@
var/static/list/locked = list()
/datum/datacore/proc/get_manifest(monochrome, OOC)
/datum/datacore/proc/get_manifest(monochrome, OOC,var/snowflake = FALSE) //CHOMPStation Edit
var/list/heads = new()
var/list/sec = new()
var/list/eng = new()
@@ -40,8 +40,9 @@
.manifest tr.alt td {[monochrome?"border-top-width: 2px":"background-color: [OOC?"#373737; color:white":"#DEF"]"]}
</style></head>
<table class="manifest" width='350px'>
[snowflake?"<tr><th colspan=3 style = \"background-color: #026e6a\"><b>Online players:</b> [TGS_CLIENT_COUNT]</th></tr><tr><th colspan=3 style = \"background-color: #027a76\"><b>Crew members:</b> [data_core.general.len]</th></tr><tr class='head'>":""]
<tr class='head'><th>Name</th><th>Rank</th><th>Activity</th></tr>
"}
"} //Also a chompstation edit with the snowflake stuff on line 43
var/even = 0
// sort mobs
for(var/datum/data/record/t in data_core.general)
@@ -329,7 +330,7 @@ var/global/list/PDA_Manifest = list()
if(H.mind && !player_is_antag(H.mind, only_offstation_roles = 1))
var/assignment = GetAssignment(H)
var/hidden
var/datum/job/J = SSjob.get_job(assignment)
var/datum/job/J = SSjob.get_job(H.mind.assigned_role)
hidden = J?.offmap_spawn
/* Note: Due to cached_character_icon, a number of emergent properties occur due to the initialization

View File

@@ -47,7 +47,7 @@ GLOBAL_DATUM(revdata, /datum/getrev)
. += "The following pull requests are currently test merged:"
for(var/line in testmerge)
var/datum/tgs_revision_information/test_merge/tm = line
var/cm = tm.pull_request_commit
var/cm = tm.head_commit //CHOMPStation Edit TGS4
var/details = ": '" + html_encode(tm.title) + "' by " + html_encode(tm.author) + " at commit " + html_encode(copytext_char(cm, 1, 11))
if(details && findtext(details, "\[s\]") && (!usr || !usr.client.holder))
continue

View File

@@ -55,6 +55,9 @@
var/rev_cooldown = 0
var/tcrystals = 0
var/list/purchase_log = new
var/used_TC = 0
// the world.time since the mob has been brigged, or -1 if not at all
var/brigged_since = -1
@@ -73,7 +76,7 @@
/datum/mind/New(var/key)
src.key = key
purchase_log = list()
..()
/datum/mind/proc/transfer_to(mob/living/new_character)
@@ -510,8 +513,9 @@
//HUMAN
/mob/living/carbon/human/mind_initialize()
..()
if(!mind.assigned_role) mind.assigned_role = USELESS_JOB //defualt //VOREStation Edit - Visitor not Assistant
. = ..()
if(!mind.assigned_role)
mind.assigned_role = USELESS_JOB //defualt //VOREStation Edit - Visitor not Assistant
//slime
/mob/living/simple_mob/slime/mind_initialize()

View File

@@ -41,7 +41,7 @@
//VOREStation Edit - More cyberpunky
/decl/hierarchy/outfit/job/security/detective/forensic
name = OUTFIT_JOB_NAME("Forensic technician")
head = /obj/item/clothing/head/helmet/detective_alt
head = null
suit = /datum/gear/uniform/detective_alt2
uniform = /obj/item/clothing/under/det
//VOREStation Edit End

View File

@@ -39,7 +39,9 @@ var/list/outfits_decls_by_type_
var/suit_store = null
var/r_hand = null
var/l_hand = null
var/list/backpack_contents = list() // In the list(path=count,otherpath=count) format
// In the list(path=count,otherpath=count) format
var/list/uniform_accessories = list() // webbing, armbands etc - fits in slot_tie
var/list/backpack_contents = list()
var/id_type
var/id_desc
@@ -145,6 +147,12 @@ var/list/outfits_decls_by_type_
H.put_in_l_hand(new l_hand(H))
if(r_hand)
H.put_in_r_hand(new r_hand(H))
for(var/path in uniform_accessories)
var/number = uniform_accessories[path]
for(var/i=0,i<number,i++)
H.equip_to_slot_or_del(new path(H), slot_tie)
if(H.species)
H.species.equip_survival_gear(H, flags&OUTFIT_EXTENDED_SURVIVAL, flags&OUTFIT_COMPREHENSIVE_SURVIVAL)

View File

@@ -123,11 +123,12 @@ Keep outfits simple. Spawn with basic uniforms and minimal gear. Gear instead go
/decl/hierarchy/outfit/job/pilot
name = OUTFIT_JOB_NAME("Pilot")
shoes = /obj/item/clothing/shoes/black
uniform = /obj/item/clothing/under/rank/pilot1
uniform = /obj/item/clothing/under/rank/pilot1/no_webbing
suit = /obj/item/clothing/suit/storage/toggle/bomber/pilot
gloves = /obj/item/clothing/gloves/fingerless
glasses = /obj/item/clothing/glasses/fakesunglasses/aviator
l_ear = /obj/item/device/radio/headset/pilot/alt
uniform_accessories = list(/obj/item/clothing/accessory/storage/webbing/pilot1 = 1)
id_slot = slot_wear_id
pda_slot = slot_belt
pda_type = /obj/item/device/pda

View File

@@ -0,0 +1,101 @@
GLOBAL_LIST(department_goals)
GLOBAL_LIST(active_department_goals)
/hook/startup/proc/initializeDepartmentGoals()
GLOB.department_goals = list(GOAL_GENERAL, GOAL_MEDICAL, GOAL_SECURITY, GOAL_ENGINEERING, GOAL_CARGO, GOAL_RESEARCH)
GLOB.active_department_goals = list(GOAL_GENERAL, GOAL_MEDICAL, GOAL_SECURITY, GOAL_ENGINEERING, GOAL_CARGO, GOAL_RESEARCH)
for(var/category in GLOB.department_goals)
GLOB.department_goals[category] = list()
for(var/subtype in subtypesof(/datum/goal))
var/datum/goal/SG = new subtype()
if(SG.name == "goal")
continue
if(SG.category == category)
GLOB.department_goals[category] |= SG
for(var/category in GLOB.active_department_goals)
GLOB.active_department_goals[category] = list()
var/list/cat_goals = GLOB.department_goals[category]
var/goal_count = rand(2,4)
for(var/count = 1 to goal_count)
var/datum/goal/G
if(LAZYLEN(cat_goals))
G = pick(cat_goals)
if(G)
G.active_goal = TRUE
cat_goals -= G
GLOB.active_department_goals[category] |= G
return 1
/hook/roundend/proc/checkDepartmentGoals()
for(var/category in GLOB.active_department_goals)
var/list/cat_goals = GLOB.active_department_goals[category]
to_world("<span class='filter_system'><b>[category]</b></span>")
if(!LAZYLEN(cat_goals))
to_world("<span class='filter_system'>There were no assigned goals!</span>")
else
for(var/datum/goal/G in cat_goals)
var/success = G.check_completion()
to_world("<span class='filter_system'>[success ? "<span class='notice'>[G.name]</span>" : "<span class='warning'>[G.name]</span>"]</span>")
to_world("<span class='filter_system'>[G.goal_text]</span>")
return 1
/datum/goal
var/name = "goal"
var/goal_text = "Do nothing! Congratulations."
var/active_goal = FALSE
var/category = GOAL_GENERAL
/datum/goal/proc/check_completion()
return FALSE
/datum/goal/common
name = "goal"
goal_text = "Congratulations, you still do nothing."
/datum/goal/medical
name = "goal"
goal_text = "Congratulations, you still do nothing."
category = GOAL_MEDICAL
/datum/goal/security
name = "goal"
goal_text = "Congratulations, you still do nothing."
category = GOAL_SECURITY
/datum/goal/engineering
name = "goal"
goal_text = "Congratulations, you still do nothing."
category = GOAL_ENGINEERING
/datum/goal/cargo
name = "goal"
goal_text = "Congratulations, you still do nothing."
category = GOAL_CARGO
/datum/goal/research
name = "goal"
goal_text = "Congratulations, you still do nothing."
category = GOAL_RESEARCH

View File

@@ -17,6 +17,7 @@
/obj/item/weapon/reagent_containers/food/drinks/bottle/patron,
/obj/item/weapon/reagent_containers/food/drinks/bottle/goldschlager,
/obj/item/weapon/reagent_containers/food/drinks/bottle/specialwhiskey,
/obj/item/weapon/reagent_containers/food/drinks/bottle/jager,
/obj/item/weapon/storage/fancy/cigarettes/dromedaryco,
/obj/item/weapon/lipstick/random,
/obj/item/weapon/reagent_containers/food/drinks/bottle/small/ale = 2,

View File

@@ -35,6 +35,13 @@
containertype = /obj/structure/closet/crate/grayson
containername = "Plastic sheets crate"
/datum/supply_pack/materials/copper50
name = "50 copper ingots"
contains = list(/obj/fiftyspawner/copper)
cost = 60
containertype = /obj/structure/closet/crate/grayson
containername = "Copper ingots crate"
/datum/supply_pack/materials/cardboard_sheets
contains = list(/obj/fiftyspawner/cardboard)
name = "50 cardboard sheets"

View File

@@ -51,7 +51,7 @@
/obj/item/weapon/reagent_containers/glass/paint/purple,
/obj/item/weapon/reagent_containers/glass/paint/black,
/obj/item/weapon/reagent_containers/glass/paint/white,
/obj/item/weapon/contraband/poster,
/obj/item/weapon/contraband/poster/custom,
/obj/item/weapon/wrapping_paper = 3
)
cost = 10

View File

@@ -20,7 +20,7 @@
/obj/item/clothing/suit/straight_jacket,
/obj/item/weapon/handcuffs/legcuffs/fuzzy,
/obj/item/weapon/melee/fluff/holochain/mass,
/obj/item/weapon/material/twohanded/fluff/riding_crop,
/obj/item/weapon/material/twohanded/riding_crop,
/obj/item/clothing/under/fluff/latexmaid
)
containertype = /obj/structure/closet/crate

View File

@@ -189,6 +189,17 @@
containername = "Jumper kit crate"
access = access_robotics
/datum/supply_pack/robotics/restrainingbolt
name = "Restraining bolt crate"
contains = list(
/obj/item/weapon/implanter = 1,
/obj/item/weapon/implantcase/restrainingbolt = 2
)
cost = 40
containertype = /obj/structure/closet/crate/secure/cybersolutions
containername = "Restraining bolt crate"
access = access_robotics
/datum/supply_pack/robotics/bike
name = "Spacebike Crate"
contains = list()

View File

@@ -281,10 +281,7 @@
name = "Armor - Riot plates"
contains = list(
/obj/item/clothing/head/helmet/riot,
/obj/item/clothing/suit/armor/pcarrier,
/obj/item/clothing/accessory/armor/armorplate/riot,
/obj/item/clothing/accessory/armor/armguards/riot,
/obj/item/clothing/accessory/armor/legguards/riot
/obj/item/clothing/suit/armor/pcarrier/riot/full
)
cost = 40
containertype = /obj/structure/closet/crate/secure/lawson
@@ -308,10 +305,7 @@
name = "Armor - Ablative plates"
contains = list(
/obj/item/clothing/head/helmet/laserproof,
/obj/item/clothing/suit/armor/pcarrier,
/obj/item/clothing/accessory/armor/armorplate/laserproof,
/obj/item/clothing/accessory/armor/armguards/laserproof,
/obj/item/clothing/accessory/armor/legguards/laserproof
/obj/item/clothing/suit/armor/pcarrier/laserproof/full
)
cost = 50
containertype = /obj/structure/closet/crate/secure/lawson
@@ -336,10 +330,7 @@
name = "Armor - Ballistic plates"
contains = list(
/obj/item/clothing/head/helmet/bulletproof,
/obj/item/clothing/suit/armor/pcarrier,
/obj/item/clothing/accessory/armor/armorplate/bulletproof,
/obj/item/clothing/accessory/armor/armguards/bulletproof,
/obj/item/clothing/accessory/armor/legguards/bulletproof
/obj/item/clothing/suit/armor/pcarrier/bulletproof/full
)
cost = 50
containertype = /obj/structure/closet/crate/secure/heph

View File

@@ -186,4 +186,14 @@
/datum/category_item/underwear/undershirt/pinkblack_tshirt
name = "Pink and Black T-Shirt"
icon_state = "pinkblack_tshirt"
icon_state = "pinkblack_tshirt"
/datum/category_item/underwear/undershirt/turtle
name = "Turtleneck"
icon_state = "turtleneck"
has_color = TRUE
/datum/category_item/underwear/undershirt/sleevelessturtle
name = "Turtleneck, Sleeveless"
icon_state = "sleevelessturtle"
has_color = TRUE

View File

@@ -22,22 +22,22 @@
desc = "Buys you one random item."
/datum/uplink_item/item/badassery/random_one/buy(var/obj/item/device/uplink/U, var/mob/user)
var/datum/uplink_item/item = default_uplink_selection.get_random_item(U.uses)
var/datum/uplink_item/item = default_uplink_selection.get_random_item((user ? user.mind.tcrystals : DEFAULT_TELECRYSTAL_AMOUNT), U)
return item.buy(U, user)
/datum/uplink_item/item/badassery/random_one/can_buy(obj/item/device/uplink/U)
return default_uplink_selection.get_random_item(U.uses, U) != null
/datum/uplink_item/item/badassery/random_one/can_buy(var/obj/item/device/uplink/U, var/telecrystals)
return default_uplink_selection.get_random_item(telecrystals, U) != null
/datum/uplink_item/item/badassery/random_many
name = "Random Items"
desc = "Buys you as many random items you can afford. Convenient packaging NOT included."
/datum/uplink_item/item/badassery/random_many/cost(var/telecrystals)
/datum/uplink_item/item/badassery/random_many/cost(obj/item/device/uplink/U, var/telecrystals)
return max(1, telecrystals)
/datum/uplink_item/item/badassery/random_many/get_goods(var/obj/item/device/uplink/U, var/loc)
/datum/uplink_item/item/badassery/random_many/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/M)
var/list/bought_items = list()
for(var/datum/uplink_item/UI in get_random_uplink_items(U, U.uses, loc))
for(var/datum/uplink_item/UI in get_random_uplink_items(U, M.mind.tcrystals, loc))
UI.purchase_log(U)
var/obj/item/I = UI.get_goods(U, loc)
if(istype(I))
@@ -47,7 +47,7 @@
/datum/uplink_item/item/badassery/random_many/purchase_log(obj/item/device/uplink/U)
feedback_add_details("traitor_uplink_items_bought", "[src]")
log_and_message_admins("used \the [U.loc] to buy \a [src]")
log_and_message_admins("used \the [U.loc] to buy \a [src] at random")
/****************
* Surplus Crate *

View File

@@ -5,8 +5,8 @@
category = /datum/uplink_category/telecrystals
blacklisted = 1
/datum/uplink_item/item/telecrystal/get_goods(var/obj/item/device/uplink/U, var/loc)
return new /obj/item/stack/telecrystal(loc, cost(U.uses))
/datum/uplink_item/item/telecrystal/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/M)
return new /obj/item/stack/telecrystal(loc, cost(U, M.mind.tcrystals))
/datum/uplink_item/item/telecrystal/one
name = "Telecrystal - 01"
@@ -35,5 +35,5 @@
/datum/uplink_item/item/telecrystal/all
name = "Telecrystals - Empty Uplink"
/datum/uplink_item/item/telecrystal/all/cost(var/telecrystals)
return max(1, telecrystals)
/datum/uplink_item/item/telecrystal/all/cost(obj/item/device/uplink/U, mob/M)
return max(1, M.mind.tcrystals)

View File

@@ -92,6 +92,12 @@
desc = "A device which is capable of disrupting subspace communications, preventing the use of headsets, PDAs, and communicators within \
a radius of seven meters. It runs off weapon cells, which can be replaced as needed. One cell will last for approximately ten minutes."
/datum/uplink_item/item/tools/wall_elecrtifier
name = "Wall Electrifier"
item_cost = 10
path = /obj/item/weapon/cell/spike
desc = "A modified powercell which will electrify walls and reinforced floors in a 3x3 tile range around it. Always active."
/datum/uplink_item/item/tools/emag
name = "Cryptographic Sequencer"
item_cost = 30

View File

@@ -36,6 +36,11 @@
item_cost = 10
path = /obj/item/clothing/suit/space/void/autolok
/datum/uplink_item/item/tools/inflatable
name = "Inflatables"
item_cost = 10
path = /obj/item/weapon/storage/briefcase/inflatable
/datum/uplink_item/item/tools/elitetablet
name = "Tablet (Advanced)"
item_cost = 15

View File

@@ -6,12 +6,6 @@
..()
items = list()
/datum/uplink_category/proc/can_view(obj/item/device/uplink/U)
for(var/datum/uplink_item/item in items)
if(item.can_view(U))
return 1
return 0
datum/uplink_category/ammunition
name = "Ammunition"

View File

@@ -31,7 +31,7 @@ var/datum/uplink/uplink = new()
var/item_cost = 0
var/datum/uplink_category/category // Item category
var/list/datum/antagonist/antag_roles // Antag roles this item is displayed to. If empty, display to all.
var/blacklisted = 0
var/blacklisted = FALSE
/datum/uplink_item/item
var/path = null
@@ -48,50 +48,34 @@ var/datum/uplink/uplink = new()
if(!extra_args)
return
if(!can_buy(U))
if(!can_buy(U, user.mind.tcrystals))
return
if(U.tgui_status(user, GLOB.tgui_inventory_state) != STATUS_INTERACTIVE)
if(U.tgui_status(user, GLOB.tgui_deep_inventory_state) != STATUS_INTERACTIVE)
return
var/cost = cost(U.uses, U)
var/cost = cost(U, user.mind.tcrystals)
var/goods = get_goods(U, get_turf(user), user, extra_args)
if(!goods)
return
purchase_log(U)
purchase_log(user)
user.mind.tcrystals -= cost
U.used_TC += cost
user.mind.used_TC += cost
return goods
// Any additional arguments you wish to send to the get_goods
/datum/uplink_item/proc/extra_args(var/mob/user)
return 1
return TRUE
/datum/uplink_item/proc/can_buy(obj/item/device/uplink/U)
if(cost(U.uses, U) > U.uses)
return 0
/datum/uplink_item/proc/can_buy(var/obj/item/device/uplink/U, var/telecrystals)
if(cost(U, telecrystals) > telecrystals)
return FALSE
return can_view(U)
return TRUE
/datum/uplink_item/proc/can_view(obj/item/device/uplink/U)
// Making the assumption that if no uplink was supplied, then we don't care about antag roles
if(!U || !antag_roles.len)
return 1
// With no owner, there's no need to check antag status.
if(!U.uplink_owner)
return 0
for(var/antag_role in antag_roles)
var/datum/antagonist/antag = all_antag_types[antag_role]
if(!isnull(antag))
if(antag.is_antagonist(U.uplink_owner))
return 1
return 0
/datum/uplink_item/proc/cost(var/telecrystals, obj/item/device/uplink/U)
/datum/uplink_item/proc/cost(obj/item/device/uplink/U, mob/M)
. = item_cost
if(U)
. = U.get_item_cost(src, .)
@@ -100,19 +84,19 @@ var/datum/uplink/uplink = new()
return desc
// get_goods does not necessarily return physical objects, it is simply a way to acquire the uplink item without paying
/datum/uplink_item/proc/get_goods(var/obj/item/device/uplink/U, var/loc)
return 0
/datum/uplink_item/proc/get_goods(var/obj/item/device/uplink/U, var/loc, mob/user)
return FALSE
/datum/uplink_item/proc/log_icon()
return
/datum/uplink_item/proc/purchase_log(obj/item/device/uplink/U)
/datum/uplink_item/proc/purchase_log(mob/M)
feedback_add_details("traitor_uplink_items_bought", "[src]")
log_and_message_admins("used \the [U.loc] to buy \a [src]")
U.purchase_log[src] = U.purchase_log[src] + 1
log_and_message_admins("\the [M] bought \a [src] through the uplink")
M.mind.purchase_log[src] += 1
datum/uplink_item/dd_SortValue()
return cost(INFINITY)
return item_cost
/********************************
* *
@@ -133,7 +117,7 @@ datum/uplink_item/dd_SortValue()
A.put_in_any_hand_if_possible(I)
return I
/datum/uplink_item/item/get_goods(var/obj/item/device/uplink/U, var/loc)
/datum/uplink_item/item/get_goods(var/obj/item/device/uplink/U, var/loc, var/mob/user)
var/obj/item/I = new path(loc)
return I
@@ -208,7 +192,7 @@ datum/uplink_item/dd_SortValue()
/proc/get_surplus_items(var/obj/item/device/uplink/U, var/remaining_TC, var/loc)
var/list/bought_items = list()
var/override = 1
var/override = TRUE
while(remaining_TC)
var/datum/uplink_item/I = all_uplink_selection.get_random_item(remaining_TC, U, bought_items, override)
if(!I)

View File

@@ -1,5 +1,5 @@
/datum/wires/mines
wire_count = 6
wire_count = 7
randomize = TRUE
holder_type = /obj/effect/mine
proper_name = "Explosive Wires"
@@ -7,6 +7,7 @@
/datum/wires/mines/New(atom/_holder)
wires = list(WIRE_EXPLODE, WIRE_EXPLODE_DELAY, WIRE_DISARM, WIRE_BADDISARM)
return ..()
#define WIRE_TRAP 64
/datum/wires/mines/get_status()
. = ..()
@@ -29,7 +30,13 @@
if(WIRE_DISARM)
C.visible_message("[bicon(C)] *click!*", "[bicon(C)] *click!*")
new C.mineitemtype(get_turf(C))
var/obj/effect/mine/MI = new C.mineitemtype(get_turf(C))
if(C.trap)
MI.trap = C.trap
C.trap = null
MI.trap.forceMove(MI)
spawn(0)
qdel(C)
@@ -37,6 +44,15 @@
C.visible_message("[bicon(C)] *BEEPBEEPBEEP*", "[bicon(C)] *BEEPBEEPBEEP*")
spawn(20)
C.explode()
if(WIRE_TRAP)
C.visible_message("[bicon(C)] *click!*", "[bicon(C)] *click!*")
if(mend)
C.visible_message("[bicon(C)] - The mine recalibrates[C.camo_net ? ", revealing \the [C.trap] inside." : "."]")
C.alpha = 255
..()
/datum/wires/mines/on_pulse(wire)
@@ -57,6 +73,10 @@
if(WIRE_BADDISARM)
C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*")
if(WIRE_TRAP)
C.visible_message("[bicon(C)] *ping*", "[bicon(C)] *ping*")
..()
/datum/wires/mines/interactable(mob/user)

View File

@@ -7,14 +7,15 @@ proc/sql_poll_population()
if(M.client)
playercount += 1
establish_db_connection()
if(!dbcon.IsConnected())
if(!SSdbcore.IsConnected()) //CHOMPEdit TGSQL
log_game("SQL ERROR during population polling. Failed to connect.")
else
var/sqltime = time2text(world.realtime, "YYYY-MM-DD hh:mm:ss")
var/DBQuery/query = dbcon_old.NewQuery("INSERT INTO `tgstation`.`population` (`playercount`, `admincount`, `time`) VALUES ([playercount], [admincount], '[sqltime]')")
var/DBQuery/query = SSdbcore.NewQuery("INSERT INTO `population` (`playercount`, `admincount`, `time`) VALUES ([playercount], [admincount], '[sqltime]')") //CHOMPEdit TGSQL
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during population polling. Error : \[[err]\]\n")
qdel(query) //CHOMPEdit TGSQL
proc/sql_report_round_start()
// TODO
@@ -50,13 +51,14 @@ proc/sql_report_death(var/mob/living/carbon/human/H)
var/coord = "[H.x], [H.y], [H.z]"
//to_world("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])")
establish_db_connection()
if(!dbcon.IsConnected())
if(!SSdbcore.IsConnected()) //CHOMPEdit TGSQL
log_game("SQL ERROR during death reporting. Failed to connect.")
else
var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
var/DBQuery/query = SSdbcore.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES (:t_name, :t_byondkey, :t_job, :t_special, :t_pod, '[sqltime]', :t_laname, :t_lakey, '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')", list("t_name" = sqlname,"t_byondkey" = sqlkey, "t_job" = sqljob, "t_special" = sqlspecial, "t_pod" = sqlpod, "t_laname" = laname, "t_lakey" = lakey)) //CHOMPEdit TGSQL
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
qdel(query) //CHOMPEdit TGSQL
proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H)
@@ -84,13 +86,14 @@ proc/sql_report_cyborg_death(var/mob/living/silicon/robot/H)
var/coord = "[H.x], [H.y], [H.z]"
//to_world("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.bruteloss], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()])")
establish_db_connection()
if(!dbcon.IsConnected())
if(!SSdbcore.IsConnected()) //CHOMPEdit TGSQL
log_game("SQL ERROR during death reporting. Failed to connect.")
else
var/DBQuery/query = dbcon.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES ('[sqlname]', '[sqlkey]', '[sqljob]', '[sqlspecial]', '[sqlpod]', '[sqltime]', '[laname]', '[lakey]', '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')")
var/DBQuery/query = SSdbcore.NewQuery("INSERT INTO death (name, byondkey, job, special, pod, tod, laname, lakey, gender, bruteloss, fireloss, brainloss, oxyloss, coord) VALUES (:t_name, :t_byondkey, :t_job, :t_special, :t_pod, '[sqltime]', :t_laname, :t_lakey, '[H.gender]', [H.getBruteLoss()], [H.getFireLoss()], [H.brainloss], [H.getOxyLoss()], '[coord]')", list("t_name" = sqlname,"t_byondkey" = sqlkey, "t_job" = sqljob, "t_special" = sqlspecial, "t_pod" = sqlpod, "t_laname" = laname, "t_lakey" = lakey)) //CHOMPEdit TGSQL
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
qdel(query) //CHOMPEdit TGSQL
proc/statistic_cycle()
@@ -115,18 +118,18 @@ proc/sql_commit_feedback()
return
establish_db_connection()
if(!dbcon.IsConnected())
if(!SSdbcore.IsConnected()) //CHOMPEdit TGSQL
log_game("SQL ERROR during feedback reporting. Failed to connect.")
else
var/DBQuery/max_query = dbcon.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback")
var/DBQuery/max_query = SSdbcore.NewQuery("SELECT MAX(roundid) AS max_round_id FROM erro_feedback") //CHOMPEdit TGSQL
max_query.Execute()
var/newroundid
while(max_query.NextRow())
newroundid = max_query.item[1]
qdel(max_query) //CHOMPEdit TGSQL
if(!(isnum(newroundid)))
newroundid = text2num(newroundid)
@@ -139,7 +142,8 @@ proc/sql_commit_feedback()
var/variable = item.get_variable()
var/value = item.get_value()
var/DBQuery/query = dbcon.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')")
var/DBQuery/query = SSdbcore.NewQuery("INSERT INTO erro_feedback (id, roundid, time, variable, value) VALUES (null, [newroundid], Now(), '[variable]', '[value]')") //CHOMPEdit TGSQL
if(!query.Execute())
var/err = query.ErrorMsg()
log_game("SQL ERROR during death reporting. Error : \[[err]\]\n")
qdel(query) //CHOMPEdit TGSQL

View File

@@ -1,7 +1,7 @@
/datum/antagonist/proc/print_player_summary()
if(!current_antagonists.len)
return 0
return FALSE
var/text = "<br><br><font size = 2><b>The [current_antagonists.len == 1 ? "[role_text] was" : "[role_text_plural] were"]:</b></font>"
for(var/datum/mind/P in current_antagonists)
@@ -21,7 +21,7 @@
else
text += "<font color='red'>Fail.</font>"
feedback_add_details(feedback_tag,"[O.type]|FAIL")
failed = 1
failed = TRUE
num++
if(failed)
text += "<br><font color='red'><B>The [role_text] has failed.</B></font>"
@@ -32,7 +32,7 @@
text += "<BR><FONT size = 2>Their objectives were:</FONT>"
var/num = 1
for(var/datum/objective/O in global_objectives)
text += print_objective(O, num, 1)
text += print_objective(O, num, TRUE)
num++
// Display the results.
@@ -68,14 +68,14 @@
/datum/antagonist/proc/print_player_full(var/datum/mind/ply)
var/text = print_player_lite(ply)
var/TC_uses = 0
var/uplink_true = 0
var/TC_uses = FALSE
var/uplink_true = FALSE
var/purchases = ""
for(var/obj/item/device/uplink/H in GLOB.world_uplinks)
if(H && H.uplink_owner && H.uplink_owner == ply)
TC_uses += H.used_TC
uplink_true = 1
purchases += get_uplink_purchases(H)
for(var/mob/M in player_list)
if(M.mind && M.mind.used_TC)
TC_uses += M.mind.used_TC
uplink_true = TRUE
purchases += get_uplink_purchases(M.mind)
if(uplink_true)
text += " (used [TC_uses] TC)"
if(purchases)
@@ -83,18 +83,8 @@
return text
/proc/print_ownerless_uplinks()
var/has_printed = 0
for(var/obj/item/device/uplink/H in GLOB.world_uplinks)
if(isnull(H.uplink_owner) && H.used_TC)
if(!has_printed)
has_printed = 1
to_world("<b>Ownerless Uplinks</b>")
to_world("[H.loc] (used [H.used_TC] TC)")
to_world(get_uplink_purchases(H))
/proc/get_uplink_purchases(var/obj/item/device/uplink/H)
/proc/get_uplink_purchases(var/datum/mind/M)
var/list/refined_log = new()
for(var/datum/uplink_item/UI in H.purchase_log)
refined_log.Add("[H.purchase_log[UI]]x[UI.log_icon()][UI.name]")
for(var/datum/uplink_item/UI in M.purchase_log)
refined_log.Add("[M.purchase_log[UI]]x[UI.log_icon()][UI.name]")
. = english_list(refined_log, nothing_text = "")

View File

@@ -50,13 +50,12 @@
var/turf/base_turf //The base turf type of the area, which can be used to override the z-level's base turf
var/forbid_events = FALSE // If true, random events will not start inside this area.
var/no_spoilers = FALSE // If true, makes it much more difficult to see what is inside an area with things like mesons.
var/soundproofed = FALSE // If true, blocks sounds from other areas and prevents hearers on other areas from hearing the sounds within.
/area/Initialize()
. = ..()
luminosity = !(dynamic_lighting)
icon_state = ""
return INITIALIZE_HINT_LATELOAD // Areas tradiationally are initialized AFTER other atoms.
/area/LateInitialize()
@@ -67,7 +66,6 @@
power_change() // all machines set to current power level, also updates lighting icon
if(no_spoilers)
set_spoiler_obfuscation(TRUE)
return INITIALIZE_HINT_LATELOAD
// Changes the area of T to A. Do not do this manually.
// Area is expected to be a non-null instance.
@@ -379,9 +377,9 @@ var/list/mob/living/forced_ambiance_list = new
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(!(L && L.is_preference_enabled(/datum/client_preference/play_ambiance)))
return
var/volume_mod = L.get_preference_volume_channel(VOLUME_CHANNEL_AMBIENCE)
// If we previously were in an area with force-played ambiance, stop it.
if((L in forced_ambiance_list) && initial)
L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
@@ -399,7 +397,7 @@ var/list/mob/living/forced_ambiance_list = new
L << chosen_ambiance
else
L << sound(null, channel = CHANNEL_AMBIENCE_FORCED)
else if(src.ambience.len)
else if(src.ambience && src.ambience.len)
var/ambience_odds = L?.client.prefs.ambience_chance
if(prob(ambience_odds) && (world.time >= L.client.time_last_ambience_played + 1 MINUTE))
var/sound = pick(ambience)

View File

@@ -627,7 +627,7 @@
speech_bubble_hearers += M.client
if(length(speech_bubble_hearers))
var/image/I = image('icons/mob/talk.dmi', src, "[bubble_icon][say_test(message)]", FLY_LAYER)
var/image/I = generate_speech_bubble(src, "[bubble_icon][say_test(message)]", FLY_LAYER)
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_hearers, 30)

View File

@@ -134,7 +134,7 @@
for(var/i in loc)
var/atom/movable/thing = i
// We don't call parent so we are calling this for byond
thing.Crossed(src)
thing.Crossed(src, oldloc)
// We're a multi-tile object (multiple locs)
else if(. && newloc)
@@ -303,6 +303,8 @@
if(AM == src)
continue
AM.Uncrossed(src)
if(loc != destination) // Uncrossed() triggered a separate movement
return
// Information about turf and z-levels for source and dest collected
var/turf/oldturf = get_turf(oldloc)
@@ -327,6 +329,8 @@
if(AM == src)
continue
AM.Crossed(src, oldloc)
if(loc != destination) // Crossed triggered a separate movement
return
// Call our thingy to inform everyone we moved
Moved(oldloc, NONE, TRUE)
@@ -462,6 +466,8 @@
minor_dir = dx
minor_dist = dist_x
range = min(dist_x + dist_y, range)
while(src && target && src.throwing && istype(src.loc, /turf) \
&& ((abs(target.x - src.x)+abs(target.y - src.y) > 0 && dist_travelled < range) \
|| (a && a.has_gravity == 0) \

View File

@@ -118,6 +118,10 @@ var/global/list/datum/dna/gene/dna_genes[0]
var/base_species = "Human"
var/list/species_traits = list()
var/blood_color = "#A10808"
var/custom_say
var/custom_ask
var/custom_whisper
var/custom_exclaim
// VOREStation
// New stuff
@@ -139,6 +143,10 @@ var/global/list/datum/dna/gene/dna_genes[0]
new_dna.custom_species=custom_species //VOREStaton Edit
new_dna.species_traits=species_traits.Copy() //VOREStation Edit
new_dna.blood_color=blood_color //VOREStation Edit
new_dna.custom_say=custom_say //VOREStaton Edit
new_dna.custom_ask=custom_ask //VOREStaton Edit
new_dna.custom_whisper=custom_whisper //VOREStaton Edit
new_dna.custom_exclaim=custom_exclaim //VOREStaton Edit
for(var/b=1;b<=DNA_SE_LENGTH;b++)
new_dna.SE[b]=SE[b]
if(b<=DNA_UI_LENGTH)
@@ -200,29 +208,15 @@ var/global/list/datum/dna/gene/dna_genes[0]
size_multiplier = player_sizes_list.Find(N)
break
var/taurtype = /datum/sprite_accessory/tail/taur/spider
if(istype(character.tail_style, taurtype))
character.verbs += /mob/living/proc/weaveWebBindings
// Technically custom_species is not part of the UI, but this place avoids merge problems.
src.custom_species = character.custom_species
if(istype(character.species,/datum/species/custom))
var/datum/species/custom/CS = character.species
src.species_traits = CS.traits.Copy()
src.base_species = CS.base_species
src.blood_color = CS.blood_color
if(istype(character.species,/datum/species/xenochimera))
var/datum/species/xenochimera/CS = character.species
//src.species_traits = CS.traits.Copy() //No traits
src.base_species = CS.base_species
src.blood_color = CS.blood_color
if(istype(character.species,/datum/species/alraune))
var/datum/species/alraune/CS = character.species
//src.species_traits = CS.traits.Copy() //No traits
src.base_species = CS.base_species
src.blood_color = CS.blood_color
src.base_species = character.species.base_species
src.blood_color = character.species.blood_color
src.species_traits = character.species.traits.Copy()
src.custom_say = character.custom_say
src.custom_ask = character.custom_ask
src.custom_whisper = character.custom_whisper
src.custom_exclaim = character.custom_exclaim
// +1 to account for the none-of-the-above possibility
SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1)

View File

@@ -237,20 +237,13 @@
// Technically custom_species is not part of the UI, but this place avoids merge problems.
H.custom_species = dna.custom_species
if(istype(H.species,/datum/species/custom))
var/datum/species/custom/CS = H.species
var/datum/species/custom/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src)
new_CS.blood_color = dna.blood_color
if(istype(H.species,/datum/species/xenochimera))
var/datum/species/xenochimera/CS = H.species
var/datum/species/xenochimera/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src)
new_CS.blood_color = dna.blood_color
if(istype(H.species,/datum/species/alraune))
var/datum/species/alraune/CS = H.species
var/datum/species/alraune/new_CS = CS.produceCopy(dna.base_species,dna.species_traits,src)
new_CS.blood_color = dna.blood_color
H.custom_say = dna.custom_say
H.custom_ask = dna.custom_ask
H.custom_whisper = dna.custom_whisper
H.custom_exclaim = dna.custom_exclaim
H.species.blood_color = dna.blood_color
var/datum/species/S = H.species
S.produceCopy(dna.base_species,dna.species_traits,src)
// VOREStation Edit End
H.force_update_organs() //VOREStation Add - Gotta do this too

View File

@@ -34,7 +34,7 @@
var/last_activation = 0
/obj/structure/cult/pylon/Initialize()
..()
. = ..()
START_PROCESSING(SSobj, src)
/obj/structure/cult/pylon/attack_hand(mob/M as mob)

View File

@@ -292,7 +292,6 @@ var/global/list/additional_antag_types = list()
antag.check_victory()
antag.print_player_summary()
sleep(10)
print_ownerless_uplinks()
var/clients = 0
var/surviving_humans = 0
@@ -303,10 +302,16 @@ var/global/list/additional_antag_types = list()
var/escaped_on_pod_1 = 0
var/escaped_on_pod_2 = 0
var/escaped_on_pod_3 = 0
var/escaped_on_pod_4 = 0 //CHOMP Add
var/escaped_on_pod_5 = 0
var/escaped_on_pod_6 = 0 //CHOMP Add
var/escaped_on_shuttle = 0
var/escaped_on_pod_large_1 = 0 //CHOMP Add
var/escaped_on_pod_large_2 = 0 //CHOMP Add
var/escaped_on_cryopod = 0 //CHOMP Add
var/list/area/escape_locations = list(/area/shuttle/escape, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom) //VOREStation Edit
var/list/area/escape_locations = list(/area/shuttle/escape/centcom, /area/shuttle/cryo/centcom, /area/shuttle/escape_pod1/centcom, /area/shuttle/escape_pod2/centcom, /area/shuttle/escape_pod3/centcom, /area/shuttle/escape_pod5/centcom, /area/shuttle/escape_pod6/centcom, /area/shuttle/large_escape_pod1/centcom
, /area/shuttle/large_escape_pod2/centcom) //CHOMP Edit: Appended /centcom to the escape shuttle again to fix transfer message. Added some escape pods to the list.
for(var/mob/M in player_list)
if(M.client)
@@ -330,8 +335,20 @@ var/global/list/additional_antag_types = list()
escaped_on_pod_2++
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod3/centcom)
escaped_on_pod_3++
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod4/centcom) //CHOMP Add
escaped_on_pod_4++
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod5/centcom)
escaped_on_pod_5++
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/escape_pod6/centcom) //CHOMP Add
escaped_on_pod_6++
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/large_escape_pod1/centcom) //CHOMP Add
escaped_on_pod_large_1++
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/large_escape_pod2/centcom) //CHOMP Add
escaped_on_pod_large_2++
if(M.loc && M.loc.loc && M.loc.loc.type == /area/shuttle/cryo/centcom) //CHOMP Add
escaped_on_cryopod++
if(isobserver(M))
ghosts++
@@ -364,8 +381,18 @@ var/global/list/additional_antag_types = list()
feedback_set("escaped_on_pod_2",escaped_on_pod_2)
if(escaped_on_pod_3 > 0)
feedback_set("escaped_on_pod_3",escaped_on_pod_3)
if(escaped_on_pod_4 > 0) //CHOMP Add
feedback_set("escaped_on_pod_4",escaped_on_pod_4)
if(escaped_on_pod_5 > 0)
feedback_set("escaped_on_pod_5",escaped_on_pod_5)
if(escaped_on_pod_6 > 0) //CHOMP Add
feedback_set("escaped_on_pod_6",escaped_on_pod_6)
if(escaped_on_pod_large_1 > 0) //CHOMP Add
feedback_set("escaped_on_pod_large_1",escaped_on_pod_large_1)
if(escaped_on_pod_large_2 > 0) //CHOMP Add
feedback_set("escaped_on_pod_large_2",escaped_on_pod_large_2)
if(escaped_on_cryopod > 0) //CHOMP Add
feedback_set("escaped_on_cryopod",escaped_on_cryopod)
send2mainirc("A round of [src.name] has ended - [surviving_total] survivors, [ghosts] ghosts.")

View File

@@ -273,6 +273,7 @@
var/outgoing_instability = (amount) * ( 1 / (radius**2) )
L.receive_radiated_instability(outgoing_instability)
src.adjust_instability(-outgoing_instability) //This should prevent feedback loops
// This should only be used for EXTERNAL sources of instability, such as from someone or something glowing.
/mob/living/proc/receive_radiated_instability(amount)

View File

@@ -44,7 +44,7 @@
src.loc = null
user.put_in_hands(I)
user.visible_message("<span class='notice'>\A [I] appears in \the [user]'s hand!</span>")
log_and_message_admins("has stolen [I] with [src].")
add_attack_logs(user,I,"Stolen with [src]")
qdel(src)
//Now let's try to teleport a living mob.
else if(istype(hit_atom, /mob/living))

View File

@@ -68,7 +68,7 @@
else
safe_blink(AM, calculate_spell_power(3))
adjust_instability(3)
log_and_message_admins("has blinked [AM] away.")
add_attack_logs(user,AM,"Blinked")
else
to_chat(user, "<span class='warning'>You need more energy to blink [AM] away!</span>")
@@ -82,7 +82,7 @@
else
safe_blink(user, calculate_spell_power(6))
adjust_instability(1)
log_and_message_admins("has blinked themselves away.")
add_attack_logs(user,user,"Blinked")
else
to_chat(user, "<span class='warning'>You need more energy to blink yourself away!</span>")
@@ -99,6 +99,6 @@
else
safe_blink(AM, 6)
adjust_instability(2)
log_and_message_admins("has blinked [AM] away.")
add_attack_logs(user,AM,"Blinked")
else
to_chat(user, "<span class='warning'>You need more energy to blink [AM] away!</span>")

View File

@@ -36,9 +36,9 @@
var/turf/simulated/frozen = desired_turf
frozen.freeze_floor()
if(check_for_scepter())
log_and_message_admins("has iced the floor with [src] at [T.x],[T.y],[T.z].")
add_attack_logs(user,hit_atom,"Iced the floor with [src] at [T.x],[T.y],[T.z]")
else
log_and_message_admins("has wetted the floor with [src] at [T.x],[T.y],[T.z].")
add_attack_logs(user,hit_atom,"Wetted the floor with [src] at [T.x],[T.y],[T.z]")
else if(hit_atom.reagents && !ismob(hit_atom)) //TODO: Something for the scepter
hit_atom.reagents.add_reagent(id = "water", amount = 60, data = null, safety = 0)
adjust_instability(5)

View File

@@ -125,7 +125,7 @@
return 0
if(pay_energy(25 * controlled_mobs.len))
attack_all(L)
log_and_message_admins("has commanded their army of [controlled_mobs.len] to attack [L].")
add_attack_logs(user,L,"Commanded their army of [controlled_mobs.len]")
to_chat(user, "<span class='notice'>You command your [controlled_mobs.len > 1 ? "entities" : "[controlled_mobs[1]]"] to \
attack \the [L].</span>")
//This is to stop someone from controlling beepsky and getting him to stun someone 5 times a second.

View File

@@ -57,7 +57,7 @@
return 0
siphoning = AM
update_icon()
log_and_message_admins("is siphoning energy from \a [AM].")
add_attack_logs(user,AM,"Siphoned energy from [src]")
else
stop_siphoning()

View File

@@ -46,7 +46,7 @@
visible_message("<span class='danger'>\The [user] reaches out towards \the [L] with the flaming hand, and they ignite!</span>")
to_chat(L, "<span class='danger'>You ignite!</span>")
L.fire_act()
log_and_message_admins("has ignited [L] with [src].")
add_attack_logs(user,L,"Ignited with [src]")
adjust_instability(12)
else
//This is needed in order for the welder to work, and works similarly to grippers.

View File

@@ -33,6 +33,7 @@
if(pay_energy(500))
illusion = new(T)
illusion.copy_appearance(copied)
illusion.copy_overlays(copied, TRUE)
to_chat(user, "<span class='notice'>An illusion of \the [copied] is made on \the [T].</span>")
user << 'sound/effects/pop.ogg'
return 1

View File

@@ -45,7 +45,7 @@
return
var/obj/item/weapon/inserted_spell/inserted = new inserting(L,user,src)
inserted.spell_power_at_creation = calculate_spell_power(1.0)
log_and_message_admins("has casted [src] on [L].")
add_attack_logs(user,L,"Casted [src]")
qdel(src)
/obj/item/weapon/spell/insert/on_melee_cast(atom/hit_atom, mob/user)

View File

@@ -14,7 +14,7 @@
var/obj/item/projectile/new_projectile = make_projectile(spell_projectile, user)
new_projectile.old_style_target(hit_atom)
new_projectile.fire()
log_and_message_admins("has casted [src] at \the [hit_atom].")
add_attack_logs(user,hit_atom,"Casted [src]")
if(fire_sound)
playsound(src, fire_sound, 75, 1)
adjust_instability(instability_per_shot)
@@ -39,4 +39,4 @@
return TRUE
return FALSE // We got dropped before the firing occured.
return TRUE // No delay, no need to check.
return FALSE
return FALSE

View File

@@ -62,7 +62,7 @@
spark_system.start()
playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
// now send a log so that admins don't think they're shooting themselves on purpose.
log_and_message_admins("[user] reflected [attacker]'s attack back at them.")
add_attack_logs(user,attacker,"Reflected [attacker]'s attack")
if(!reflecting)
reflecting = 1
@@ -82,7 +82,7 @@
spark_system.start()
playsound(src, 'sound/weapons/blade1.ogg', 50, 1)
log_and_message_admins("[user] reflected [attacker]'s attack back at them.")
add_attack_logs(user,attacker,"Reflected [attacker]'s attack")
if(!reflecting)
reflecting = 1

View File

@@ -76,5 +76,5 @@
I.afterattack(chosen_target, user)
else
chosen_target.attack_hand(user)
log_and_message_admins("has warp striked [chosen_target].")
add_attack_logs(user,chosen_target,"Warp striked")

View File

@@ -27,4 +27,22 @@ var/const/access_pilot = 67
/datum/access/entertainment
id = access_entertainment
desc = "Entertainment Backstage"
region = ACCESS_REGION_GENERAL
region = ACCESS_REGION_GENERAL
/var/const/access_mime = 138
/datum/access/mime
id = access_mime
desc = "Mime Office"
region = ACCESS_REGION_GENERAL
/var/const/access_clown = 136
/datum/access/clown
id = access_clown
desc = "Clown Office"
region = ACCESS_REGION_GENERAL
/var/const/access_tomfoolery = 137
/datum/access/tomfoolery
id = access_tomfoolery
desc = "Tomfoolery Closet"
region = ACCESS_REGION_GENERAL

View File

@@ -26,13 +26,13 @@
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
access_hop, access_RC_announce, access_keycard_auth)
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
minimal_access = list(access_security, access_sec_doors, access_brig, access_forensics_lockers,
access_medical, access_engine, access_change_ids, access_ai_upload, access_eva, access_heads,
access_all_personal_lockers, access_maint_tunnels, access_bar, access_janitor, access_construction, access_morgue,
access_crematorium, access_kitchen, access_cargo, access_cargo_bot, access_mailsorting, access_qm, access_hydroponics, access_lawyer,
access_chapel_office, access_library, access_research, access_mining, access_heads_vault, access_mining_station,
access_hop, access_RC_announce, access_keycard_auth)
access_hop, access_RC_announce, access_clown, access_tomfoolery, access_mime, access_keycard_auth, access_gateway)
/datum/alt_title/deputy_director
title = "Deputy Director"

View File

@@ -198,7 +198,9 @@
job_description = "An entertainer does just that, entertains! Put on plays, play music, sing songs, tell stories, or read your favorite fanfic."
alt_titles = list("Performer" = /datum/alt_title/performer, "Musician" = /datum/alt_title/musician, "Stagehand" = /datum/alt_title/stagehand,
"Actor" = /datum/alt_title/actor, "Dancer" = /datum/alt_title/dancer, "Singer" = /datum/alt_title/singer,
"Magician" = /datum/alt_title/magician, "Comedian" = /datum/alt_title/comedian, "Tragedian" = /datum/alt_title/tragedian)
"Magician" = /datum/alt_title/magician, "Comedian" = /datum/alt_title/comedian, "Tragedian" = /datum/alt_title/tragedian,
"Clown" = /datum/alt_title/clown, "Jester" = /datum/alt_title/clown/jester,"Fool" = /datum/alt_title/clown/fool,
"Mime"= /datum/alt_title/mime,"Poseur"= /datum/alt_title/mime/poseur) //CHOMPEDIT: Adding clown + mime and their alts as alts of entertainer
// Entertainer Alt Titles
/datum/alt_title/actor

View File

@@ -6,12 +6,12 @@
access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
minimal_access = list(access_engine, access_engine_equip, access_tech_storage, access_maint_tunnels,
access_teleporter, access_external_airlocks, access_atmospherics, access_emergency_storage, access_eva,
access_heads, access_construction,
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload)
access_ce, access_RC_announce, access_keycard_auth, access_tcomsat, access_ai_upload, access_gateway)
alt_titles = list("Head Engineer" = /datum/alt_title/head_engineer, "Foreman" = /datum/alt_title/foreman, "Maintenance Manager" = /datum/alt_title/maintenance_manager)
/datum/alt_title/head_engineer

View File

@@ -1,8 +1,3 @@
var/const/PATHFINDER =(1<<11)
var/const/EXPLORER =(1<<12)
var/const/PILOT =(1<<13)
var/const/SAR =(1<<14)
/obj/item/weapon/card/id/medical/sar
assignment = "Field Medic"
rank = "Field Medic"
@@ -41,7 +36,7 @@ var/const/SAR =(1<<14)
faction = "Station"
total_positions = 1
spawn_positions = 1
supervisors = "the Head of Personnel"
supervisors = "the Research Director" //CHOMPedit
selection_color = "#d6d05c"
economic_modifier = 8
minimal_player_age = 7
@@ -64,20 +59,20 @@ var/const/SAR =(1<<14)
/datum/job/pilot
title = "Pilot"
flag = PILOT
departments = list(DEPARTMENT_PLANET)
department_flag = MEDSCI
departments = list(DEPARTMENT_PLANET) //CHOMPedit: keep them part of exploration
department_flag = MEDSCI //CHOMPedit
faction = "Station"
total_positions = 4
spawn_positions = 4
supervisors = "the Pathfinder and the Head of Personnel"
selection_color = "#999440"
total_positions = 5
spawn_positions = 5
supervisors = "the Pathfinder" //CHOMPedit
selection_color = "#515151"
economic_modifier = 5
minimal_player_age = 3
pto_type = PTO_EXPLORATION
access = list(access_pilot)
minimal_access = list(access_pilot)
outfit_type = /decl/hierarchy/outfit/job/pilot
job_description = "A Pilot flies the various shuttles in the Virgo-Erigone System."
job_description = "A Pilot flies the various shuttles in the Vir System." //CHOMPedit: Replaces Virgo reference with Vir.
alt_titles = list("Co-Pilot" = /datum/alt_title/co_pilot, "Navigator" = /datum/alt_title/navigator)
/datum/alt_title/co_pilot
@@ -96,7 +91,7 @@ var/const/SAR =(1<<14)
faction = "Station"
total_positions = 3
spawn_positions = 3
supervisors = "the Pathfinder and the Head of Personnel"
supervisors = "the Pathfinder" //CHOMPedit
selection_color = "#999440"
economic_modifier = 6
pto_type = PTO_EXPLORATION
@@ -121,7 +116,7 @@ var/const/SAR =(1<<14)
faction = "Station"
total_positions = 2
spawn_positions = 2
supervisors = "the Pathfinder and the Chief Medical Officer"
supervisors = "the Pathfinder" //CHOMPedit
selection_color = "#999440"
economic_modifier = 6
minimal_player_age = 3

View File

@@ -5,11 +5,11 @@
access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_teleporter, //CHOMPEdit
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
minimal_access = list(access_medical, access_medical_equip, access_morgue, access_genetics, access_heads,
access_chemistry, access_virology, access_cmo, access_surgery, access_RC_announce, access_teleporter,//CHOMPEdit
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels)
access_keycard_auth, access_psychiatrist, access_eva, access_external_airlocks, access_maint_tunnels, access_gateway)
alt_titles = list("Chief Physician" = /datum/alt_title/chief_physician, "Medical Director" = /datum/alt_title/medical_director, /*CHOMPEdit Removal"Healthcare Manager" = /datum/alt_title/healthcare_manager*/)
/datum/alt_title/chief_physician

View File

@@ -13,6 +13,9 @@
access_research, access_robotics, access_xenobiology, access_ai_upload, access_tech_storage,
access_RC_announce, access_keycard_auth, access_tcomsat, access_gateway, access_xenoarch, access_eva, access_network,
access_explorer, access_pathfinder, access_xenobotany) //YW Edit access_gateway, _explorer, _pathfinder, and _xenobotany
alt_titles = list("Research Supervisor" = /datum/alt_title/research_supervisor, "Research Manager" = /datum/alt_title/research_manager,
"Head of Development" = /datum/alt_title/head_of_development,"Head Scientist" = /datum/alt_title/head_scientist)
/datum/alt_title/research_manager
title = "Research Manager"

View File

@@ -77,16 +77,16 @@
title = "Clown"
flag = CLOWN
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
department_flag = ENGSEC
faction = "Station"
total_positions = -1
spawn_positions = -1
total_positions = -1 //CHOMP Edit: Disable. Change to + integer to enable.
spawn_positions = -1 //CHOMP Edit: Disable. Change to + integer to enable.
supervisors = "the spirit of laughter"
selection_color = "#515151"
economic_modifier = 1
job_description = "A Clown is there to entertain the crew and keep high morale using various harmless pranks and ridiculous jokes!"
whitelist_only = 1
latejoin_only = 1
latejoin_only = 0
outfit_type = /decl/hierarchy/outfit/job/clown
pto_type = PTO_CIVILIAN
alt_titles = list("Jester" = /datum/alt_title/jester, "Fool" = /datum/alt_title/fool)
@@ -99,25 +99,25 @@
/datum/job/clown/get_access()
if(config.assistant_maint)
return list(access_maint_tunnels, access_entertainment)
return list(access_maint_tunnels, access_entertainment, access_clown, access_tomfoolery)
else
return list(access_entertainment)
return list(access_entertainment, access_clown, access_tomfoolery)
/datum/job/mime
title = "Mime"
flag = MIME
departments = list(DEPARTMENT_CIVILIAN)
department_flag = CIVILIAN
department_flag = ENGSEC
faction = "Station"
total_positions = -1
spawn_positions = -1
total_positions = -1 //CHOMP Edit: Disable. Change to + integer to enable.
spawn_positions = -1 //CHOMP Edit: Disable. Change to + integer to enable.
supervisors = "the spirit of performance"
selection_color = "#515151"
economic_modifier = 1
job_description = "A Mime is there to entertain the crew and keep high morale using unbelievable performances and acting skills!"
alt_titles = list("Poseur" = /datum/alt_title/poseur)
whitelist_only = 1
latejoin_only = 1
latejoin_only = 0
outfit_type = /decl/hierarchy/outfit/job/mime
pto_type = PTO_CIVILIAN
@@ -126,6 +126,6 @@
/datum/job/mime/get_access()
if(config.assistant_maint)
return list(access_maint_tunnels, access_entertainment)
return list(access_maint_tunnels, access_entertainment, access_tomfoolery, access_mime)
else
return list(access_entertainment)
return list(access_entertainment, access_tomfoolery, access_mime)

View File

@@ -0,0 +1,31 @@
/datum/job/entertainer
alt_titles = list("Performer" = /datum/alt_title/performer, "Musician" = /datum/alt_title/musician, "Stagehand" = /datum/alt_title/stagehand,
"Actor" = /datum/alt_title/actor, "Dancer" = /datum/alt_title/dancer, "Singer" = /datum/alt_title/singer,
"Magician" = /datum/alt_title/magician, "Comedian" = /datum/alt_title/comedian, "Tragedian" = /datum/alt_title/tragedian,
"Clown" = /datum/alt_title/clown, "Jester" = /datum/alt_title/clown/jester,"Fool" = /datum/alt_title/clown/fool,
"Mime"= /datum/alt_title/mime,"Poseur"= /datum/alt_title/mime/poseur, "Fitness Instructor" = /datum/alt_title/fitness) //CHOMPEDIT: Adding clown + mime and their alts as alts of entertainer, as well as fitness instructor
/datum/alt_title/fitness
title = "Fitness Instructor"
title_blurb = "A Fitness Instructor's goal is to keep the station in shape. Get the crew shaving up those built up pounds and get them to eat something other than chocolate bars and burgers for once"
//Below, well sort off, these are the clown and mime returning! as entertainer alts
//They even get their respective outfits.
/datum/alt_title/clown
title = "Clown"
title_blurb = "A Clown is there to entertain the crew and keep high morale using various harmless pranks and ridiculous jokes!"
title_outfit = /decl/hierarchy/outfit/job/clown
/datum/alt_title/clown/jester
title = "Jester"
/datum/alt_title/clown/fool
title = "Fool"
/datum/alt_title/mime
title = "Mime"
title_blurb = "A Mime is there to entertain the crew and keep high morale using unbelievable performances and acting skills!"
title_outfit = /decl/hierarchy/outfit/job/mime
/datum/alt_title/mime/poseur
title = "Poseur"

View File

@@ -414,7 +414,7 @@ var/global/datum/controller/occupations/job_master
// Implants get special treatment
if(G.slot == "implant")
var/obj/item/weapon/implant/I = G.spawn_item(H)
var/obj/item/weapon/implant/I = G.spawn_item(H, H.client.prefs.gear[G.display_name])
I.invisibility = 100
I.implant_loadout(H)
continue
@@ -510,22 +510,23 @@ var/global/datum/controller/occupations/job_master
to_chat(H, "<span class='danger'>Failed to locate a storage object on your mob, either you spawned with no arms and no backpack or this is a bug.</span>")
if(istype(H)) //give humans wheelchairs, if they need them.
if(istype(H.loc, /obj/belly)) //unless in a gut
if(istype(H.loc, /obj/belly)) //CHOMPedit start unless in a gut
var/obj/item/organ/external/l_foot = H.get_organ("l_foot")
var/obj/item/organ/external/r_foot = H.get_organ("r_foot")
var/obj/item/weapon/storage/S = locate() in H.contents
var/obj/item/wheelchair/R = null
var/obj/item/wheelchair/R
if(S)
R = locate() in S.contents
if(!l_foot || !r_foot || R)
var/obj/structure/bed/chair/wheelchair/W = new /obj/structure/bed/chair/wheelchair(H.loc)
var/wheelchair_type = R?.unfolded_type || /obj/structure/bed/chair/wheelchair
var/obj/structure/bed/chair/wheelchair/W = new wheelchair_type(H.loc)
W.buckle_mob(H)
H.update_canmove()
W.set_dir(H.dir)
W.add_fingerprint(H)
if(R)
W.color = R.color
qdel(R)
qdel(R) //CHOMPedit end
to_chat(H, "<B>You are [job.total_positions == 1 ? "the" : "a"] [alt_title ? alt_title : rank].</B>")
@@ -745,7 +746,7 @@ var/global/datum/controller/occupations/job_master
to_chat(C, "Your chosen spawnpoint ([spawnpos.display_name]) is unavailable for your chosen job. Spawning you at the Arrivals shuttle instead.")
var/spawning = pick(latejoin)
.["turf"] = get_turf(spawning)
.["msg"] = "will arrive at the station shortly" //VOREStation Edit - Grammar but mostly 'shuttle' reference removal, and this also applies to notified spawn-character verb use
.["msg"] = "will arrive at the station shortly"
else if(!fail_deadly)
var/spawning = pick(latejoin)
.["turf"] = get_turf(spawning)

View File

@@ -11,8 +11,8 @@ var/const/ENGINEER =(1<<6)
var/const/ATMOSTECH =(1<<7)
var/const/AI =(1<<8)
var/const/CYBORG =(1<<9)
var/const/BLUESHIELD =(1<<13) //YW addition
var/const/SECPILOT =(1<<14) //YW addition
var/const/CLOWN =(1<<13) //VOREStation Add
var/const/MIME =(1<<14) //VOREStation Add
var/const/INTERN =(1<<15) //VOREStation Add
var/const/MEDSCI =(1<<1)
@@ -28,7 +28,10 @@ var/const/PSYCHIATRIST =(1<<7)
var/const/ROBOTICIST =(1<<8)
var/const/XENOBIOLOGIST =(1<<9)
var/const/PARAMEDIC =(1<<10)
var/const/XENOBOTANIST =(1<<15) //VOREStation Add
var/const/PATHFINDER =(1<<11) //VOREStation Add
var/const/EXPLORER =(1<<12) //VOREStation Add
var/const/SAR =(1<<13) //VOREStation Add
var/const/XENOBOTANIST =(1<<14) //VOREStation Add
var/const/CIVILIAN =(1<<2)
@@ -45,9 +48,8 @@ var/const/LAWYER =(1<<9)
var/const/CHAPLAIN =(1<<10)
var/const/ASSISTANT =(1<<11)
var/const/BRIDGE =(1<<12)
var/const/CLOWN =(1<<13) //VOREStation Add
var/const/MIME =(1<<14) //VOREStation Add
var/const/ENTERTAINER =(1<<15) //VOREStation Add
var/const/PILOT =(1<<13) //VOREStation Add
var/const/ENTERTAINER =(1<<14) //VOREStation Add
var/list/assistant_occupations = list(
)

View File

@@ -529,5 +529,5 @@
stasis_level = 100 //Just one setting
/obj/machinery/sleeper/survival_pod/Initialize()
..()
. = ..()
RefreshParts(1)

View File

@@ -14,7 +14,6 @@
active_power_usage = 10000 //10 kW. It's a big all-body scanner.
light_color = "#00FF00"
var/obj/machinery/body_scanconsole/console
var/known_implants = list(/obj/item/weapon/implant/health, /obj/item/weapon/implant/chem, /obj/item/weapon/implant/death_alarm, /obj/item/weapon/implant/loyalty, /obj/item/weapon/implant/tracking, /obj/item/weapon/implant/language, /obj/item/weapon/implant/language/eal, /obj/item/weapon/implant/backup, /obj/item/device/nif) //VOREStation Add - Backup Implant, NIF
var/printing_text = null
/obj/machinery/bodyscanner/Initialize()
@@ -255,12 +254,11 @@
organData["broken"] = E.min_broken_damage
var/implantData[0]
for(var/obj/I in E.implants)
for(var/obj/thing in E.implants)
var/implantSubData[0]
implantSubData["name"] = I.name
if(is_type_in_list(I, known_implants))
implantSubData["known"] = 1
var/obj/item/weapon/implant/I = thing
implantSubData["name"] = I.name
implantSubData["known"] = istype(I) && I.known_implant
implantData.Add(list(implantSubData))
organData["implants"] = implantData
@@ -464,8 +462,9 @@
infected = "Gangrene Detected:"
var/unknown_body = 0
for(var/I in e.implants)
if(is_type_in_list(I,known_implants))
for(var/thing in e.implants)
var/obj/item/weapon/implant/I = thing
if(istype(I) && I.known_implant)
imp += "[I] implanted:"
else
unknown_body++

View File

@@ -39,6 +39,14 @@
if(!autolathe_recipes)
autolathe_recipes = new()
wires = new(src)
for(var/Name in name_to_material)
if(Name in stored_material)
continue
stored_material[Name] = 0
storage_capacity[Name] = 0
default_apply_parts()
RefreshParts()
@@ -273,6 +281,15 @@
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
if(LAZYLEN(I.matter)) // Sadly we must obey the laws of equivalent exchange.
I.matter.Cut()
else
I.matter = list()
for(var/material in making.resources) // Handle the datum's autoscaling for waste, so we're properly wasting material, but not so much if we have efficiency.
I.matter[material] = round(making.resources[material] / (making.no_scale ? 1 : 1.25)) * (making.no_scale ? 1 : mat_efficiency)
flick("[initial(icon_state)]_finish", src)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
@@ -280,7 +297,16 @@
S.amount = multiplier
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
new making.path(src.loc)
I = new making.path(src.loc)
// We've already deducted the cost of multiple items. Process the matter the same.
if(LAZYLEN(I.matter))
I.matter.Cut()
else
I.matter = list()
for(var/material in making.resources)
I.matter[material] = round(making.resources[material] / (making.no_scale ? 1 : 1.25)) * (making.no_scale ? 1 : mat_efficiency)
return TRUE
return FALSE
@@ -306,10 +332,9 @@
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
man_rating += M.rating
storage_capacity[DEFAULT_WALL_MATERIAL] = mb_rating * 25000
storage_capacity[MAT_PLASTIC] = mb_rating * 20000
storage_capacity[MAT_PLASTEEL] = mb_rating * 16250
storage_capacity["glass"] = mb_rating * 12500
for(var/mat_name in storage_capacity)
storage_capacity[mat_name] = mb_rating * 25000
build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5
update_tgui_static_data(usr)

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