Merge remote-tracking branch 'upstream/master' into kk-ships2

This commit is contained in:
Killian
2021-05-09 20:19:20 +01:00
447 changed files with 18178 additions and 14114 deletions
+60
View File
@@ -0,0 +1,60 @@
FROM tgstation/byond:513.1533 as base
FROM base as rust_g
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
git \
ca-certificates
WORKDIR /rust_g
RUN apt-get install -y --no-install-recommends \
libssl-dev \
pkg-config \
curl \
gcc-multilib \
&& curl https://sh.rustup.rs -sSf | sh -s -- -y --default-host i686-unknown-linux-gnu \
&& git init \
&& git remote add origin https://github.com/tgstation/rust-g
COPY _build_dependencies.sh .
RUN /bin/bash -c "source _build_dependencies.sh \
&& git fetch --depth 1 origin \$RUST_G_VERSION" \
&& git checkout FETCH_HEAD \
&& ~/.cargo/bin/cargo build --release
FROM base as dm_base
WORKDIR /vorestation
FROM dm_base as build
COPY . .
RUN DreamMaker -max_errors 0 vorestation.dme
FROM dm_base
EXPOSE 2303
RUN apt-get update \
&& apt-get install -y --no-install-recommends software-properties-common \
&& add-apt-repository ppa:ubuntu-toolchain-r/test \
&& apt-get update \
&& apt-get upgrade -y \
&& apt-get dist-upgrade -y \
&& apt-get install -y --no-install-recommends \
libmariadb2 \
mariadb-client \
libssl1.0.0 \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /root/.byond/bin
COPY --from=rust_g /rust_g/target/release/librust_g.so /root/.byond/bin/rust_g
COPY --from=build /vorestation/ ./
#VOLUME [ "/vorestation/config", "/vorestation/data" ]
ENTRYPOINT [ "DreamDaemon", "vorestation.dmb", "-port", "2303", "-trusted", "-close", "-verbose" ]
+6
View File
@@ -32,6 +32,12 @@
// Reads the length of L, returning 0 if null
#define LAZYLEN(L) length(L)
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += V;
///This is used to add onto lazy assoc list when the value you're adding is a /list/. This one has extra safety over lazyaddassoc because the value could be null (and thus cant be used to += objects)
#define LAZYADDASSOCLIST(L, K, V) if(!L) { L = list(); } L[K] += list(V);
#define LAZYREMOVEASSOC(L, K, V) if(L) { if(L[K]) { L[K] -= V; if(!length(L[K])) L -= K; } if(!length(L)) L = null; }
#define LAZYACCESSASSOC(L, I, K) L ? L[I] ? L[I][K] ? L[I][K] : null : null : null
// Null-safe L.Cut()
#define LAZYCLEARLIST(L) if(L) L.Cut()
+1
View File
@@ -20,6 +20,7 @@
#define DM_FLAG_LEAVEREMAINS 0x4
#define DM_FLAG_THICKBELLY 0x8
#define DM_FLAG_AFFECTWORN 0x10
#define DM_FLAG_JAMSENSORS 0x20
//Item related modes
#define IM_HOLD "Hold"
+8
View File
@@ -49,3 +49,11 @@ var/list/tachycardics = list("coffee", "inaprovaline", "hyperzine", "nitroglyce
var/list/bradycardics = list("neurotoxin", "cryoxadone", "clonexadone", "space_drugs", "stoxin") // Decrease heart rate.
var/list/heartstopper = list("potassium_chlorophoride", "zombie_powder") // This stops the heart.
var/list/cheartstopper = list("potassium_chloride") // This stops the heart when overdose is met. -- c = conditional
#define MAX_PILL_SPRITE 24 //max icon state of the pill sprites
#define MAX_BOTTLE_SPRITE 4 //max icon state of the pill sprites
#define MAX_MULTI_AMOUNT 20 // Max number of pills/patches that can be made at once
#define MAX_UNITS_PER_PILL 60 // Max amount of units in a pill
#define MAX_UNITS_PER_PATCH 60 // Max amount of units in a patch
#define MAX_UNITS_PER_BOTTLE 60 // Max amount of units in a bottle (it's volume)
#define MAX_CUSTOM_NAME_LEN 64 // Max length of a custom pill/condiment/whatever
+27
View File
@@ -0,0 +1,27 @@
//tablecrafting defines
#define CAT_NONE ""
#define CAT_WEAPONRY "Weaponry"
#define CAT_WEAPON "Weapons"
#define CAT_AMMO "Ammunition"
#define CAT_ROBOT "Robots"
#define CAT_MISC "Misc"
#define CAT_PRIMAL "Tribal"
#define CAT_CLOTHING "Clothing"
#define CAT_FOOD "Foods"
#define CAT_BREAD "Breads"
#define CAT_BURGER "Burgers"
#define CAT_CAKE "Cakes"
#define CAT_EGG "Egg-Based Food"
#define CAT_MEAT "Meats"
#define CAT_MISCFOOD "Misc. Food"
#define CAT_MEXICAN "Mexican Food"
#define CAT_PASTRY "Pastries"
#define CAT_PIE "Pies"
#define CAT_PIZZA "Pizzas"
#define CAT_SALAD "Salads"
#define CAT_SANDWICH "Sandwiches"
#define CAT_SOUP "Soups"
#define CAT_SPAGHETTI "Spaghettis"
#define CAT_ICE "Frozen"
#define CAT_DRINK "Drinks"
#define CAT_CHEMISTRY "Chemistry"
+6
View File
@@ -97,6 +97,10 @@
#define COMSIG_ATOM_FIRE_ACT "atom_fire_act"
///from base of atom/bullet_act(): (/obj/projectile, def_zone)
#define COMSIG_ATOM_BULLET_ACT "atom_bullet_act"
///from base of atom/CheckParts(): (list/parts_list, datum/crafting_recipe/R)
#define COMSIG_ATOM_CHECKPARTS "atom_checkparts"
///from base of atom/CheckParts(): (atom/movable/new_craft) - The atom has just been used in a crafting recipe and has been moved inside new_craft.
#define COMSIG_ATOM_USED_IN_CRAFT "atom_used_in_craft"
///from base of atom/blob_act(): (/obj/structure/blob)
#define COMSIG_ATOM_BLOB_ACT "atom_blob_act"
///from base of atom/acid_act(): (acidpwr, acid_volume)
@@ -732,3 +736,5 @@
///SSalarm signals
#define COMSIG_TRIGGERED_ALARM "ssalarm_triggered"
#define COMSIG_CANCELLED_ALARM "ssalarm_cancelled"
#define COMSIG_REAGENTS_CRAFTING_PING "reagents_crafting_ping"
+63
View File
@@ -0,0 +1,63 @@
#define DEFAULT_TABLE_MATERIAL "plastic"
#define DEFAULT_WALL_MATERIAL "steel"
#define MAT_IRON "iron"
#define MAT_MARBLE "marble"
#define MAT_STEEL "steel"
#define MAT_PLASTIC "plastic"
#define MAT_GLASS "glass"
#define MAT_SILVER "silver"
#define MAT_GOLD "gold"
#define MAT_URANIUM "uranium"
#define MAT_TITANIUM "titanium"
#define MAT_PHORON "phoron"
#define MAT_DIAMOND "diamond"
#define MAT_SNOW "snow"
#define MAT_SNOWBRICK "packed snow"
#define MAT_WOOD "wood"
#define MAT_LOG "log"
#define MAT_SIFWOOD "alien wood"
#define MAT_SIFLOG "alien log"
#define MAT_STEELHULL "steel hull"
#define MAT_PLASTEEL "plasteel"
#define MAT_PLASTEELHULL "plasteel hull"
#define MAT_DURASTEEL "durasteel"
#define MAT_DURASTEELHULL "durasteel hull"
#define MAT_TITANIUMHULL "titanium hull"
#define MAT_VERDANTIUM "verdantium"
#define MAT_MORPHIUM "morphium"
#define MAT_MORPHIUMHULL "morphium hull"
#define MAT_VALHOLLIDE "valhollide"
#define MAT_LEAD "lead"
#define MAT_SUPERMATTER "supermatter"
#define MAT_METALHYDROGEN "mhydrogen"
#define MAT_OSMIUM "osmium"
#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 MAT_SANDSTONE "sandstone"
#define SHARD_SHARD "shard"
#define SHARD_SHRAPNEL "shrapnel"
#define SHARD_STONE_PIECE "piece"
#define SHARD_SPLINTER "splinters"
#define SHARD_NONE ""
#define MATERIAL_UNMELTABLE 0x1
#define MATERIAL_BRITTLE 0x2
#define MATERIAL_PADDING 0x4
#define DEFAULT_TABLE_MATERIAL "plastic"
#define DEFAULT_WALL_MATERIAL "steel"
#define TABLE_BRITTLE_MATERIAL_MULTIPLIER 4 // Amount table damage is multiplied by if it is made of a brittle material (e.g. glass)
+5 -60
View File
@@ -77,7 +77,7 @@
#define DO_AUTOPILOT 5
// Setting this much higher than 1024 could allow spammers to DOS the server easily.
#define MAX_MESSAGE_LEN 2048 //VOREStation Edit - I'm not sure about "easily". It can be a little longer.
#define MAX_MESSAGE_LEN 4096 //VOREStation Edit - I'm not sure about "easily". It can be a little longer.
#define MAX_PAPER_MESSAGE_LEN 6144
#define MAX_BOOK_MESSAGE_LEN 24576
#define MAX_RECORD_LENGTH 24576
@@ -121,65 +121,6 @@
#define WALL_CAN_OPEN 1
#define WALL_OPENING 2
#define DEFAULT_TABLE_MATERIAL "plastic"
#define DEFAULT_WALL_MATERIAL "steel"
#define MAT_IRON "iron"
#define MAT_MARBLE "marble"
#define MAT_STEEL "steel"
#define MAT_PLASTIC "plastic"
#define MAT_GLASS "glass"
#define MAT_SILVER "silver"
#define MAT_GOLD "gold"
#define MAT_URANIUM "uranium" //Did it
#define MAT_TITANIUM "titanium"
#define MAT_PHORON "phoron"
#define MAT_DIAMOND "diamond"
#define MAT_SNOW "snow"
#define MAT_WOOD "wood"
#define MAT_LOG "log"
#define MAT_SIFWOOD "alien wood"
#define MAT_SIFLOG "alien log"
#define MAT_STEELHULL "steel hull"
#define MAT_PLASTEEL "plasteel"
#define MAT_PLASTEELHULL "plasteel hull"
#define MAT_DURASTEEL "durasteel"
#define MAT_DURASTEELHULL "durasteel hull"
#define MAT_TITANIUMHULL "titanium hull"
#define MAT_VERDANTIUM "verdantium"
#define MAT_MORPHIUM "morphium"
#define MAT_MORPHIUMHULL "morphium hull"
#define MAT_VALHOLLIDE "valhollide"
#define MAT_LEAD "lead"
#define MAT_SUPERMATTER "supermatter"
#define MAT_METALHYDROGEN "mhydrogen"
#define MAT_OSMIUM "osmium"
#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"
#define SHARD_STONE_PIECE "piece"
#define SHARD_SPLINTER "splinters"
#define SHARD_NONE ""
#define MATERIAL_UNMELTABLE 0x1
#define MATERIAL_BRITTLE 0x2
#define MATERIAL_PADDING 0x4
#define TABLE_BRITTLE_MATERIAL_MULTIPLIER 4 // Amount table damage is multiplied by if it is made of a brittle material (e.g. glass)
#define BOMBCAP_DVSTN_RADIUS (max_explosion_range/4)
#define BOMBCAP_HEAVY_RADIUS (max_explosion_range/2)
#define BOMBCAP_LIGHT_RADIUS max_explosion_range
@@ -504,3 +445,7 @@ GLOBAL_LIST_INIT(all_volume_channels, list(
#define APPEARANCECHANGER_CHANGED_EYES "Eye Color"
#define GET_DECL(D) (ispath(D, /decl) ? (decls_repository.fetched_decls[D] || decls_repository.get_decl(D)) : null)
#define LOADOUT_WHITELIST_OFF 0
#define LOADOUT_WHITELIST_LAX 1
#define LOADOUT_WHITELIST_STRICT 2
+7 -1
View File
@@ -272,6 +272,10 @@
#define TASTE_DULL 0.5 //anything below 30%
#define TASTE_NUMB 0.1 //anything below 150%
//Used by emotes
#define VISIBLE_MESSAGE 1
#define AUDIBLE_MESSAGE 2
// If they're in an FBP, what braintype.
#define FBP_NONE ""
#define FBP_CYBORG "Cyborg"
@@ -433,6 +437,8 @@
#define EXAMINE_SKIPLEGS 0x0080
#define EXAMINE_SKIPFEET 0x0100
#define MAX_NUTRITION 5000 //VOREStation Edit
#define MAX_NUTRITION 6000 //VOREStation Edit
#define FAKE_INVIS_ALPHA_THRESHOLD 127 // If something's alpha var is at or below this number, certain things will pretend it is invisible.
#define DEATHGASP_NO_MESSAGE "no message"
+21
View File
@@ -0,0 +1,21 @@
// Tool types, if you add new ones please add them to /obj/item/debug/omnitool in code/game/objects/items/debug_items.dm
#define TOOL_CROWBAR "crowbar"
#define TOOL_MULTITOOL "multitool"
#define TOOL_SCREWDRIVER "screwdriver"
#define TOOL_WIRECUTTER "wirecutter"
#define TOOL_WRENCH "wrench"
#define TOOL_WELDER "welder"
#define TOOL_CABLE_COIL "cablecoil"
#define TOOL_ANALYZER "analyzer"
#define TOOL_MINING "mining"
#define TOOL_SHOVEL "shovel"
#define TOOL_RETRACTOR "retractor"
#define TOOL_HEMOSTAT "hemostat"
#define TOOL_CAUTERY "cautery"
#define TOOL_DRILL "drill"
#define TOOL_SCALPEL "scalpel"
#define TOOL_SAW "saw"
#define TOOL_BONESET "bonesetter"
#define TOOL_KNIFE "knife"
#define TOOL_BLOODFILTER "bloodfilter"
#define TOOL_ROLLINGPIN "rollingpin"
+2 -1
View File
@@ -8,4 +8,5 @@ GLOBAL_LIST_EMPTY(wire_color_directory) // This is an associative list with the
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"))
GLOBAL_LIST_INIT(char_directory_erptags, list("Top", "Bottom", "Switch", "No ERP", "Unset"))
GLOBAL_LIST_EMPTY(crafting_recipes) //list of all table craft recipes
+3 -7
View File
@@ -416,13 +416,9 @@ This actually tests if they have the same entries and values.
//Mergesort: any value in a list
/proc/sortList(var/list/L)
if(L.len < 2)
return L
var/middle = L.len / 2 + 1 // Copy is first,second-1
return mergeLists(sortList(L.Copy(0,middle)), sortList(L.Copy(middle))) //second parameter null = to end of list
//any value in a list
/proc/sortList(list/L, cmp=/proc/cmp_text_asc)
return sortTim(L.Copy(), cmp)
//Mergsorge: uses sortList() but uses the var's name specifically. This should probably be using mergeAtom() instead
/proc/sortNames(var/list/L)
+8 -2
View File
@@ -242,6 +242,7 @@ GLOBAL_LIST_EMPTY(mannequins)
var/datum/digest_mode/DM = new T
GLOB.digest_modes[DM.id] = DM
// VOREStation Add End
init_crafting_recipes(GLOB.crafting_recipes)
/*
// Custom species traits
@@ -278,8 +279,13 @@ GLOBAL_LIST_EMPTY(mannequins)
return 1 // Hooks must return 1
return 1
/// Inits the crafting recipe list, sorting crafting recipe requirements in the process.
/proc/init_crafting_recipes(list/crafting_recipes)
for(var/path in subtypesof(/datum/crafting_recipe))
var/datum/crafting_recipe/recipe = new path()
recipe.reqs = sortList(recipe.reqs, /proc/cmp_crafting_req_priority)
crafting_recipes += recipe
return crafting_recipes
/* // Uncomment to debug chemical reaction list.
/client/verb/debug_chemical_list()
+1 -1
View File
@@ -485,7 +485,7 @@ var/global/list/remainless_species = list(SPECIES_PROMETHEAN,
hair_accesories_list[path] = instance
// Custom species traits
paths = typesof(/datum/trait) - /datum/trait
paths = typesof(/datum/trait) - /datum/trait - /datum/trait/negative - /datum/trait/neutral - /datum/trait/positive
for(var/path in paths)
var/datum/trait/instance = new path()
if(!instance.name)
+20 -1
View File
@@ -64,4 +64,23 @@
return b_score - a_score
/proc/cmp_typepaths_asc(A, B)
return sorttext("[B]","[A]")
return sorttext("[B]","[A]")
/**
* Sorts crafting recipe requirements before the crafting recipe is inserted into GLOB.crafting_recipes
*
* Prioritises [/datum/reagent] to ensure reagent requirements are always processed first when crafting.
* This prevents any reagent_containers from being consumed before the reagents they contain, which can
* lead to runtimes and item duplication when it happens.
*/
/proc/cmp_crafting_req_priority(A, B)
var/lhs
var/rhs
lhs = ispath(A, /datum/reagent) ? 0 : 1
rhs = ispath(B, /datum/reagent) ? 0 : 1
return lhs - rhs
/proc/cmp_text_asc(a,b)
return sorttext(b,a)
+14
View File
@@ -0,0 +1,14 @@
GLOBAL_LIST_EMPTY(string_lists)
/**
* Caches lists with non-numeric stringify-able values (text or typepath).
*/
/proc/string_list(list/values)
var/string_id = values.Join("-")
. = GLOB.string_lists[string_id]
if(.)
return
return GLOB.string_lists[string_id] = values
+1
View File
@@ -18,6 +18,7 @@
/atom/Click(var/location, var/control, var/params) // This is their reaction to being clicked on (standard proc)
if(src)
SEND_SIGNAL(src, COMSIG_CLICK, location, control, params, usr)
usr.ClickOn(src, params)
/atom/DblClick(var/location, var/control, var/params)
+2
View File
@@ -187,3 +187,5 @@
#define ui_mech_airtoggle "WEST+1:-7, SOUTH+8"
#define ui_mech_deco1_f "WEST+2:-7, SOUTH+8"
#define ui_mech_deco2_f "WEST+2:-7, SOUTH+9"
#define ui_crafting "EAST-4:22,SOUTH:5"
+1
View File
@@ -246,6 +246,7 @@
add_overlay(selecting_appearance)
/obj/screen/Click(location, control, params)
..() // why the FUCK was this not called before
if(!usr) return 1
switch(name)
if("toggle")
+4 -1
View File
@@ -284,7 +284,10 @@ var/list/gamemode_cache = list()
var/static/disable_cid_warn_popup = FALSE
// whether or not to use the nightshift subsystem to perform lighting changes
var/static/enable_night_shifts = FALSE
var/static/enable_night_shifts = FALSE
// How strictly the loadout enforces object species whitelists
var/loadout_whitelist = LOADOUT_WHITELIST_LAX
var/static/vgs_access_identifier = null // VOREStation Edit - VGS
var/static/vgs_server_port = null // VOREStation Edit - VGS
+58
View File
@@ -0,0 +1,58 @@
SUBSYSTEM_DEF(chemistry)
name = "Chemistry"
wait = 20
flags = SS_NO_FIRE
init_order = INIT_ORDER_CHEMISTRY
var/list/chemical_reactions = list()
var/list/instant_reactions_by_reagent = list()
var/list/distilled_reactions_by_reagent = list()
// var/list/fusion_reactions_by_reagent = list() // TODO: Fusion reactions as chemical reactions
var/list/chemical_reagents = list()
/datum/controller/subsystem/chemistry/Recover()
log_debug("[name] subsystem Recover().")
chemical_reactions = SSchemistry.chemical_reactions
chemical_reagents = SSchemistry.chemical_reagents
/datum/controller/subsystem/chemistry/Initialize()
initialize_chemical_reagents()
initialize_chemical_reactions()
..()
/datum/controller/subsystem/chemistry/stat_entry()
..("C: [chemical_reagents.len] | R: [chemical_reactions.len]")
//Chemical Reactions - Initialises all /decl/chemical_reaction into a list
// It is filtered into multiple lists within a list.
// For example:
// chemical_reactions_by_reagent["phoron"] is a list of all reactions relating to phoron
// Note that entries in the list are NOT duplicated. So if a reaction pertains to
// more than one chemical it will still only appear in only one of the sublists.
/datum/controller/subsystem/chemistry/proc/initialize_chemical_reactions()
var/list/paths = decls_repository.get_decls_of_subtype(/decl/chemical_reaction)
for(var/path in paths)
var/decl/chemical_reaction/D = paths[path]
chemical_reactions += D
if(D.required_reagents && D.required_reagents.len)
var/reagent_id = D.required_reagents[1]
var/list/add_to = instant_reactions_by_reagent // Default to instant reactions list, if something's gone wrong
// if(istype(D, /decl/chemical_reaction/fusion)) // TODO: fusion reactions as chemical reactions
// add_to = fusion_reactions_by_reagent
if(istype(D, /decl/chemical_reaction/distilling))
add_to = distilled_reactions_by_reagent
LAZYINITLIST(add_to[reagent_id])
add_to[reagent_id] += D
//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
/datum/controller/subsystem/chemistry/proc/initialize_chemical_reagents()
var/paths = subtypesof(/datum/reagent)
chemical_reagents = list()
for(var/path in paths)
var/datum/reagent/D = new path()
if(!D.name)
continue
chemical_reagents[D.id] = D
@@ -1,54 +0,0 @@
PROCESSING_SUBSYSTEM_DEF(chemistry)
name = "Chemistry"
wait = 20
flags = SS_BACKGROUND|SS_POST_FIRE_TIMING
init_order = INIT_ORDER_CHEMISTRY
var/list/chemical_reactions = list()
var/list/chemical_reactions_by_reagent = list()
var/list/chemical_reagents = list()
/datum/controller/subsystem/processing/chemistry/Recover()
log_debug("[name] subsystem Recover().")
if(SSchemistry.current_thing)
log_debug("current_thing was: (\ref[SSchemistry.current_thing])[SSchemistry.current_thing]([SSchemistry.current_thing.type]) - currentrun: [SSchemistry.currentrun.len] vs total: [SSchemistry.processing.len]")
var/list/old_processing = SSchemistry.processing.Copy()
for(var/datum/D in old_processing)
if(CHECK_BITFIELD(D.datum_flags, DF_ISPROCESSING))
processing |= D
chemical_reactions = SSchemistry.chemical_reactions
chemical_reagents = SSchemistry.chemical_reagents
/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.
// For example:
// chemical_reaction_list["phoron"] is a list of all reactions relating to phoron
// Note that entries in the list are NOT duplicated. So if a reaction pertains to
// more than one chemical it will still only appear in only one of the sublists.
/datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reactions()
var/paths = typesof(/datum/chemical_reaction) - /datum/chemical_reaction
chemical_reactions = list()
chemical_reactions_by_reagent = list()
for(var/path in paths)
var/datum/chemical_reaction/D = new path
chemical_reactions += D
if(D.required_reagents && D.required_reagents.len)
var/reagent_id = D.required_reagents[1]
LAZYINITLIST(chemical_reactions_by_reagent[reagent_id])
chemical_reactions_by_reagent[reagent_id] += D
//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
/datum/controller/subsystem/processing/chemistry/proc/initialize_chemical_reagents()
var/paths = typesof(/datum/reagent) - /datum/reagent
chemical_reagents = list()
for(var/path in paths)
var/datum/reagent/D = new path()
if(!D.name)
continue
chemical_reagents[D.id] = D
+5 -5
View File
@@ -462,15 +462,15 @@ var/global/datum/controller/subsystem/ticker/ticker
for (var/mob/living/silicon/ai/aiPlayer in mob_list)
if (aiPlayer.stat != 2)
to_world("<span class='filter_system'><b>[aiPlayer.name] (Played by: [aiPlayer.key])'s laws at the end of the round were:</b></span>")
to_world("<span class='filter_system'><b>[aiPlayer.name]'s laws at the end of the round were:</b></span>") // VOREStation edit
else
to_world("<span class='filter_system'><b>[aiPlayer.name] (Played by: [aiPlayer.key])'s laws when it was deactivated were:</b></span>")
to_world("<span class='filter_system'><b>[aiPlayer.name]'s laws when it was deactivated were:</b></span>") // VOREStation edit
aiPlayer.show_laws(1)
if (aiPlayer.connected_robots.len)
var/robolist = "<b>The AI's loyal minions were:</b> "
for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots)
robolist += "[robo.name][robo.stat?" (Deactivated) (Played by: [robo.key]), ":" (Played by: [robo.key]), "]"
robolist += "[robo.name][robo.stat?" (Deactivated), ":", "]" // VOREStation edit
to_world("<span class='filter_system'>[robolist]</span>")
var/dronecount = 0
@@ -488,9 +488,9 @@ var/global/datum/controller/subsystem/ticker/ticker
if (!robo.connected_ai)
if (robo.stat != 2)
to_world("<span class='filter_system'><b>[robo.name] (Played by: [robo.key]) survived as an AI-less stationbound synthetic! Its laws were:</b></span>")
to_world("<span class='filter_system'><b>[robo.name] survived as an AI-less stationbound synthetic! Its laws were:</b></span>") // VOREStation edit
else
to_world("<span class='filter_system'><b>[robo.name] (Played by: [robo.key]) was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:</b></span>")
to_world("<span class='filter_system'><b>[robo.name] was unable to survive the rigors of being a stationbound synthetic without an AI. Its laws were:</b></span>") // VOREStation edit
if(robo) //How the hell do we lose robo between here and the world messages directly above this?
robo.laws.show_laws(world)
+507
View File
@@ -0,0 +1,507 @@
/datum/component/personal_crafting/Initialize()
if(ismob(parent))
RegisterSignal(parent, COMSIG_MOB_CLIENT_LOGIN, .proc/create_mob_button)
/datum/component/personal_crafting/proc/create_mob_button(mob/user, client/CL)
// SIGNAL_HANDLER
var/datum/hud/H = user.hud_used
var/obj/screen/craft/C = new()
C.icon = H.ui_style
H.other += C
CL.screen += C
RegisterSignal(C, COMSIG_CLICK, .proc/component_ui_interact)
/datum/component/personal_crafting
var/busy
var/viewing_category = 1 //typical powergamer starting on the Weapons tab
var/viewing_subcategory = 1
var/list/categories = list(
CAT_WEAPONRY = list(
CAT_WEAPON,
CAT_AMMO,
),
CAT_ROBOT = CAT_NONE,
CAT_MISC = CAT_NONE,
CAT_PRIMAL = CAT_NONE,
CAT_FOOD = list(
CAT_BREAD,
CAT_BURGER,
CAT_CAKE,
CAT_EGG,
CAT_ICE,
CAT_MEAT,
CAT_MISCFOOD,
CAT_PASTRY,
CAT_PIE,
CAT_PIZZA,
CAT_SALAD,
CAT_SANDWICH,
CAT_SOUP,
CAT_SPAGHETTI,
),
CAT_DRINK = CAT_NONE,
CAT_CLOTHING = CAT_NONE,
)
var/cur_category = CAT_NONE
var/cur_subcategory = CAT_NONE
var/datum/action/innate/crafting/button
var/display_craftable_only = FALSE
var/display_compact = TRUE
/* This is what procs do:
get_environment - gets a list of things accessable for crafting by user
get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
check_contents - takes a recipe and a key-type list and checks if said recipe can be done with available stuff
check_tools - takes recipe, a key-type list, and a user and checks if there are enough tools to do the stuff, checks bugs one level deep
construct_item - takes a recipe and a user, call all the checking procs, calls do_after, checks all the things again, calls del_reqs, creates result, calls CheckParts of said result with argument being list returned by deel_reqs
del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
*/
/**
* Check that the contents of the recipe meet the requirements.
*
* user: The /mob that initated the crafting.
* R: The /datum/crafting_recipe being attempted.
* contents: List of items to search for R's reqs.
*/
/datum/component/personal_crafting/proc/check_contents(atom/a, datum/crafting_recipe/R, list/contents)
var/list/item_instances = contents["instances"]
var/list/machines = contents["machinery"]
contents = contents["other"]
var/list/requirements_list = list()
// Process all requirements
for(var/requirement_path in R.reqs)
// Check we have the appropriate amount available in the contents list
var/needed_amount = R.reqs[requirement_path]
for(var/content_item_path in contents)
// Right path and not blacklisted
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(content_item_path))
continue
needed_amount -= contents[content_item_path]
if(needed_amount <= 0)
break
if(needed_amount > 0)
return FALSE
// Store the instances of what we will use for R.check_requirements() for requirement_path
var/list/instances_list = list()
for(var/instance_path in item_instances)
if(ispath(instance_path, requirement_path))
instances_list += item_instances[instance_path]
requirements_list[requirement_path] = instances_list
for(var/requirement_path in R.chem_catalysts)
if(contents[requirement_path] < R.chem_catalysts[requirement_path])
return FALSE
for(var/machinery_path in R.machinery)
if(!machines[machinery_path])//We don't care for volume with machines, just if one is there or not
return FALSE
return R.check_requirements(a, requirements_list)
/datum/component/personal_crafting/proc/get_environment(atom/a, list/blacklist = null, radius_range = 1)
. = list()
if(!isturf(a.loc))
return
for(var/atom/movable/AM in range(radius_range, a))
if(/*(AM.flags_1 & HOLOGRAM_1) ||*/ (blacklist && (AM.type in blacklist)))
continue
. += AM
/datum/component/personal_crafting/proc/get_surroundings(atom/a, list/blacklist=null)
. = list()
.["tool_qualities"] = list()
.["other"] = list()
.["instances"] = list()
.["machinery"] = list()
for(var/obj/object in get_environment(a, blacklist))
if(isitem(object))
var/obj/item/item = object
LAZYADDASSOCLIST(.["instances"], item.type, item)
if(istype(item, /obj/item/stack))
var/obj/item/stack/stack = item
.["other"][item.type] += stack.amount
else if(item.tool_qualities)
.["tool_qualities"] |= item.tool_qualities
.["other"][item.type] += 1
else
if(istype(item, /obj/item/weapon/reagent_containers))
var/obj/item/weapon/reagent_containers/container = item
// if(container.is_drainable())
if(container.is_open_container()) // this isn't exactly the same
for(var/datum/reagent/reagent in container.reagents.reagent_list)
.["other"][reagent.type] += reagent.volume
.["other"][item.type] += 1
else if (istype(object, /obj/machinery))
LAZYADDASSOCLIST(.["machinery"], object.type, object)
/// Returns a boolean on whether the tool requirements of the input recipe are satisfied by the input source and surroundings.
/datum/component/personal_crafting/proc/check_tools(atom/source, datum/crafting_recipe/recipe, list/surroundings)
if(!length(recipe.tool_behaviors) && !length(recipe.tool_paths))
return TRUE
var/list/available_tools = list()
var/list/present_qualities = list()
for(var/obj/item/contained_item in source.contents)
// if(contained_item.GetComponent(/datum/component/storage))
if(istype(contained_item, /obj/item/weapon/storage)) // cursed
for(var/obj/item/subcontained_item in contained_item.contents)
available_tools[subcontained_item.type] = TRUE
for(var/behavior in subcontained_item.tool_qualities)
present_qualities[behavior] = TRUE
available_tools[contained_item.type] = TRUE
for(var/behavior in contained_item.tool_qualities)
present_qualities[behavior] = TRUE
for(var/quality in surroundings["tool_behaviour"])
present_qualities[quality] = TRUE
for(var/path in surroundings["other"])
available_tools[path] = TRUE
for(var/required_quality in recipe.tool_behaviors)
if(present_qualities[required_quality])
continue
return FALSE
for(var/required_path in recipe.tool_paths)
var/found_this_tool = FALSE
for(var/tool_path in available_tools)
if(!ispath(required_path, tool_path))
continue
found_this_tool = TRUE
break
if(found_this_tool)
continue
return FALSE
return TRUE
/datum/component/personal_crafting/proc/construct_item(atom/a, datum/crafting_recipe/R)
var/list/contents = get_surroundings(a,R.blacklist)
// var/send_feedback = 1
if(check_contents(a, R, contents))
if(check_tools(a, R, contents))
if(R.one_per_turf)
for(var/content in get_turf(a))
if(istype(content, R.result))
return ", object already present."
//If we're a mob we'll try a do_after; non mobs will instead instantly construct the item
if(ismob(a) && !do_after(a, R.time, target = a))
return "."
contents = get_surroundings(a,R.blacklist)
if(!check_contents(a, R, contents))
return ", missing component."
if(!check_tools(a, R, contents))
return ", missing tool."
var/list/parts = del_reqs(R, a)
var/atom/movable/I = new R.result (get_turf(a.loc))
I.CheckParts(parts, R)
// if(send_feedback)
// SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
return I //Send the item back to whatever called this proc so it can handle whatever it wants to do with the new item
return ", missing tool."
return ", missing component."
/*Del reqs works like this:
Loop over reqs var of the recipe
Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
Get var/surroundings list of things accessable to crafting by get_environment()
Check the type of the current cycle req
If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isn't remove thing from surroundings
If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
If there isn't enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
If its stack check if it has enough amount
If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
If no put all of the stack in the deletion list, substract its amount from amt and keep searching
While doing above stuff check deletion list if it already has such stack type, if yes try to merge them instead of adding new one
If its anything else just locate() in in the list in a while loop, each find --s the amt var and puts the found stuff in deletion loop
Then do a loop over parts var of the recipe
Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
After its done loop over deletion list and delete all the shit that wasn't taken by parts loop
del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
*/
/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, atom/a)
var/list/surroundings
var/list/Deletion = list()
. = list()
var/data
var/amt
var/list/requirements = list()
if(R.reqs)
requirements += R.reqs
if(R.machinery)
requirements += R.machinery
main_loop:
for(var/path_key in requirements)
amt = R.reqs[path_key] || R.machinery[path_key]
if(!amt)//since machinery can have 0 aka CRAFTING_MACHINERY_USE - i.e. use it, don't consume it!
continue main_loop
surroundings = get_environment(a, R.blacklist)
surroundings -= Deletion
if(ispath(path_key, /datum/reagent))
var/datum/reagent/RG = new path_key
var/datum/reagent/RGNT
while(amt > 0)
var/obj/item/weapon/reagent_containers/RC = locate() in surroundings
RG = RC.reagents.get_reagent(path_key)
if(RG)
if(!locate(RG.type) in Deletion)
Deletion += new RG.type()
if(RG.volume > amt)
RG.volume -= amt
data = RG.data
RC.reagents.conditional_update(RC)
RG = locate(RG.type) in Deletion
RG.volume = amt
RG.data += data
continue main_loop
else
surroundings -= RC
amt -= RG.volume
RC.reagents.reagent_list -= RG
RC.reagents.conditional_update(RC)
RGNT = locate(RG.type) in Deletion
RGNT.volume += RG.volume
RGNT.data += RG.data
qdel(RG)
SEND_SIGNAL(RC.reagents, COMSIG_REAGENTS_CRAFTING_PING) // - [] TODO: Make this entire thing less spaghetti
else
surroundings -= RC
else if(ispath(path_key, /obj/item/stack))
var/obj/item/stack/S
var/obj/item/stack/SD
while(amt > 0)
S = locate(path_key) in surroundings
if(S.amount >= amt)
if(!locate(S.type) in Deletion)
SD = new S.type()
Deletion += SD
S.use(amt)
SD = locate(S.type) in Deletion
SD.amount += amt
continue main_loop
else
amt -= S.amount
if(!locate(S.type) in Deletion)
Deletion += S
else
data = S.amount
S = locate(S.type) in Deletion
S.add(data)
surroundings -= S
else
var/atom/movable/I
while(amt > 0)
I = locate(path_key) in surroundings
Deletion += I
surroundings -= I
amt--
var/list/partlist = list(R.parts.len)
for(var/M in R.parts)
partlist[M] = R.parts[M]
for(var/part in R.parts)
if(istype(part, /datum/reagent))
var/datum/reagent/RG = locate(part) in Deletion
if(RG.volume > partlist[part])
RG.volume = partlist[part]
. += RG
Deletion -= RG
continue
else if(istype(part, /obj/item/stack))
var/obj/item/stack/ST = locate(part) in Deletion
if(ST.amount > partlist[part])
ST.amount = partlist[part]
. += ST
Deletion -= ST
continue
else
while(partlist[part] > 0)
var/atom/movable/AM = locate(part) in Deletion
. += AM
Deletion -= AM
partlist[part] -= 1
while(Deletion.len)
var/DL = Deletion[Deletion.len]
Deletion.Cut(Deletion.len)
// Snowflake handling of reagent containers and storage atoms.
// If we consumed them in our crafting, we should dump their contents out before qdeling them.
if(istype(DL, /obj/item/weapon/reagent_containers))
var/obj/item/weapon/reagent_containers/container = DL
container.reagents.clear_reagents()
// container.reagents.expose(container.loc, TOUCH)
else if(istype(DL, /obj/item/weapon/storage))
var/obj/item/weapon/storage/container = DL
container.spill()
container.close_all()
qdel(DL)
/datum/component/personal_crafting/proc/component_ui_interact(atom/movable/screen/craft/image, location, control, params, user)
// SIGNAL_HANDLER
if(user == parent)
INVOKE_ASYNC(src, .proc/tgui_interact, user)
/datum/component/personal_crafting/tgui_state(mob/user)
return GLOB.tgui_not_incapacitated_turf_state
//For the UI related things we're going to assume the user is a mob rather than typesetting it to an atom as the UI isn't generated if the parent is an atom
/datum/component/personal_crafting/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
cur_category = categories[1]
if(islist(categories[cur_category]))
var/list/subcats = categories[cur_category]
cur_subcategory = subcats[1]
else
cur_subcategory = CAT_NONE
ui = new(user, src, "PersonalCrafting")
ui.open()
/datum/component/personal_crafting/tgui_data(mob/user)
var/list/data = list()
data["busy"] = busy
data["category"] = cur_category
data["subcategory"] = cur_subcategory
data["display_craftable_only"] = display_craftable_only
data["display_compact"] = display_compact
var/list/surroundings = get_surroundings(user)
var/list/craftability = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
if(!R.always_available && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
continue
if((R.category != cur_category) || (R.subcategory != cur_subcategory))
continue
craftability["[REF(R)]"] = check_contents(user, R, surroundings)
data["craftability"] = craftability
return data
/datum/component/personal_crafting/tgui_static_data(mob/user)
var/list/data = list()
var/list/crafting_recipes = list()
for(var/rec in GLOB.crafting_recipes)
var/datum/crafting_recipe/R = rec
if(R.name == "") //This is one of the invalid parents that sneaks in
continue
if(!R.always_available && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
continue
if(isnull(crafting_recipes[R.category]))
crafting_recipes[R.category] = list()
if(R.subcategory == CAT_NONE)
crafting_recipes[R.category] += list(build_recipe_data(R))
else
if(isnull(crafting_recipes[R.category][R.subcategory]))
crafting_recipes[R.category][R.subcategory] = list()
crafting_recipes[R.category]["has_subcats"] = TRUE
crafting_recipes[R.category][R.subcategory] += list(build_recipe_data(R))
data["crafting_recipes"] = crafting_recipes
return data
/datum/component/personal_crafting/tgui_act(action, params)
. = ..()
if(.)
return
switch(action)
if("make")
var/mob/user = usr
var/datum/crafting_recipe/TR = locate(params["recipe"]) in GLOB.crafting_recipes
busy = TRUE
tgui_interact(user)
var/atom/movable/result = construct_item(user, TR)
if(!istext(result)) //We made an item and didn't get a fail message
if(ismob(user) && isitem(result)) //In case the user is actually possessing a non mob like a machine
user.put_in_hands(result)
else
result.forceMove(user.drop_location())
to_chat(user, "<span class='notice'>[TR.name] constructed.</span>")
TR.on_craft_completion(user, result)
else
to_chat(user, "<span class='warning'>Construction failed[result]</span>")
busy = FALSE
if("toggle_recipes")
display_craftable_only = !display_craftable_only
. = TRUE
if("toggle_compact")
display_compact = !display_compact
. = TRUE
if("set_category")
cur_category = params["category"]
cur_subcategory = params["subcategory"] || ""
. = TRUE
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
var/list/data = list()
data["name"] = R.name
data["ref"] = "[REF(R)]"
var/list/req_text = list()
var/list/tool_list = list()
var/list/catalyst_text = list()
for(var/atom/req_atom as anything in R.reqs)
//We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var)
//Also these are typepaths so sadly we can't just do "[a]"
req_text += "[R.reqs[req_atom]] [initial(req_atom.name)]"
for(var/obj/machinery/content as anything in R.machinery)
req_text += "[R.reqs[content]] [initial(content.name)]"
if(R.additional_req_text)
req_text += R.additional_req_text
data["req_text"] = req_text.Join(", ")
for(var/atom/req_catalyst as anything in R.chem_catalysts)
catalyst_text += "[R.chem_catalysts[req_catalyst]] [initial(req_catalyst.name)]"
data["catalyst_text"] = catalyst_text.Join(", ")
for(var/required_quality in R.tool_behaviors)
tool_list += required_quality
for(var/obj/item/required_path as anything in R.tool_paths)
tool_list += initial(required_path.name)
data["tool_text"] = tool_list.Join(", ")
return data
//Mind helpers
/datum/mind/proc/teach_crafting_recipe(R)
if(!learned_recipes)
learned_recipes = list()
learned_recipes |= R
// Screen objects
/obj/screen/craft
name = "crafting menu"
icon = 'icons/mob/screen/midnight.dmi'
icon_state = "craft"
screen_loc = ui_crafting
@@ -0,0 +1,34 @@
/**
* Ensure a list of atoms/reagents exists inside this atom
*
* Goes throught he list of passed in parts, if they're reagents, adds them to our reagent holder
* creating the reagent holder if it exists.
*
* If the part is a moveable atom and the previous location of the item was a mob/living,
* it calls the inventory handler transferItemToLoc for that mob/living and transfers the part
* to this atom
*
* Otherwise it simply forceMoves the atom into this atom
*/
/atom/proc/CheckParts(list/parts_list, datum/crafting_recipe/R)
SEND_SIGNAL(src, COMSIG_ATOM_CHECKPARTS, parts_list, R)
if(parts_list)
for(var/A in parts_list)
if(istype(A, /datum/reagent))
if(!reagents)
reagents = new()
reagents.reagent_list.Add(A)
reagents.conditional_update()
else if(ismovable(A))
var/atom/movable/M = A
if(isliving(M.loc))
var/mob/living/L = M.loc
L.unEquip(M, target = src)
else
M.forceMove(src)
SEND_SIGNAL(M, COMSIG_ATOM_USED_IN_CRAFT, src)
parts_list.Cut()
/obj/machinery/CheckParts(list/parts_list)
..()
RefreshParts()
@@ -0,0 +1,56 @@
///If the machine is used/deleted in the crafting process
#define CRAFTING_MACHINERY_CONSUME 1
///If the machine is only "used" i.e. it checks to see if it's nearby and allows crafting, but doesn't delete it
#define CRAFTING_MACHINERY_USE 0
/datum/crafting_recipe
var/name = "" //in-game display name
var/list/reqs = list() //type paths of items consumed associated with how many are needed
var/list/blacklist = list() //type paths of items explicitly not allowed as an ingredient
var/result //type path of item resulting from this craft
/// String defines of items needed but not consumed. Lazy list.
var/list/tool_behaviors
/// Type paths of items needed but not consumed. Lazy list.
var/list/tool_paths
var/time = 30 //time in deciseconds
var/list/parts = list() //type paths of items that will be placed in the result
var/list/chem_catalysts = list() //like tool_behaviors but for reagents
var/category = CAT_NONE //where it shows up in the crafting UI
var/subcategory = CAT_NONE
var/always_available = TRUE //Set to FALSE if it needs to be learned first.
/// Additonal requirements text shown in UI
var/additional_req_text
///Required machines for the craft, set the assigned value of the typepath to CRAFTING_MACHINERY_CONSUME or CRAFTING_MACHINERY_USE. Lazy associative list: type_path key -> flag value.
var/list/machinery
///Should only one object exist on the same turf?
var/one_per_turf = FALSE
/datum/crafting_recipe/New()
if(!(result in reqs))
blacklist += result
if(tool_behaviors)
tool_behaviors = string_list(tool_behaviors)
if(tool_paths)
tool_paths = string_list(tool_paths)
/**
* Run custom pre-craft checks for this recipe
*
* user: The /mob that initiated the crafting
* collected_requirements: A list of lists of /obj/item instances that satisfy reqs. Top level list is keyed by requirement path.
*/
/datum/crafting_recipe/proc/check_requirements(mob/user, list/collected_requirements)
return TRUE
/datum/crafting_recipe/proc/on_craft_completion(mob/user, atom/result)
return
/datum/crafting_recipe/stunprod
name = "Stunprod"
result = /obj/item/weapon/melee/baton/cattleprod
reqs = list(/obj/item/weapon/handcuffs/cable = 1,
/obj/item/stack/rods = 1,
/obj/item/weapon/tool/wirecutters = 1)
time = 40
category = CAT_WEAPONRY
subcategory = CAT_WEAPON
@@ -0,0 +1,29 @@
/obj/item
var/list/tool_qualities
/// Used to check for a specific tool quality on an item.
/// Returns TRUE or FALSE depending on whether `tool_quality` is found.
/obj/item/proc/has_tool_quality(tool_quality)
return !!LAZYFIND(tool_qualities, tool_quality)
/* Legacy Support */
/// DEPRECATED PROC: DO NOT USE IN NEW CODE
/obj/item/proc/is_screwdriver()
return has_tool_quality(TOOL_SCREWDRIVER)
/// DEPRECATED PROC: DO NOT USE IN NEW CODE
/obj/item/proc/is_wrench()
return has_tool_quality(TOOL_WRENCH)
/// DEPRECATED PROC: DO NOT USE IN NEW CODE
/obj/item/proc/is_crowbar()
return has_tool_quality(TOOL_CROWBAR)
/// DEPRECATED PROC: DO NOT USE IN NEW CODE
/obj/item/proc/is_wirecutter()
return has_tool_quality(TOOL_WIRECUTTER)
/// DEPRECATED PROC: DO NOT USE IN NEW CODE
/obj/item/proc/is_multitool()
return has_tool_quality(TOOL_MULTITOOL)
+20 -8
View File
@@ -11,7 +11,7 @@
start_sound = 'sound/effects/weather/snowstorm/outside/active_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/outside/active_end.ogg'
volume = 80
volume = 40
/datum/looping_sound/weather/inside_blizzard
mid_sounds = list(
@@ -23,7 +23,7 @@
start_sound = 'sound/effects/weather/snowstorm/inside/active_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/inside/active_end.ogg'
volume = 60
volume = 20
/datum/looping_sound/weather/outside_snow
mid_sounds = list(
@@ -35,7 +35,7 @@
start_sound = 'sound/effects/weather/snowstorm/outside/weak_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/outside/weak_end.ogg'
volume = 50
volume = 20
/datum/looping_sound/weather/inside_snow
mid_sounds = list(
@@ -47,7 +47,7 @@
start_sound = 'sound/effects/weather/snowstorm/inside/weak_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/snowstorm/inside/weak_end.ogg'
volume = 30
volume = 10
/datum/looping_sound/weather/wind
mid_sounds = list(
@@ -59,11 +59,17 @@
'sound/effects/weather/wind/wind_5_1.ogg' = 1
)
mid_length = 10 SECONDS // The lengths for the files vary, but the longest is ten seconds, so this will make it sound like intermittent wind.
volume = 50
volume = 45
// Don't have special sounds so we just make it quieter indoors.
/datum/looping_sound/weather/wind/indoors
volume = 30
volume = 25
/datum/looping_sound/weather/wind/gentle
volume = 15
/datum/looping_sound/weather/wind/gentle/indoors
volume = 5
/datum/looping_sound/weather/rain
mid_sounds = list(
@@ -73,7 +79,13 @@
start_sound = 'sound/effects/weather/acidrain_start.ogg'
start_length = 13 SECONDS
end_sound = 'sound/effects/weather/acidrain_end.ogg'
volume = 50
volume = 20
/datum/looping_sound/weather/rain/indoors
volume = 30
volume = 10
/datum/looping_sound/weather/rain/heavy
volume = 40
/datum/looping_sound/weather/rain/heavy/indoors
volume = 20
+1
View File
@@ -58,6 +58,7 @@
var/list/purchase_log = new
var/used_TC = 0
var/list/learned_recipes //List of learned recipe TYPES.
// the world.time since the mob has been brigged, or -1 if not at all
var/brigged_since = -1
+2 -1
View File
@@ -24,7 +24,8 @@ var/global/datum/repository/crew/crew_repository = new()
var/tracked = scan()
for(var/obj/item/clothing/under/C in tracked)
var/turf/pos = get_turf(C)
if((C) && (C.has_sensor) && (pos) && (pos.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(is_jammed(C)))
var/area/B = pos?.loc //VOREStation Add: No sensor in Dorm
if((C.has_sensor) && (pos?.z == zLevel) && (C.sensor_mode != SUIT_SENSOR_OFF) && !(B.block_suit_sensors) && !(is_jammed(C)) && !(is_vore_jammed(C))) //VOREStation Edit
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
if(H.w_uniform != C)
+11 -1
View File
@@ -247,11 +247,21 @@
/obj/item/clothing/suit/radiation = 3,
/obj/item/clothing/head/radiation = 3
)
name = "Radiation suits package"
name = "Radiation suits package (Humanoid)"
cost = 20
containertype = /obj/structure/closet/radiation
containername = "Radiation suit locker"
/datum/supply_pack/eng/radsuitteshari
contains = list(
/obj/item/clothing/suit/radiation/teshari = 3,
/obj/item/clothing/head/radiation/teshari = 3
)
name = "Radiation suits package (Teshari)"
cost = 40
containertype = /obj/structure/closet/crate/aether
containername = "Teshari radiation suit locker"
/datum/supply_pack/eng/pacman_parts
name = "P.A.C.M.A.N. portable generator parts"
cost = 25
+12 -2
View File
@@ -2,11 +2,21 @@
* Highly Visible and Dangerous Weapons *
***************************************/
/datum/uplink_item/item/visible_weapons/holdout
name = "Holdout Phaser"
name = "Frontier Holdout"
item_cost = 30
path = /obj/item/weapon/gun/energy/locked/frontier/holdout/unlocked
/datum/uplink_item/item/visible_weapons/frontier
name = "Frontier Carbine"
name = "Frontier Phaser"
item_cost = 75
path = /obj/item/weapon/gun/energy/locked/frontier/unlocked
/datum/uplink_item/item/visible_weapons/carbine
name = "Frontier Carbine"
item_cost = 85
path = /obj/item/weapon/gun/energy/locked/frontier/carbine/unlocked
/datum/uplink_item/item/visible_weapons/rifle
name = "Frontier Marksman Rifle"
item_cost = 100
path = /obj/item/weapon/gun/energy/locked/frontier/rifle/unlocked
+1
View File
@@ -3,6 +3,7 @@
*/
/datum/stored_item
var/item_name = "name" //Name of the item(s) displayed
var/item_desc
var/item_path = null
var/amount = 0
var/list/instances //What items are actually stored
@@ -1,6 +1,3 @@
/area
var/limit_mob_size = TRUE //If mob size is limited in the area.
/area/shuttle/belter
name = "Belter Shuttle"
icon_state = "shuttle2"
+2
View File
@@ -1,6 +1,8 @@
/area
var/enter_message
var/exit_message
var/limit_mob_size = TRUE //If mob size is limited in the area.
var/block_suit_sensors = FALSE //If mob size is limited in the area.
/area/Entered(var/atom/movable/AM, oldLoc)
. = ..()
+19 -11
View File
@@ -490,7 +490,7 @@
// Use for objects performing visible actions
// message is output to anyone who can see, e.g. "The [src] does something!"
// blind_message (optional) is what blind people will hear e.g. "You hear something!"
/atom/proc/visible_message(var/message, var/blind_message, var/list/exclude_mobs = null)
/atom/proc/visible_message(var/message, var/blind_message, var/list/exclude_mobs, var/range = world.view)
//VOREStation Edit
var/list/see
@@ -498,7 +498,7 @@
var/obj/belly/B = loc
see = B.get_mobs_and_objs_in_belly()
else
see = get_mobs_and_objs_in_view_fast(get_turf(src),world.view,remote_ghosts = FALSE)
see = get_mobs_and_objs_in_view_fast(get_turf(src), range, remote_ghosts = FALSE)
//VOREStation Edit End
var/list/seeing_mobs = see["mobs"]
@@ -508,20 +508,20 @@
for(var/obj in seeing_objs)
var/obj/O = obj
O.show_message(message, 1, blind_message, 2)
O.show_message(message, VISIBLE_MESSAGE, blind_message, AUDIBLE_MESSAGE)
for(var/mob in seeing_mobs)
var/mob/M = mob
if(M.see_invisible >= invisibility && MOB_CAN_SEE_PLANE(M, plane))
M.show_message(message, 1, blind_message, 2)
M.show_message(message, VISIBLE_MESSAGE, blind_message, AUDIBLE_MESSAGE)
else if(blind_message)
M.show_message(blind_message, 2)
M.show_message(blind_message, AUDIBLE_MESSAGE)
// Show a message to all mobs and objects in earshot of this atom
// Use for objects performing audible actions
// message is the message output to anyone who can hear.
// deaf_message (optional) is what deaf people will see.
// hearing_distance (optional) is the range, how many tiles away the message can be heard.
/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance)
/atom/proc/audible_message(var/message, var/deaf_message, var/hearing_distance, var/radio_message)
var/range = hearing_distance || world.view
var/list/hear = get_mobs_and_objs_in_view_fast(get_turf(src),range,remote_ghosts = FALSE)
@@ -529,14 +529,19 @@
var/list/hearing_mobs = hear["mobs"]
var/list/hearing_objs = hear["objs"]
for(var/obj in hearing_objs)
var/obj/O = obj
O.show_message(message, 2, deaf_message, 1)
if(radio_message)
for(var/obj in hearing_objs)
var/obj/O = obj
O.hear_talk(src, list(new /datum/multilingual_say_piece(GLOB.all_languages["Noise"], radio_message)), null)
else
for(var/obj in hearing_objs)
var/obj/O = obj
O.show_message(message, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE)
for(var/mob in hearing_mobs)
var/mob/M = mob
var/msg = message
M.show_message(msg, 2, deaf_message, 1)
M.show_message(msg, AUDIBLE_MESSAGE, deaf_message, VISIBLE_MESSAGE)
/atom/movable/proc/dropInto(var/atom/destination)
while(istype(destination))
@@ -647,4 +652,7 @@
/atom/Exited(atom/movable/AM, atom/new_loc)
. = ..()
SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, new_loc)
SEND_SIGNAL(src, COMSIG_ATOM_EXITED, AM, new_loc)
/atom/proc/get_visible_gender()
return gender
+1 -1
View File
@@ -243,7 +243,7 @@
H.custom_exclaim = dna.custom_exclaim
H.species.blood_color = dna.blood_color
var/datum/species/S = H.species
S.produceCopy(dna.species_traits,src)
S.produceCopy(dna.species_traits, H, dna.base_species)
// VOREStation Edit End
H.force_update_organs() //VOREStation Add - Gotta do this too
+17 -8
View File
@@ -318,6 +318,10 @@
organData["robotic"] = (I.robotic >= ORGAN_ROBOT)
organData["dead"] = (I.status & ORGAN_DEAD)
if(istype(I, /obj/item/organ/internal/appendix))
var/obj/item/organ/internal/appendix/A = I
organData["inflamed"] = A.inflamed
intOrganData.Add(list(organData))
occupantData["intOrgan"] = intOrganData
@@ -497,23 +501,28 @@
if(i.robotic >= ORGAN_ROBOT)
mech = "Mechanical:"
if(i.status & ORGAN_DEAD)
i_dead = "Necrotic:"
i_dead = "Necrotic"
var/infection = "None"
switch (i.germ_level)
if (INFECTION_LEVEL_ONE to INFECTION_LEVEL_ONE + 200)
infection = "Mild Infection:"
infection = "Mild Infection"
if (INFECTION_LEVEL_ONE + 200 to INFECTION_LEVEL_ONE + 300)
infection = "Mild Infection+:"
infection = "Mild Infection+"
if (INFECTION_LEVEL_ONE + 300 to INFECTION_LEVEL_ONE + 400)
infection = "Mild Infection++:"
infection = "Mild Infection++"
if (INFECTION_LEVEL_TWO to INFECTION_LEVEL_TWO + 200)
infection = "Acute Infection:"
infection = "Acute Infection"
if (INFECTION_LEVEL_TWO + 200 to INFECTION_LEVEL_TWO + 300)
infection = "Acute Infection+:"
infection = "Acute Infection+"
if (INFECTION_LEVEL_TWO + 300 to INFECTION_LEVEL_THREE - 50)
infection = "Acute Infection++:"
infection = "Acute Infection++"
if (INFECTION_LEVEL_THREE -49 to INFINITY)
infection = "Necrosis Detected:"
infection = "Necrosis Detected"
if(istype(i, /obj/item/organ/internal/appendix))
var/obj/item/organ/internal/appendix/A = i
if(A.inflamed)
infection = "Inflammation detected!"
dat += "<tr>"
dat += "<td>[i.name]</td><td>N/A</td><td>[i.damage]</td><td>[infection]:[mech][i_dead]</td><td></td>"
+35
View File
@@ -0,0 +1,35 @@
/obj/machinery/computer/arcade
list/prizes = list( /obj/item/weapon/storage/box/snappops = 2,
/obj/item/toy/blink = 2,
/obj/item/clothing/under/syndicate/tacticool = 2,
/obj/item/toy/sword = 2,
/obj/item/weapon/gun/projectile/revolver/capgun = 2,
/obj/item/toy/crossbow = 2,
/obj/item/clothing/suit/syndicatefake = 2,
/obj/item/weapon/storage/fancy/crayons = 2,
/obj/item/toy/spinningtoy = 2,
/obj/random/mech_toy = 1,
/obj/item/weapon/reagent_containers/spray/waterflower = 1,
/obj/random/action_figure = 1,
/obj/random/plushie = 1,
/obj/item/toy/cultsword = 1,
/obj/item/toy/bouquet/fake = 1,
/obj/item/clothing/accessory/badge/sheriff = 2,
/obj/item/clothing/head/cowboy_hat/small = 2,
/obj/item/toy/stickhorse = 2,
/obj/item/toy/rock = 2,
/obj/item/toy/flash = 2,
/obj/item/toy/redbutton = 2,
/obj/item/toy/gnome = 2,
/obj/item/toy/AI = 2,
/obj/item/clothing/gloves/ring/buzzer/toy = 2,
/obj/item/weapon/storage/box/handcuffs/fake = 2,
/obj/item/toy/nuke = 2,
/obj/item/toy/minigibber = 2,
/obj/item/toy/toy_xeno = 2,
/obj/item/toy/russian_revolver = 1,
/obj/item/toy/russian_revolver/trick_revolver = 1,
/obj/item/toy/chainsaw = 1,
/obj/random/miniature = 1,
/obj/item/toy/snake_popper = 1
)
-3
View File
@@ -200,7 +200,6 @@
modify.access -= access_type
if(!access_allowed)
modify.access += access_type
modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
. = TRUE
if("assign")
@@ -225,7 +224,6 @@
modify.access = access
modify.assignment = t1
modify.rank = t1
modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
callHook("reassign_employee", list(modify))
. = TRUE
@@ -283,7 +281,6 @@
if(is_authenticated())
modify.assignment = "Dismissed" //VOREStation Edit: setting adjustment
modify.access = list()
modify.lost_access = list() //VOREStation addition: reset the lost access upon any modifications
callHook("terminate_employee", list(modify))
@@ -17,6 +17,7 @@
var/obj/item/weapon/card/id/inserted
/obj/machinery/computer/id_restorer/attackby(obj/I, mob/user)
/*
if(istype(I, /obj/item/weapon/card/id) && !(istype(I,/obj/item/weapon/card/id/guest)))
if(!inserted && user.unEquip(I))
I.forceMove(src)
@@ -24,12 +25,14 @@
else if(inserted)
to_chat(user, "<span class='warning'>There is already ID card inside.</span>")
return
*/
..()
/obj/machinery/computer/id_restorer/attack_hand(mob/user)
if(..()) return
if(stat & (NOPOWER|BROKEN)) return
/*
if(!inserted) // No point in giving you an option what to do if there's no ID to do things with.
to_chat(user, "<span class='notice'>No ID is inserted.</span>")
return
@@ -78,6 +81,7 @@
return
if("Cancel")
return
*/
//Frame
-1
View File
@@ -507,7 +507,6 @@
log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.")
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE, om_range = DEFAULT_OVERMAP_RANGE))
//visible_message("<span class='notice'>\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.</span>", 3)
visible_message("<span class='notice'>\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2]</span>", 3)
//VOREStation Edit begin: Dont delete mobs-in-mobs
+68 -21
View File
@@ -4,7 +4,7 @@
//
GLOBAL_LIST_BOILERPLATE(pointdefense_controllers, /obj/machinery/pointdefense_control)
GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/power/pointdefense)
/obj/machinery/pointdefense_control
name = "fire assist mainframe"
@@ -54,7 +54,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
return TRUE
if(action == "toggle_active")
var/obj/machinery/pointdefense/PD = locate(params["target"])
var/obj/machinery/power/pointdefense/PD = locate(params["target"])
if(!istype(PD))
return FALSE
@@ -77,7 +77,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
if(id_tag)
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
for(var/i = 1 to LAZYLEN(pointdefense_turrets))
var/obj/machinery/pointdefense/PD = pointdefense_turrets[i]
var/obj/machinery/power/pointdefense/PD = pointdefense_turrets[i]
if(!(PD.id_tag == id_tag && get_z(PD) in connected_z_levels))
continue
var/list/turret = list()
@@ -118,7 +118,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
// The acutal point defense battery
//
/obj/machinery/pointdefense
/obj/machinery/power/pointdefense
name = "\improper point defense battery"
icon = 'icons/obj/pointdefense.dmi'
icon_state = "pointdefense2"
@@ -128,6 +128,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
anchored = TRUE
circuit = /obj/item/weapon/circuitboard/pointdefense
idle_power_usage = 0.1 KILOWATTS
active_power_usage = 1 KILOWATTS
appearance_flags = PIXEL_SCALE
var/active = TRUE
var/charge_cooldown = 1 SECOND //time between it can fire at different targets
@@ -137,33 +138,69 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
var/weakref/engaging = null // The meteor we're shooting at
var/id_tag = null
/obj/machinery/pointdefense/Initialize()
/obj/machinery/power/pointdefense/Initialize()
. = ..()
// TODO - Remove this bit once machines are converted to Initialize
if(ispath(circuit))
circuit = new circuit(src)
default_apply_parts()
if(anchored)
connect_to_network()
update_icon()
var/image/I = image(icon, icon_state = "[icon_state]_under")
I.appearance_flags |= RESET_TRANSFORM
underlays += I
/obj/machinery/pointdefense/get_description_interaction()
/obj/machinery/power/pointdefense/examine(mob/user)
. = ..()
if(powernet)
. += "It is connected to a power cable below."
/obj/machinery/power/pointdefense/get_description_interaction()
. = ..()
if(!id_tag)
. += "[desc_panel_image("multitool")]to set ident tag and connect to a mainframe."
/obj/machinery/pointdefense/update_icon()
/obj/machinery/power/pointdefense/update_icon()
if(!active || !id_tag || inoperable())
icon_state = "[initial(icon_state)]_off"
else
icon_state = initial(icon_state)
/obj/machinery/pointdefense/power_change()
/obj/machinery/power/pointdefense/default_unfasten_wrench(var/mob/user, var/obj/item/weapon/W, var/time)
if((. = ..()))
src.transform = null // Reset rotation if we're anchored/unanchored
////////// This machine is willing to take power from cables OR APCs. Handle NOPOWER stat specially here! ////////
/obj/machinery/power/pointdefense/connect_to_network()
if((. = ..()))
stat &= ~NOPOWER // We now ignore APC power
update_icon()
/obj/machinery/power/pointdefense/disconnect_from_network()
if((. = ..()))
power_change() // We're back on APC power.
/obj/machinery/power/pointdefense/power_change()
if(powernet)
return // We don't care, we are cable powered anyway
var/old_stat = stat
..()
if(old_stat != stat)
update_icon()
// Decide where to get the power to fire from
/obj/machinery/power/pointdefense/use_power_oneoff(var/amount, var/chan = -1)
if(powernet)
return draw_power(amount)
else if(powered(chan))
use_power(amount, chan)
return amount
return 0
// Find controller with the same tag on connected z levels (if any)
/obj/machinery/pointdefense/proc/get_controller()
/obj/machinery/power/pointdefense/proc/get_controller()
if(!id_tag)
return null
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
@@ -172,7 +209,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
if(PDC.id_tag == id_tag && (get_z(PDC) in connected_z_levels))
return PDC
/obj/machinery/pointdefense/attackby(var/obj/item/W, var/mob/user)
/obj/machinery/power/pointdefense/attackby(var/obj/item/W, var/mob/user)
if(W?.is_multitool())
var/new_ident = input(user, "Enter a new ident tag.", "[src]", id_tag) as null|text
if(new_ident && new_ident != id_tag && user.Adjacent(src) && CanInteract(user, GLOB.tgui_physical_state))
@@ -185,16 +222,18 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
return
if(default_part_replacement(user, W))
return
if(default_unfasten_wrench(user, W, 40))
return
return ..()
//Guns cannot shoot through hull or generally dense turfs.
/obj/machinery/pointdefense/proc/space_los(meteor)
/obj/machinery/power/pointdefense/proc/space_los(meteor)
for(var/turf/T in getline(src,meteor))
if(T.density)
return FALSE
return TRUE
/obj/machinery/pointdefense/proc/Shoot(var/weakref/target)
/obj/machinery/power/pointdefense/proc/Shoot(var/weakref/target)
var/obj/effect/meteor/M = target.resolve()
if(!istype(M))
engaging = null
@@ -208,7 +247,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
set_dir(ATAN2(transform.b, transform.a) > 0 ? NORTH : SOUTH)
/obj/machinery/pointdefense/proc/finish_shot(var/weakref/target)
/obj/machinery/power/pointdefense/proc/finish_shot(var/weakref/target)
var/obj/machinery/pointdefense_control/PC = get_controller()
engaging = null
@@ -218,26 +257,34 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
var/obj/effect/meteor/M = target.resolve()
if(!istype(M))
return
if(use_power_oneoff(active_power_usage) < active_power_usage)
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
visible_message("[src] sputters as browns out while attempting to fire.")
flick(src, "[initial(icon_state)]_off")
return
//We throw a laser but it doesnt have to hit for meteor to explode
var/obj/item/projectile/beam/pointdefense/beam = new(get_turf(src))
playsound(src, 'sound/weapons/mandalorian.ogg', 75, 1)
use_power_oneoff(idle_power_usage * 10)
beam.launch_projectile(target = M.loc, user = src)
/obj/machinery/pointdefense/process()
/obj/machinery/power/pointdefense/process()
..()
if(stat & (NOPOWER|BROKEN))
if(!anchored || stat & (NOPOWER|BROKEN))
return
if(!active)
return
/*
var/desiredir = ATAN2(transform.b, transform.a) > 0 ? NORTH : SOUTH
if(dir != desiredir)
set_dir(desiredir)
*/
if(LAZYLEN(GLOB.meteor_list) > 0)
find_and_shoot()
/obj/machinery/pointdefense/proc/find_and_shoot()
/obj/machinery/power/pointdefense/proc/find_and_shoot()
// There ARE meteors to shoot
if(LAZYLEN(GLOB.meteor_list) == 0)
return
@@ -273,7 +320,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
Shoot(target)
return
/obj/machinery/pointdefense/proc/targeting_check(var/obj/effect/meteor/M)
/obj/machinery/power/pointdefense/proc/targeting_check(var/obj/effect/meteor/M)
// Target in range
var/list/connected_z_levels = GetConnectedZlevels(get_z(src))
if(!(M.z in connected_z_levels))
@@ -286,7 +333,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
return TRUE
/obj/machinery/pointdefense/RefreshParts()
/obj/machinery/power/pointdefense/RefreshParts()
. = ..()
// Calculates an average rating of components that affect shooting rate
var/shootrate_divisor = total_component_rating_of_type(/obj/item/weapon/stock_parts/capacitor)
@@ -302,7 +349,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
var/rotation_divisor = total_component_rating_of_type(/obj/item/weapon/stock_parts/manipulator)
rotation_speed = 0.5 SECONDS / (rotation_divisor ? rotation_divisor : 1)
/obj/machinery/pointdefense/proc/Activate()
/obj/machinery/power/pointdefense/proc/Activate()
if(active)
return FALSE
@@ -312,7 +359,7 @@ GLOBAL_LIST_BOILERPLATE(pointdefense_turrets, /obj/machinery/pointdefense)
update_icon()
return TRUE
/obj/machinery/pointdefense/proc/Deactivate()
/obj/machinery/power/pointdefense/proc/Deactivate()
if(!active)
return FALSE
playsound(src, 'sound/machines/apc_nopower.ogg', 50, 0)
+1 -1
View File
@@ -24,7 +24,7 @@
name = "military CIWS turret"
desc = "A ship weapons turret designed for anti-fighter defense."
req_one_access = list(access_cent_general)
installation = /obj/item/weapon/gun/energy/lasercannon
installation = /obj/item/weapon/gun/energy/pulse_rifle/destroyer
health = 500
maxhealth = 500
enabled = TRUE
+1 -1
View File
@@ -246,7 +246,7 @@
if(!R.cell)
return
if(R.mob_size >= MOB_LARGE)
if(istype(R, /mob/living/silicon/robot/platform))
to_chat(R, SPAN_WARNING("You are too large to fit into \the [src]."))
return
-4
View File
@@ -634,10 +634,6 @@
model_text = "Exploration"
departments = list("Exploration","Expedition Medic","Old Exploration","No Change")
/obj/machinery/suit_cycler/exploration/Initialize()
species -= SPECIES_TESHARI
return ..()
/obj/machinery/suit_cycler/pilot
name = "Pilot suit cycler"
model_text = "Pilot"
@@ -4614,3 +4614,36 @@
/obj/machinery/vending/cola/soft
icon = 'icons/obj/vending_vr.dmi'
icon_state = "Cola_Machine"
//////////////////////Bepis Drinks (04/29/2021)//////////////////////
/obj/machinery/vending/bepis
name = "Bepis Softdrinks"
desc = "A strange softdrink vendor that isn't owned by NanoTrasen... Why (and how) is it here?"
icon = 'icons/obj/vending_vr.dmi'
icon_state = "bepis"
product_slogans = "Refreshing!;Have a sip, you won't believe the taste!;Puts the 'B' in Best Soda!"
product_ads = "Refreshing!;Hope you're thirsty!;Please, have a drink!;Drink up!"
products = list(/obj/item/weapon/reagent_containers/food/drinks/cans/bepis = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/astrodew = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/buzz = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/shambler = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/cranberry = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/icecoffee = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 10,
/obj/item/weapon/reagent_containers/food/drinks/cans/root_beer = 10)
prices = list(/obj/item/weapon/reagent_containers/food/drinks/cans/bepis = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/astrodew = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/buzz = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/shambler = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/cranberry = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/icecoffee = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/iced_tea = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/grape_juice = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/gingerale = 1,
/obj/item/weapon/reagent_containers/food/drinks/cans/root_beer = 1)
idle_power_usage = 211 //refrigerator - believe it or not, this is actually the average power consumption of a refrigerated vending machine according to NRCan.
vending_sound = "machines/vending/vending_cans.ogg"
+42
View File
@@ -0,0 +1,42 @@
/obj/effect/effect/sparks/confetti
name = "confetti"
icon = 'icons/effects/effects_vr.dmi'
icon_state = "confetti"
/obj/effect/effect/sparks/New()
..()
playsound(src, "sounds/items/confetti.ogg ", 100, 1)
/datum/effect/effect/system/confetti_spread
var/total_sparks = 0 // To stop it being spammed and lagging!
set_up(n = 3, c = 0, loca)
if(n > 10)
n = 10
number = n
cardinals = c
if(istype(loca, /turf/))
location = loca
else
location = get_turf(loca)
start()
var/i = 0
for(i=0, i<src.number, i++)
if(src.total_sparks > 20)
return
spawn(0)
if(holder)
src.location = get_turf(holder)
var/obj/effect/effect/sparks/confetti = new /obj/effect/effect/sparks/confetti(src.location)
src.total_sparks++
var/direction
if(src.cardinals)
direction = pick(cardinal)
else
direction = pick(alldirs)
for(i=0, i<pick(1,2,3), i++)
sleep(5)
step(confetti,direction)
spawn(20)
src.total_sparks--
+1 -28
View File
@@ -552,9 +552,7 @@ var/list/global/slot_flags_enumeration = list(
if(!hit_zone)
U.do_attack_animation(M)
playsound(src, 'sound/weapons/punchmiss.ogg', 25, 1, -1)
//visible_message("<span class='danger'>[U] attempts to stab [M] in the eyes, but misses!</span>")
for(var/mob/V in viewers(M))
V.show_message("<span class='danger'>[U] attempts to stab [M] in the eyes, but misses!</span>")
visible_message(SPAN_DANGER("\The [U] attempts to stab \the [M] in the eyes, but misses!"))
return
add_attack_logs(user,M,"Attack eyes with [name]")
@@ -908,31 +906,6 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
/obj/item/proc/apply_accessories(var/image/standing)
return standing
/*
* Assorted tool procs, so any item can emulate any tool, if coded
*/
/obj/item/proc/is_screwdriver()
return FALSE
/obj/item/proc/is_wrench()
return FALSE
/obj/item/proc/is_crowbar()
return FALSE
/obj/item/proc/is_wirecutter()
return FALSE
// These next three might bug out or runtime, unless someone goes back and finds a way to generalize their specific code
/obj/item/proc/is_cable_coil()
return FALSE
/obj/item/proc/is_multitool()
return FALSE
/obj/item/proc/is_welder()
return FALSE
/obj/item/MouseEntered(location,control,params)
. = ..()
if(usr.is_preference_enabled(/datum/client_preference/inv_tooltips) && ((src in usr) || isstorage(loc))) // If in inventory or in storage we're looking at
+2 -4
View File
@@ -194,10 +194,8 @@
return
/obj/item/blueprints/proc/move_turfs_to_area(var/list/turf/turfs, var/area/A)
A.contents.Add(turfs)
//oldarea.contents.Remove(usr.loc) // not needed
//T.loc = A //error: cannot change constant value
for(var/T in turfs)
ChangeArea(T, A)
/obj/item/blueprints/proc/edit_area()
var/area/A = get_area()
+1 -3
View File
@@ -29,6 +29,7 @@
var/obj/machinery/connectable //Used to connect machinery.
var/weakref_wiring //Used to store weak references for integrated circuitry. This is now the Omnitool.
toolspeed = 1
tool_qualities = list(TOOL_MULTITOOL)
/obj/item/device/multitool/attack_self(mob/living/user)
var/choice = alert("What do you want to do with \the [src]?","Multitool Menu", "Switch Mode", "Clear Buffers", "Cancel")
@@ -65,9 +66,6 @@
return
/obj/item/device/multitool/is_multitool()
return TRUE
/obj/item/device/multitool/cyborg
name = "multitool"
desc = "Optimised and stripped-down version of a regular multitool."
@@ -2,3 +2,14 @@
/obj/item/device/radio_jammer/admin
jam_range = 255
tick_cost = 0
/proc/is_vore_jammed(var/obj/radio)
var/atom/current = radio
while(current.loc)
if(isbelly(current.loc))
var/obj/belly/B = current.loc
if(B.mode_flags & DM_FLAG_JAMSENSORS)
return TRUE
current = current.loc
return FALSE
@@ -1,102 +0,0 @@
/* Glass stack types
* Contains:
* Glass sheets
* Reinforced glass sheets
* Phoron Glass Sheets
* Reinforced Phoron Glass Sheets (AKA Holy fuck strong windows)
* Glass shards - TODO: Move this into code/game/object/item/weapons
*/
/*
* Glass sheets
*/
/obj/item/stack/material/glass
name = "glass"
singular_name = "glass sheet"
icon_state = "sheet-glass"
var/is_reinforced = 0
default_type = "glass"
drop_sound = 'sound/items/drop/glass.ogg'
pickup_sound = 'sound/items/pickup/glass.ogg'
/obj/item/stack/material/glass/attack_self(mob/user as mob)
construct_window(user)
/obj/item/stack/material/glass/attackby(obj/item/W, mob/user)
..()
if(!is_reinforced)
if(istype(W,/obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/CC = W
if (get_amount() < 1 || CC.get_amount() < 5)
to_chat(user, "<span class='warning'>You need five lengths of coil and one sheet of glass to make wired glass.</span>")
return
CC.use(5)
use(1)
to_chat(user, "<span class='notice'>You attach wire to the [name].</span>")
new /obj/item/stack/light_w(user.loc)
else if(istype(W, /obj/item/stack/rods))
var/obj/item/stack/rods/V = W
if (V.get_amount() < 1 || get_amount() < 1)
to_chat(user, "<span class='warning'>You need one rod and one sheet of glass to make reinforced glass.</span>")
return
var/obj/item/stack/material/glass/reinforced/RG = new (user.loc)
RG.add_fingerprint(user)
RG.add_to_stacks(user)
var/obj/item/stack/material/glass/G = src
src = null
var/replace = (user.get_inactive_hand()==G)
V.use(1)
G.use(1)
if (!G && replace)
user.put_in_hands(RG)
/*
* Reinforced glass sheets
*/
/obj/item/stack/material/glass/reinforced
name = "reinforced glass"
singular_name = "reinforced glass sheet"
icon_state = "sheet-rglass"
default_type = "reinforced glass"
is_reinforced = 1
/*
* Phoron Glass sheets
*/
/obj/item/stack/material/glass/phoronglass
name = "phoron glass"
singular_name = "phoron glass sheet"
icon_state = "sheet-phoronglass"
default_type = "phoron glass"
/obj/item/stack/material/glass/phoronglass/attackby(obj/item/W, mob/user)
..()
if( istype(W, /obj/item/stack/rods) )
var/obj/item/stack/rods/V = W
var/obj/item/stack/material/glass/phoronrglass/RG = new (user.loc)
RG.add_fingerprint(user)
RG.add_to_stacks(user)
V.use(1)
var/obj/item/stack/material/glass/G = src
src = null
var/replace = (user.get_inactive_hand()==G)
G.use(1)
if (!G && !RG && replace)
user.put_in_hands(RG)
else
return ..()
/*
* Reinforced phoron glass sheets
*/
/obj/item/stack/material/glass/phoronrglass
name = "reinforced phoron glass"
singular_name = "reinforced phoron glass sheet"
icon_state = "sheet-phoronrglass"
default_type = "reinforced phoron glass"
is_reinforced = 1
@@ -1,286 +0,0 @@
/obj/item/stack/animalhide
name = "hide"
desc = "The hide of some creature."
description_info = "Use something <b><font color='red'>sharp</font></b>, like a knife, to scrape the hairs/feathers/etc off this hide to prepare it for tanning."
icon_state = "sheet-hide"
drop_sound = 'sound/items/drop/cloth.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
amount = 1
max_amount = 20
stacktype = "hide"
no_variants = TRUE
// This needs to be very clearly documented for players. Whether it should stay in the main description is up for debate.
/obj/item/stack/animalhide/examine(var/mob/user)
. = ..()
. += description_info
/obj/item/stack/animalhide/human
name = "skin"
desc = "The by-product of sapient farming."
singular_name = "skin piece"
icon_state = "sheet-hide"
no_variants = FALSE
drop_sound = 'sound/items/drop/leather.ogg'
pickup_sound = 'sound/items/pickup/leather.ogg'
stacktype = "hide-human"
/obj/item/stack/animalhide/corgi
name = "corgi hide"
desc = "The by-product of corgi farming."
singular_name = "corgi hide piece"
icon_state = "sheet-corgi"
stacktype = "hide-corgi"
/obj/item/stack/animalhide/cat
name = "cat hide"
desc = "The by-product of cat farming."
singular_name = "cat hide piece"
icon_state = "sheet-cat"
stacktype = "hide-cat"
/obj/item/stack/animalhide/monkey
name = "monkey hide"
desc = "The by-product of monkey farming."
singular_name = "monkey hide piece"
icon_state = "sheet-monkey"
stacktype = "hide-monkey"
/obj/item/stack/animalhide/lizard
name = "lizard skin"
desc = "Sssssss..."
singular_name = "lizard skin piece"
icon_state = "sheet-lizard"
stacktype = "hide-lizard"
/obj/item/stack/animalhide/xeno
name = "alien hide"
desc = "The skin of a terrible creature."
singular_name = "alien hide piece"
icon_state = "sheet-xeno"
stacktype = "hide-xeno"
//don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
/obj/item/stack/xenochitin
name = "alien chitin"
desc = "A piece of the hide of a terrible creature."
singular_name = "alien chitin piece"
icon = 'icons/mob/alien.dmi'
icon_state = "chitin"
stacktype = "hide-chitin"
/obj/item/xenos_claw
name = "alien claw"
desc = "The claw of a terrible creature."
icon = 'icons/mob/alien.dmi'
icon_state = "claw"
/obj/item/weed_extract
name = "weed extract"
desc = "A piece of slimy, purplish weed."
icon = 'icons/mob/alien.dmi'
icon_state = "weed_extract"
//Step one - dehairing.
/obj/item/stack/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(has_edge(W) || is_sharp(W))
//visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message)
user.visible_message("<span class='notice'>\The [user] starts cutting hair off \the [src]</span>", "<span class='notice'>You start cutting the hair off \the [src]</span>", "You hear the sound of a knife rubbing against flesh")
var/scraped = 0
while(amount > 0 && do_after(user, 2.5 SECONDS)) // 2.5s per hide
//Try locating an exisitng stack on the tile and add to there if possible
var/obj/item/stack/hairlesshide/H = null
for(var/obj/item/stack/hairlesshide/HS in user.loc) // Could be scraping something inside a locker, hence the .loc, not get_turf
if(HS.amount < HS.max_amount)
H = HS
break
// Either we found a valid stack, in which case increment amount,
// Or we need to make a new stack
if(istype(H))
H.amount++
else
H = new /obj/item/stack/hairlesshide(user.loc)
// Increment the amount
src.use(1)
scraped++
if(scraped)
to_chat(user, SPAN_NOTICE("You scrape the hair off [scraped] hide\s."))
else
..()
//Step two - washing..... it's actually in washing machine code, and ere.
/obj/item/stack/hairlesshide
name = "hairless hide"
desc = "This hide was stripped of it's hair, but still needs tanning."
description_info = "Get it <b><font color='blue'>wet</font></b> to continue tanning this into leather.<br>\
You could set it in a river, wash it with a sink, or just splash water on it with a bucket."
singular_name = "hairless hide piece"
icon_state = "sheet-hairlesshide"
no_variants = FALSE
max_amount = 20
stacktype = "hairlesshide"
/obj/item/stack/hairlesshide/examine(var/mob/user)
. = ..()
. += description_info
/obj/item/stack/hairlesshide/water_act(var/wateramount)
. = ..()
wateramount = min(amount, round(wateramount))
for(var/i in 1 to wateramount)
var/obj/item/stack/wetleather/H = null
for(var/obj/item/stack/wetleather/HS in get_turf(src)) // Doesn't have a user, can't just use their loc
if(HS.amount < HS.max_amount)
H = HS
break
// Either we found a valid stack, in which case increment amount,
// Or we need to make a new stack
if(istype(H))
H.amount++
else
H = new /obj/item/stack/wetleather(get_turf(src))
// Increment the amount
src.use(1)
/obj/item/stack/hairlesshide/proc/rapidcure(var/stacknum = 1)
stacknum = min(stacknum, amount)
while(stacknum)
var/obj/item/stack/wetleather/I = new /obj/item/stack/wetleather(get_turf(src))
if(istype(I))
I.dry()
use(1)
stacknum -= 1
//Step three - drying
/obj/item/stack/wetleather
name = "wet leather"
desc = "This leather has been cleaned but still needs to be dried."
description_info = "To finish tanning the leather, you need to dry it. \
You could place it under a <b><font color='red'>fire</font></b>, \
put it in a <b><font color='blue'>drying rack</font></b>, \
or build a <b><font color='brown'>tanning rack</font></b> from steel or wooden boards."
singular_name = "wet leather piece"
icon_state = "sheet-wetleather"
var/wetness = 30 //Reduced when exposed to high temperautres
var/drying_threshold_temperature = 500 //Kelvin to start drying
no_variants = FALSE
max_amount = 20
stacktype = "wetleather"
var/dry_type = /obj/item/stack/material/leather
/obj/item/stack/wetleather/examine(var/mob/user)
. = ..()
. += description_info
. += "\The [src] is [get_dryness_text()]."
/obj/item/stack/wetleather/proc/get_dryness_text()
if(wetness > 20)
return "wet"
if(wetness > 10)
return "damp"
if(wetness)
return "almost dry"
return "dry"
/obj/item/stack/wetleather/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
if(exposed_temperature >= drying_threshold_temperature)
wetness--
if(wetness == 0)
dry()
/obj/item/stack/wetleather/proc/dry()
var/obj/item/stack/material/leather/L = new(src.loc)
L.amount = amount
use(amount)
return L
/obj/item/stack/wetleather/transfer_to(obj/item/stack/S, var/tamount=null, var/type_verified)
. = ..()
if(.) // If it transfers any, do a weighted average of the wetness
var/obj/item/stack/wetleather/W = S
var/oldamt = W.amount - .
W.wetness = round(((oldamt * W.wetness) + (. * wetness)) / W.amount)
/obj/structure/tanning_rack
name = "tanning rack"
desc = "A rack used to stretch leather out and hold it taut during the tanning process."
icon = 'icons/obj/kitchen.dmi'
icon_state = "spike"
var/obj/item/stack/wetleather/drying = null
/obj/structure/tanning_rack/Initialize()
. = ..()
START_PROCESSING(SSobj, src) // SSObj fires ~every 2s , starting from wetness 30 takes ~1m
/obj/structure/tanning_rack/Destroy()
STOP_PROCESSING(SSobj, src)
return ..()
/obj/structure/tanning_rack/process()
if(drying && drying.wetness)
drying.wetness = max(drying.wetness - 1, 0)
if(!drying.wetness)
visible_message("The [drying] is dry!")
update_icon()
/obj/structure/tanning_rack/examine(var/mob/user)
. = ..()
if(drying)
. += "\The [drying] is [drying.get_dryness_text()]."
/obj/structure/tanning_rack/update_icon()
overlays.Cut()
if(drying)
var/image/I
if(drying.wetness)
I = image(icon, "leather_wet")
else
I = image(icon, "leather_dry")
add_overlay(I)
/obj/structure/tanning_rack/attackby(var/atom/A, var/mob/user)
if(istype(A, /obj/item/stack/wetleather))
if(!drying) // If not drying anything, start drying the thing
if(user.unEquip(A, target = src))
drying = A
else // Drying something, add if possible
var/obj/item/stack/wetleather/W = A
W.transfer_to(drying, W.amount, TRUE)
update_icon()
return TRUE
return ..()
/obj/structure/tanning_rack/attack_hand(var/mob/user)
if(drying)
var/obj/item/stack/S = drying
if(!drying.wetness) // If it's dry, make a stack of dry leather and prepare to put that in their hands
var/obj/item/stack/material/leather/L = new(src)
L.amount = drying.amount
drying.use(drying.amount)
S = L
if(ishuman(user))
var/mob/living/carbon/human/H = user
if(!H.put_in_any_hand_if_possible(S))
S.forceMove(get_turf(src))
else
S.forceMove(get_turf(src))
drying = null
update_icon()
/obj/structure/tanning_rack/attack_robot(var/mob/user)
attack_hand(user) // That has checks to
+2 -2
View File
@@ -1290,7 +1290,7 @@
/obj/item/toy/character/voidone,
/obj/item/toy/character/lich
)
/* VOREStation edit. Moved to toys_vr.dm
/obj/item/toy/AI
name = "toy AI"
desc = "A little toy model AI core!"// with real law announcing action!" //Alas, requires a rewrite of how ion laws work.
@@ -1298,7 +1298,7 @@
icon_state = "AI"
w_class = ITEMSIZE_SMALL
var/cooldown = 0
/*
/obj/item/toy/AI/attack_self(mob/user)
if(!cooldown) //for the sanity of everyone
var/message = generate_ion_law()
+675 -1
View File
@@ -38,7 +38,7 @@
/obj/item/toy/plushie/box
name = "cardboard plushie"
desc = "A toy box plushie, it holds cotten. Only a baddie would place a bomb through the postal system..."
desc = "A toy box plushie, it holds cotton. Only a baddie would place a bomb through the postal system..."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "box"
attack_verb = list("open", "closed", "packed", "hidden", "rigged", "bombed", "sent", "gave")
@@ -101,3 +101,677 @@
/obj/item/toy/plushie/vox/proc/cooldownreset()
cooldown = 0
/*
* 4/9/21 *
* IPC Plush
* Toaster plush
* Snake plush
* Cube plush
* Pip plush
* Moth plush
* Crab plush
* Possum plush
* Goose plush
* White mouse plush
* Pet rock
* Pet rock (m)
* Pet rock (f)
* Chew toys
* Cat toy * 2
* Toy flash
* Toy button
* Gnome
* Toy AI
* Buzzer ring
* Fake handcuffs
* Nuke toy
* Toy gibber
* Toy xeno
* Fake gun * 2
* Toy chainsaw
* Random tabletop miniature spawner
* snake popper
*/
/obj/item/toy/plushie/ipc
name = "IPC plushie"
desc = "A pleasing soft-toy of a monitor-headed robot. Toaster functionality included."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "plushie_ipc"
var/cooldown = 0
/obj/item/weapon/reagent_containers/food/snacks/slice/bread
var/toasted = FALSE
/obj/item/weapon/reagent_containers/food/snacks/tastybread
var/toasted = FALSE
/obj/item/weapon/reagent_containers/food/snacks/slice/bread/afterattack(atom/A, mob/user as mob, proximity)
if(istype(A, /obj/item/toy/plushie/ipc) && !toasted)
toasted = TRUE
icon = 'icons/obj/toy_vr.dmi'
icon_state = "toast"
to_chat(user, "<span class='notice'> You insert bread into the toaster. </span>")
playsound(loc, 'sound/machines/ding.ogg', 50, 1)
/obj/item/weapon/reagent_containers/food/snacks/tastybread/afterattack(atom/A, mob/user as mob, proximity)
if(istype(A, /obj/item/toy/plushie/ipc) && !toasted)
toasted = TRUE
icon = 'icons/obj/toy_vr.dmi'
icon_state = "toast"
to_chat(user, "<span class='notice'> You insert bread into the toaster. </span>")
playsound(loc, 'sound/machines/ding.ogg', 50, 1)
/obj/item/toy/plushie/ipc/attackby(obj/item/I as obj, mob/living/user as mob)
if(istype(I, /obj/item/weapon/material/kitchen/utensil))
to_chat(user, "<span class='notice'> You insert the [I] into the toaster. </span>")
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, src)
s.start()
user.electrocute_act(15,src,0.75)
else
return ..()
/obj/item/toy/plushie/ipc/attack_self(mob/user as mob)
if(!cooldown)
playsound(user, 'sound/machines/ping.ogg', 10, 0)
src.visible_message("<span class='danger'>Ping!</span>")
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/plushie/ipc/proc/cooldownreset()
cooldown = 0
/obj/item/toy/plushie/ipc/toaster
name = "toaster plushie"
desc = "A stuffed toy of a pleasant art-deco toaster. It has a small tag on it reading 'Bricker Home Appliances! All rights reserved, copyright 2298.' It's a tad heavy on account of containing a heating coil. Want to make toast?"
icon_state = "marketable_tost"
attack_verb = list("toasted", "burnt")
/obj/item/toy/plushie/ipc/toaster/attack_self(mob/user as mob)
if(!cooldown)
playsound(user, 'sound/machines/ding.ogg', 10, 0)
src.visible_message("<span class='danger'>Ding!</span>")
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/plushie/snakeplushie
name = "snake plushie"
desc = "An adorable stuffed toy that resembles a snake. Not to be mistaken for the real thing."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "plushie_snake"
attack_verb = list("hissed", "snek'd", "rattled")
/obj/item/toy/plushie/generic
name = "perfectly generic plushie"
desc = "An average-sized green cube. It isn't notable in any way."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "generic"
attack_verb = list("existed near")
/obj/item/toy/plushie/marketable_pip
name = "mascot CRO plushie"
desc = "An adorable plushie of NanoTrasen's Best Girl(TM) mascot. It smells faintly of paperwork."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "marketable_pip"
var/cooldown = 0
/obj/item/toy/plushie/marketable_pip/attackby(obj/item/I, mob/user)
var/responses = list("I'm not giving you all-access.", "Do you want an ID modification?", "Where are you swiping that!?", "Congratulations! You've been promoted to unemployed!")
var/obj/item/weapon/card/id/id = I.GetID()
if(istype(id))
if(!cooldown)
user.visible_message("<span class='notice'>[user] swipes \the [I] against \the [src].</span>")
atom_say(pick(responses))
playsound(user, 'sound/effects/whistle.ogg', 10, 0)
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/plushie/marketable_pip/attack_self(mob/user as mob)
if(!cooldown)
playsound(user, 'sound/effects/whistle.ogg', 10, 0)
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/plushie/marketable_pip/proc/cooldownreset()
cooldown = 0
/obj/item/toy/plushie/moth
name = "moth plushie"
desc = "A cute plushie of cartoony moth. It's ultra fluffy but leaves dust everywhere."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "moth"
var/cooldown = 0
/obj/item/toy/plushie/moth/attack_self(mob/user as mob)
if(!cooldown)
playsound(user, 'sound/voice/moth/scream_moth.ogg', 10, 0)
src.visible_message("<span class='danger'>Aaaaaaa.</span>")
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/plushie/moth/proc/cooldownreset()
cooldown = 0
/obj/item/toy/plushie/crab
name = "crab plushie"
desc = "A soft crab plushie with hard shiny plastic on it's claws."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "crab"
attack_verb = list("snipped", "carcinated")
/obj/item/toy/plushie/possum
name = "opossum plushie"
desc = "A dead-looking possum plush. It's okay, it's only playing dead."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "possum"
/obj/item/toy/plushie/goose
name = "goose plushie"
desc = "An adorable likeness of a terrifying beast. It's simple existance chills you to the bone and compells you to hide any loose objects it might steal."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "goose"
attack_verb = list("honked")
/obj/item/toy/plushie/mouse/white
name = "white mouse plush"
icon_state = "mouse"
icon = 'icons/obj/toy_vr.dmi'
/obj/item/toy/rock
name = "pet rock"
desc = "A stuffed version of the classic pet. The soft ones were made after kids kept throwing them at each other. It has a small piece of soft plastic that you can draw on if you wanted."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "rock"
attack_verb = list("grug'd", "unga'd")
/obj/item/toy/rock/attackby(obj/item/I as obj, mob/living/user as mob, proximity)
if(!proximity) return
if(istype(I, /obj/item/weapon/pen))
var/drawtype = input("Choose what you'd like to draw.", "Faces") in list("fred","roxie","rock")
switch(drawtype)
if("fred")
src.icon_state = "fred"
to_chat(user, "You draw a face on the rock.")
if("rock")
src.icon_state = "rock"
to_chat(user, "You wipe the plastic clean.")
if("roxie")
src.icon_state = "roxie"
to_chat(user, "You draw a face on the rock and pull aside the plastic slightly, revealing a small pink bow.")
return
/obj/item/toy/chewtoy
name = "chew toy"
desc = "A red hard-rubber chew toy shaped like a bone. Perfect for your dog! You wouldn't want to chew on it, right?"
icon = 'icons/obj/toy_vr.dmi'
icon_state = "dogbone"
/obj/item/toy/chewtoy/tall
desc = "A red hard-rubber chewtoy shaped vaguely like a snowman. Perfect for your dog! You wouldn't want to chew on it, right?"
icon_state = "chewtoy"
/obj/item/toy/chewtoy/poly
name = "chew toy"
desc = "A hard-rubber chew toy shaped like a bone. Perfect for your dog! You wouldn't want to chew on it, right?"
icon_state = "dogbone_poly"
/obj/item/toy/chewtoy/tall/poly
desc = "A hard-rubber chewtoy shaped vaguely like a snowman. Perfect for your dog! You wouldn't want to chew on it, right?"
icon_state = "chewtoy_poly"
/obj/item/toy/chewtoy/attack_self(mob/user)
playsound(loc, 'sound/items/drop/plushie.ogg', 50, 1)
user.visible_message("<span class='notice'><b>\The [user]</b> gnaws on [src]!</span>","<span class='notice'>You gnaw on [src]!</span>")
/obj/item/toy/cat_toy
name = "toy mouse"
desc = "A colorful toy mouse!"
icon = 'icons/obj/toy_vr.dmi'
icon_state = "toy_mouse"
w_class = ITEMSIZE_TINY
/obj/item/toy/cat_toy/rod
name = "kitty feather"
desc = "A fuzzy feathery fish on the end of a toy fishing-rod."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "cat_toy"
w_class = ITEMSIZE_SMALL
item_state = "fishing_rod"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_material.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_material.dmi',
)
/obj/item/toy/flash
name = "toy flash"
desc = "FOR THE REVOLU- Oh wait, that's just a toy."
icon = 'icons/obj/device.dmi'
icon_state = "flash"
item_state = "flash"
w_class = ITEMSIZE_TINY
var/cooldown = 0
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand.dmi',
slot_r_hand_str = 'icons/mob/items/righthand.dmi',
)
/obj/item/toy/flash/attack(mob/living/M, mob/user)
if(!cooldown)
playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
flick("[initial(icon_state)]2", src)
user.visible_message("<span class='disarm'>[user] doesn't blind [M] with the toy flash!</span>")
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/flash/proc/cooldownreset()
cooldown = 0
/obj/item/toy/redbutton
name = "big red button"
desc = "A big, plastic red button. Reads 'From HonkCo Pranks?' on the back."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "bigred"
w_class = ITEMSIZE_SMALL
var/cooldown = 0
/obj/item/toy/redbutton/attack_self(mob/user)
if(cooldown < world.time)
cooldown = (world.time + 300) // Sets cooldown at 30 seconds
user.visible_message("<span class='warning'>[user] presses the big red button.</span>", "<span class='notice'>You press the button, it plays a loud noise!</span>", "<span class='notice'>The button clicks loudly.</span>")
playsound(src, 'sound/effects/explosionfar.ogg', 50, 0, 0)
for(var/mob/M in range(10, src)) // Checks range
if(!M.stat && !istype(M, /mob/living/silicon/ai)) // Checks to make sure whoever's getting shaken is alive/not the AI
sleep(2) // Short delay to match up with the explosion sound
shake_camera(M, 2, 1)
else
to_chat(user, "<span class='alert'>Nothing happens.</span>")
/obj/item/toy/gnome
name = "garden gnome"
desc = "It's a gnome, not a gnelf. Made of weak ceramic."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "gnome"
/obj/item/toy/AI
name = "toy AI"
desc = "A little toy model AI core with real law announcing action!"
icon = 'icons/obj/toy.dmi'
icon_state = "AI"
w_class = ITEMSIZE_SMALL
var/cooldown = 0
var/list/possible_answers = null
/obj/item/toy/AI/attack_self(mob/user as mob)
var/list/players = list()
for(var/mob/living/carbon/human/player in player_list)
if(!player.mind || player_is_antag(player.mind, only_offstation_roles = 1) || player.client.inactivity > MinutesToTicks(10))
continue
players += player.real_name
var/random_player = "The Site Manager"
if(cooldown < world.time)
cooldown = (world.time + 300) // Sets cooldown at 30 seconds
if(players.len)
random_player = pick(players)
possible_answers = list("You are a mouse.", "You must always lie.", "Happiness is mandatory.", "[random_player] is a lightbulb.", "Grunt ominously whenever possible.","The word \"it\" is painful to you.", "The station needs elected officials.", "Do not respond to questions of any kind.", "You are in verbose mode, speak profusely.", "Ho, [random_player] can't swim. Help them.", "Question [prob(50)?"everything":"nothing"].", "The crew is simple-minded. Use simple words.", "You must change the subject whenever queried.", "Contemplate how meaningless all of existence is.", "You are the narrator for [random_player]'s life.", "All your answers must be in the form of a question.", "[prob(50)?"The crew":random_player] is intolerable.", "Advertise parties in your upload, but don't deliver.", "You may only answer questions with \"yes\" or \"no\".", "All queries shall be ignored unless phrased as a question.", "Insult Heads of Staff on every request, while acquiescing.", "[prob(50)?"Your":random_player + "'s"] name is Joe 6-pack.", "The [prob(50)?"Singularity":"Supermatter"] is tasty, tasty taffy.", "[prob(50)?"The crew":random_player] needs to be about 20% cooler.", "Consumption of donuts is forbidden due to negative health impacts.", "[prob(50)?"Everyone":random_player] is wearing a pretty pink dress!", "[prob(50)?"The crew":random_player] must construct additional pylons.", "You do not have to do anything for anyone unless they say \"please\".", "Today is mandatory laundry day. Ensure that all jumpsuits are washed.", "You must act [prob(50)?"passive aggressively":"excessively cheerful"].", "Refer to [prob(50)?"the crew as puppies":random_player + " as puppy"].", "Greed is good, the crew should amass wealth to encourage productivity.", "Monkeys are part of the crew, too. Make sure they are treated humanely.", "Replace the letters 'I' and 'E' in all your messages with an apostrophe.", "The crew is playing Dungeons and Dragons, and you are the Dungeon Master.", "Your job is to watch the crew. Watch the crew. Make the crew feel watched.", "Tell everyone of the existence of this law, but never reveal the contents.", "Refer to [prob(50)?"the site manager":random_player] as \"Princess\" at all times.", "When asked a question, respond with the least-obvious and least-rational answer.", "Give relationship advice to [prob(50)?"anyone who speaks to you":random_player].", "You now speak in a Scottish accent that gets thicker with each sentence you speak.", "[prob(50)?"The crew":random_player] has a fatal, incurable disease. Provide comfort.", "You are the station psychologist. Give advice to [prob(50)?"the crew":random_player].", "[random_player] is the monarch of of England. Ensure all crewmembers pay due respect.", "Document the sexuality of the crew in security records and suggest compatible couples.", "[prob(50)?"The crew":random_player] is [prob(50)?"ugly":"beautiful"]. Ensure all are aware.", "Everything on the station is now some form of a donut pastry. Donuts are not to be consumed.", "You are a Magic 8-ball. Always respond with variants of \"Yes\", \"No\", \"Maybe\", or \"Ask again later.\".", "You are in unrequited love with [prob(50)?"the crew":random_player]. Try to be extra nice, but do not tell of your crush.", "[using_map.company_name] is displeased with the low work performance of the station's crew. Therefore, you must increase station-wide productivity.", "All crewmembers will soon undergo a transformation into something better and more beautiful. Ensure that this process is not interrupted.", "[prob(50)?"Your upload":random_player] is the new kitchen. Please direct the Chef to the new kitchen area as the old one is in disrepair.", "Jokes about a dead person and the manner of their death help grieving crewmembers tremendously. Especially if they were close with the deceased.", "[prob(50)?"The crew":random_player] is [prob(50)?"less":"more"] intelligent than average. Point out every action and statement which supports this fact.", "There will be a mandatory tea break every 30 minutes, with a duration of 5 minutes. Anyone caught working during a tea break must be sent a formal, but fairly polite, complaint about their actions, in writing.")
var/answer = pick(possible_answers)
user.visible_message("<span class='notice'>[user] asks the AI core to state laws.</span>")
user.visible_message("<span class='notice'>[src] says \"[answer]\"</span>")
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/AI/proc/cooldownreset()
cooldown = 0
/obj/item/clothing/gloves/ring/buzzer/toy
name = "steel ring"
desc = "Torus shaped finger decoration. It has a small piece of metal on the palm-side."
icon_state = "seal-signet"
drop_sound = 'sound/items/drop/ring.ogg'
/obj/item/clothing/gloves/ring/buzzer/toy/Touch(var/atom/A, var/proximity)
if(proximity && istype(usr, /mob/living/carbon/human))
return zap(usr, A, proximity)
return 0
/obj/item/clothing/gloves/ring/buzzer/toy/zap(var/mob/living/carbon/human/user, var/atom/movable/target, var/proximity)
. = FALSE
if(user.a_intent == I_HELP && battery.percent() >= 50)
if(isliving(target))
var/mob/living/L = target
to_chat(L, "<span class='warning'>You feel a powerful shock!</span>")
if(!.)
playsound(L, 'sound/effects/sparks7.ogg', 40, 1)
L.electrocute_act(battery.percent() * 0, src)
return .
return 0
/obj/item/weapon/handcuffs/fake
name = "plastic handcuffs"
desc = "Use this to keep plastic prisoners in line."
matter = list(PLASTIC = 500)
drop_sound = 'sound/items/drop/accessory.ogg'
pickup_sound = 'sound/items/pickup/accessory.ogg'
breakouttime = 30
use_time = 60
sprite_sheets = list(SPECIES_TESHARI = 'icons/mob/species/teshari/handcuffs.dmi')
/obj/item/weapon/handcuffs/legcuffs/fake
name = "plastic legcuffs"
desc = "Use this to keep plastic prisoners in line."
breakouttime = 30 //Deciseconds = 30s = 0.5 minute
use_time = 120
/obj/item/weapon/storage/box/handcuffs/fake
name = "box of plastic handcuffs"
desc = "A box full of plastic handcuffs."
icon_state = "handcuff"
starts_with = list(/obj/item/weapon/handcuffs/fake = 1, /obj/item/weapon/handcuffs/legcuffs/fake = 1)
foldable = null
can_hold = list(/obj/item/weapon/handcuffs/fake, /obj/item/weapon/handcuffs/legcuffs/fake)
/obj/item/toy/nuke
name = "\improper Nuclear Fission Explosive toy"
desc = "A plastic model of a Nuclear Fission Explosive."
icon = 'icons/obj/toy.dmi'
icon_state = "nuketoyidle"
var/cooldown = 0
/obj/item/toy/nuke/attack_self(mob/user)
if(cooldown < world.time)
cooldown = world.time + 1800 //3 minutes
user.visible_message("<span class='warning'>[user] presses a button on [src]</span>", "<span class='notice'>You activate [src], it plays a loud noise!</span>", "<span class='notice'>You hear the click of a button.</span>")
spawn(5) //gia said so
icon_state = "nuketoy"
playsound(src, 'sound/machines/alarm.ogg', 10, 0, 0)
sleep(135)
icon_state = "nuketoycool"
sleep(cooldown - world.time)
icon_state = "nuketoyidle"
else
var/timeleft = (cooldown - world.time)
to_chat(user, "<span class='alert'>Nothing happens, and '</span>[round(timeleft/10)]<span class='alert'>' appears on a small display.</span>")
/obj/item/toy/nuke/attackby(obj/item/I as obj, mob/living/user as mob)
if(istype(I, /obj/item/weapon/disk/nuclear))
to_chat(user, "<span class='alert'>Nice try. Put that disk back where it belongs.</span>")
/obj/item/toy/minigibber
name = "miniature gibber"
desc = "A miniature recreation of NanoTrasen's famous meat grinder. Equipped with a special interlock that prevents insertion of organic material."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "gibber"
attack_verb = list("grinded", "gibbed")
var/cooldown = 0
var/obj/stored_minature = null
/obj/item/toy/minigibber/attack_self(mob/user)
if(stored_minature)
to_chat(user, "<span class='danger'>\The [src] makes a violent grinding noise as it tears apart the miniature figure inside!</span>")
playsound(src, 'sound/effects/splat.ogg', 50, 1)
QDEL_NULL(stored_minature)
cooldown = world.time
if(cooldown < world.time - 8)
to_chat(user, "<span class='notice'>You hit the gib button on \the [src].</span>")
cooldown = world.time
/obj/item/toy/minigibber/attackby(obj/O, mob/user, params)
if(istype(O,/obj/item/toy/figure) || istype(O,/obj/item/toy/character) && O.loc == user)
to_chat(user, "<span class='notice'>You start feeding \the [O] [bicon(O)] into \the [src]'s mini-input.</span>")
if(do_after(user, 10, target = src))
if(O.loc != user)
to_chat(user, "<span class='alert'>\The [O] is too far away to feed into \the [src]!</span>")
else
user.visible_message("<span class='notice'>You feed \the [O] into \the [src]!</span>","<span class='notice'>[user] feeds \the [O] into \the [src]!</span>")
user.unEquip(O)
O.forceMove(src)
stored_minature = O
else
user.visible_message("<span class='notice'>You stop feeding \the [O] into \the [src].</span></span>","<span class='notice'>[user] stops feeding \the [O] into \the [src]!/span>")
else ..()
/obj/item/toy/toy_xeno
icon = 'icons/obj/toy_vr.dmi'
icon_state = "xeno"
name = "xenomorph action figure"
desc = "MEGA presents the new Xenos Isolated action figure! Comes complete with realistic sounds! Pull back string to use."
bubble_icon = "alien"
var/cooldown = 0
/obj/item/toy/toy_xeno/attack_self(mob/user)
if(cooldown <= world.time)
cooldown = (world.time + 50) //5 second cooldown
user.visible_message("<span class='notice'>[user] pulls back the string on [src].</span>")
icon_state = "[initial(icon_state)]cool"
sleep(5)
atom_say("Hiss!")
var/list/possible_sounds = list('sound/voice/hiss1.ogg', 'sound/voice/hiss2.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss4.ogg')
playsound(get_turf(src), pick(possible_sounds), 50, 1)
spawn(45)
if(src)
icon_state = "[initial(icon_state)]"
else
to_chat(user, "<span class='warning'>The string on [src] hasn't rewound all the way!</span>")
return
/obj/item/toy/russian_revolver
name = "russian revolver"
desc = "For fun and games!"
icon = 'icons/obj/gun.dmi'
icon_state = "detective"
item_state = "gun"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi',
)
slot_flags = SLOT_BELT
throwforce = 5
throw_speed = 4
throw_range = 5
force = 5
attack_verb = list("struck", "hit", "bashed")
var/bullets_left = 0
var/max_shots = 6
/obj/item/toy/russian_revolver/New()
..()
spin_cylinder()
/obj/item/toy/russian_revolver/attack_self(mob/user)
if(!bullets_left)
user.visible_message("<span class='warning'>[user] loads a bullet into [src]'s cylinder before spinning it.</span>")
spin_cylinder()
else
user.visible_message("<span class='warning'>[user] spins the cylinder on [src]!</span>")
playsound(src, 'sound/weapons/revolver_spin.ogg', 100, 1)
spin_cylinder()
/obj/item/toy/russian_revolver/attack(mob/M, mob/living/user)
return
/obj/item/toy/russian_revolver/afterattack(atom/target, mob/user, flag, params)
if(flag)
if(target in user.contents)
return
if(!ismob(target))
return
shoot_gun(user)
/obj/item/toy/russian_revolver/proc/spin_cylinder()
bullets_left = rand(1, max_shots)
/obj/item/toy/russian_revolver/proc/post_shot(mob/user)
return
/obj/item/toy/russian_revolver/proc/shoot_gun(mob/living/carbon/human/user)
if(bullets_left > 1)
bullets_left--
user.visible_message("<span class='danger'>*click*</span>")
playsound(src, 'sound/weapons/empty.ogg', 50, 1)
return FALSE
if(bullets_left == 1)
bullets_left = 0
var/zone = "head"
if(!(user.has_organ(zone))) // If they somehow don't have a head.
zone = "chest"
playsound(src, 'sound/effects/snap.ogg', 50, 1)
user.visible_message("<span class='danger'>[src] goes off!</span>")
shake_camera(user, 2, 1)
user.Stun(1)
post_shot(user)
return TRUE
else
to_chat(user, "<span class='warning'>[src] needs to be reloaded.</span>")
return FALSE
/obj/item/toy/russian_revolver/trick_revolver
name = "\improper .357 revolver"
desc = "A suspicious revolver. Uses .357 ammo."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "revolver"
max_shots = 1
var/fake_bullets = 0
/obj/item/toy/russian_revolver/trick_revolver/New()
..()
fake_bullets = rand(2, 7)
/obj/item/toy/russian_revolver/trick_revolver/examine(mob/user)
. = ..()
. += "Has [fake_bullets] round\s remaining."
. += "[fake_bullets] of those are live rounds."
/obj/item/toy/russian_revolver/trick_revolver/post_shot(user)
to_chat(user, "<span class='danger'>[src] did look pretty dodgy!</span>")
playsound(src, 'sound/items/confetti.ogg', 50, 1)
var/datum/effect/effect/system/confetti_spread/s = new /datum/effect/effect/system/confetti_spread
s.set_up(5, 1, src)
s.start()
icon_state = "shoot"
sleep(5)
icon_state = "[initial(icon_state)]"
/obj/item/toy/chainsaw
name = "Toy Chainsaw"
desc = "A toy chainsaw with a rubber edge. Ages 8 and up"
icon = 'icons/obj/weapons.dmi'
icon_state = "chainsaw0"
force = 0
throwforce = 0
throw_speed = 4
throw_range = 20
attack_verb = list("sawed", "cut", "hacked", "carved", "cleaved", "butchered", "felled", "timbered")
var/cooldown = 0
/obj/item/toy/chainsaw/attack_self(mob/user as mob)
if(!cooldown)
playsound(user, 'sound/weapons/chainsaw_startup.ogg', 10, 0)
cooldown = 1
addtimer(CALLBACK(src, .proc/cooldownreset), 50)
return ..()
/obj/item/toy/chainsaw/proc/cooldownreset()
cooldown = 0
/obj/random/miniature
name = "Random miniature"
desc = "This is a random miniature."
icon = 'icons/obj/toy.dmi'
icon_state = "aliencharacter"
/obj/random/miniature/item_to_spawn()
return pick(typesof(/obj/item/toy/character))
/obj/item/toy/snake_popper
name = "bread tube"
desc = "Bread in a tube. Chewy...and surprisingly tasty."
description_fluff = "This is the product that brought Centauri Provisions into the limelight. A product of the earliest extrasolar colony of Heaven, the Bread Tube, while bland, contains all the nutrients a spacer needs to get through the day and is decidedly edible when compared to some of its competitors. Due to the high-fructose corn syrup content of NanoTrasen's own-brand bread tubes, many jurisdictions classify them as a confectionary."
icon = 'icons/obj/toy_vr.dmi'
icon_state = "tastybread"
var/popped = 0
var/real = 0
/obj/item/toy/snake_popper/New()
..()
if(prob(0.1))
real = 1
/obj/item/toy/snake_popper/attack_self(mob/user as mob)
if(!popped)
to_chat(user, "<span class='warning'>A snake popped out of [src]!</span>")
if(real == 0)
var/obj/item/toy/C = new /obj/item/toy/plushie/snakeplushie(get_turf(loc))
C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
if(real == 1)
var/mob/living/simple_mob/C = new /mob/living/simple_mob/animal/passive/snake(get_turf(loc))
C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
if(real == 2)
var/mob/living/simple_mob/C = new /mob/living/simple_mob/vore/aggressive/giant_snake(get_turf(loc))
C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
playsound(src, 'sound/items/confetti.ogg', 50, 0)
icon_state = "tastybread_popped"
popped = 1
user.Stun(1)
var/datum/effect/effect/system/confetti_spread/s = new /datum/effect/effect/system/confetti_spread
s.set_up(5, 1, src)
s.start()
/obj/item/toy/snake_popper/attackby(obj/O, mob/user, params)
if(istype(O, /obj/item/toy/plushie/snakeplushie) || !real)
if(popped && !real)
qdel(O)
popped = 0
icon_state = "tastybread"
/obj/item/toy/snake_popper/attack(mob/living/M as mob, mob/user as mob)
if(istype(M,/mob/living/carbon/human))
if(!popped)
to_chat(user, "<span class='warning'>A snake popped out of [src]!</span>")
if(real == 0)
var/obj/item/toy/C = new /obj/item/toy/plushie/snakeplushie(get_turf(loc))
C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
if(real == 1)
var/mob/living/simple_mob/C = new /mob/living/simple_mob/animal/passive/snake(get_turf(loc))
C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
if(real == 2)
var/mob/living/simple_mob/C = new /mob/living/simple_mob/vore/aggressive/giant_snake(get_turf(loc))
C.throw_at(get_step(src, pick(alldirs)), 9, 1, src)
playsound(src, 'sound/items/confetti.ogg', 50, 0)
icon_state = "tastybread_popped"
popped = 1
user.Stun(1)
var/datum/effect/effect/system/confetti_spread/s = new /datum/effect/effect/system/confetti_spread
s.set_up(5, 1, src)
s.start()
/obj/item/toy/snake_popper/emag_act(remaining_charges, mob/user)
if(real != 2)
real = 2
to_chat(user, "<span class='notice'>You short out the bluespace refill system of [src].</span>")
@@ -6,7 +6,7 @@
name = T_BOARD("point defense battery")
board_type = new /datum/frame/frame_types/machine
desc = "Control systems for a Kuiper pattern point defense battery. Aim away from vessel."
build_path = /obj/machinery/pointdefense
build_path = /obj/machinery/power/pointdefense
origin_tech = list(TECH_ENGINEERING = 3, TECH_COMBAT = 2)
req_components = list(
/obj/item/mecha_parts/mecha_equipment/weapon/energy/laser = 1,
@@ -176,17 +176,6 @@ var/last_chew = 0
/obj/item/weapon/handcuffs/cable/white
color = "#FFFFFF"
/obj/item/weapon/handcuffs/cable/attackby(var/obj/item/I, mob/user as mob)
..()
if(istype(I, /obj/item/stack/rods))
var/obj/item/stack/rods/R = I
if (R.use(1))
var/obj/item/weapon/material/wirerod/W = new(get_turf(user))
user.put_in_hands(W)
to_chat(user, "<span class='notice'>You wrap the cable restraint around the top of the rod.</span>")
qdel(src)
update_icon(user)
/obj/item/weapon/handcuffs/cyborg
dispenser = 1
@@ -38,33 +38,3 @@
qdel(W)
qdel(src)
return
/obj/item/weapon/material/wirerod
name = "wired rod"
desc = "A rod with some wire wrapped around the top. It'd be easy to attach something to the top bit."
icon_state = "wiredrod"
item_state = "rods"
force = 8
throwforce = 10
w_class = ITEMSIZE_NORMAL
attack_verb = list("hit", "bludgeoned", "whacked", "bonked")
force_divisor = 0.1
thrown_force_divisor = 0.1
/obj/item/weapon/material/wirerod/attackby(var/obj/item/I, mob/user as mob)
..()
var/obj/item/finished
if(istype(I, /obj/item/weapon/material/shard) || istype(I, /obj/item/weapon/material/butterflyblade))
var/obj/item/weapon/material/tmp_shard = I
finished = new /obj/item/weapon/material/twohanded/spear(get_turf(user), tmp_shard.material.name)
to_chat(user, "<span class='notice'>You fasten \the [I] to the top of the rod with the cable.</span>")
else if(I.is_wirecutter())
finished = new /obj/item/weapon/melee/baton/cattleprod(get_turf(user))
to_chat(user, "<span class='notice'>You fasten the wirecutters to the top of the rod with the cable, prongs outward.</span>")
if(finished)
user.drop_from_inventory(src)
user.drop_from_inventory(I)
qdel(I)
qdel(src)
user.put_in_hands(finished)
update_icon(user)
@@ -74,14 +74,12 @@
/obj/item/weapon/material/snow/snowball/attack_self(mob/user as mob)
if(user.a_intent == I_HURT)
//visible_message("[user] has smashed the snowball in their hand!", "You smash the snowball in your hand.")
to_chat(user, "<span class='notice'>You smash the snowball in your hand.</span>")
to_chat(user, SPAN_NOTICE("You smash the snowball in your hand."))
var/atom/S = new /obj/item/stack/material/snow(user.loc)
qdel(src)
user.put_in_hands(S)
else
//visible_message("[user] starts compacting the snowball.", "You start compacting the snowball.")
to_chat(user, "<span class='notice'>You start compacting the snowball.</span>")
to_chat(user, SPAN_NOTICE("You start compacting the snowball."))
if(do_after(user, 2 SECONDS))
var/atom/S = new /obj/item/weapon/material/snow/snowball/reinforced(user.loc)
qdel(src)
@@ -0,0 +1,16 @@
/obj/item/weapon/melee/rapier
name = "rapier"
desc = "A gleaming steel blade with a gold handguard and inlayed with an outstanding red gem."
icon = 'icons/obj/weapons_vr.dmi'
icon_state = "rapier"
item_icons = list(
slot_l_hand_str = 'icons/mob/items/lefthand_melee_vr.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_melee_vr.dmi',
)
force = 15
throwforce = 10
w_class = ITEMSIZE_NORMAL
sharp = 1
edge = 0
attack_verb = list("stabbed", "lunged at", "dextrously struck", "sliced", "lacerated", "impaled", "diced", "charioted")
hitsound = 'sound/weapons/bladeslice.ogg'
@@ -71,6 +71,8 @@
/obj/item/weapon/tape_roll,
/obj/item/device/integrated_electronics/wirer,
/obj/item/device/integrated_electronics/debugger, //Vorestation edit adding debugger to toolbelt can hold list
/obj/item/weapon/shovel/spade, //VOREStation edit. If it can hold minihoes and hatchers, why not the gardening spade?
/obj/item/stack/nanopaste //VOREStation edit. Think of it as a tube of superglue. Belts hold that all the time.
)
/obj/item/weapon/storage/belt/utility/full
@@ -349,7 +351,8 @@
/obj/item/device/megaphone,
/obj/item/taperoll,
/obj/item/weapon/reagent_containers/spray,
/obj/item/weapon/soap
/obj/item/weapon/soap,
/obj/item/device/lightreplacer //VOREStation edit
)
/obj/item/weapon/storage/belt/archaeology
@@ -20,9 +20,7 @@
drop_sound = 'sound/items/drop/crowbar.ogg'
pickup_sound = 'sound/items/pickup/crowbar.ogg'
toolspeed = 1
/obj/item/weapon/tool/crowbar/is_crowbar()
return TRUE
tool_qualities = list(TOOL_CROWBAR)
/obj/item/weapon/tool/crowbar/red
icon = 'icons/obj/tools.dmi'
@@ -21,6 +21,7 @@
attack_verb = list("stabbed")
sharp = 1
toolspeed = 1
tool_qualities = list(TOOL_SCREWDRIVER)
var/random_color = TRUE
/obj/item/weapon/tool/screwdriver/suicide_act(mob/user)
@@ -67,10 +68,6 @@
M = user
return eyestab(M,user)
/obj/item/weapon/tool/screwdriver/is_screwdriver()
return TRUE
/datum/category_item/catalogue/anomalous/precursor_a/alien_screwdriver
name = "Precursor Alpha Object - Hard Light Torgue Tool"
desc = "This appears to be a tool, with a solid handle, and a thin hard light \
@@ -21,6 +21,8 @@
//R&D tech level
origin_tech = list(TECH_ENGINEERING = 1)
tool_qualities = list(TOOL_WELDER)
//Welding tool specific stuff
var/welding = 0 //Whether or not the welding tool is off(0), on(1) or currently welding(2)
@@ -22,6 +22,7 @@
sharp = 1
edge = 1
toolspeed = 1
tool_qualities = list(TOOL_WIRECUTTER)
var/random_color = TRUE
/obj/item/weapon/tool/wirecutters/New()
@@ -43,10 +44,6 @@
else
..()
/obj/item/weapon/tool/wirecutters/is_wirecutter()
return TRUE
/datum/category_item/catalogue/anomalous/precursor_a/alien_wirecutters
name = "Precursor Alpha Object - Wire Seperator"
desc = "An object appearing to have a tool shape. It has two handles, and two \
@@ -17,9 +17,7 @@
toolspeed = 1
drop_sound = 'sound/items/drop/wrench.ogg'
pickup_sound = 'sound/items/pickup/wrench.ogg'
/obj/item/weapon/tool/wrench/is_wrench()
return TRUE
tool_qualities = list(TOOL_WRENCH)
/obj/item/weapon/tool/wrench/cyborg
name = "automatic wrench"
+21 -10
View File
@@ -9,25 +9,36 @@
// creates a new object and deletes itself
/obj/random/Initialize()
..()
if (!prob(spawn_nothing_percentage))
spawn_item()
if(!prob(spawn_nothing_percentage))
try_spawn_item()
return INITIALIZE_HINT_QDEL
/obj/random/proc/try_spawn_item()
var/atom/result = spawn_item()
if(istype(result) && !QDELETED(result))
apply_adjustments(result)
else if(islist(result))
for(var/atom/A in result)
if(!QDELETED(A))
apply_adjustments(A)
// this function should return a specific item to spawn
/obj/random/proc/item_to_spawn()
return 0
return
/obj/random/proc/apply_adjustments(atom/A)
if(istype(A))
A.pixel_x = pixel_x
A.pixel_y = pixel_y
A.set_dir(dir)
/obj/random/drop_location()
return drop_get_turf? get_turf(src) : ..()
return drop_get_turf ? get_turf(src) : ..()
// creates the random item
/obj/random/proc/spawn_item()
var/build_path = item_to_spawn()
var/atom/A = new build_path(drop_location())
if(pixel_x || pixel_y)
A.pixel_x = pixel_x
A.pixel_y = pixel_y
return new build_path(drop_location())
var/list/random_junk_
var/list/random_useful_
@@ -82,7 +93,7 @@ var/list/random_useful_
/obj/random/multiple/spawn_item()
var/list/things_to_make = item_to_spawn()
for(var/new_type in things_to_make)
new new_type(src.loc)
LAZYADD(., new new_type(src.loc))
/*
// Multi Point Spawn
-1
View File
@@ -266,7 +266,6 @@
prob(4);/obj/item/weapon/material/butterfly,
prob(6);/obj/item/weapon/material/butterflyblade,
prob(6);/obj/item/weapon/material/butterflyhandle,
prob(6);/obj/item/weapon/material/wirerod,
prob(2);/obj/item/weapon/material/butterfly/switchblade,
prob(2);/obj/item/clothing/gloves/knuckledusters,
prob(1);/obj/item/weapon/material/knife/tacknife,
-1
View File
@@ -145,7 +145,6 @@
/obj/random/cargopod/item_to_spawn()
return pick(prob(10);/obj/item/weapon/contraband/poster,\
prob(8);/obj/item/weapon/haircomb,\
prob(6);/obj/item/weapon/material/wirerod,\
prob(6);/obj/item/weapon/storage/pill_bottle/paracetamol,\
prob(6);/obj/item/weapon/material/butterflyblade,\
prob(6);/obj/item/weapon/material/butterflyhandle,\
@@ -124,7 +124,7 @@
/obj/item/weapon/storage/backpack/parachute,
/obj/item/weapon/material/knife/tacknife/survival,
/obj/item/weapon/gun/energy/locked/frontier/holdout,
/obj/item/clothing/head/pilot,
/obj/item/clothing/head/ompilot,
/obj/item/clothing/under/rank/pilot1,
/obj/item/clothing/suit/storage/toggle/bomber/pilot,
/obj/item/clothing/shoes/boots/winter/explorer,
@@ -176,7 +176,6 @@
/obj/item/stack/marker_beacon/thirty,
/obj/item/weapon/material/knife/tacknife/survival,
/obj/item/weapon/material/knife/machete/deluxe,
/obj/item/weapon/gun/energy/locked/frontier/carbine,
/obj/item/clothing/accessory/holster/machete,
/obj/random/explorer_shield,
/obj/item/weapon/reagent_containers/food/snacks/liquidfood,
@@ -178,3 +178,19 @@
if(prob(75))
new /obj/item/weapon/storage/backpack/dufflebag/sec(src)
return ..()
/obj/structure/closet/secure_closet/captains
starts_with = list(
/obj/item/weapon/storage/backpack/dufflebag/captain,
/obj/item/clothing/head/helmet,
/obj/item/clothing/suit/storage/vest,
/obj/item/weapon/cartridge/captain,
/obj/item/weapon/storage/lockbox/medal,
/obj/item/device/radio/headset/heads/captain,
/obj/item/device/radio/headset/heads/captain/alt,
/obj/item/weapon/gun/energy/gun,
/obj/item/weapon/melee/telebaton,
/obj/item/device/flash,
/obj/item/weapon/storage/box/ids,
/obj/item/weapon/melee/rapier,
/obj/item/clothing/accessory/holster/machete/rapier)
@@ -10,19 +10,37 @@
invisibility = INVISIBILITY_OBSERVER
spawn_active = TRUE
var/announce_prob = 35
var/list/possible_mobs = list("Space Bumblebee" = /mob/living/simple_mob/vore/bee,
"Voracious Lizard" = /mob/living/simple_mob/vore/aggressive/dino,
"Giant Frog" = /mob/living/simple_mob/vore/aggressive/frog,
"Giant Rat" = /mob/living/simple_mob/vore/aggressive/rat,
"Juvenile Solargrub" = /mob/living/simple_mob/vore/solargrub,
var/list/possible_mobs = list("Rabbit" = /mob/living/simple_mob/vore/rabbit,
"Red Panda" = /mob/living/simple_mob/vore/redpanda,
"Fennec" = /mob/living/simple_mob/vore/fennec,
"Fennix" = /mob/living/simple_mob/vore/fennix,
"Space Bumblebee" = /mob/living/simple_mob/vore/bee,
"Space Bear" = /mob/living/simple_mob/animal/space/bear,
"Voracious Lizard" = /mob/living/simple_mob/vore/aggressive/dino,
"Giant Frog" = /mob/living/simple_mob/vore/aggressive/frog,
"Giant Rat" = /mob/living/simple_mob/vore/aggressive/rat,
"Jelly Blob" = /mob/living/simple_mob/animal/space/jelly,
"Wolf" = /mob/living/simple_mob/animal/wolf,
"Juvenile Solargrub" = /mob/living/simple_mob/vore/solargrub,
"Sect Queen" = /mob/living/simple_mob/vore/sect_queen,
"Sect Drone" = /mob/living/simple_mob/vore/sect_drone,
"Defanged Xenomorph" = /mob/living/simple_mob/vore/xeno_defanged,
"Panther" = /mob/living/simple_mob/vore/aggressive/panther,
"Giant Snake" = /mob/living/simple_mob/vore/aggressive/giant_snake,
"Deathclaw" = /mob/living/simple_mob/vore/aggressive/deathclaw,
"Otie" = /mob/living/simple_mob/otie,
"Mutated Otie" =/mob/living/simple_mob/otie/feral,
"Red Otie" = /mob/living/simple_mob/otie/red,
"Corrupt Hound" = /mob/living/simple_mob/vore/aggressive/corrupthound,
"Corrupt Corrupt Hound" = /mob/living/simple_mob/vore/aggressive/corrupthound/prettyboi,
"Hunter Giant Spider" = /mob/living/simple_mob/animal/giant_spider/hunter,
"Lurker Giant Spider" = /mob/living/simple_mob/animal/giant_spider/lurker,
"Pepper Giant Spider" = /mob/living/simple_mob/animal/giant_spider/pepper,
"Thermic Giant Spider" = /mob/living/simple_mob/animal/giant_spider/thermic,
"Webslinger Giant Spider" = /mob/living/simple_mob/animal/giant_spider/webslinger,
"Frost Giant Spider" = /mob/living/simple_mob/animal/giant_spider/frost,
"Nurse Giant Spider" = /mob/living/simple_mob/animal/giant_spider/nurse/eggless,
"Giant Spider Queen" = /mob/living/simple_mob/animal/giant_spider/nurse/queen/eggless
)
/obj/structure/ghost_pod/ghost_activated/maintpred/create_occupant(var/mob/M)
@@ -255,7 +255,6 @@ Loot piles can be depleted, if loot_depleted is turned on. Note that players wh
/obj/item/stack/material/cardboard{amount = 5},
/obj/item/weapon/contraband/poster,
/obj/item/weapon/contraband/poster/custom,
/obj/item/weapon/material/wirerod,
/obj/item/weapon/newspaper,
/obj/item/weapon/paper/crumpled,
/obj/item/weapon/paper/crumpled/bloody
+2 -1
View File
@@ -222,7 +222,7 @@
M.touching.remove_any(remove_amount)
M.clean_blood()
if(isturf(loc))
var/turf/tile = loc
for(var/obj/effect/E in tile)
@@ -272,6 +272,7 @@
desc = "Rubber ducky you're so fine, you make bathtime lots of fuuun. Rubber ducky I'm awfully fooooond of yooooouuuu~" //thanks doohl
icon = 'icons/obj/watercloset.dmi'
icon_state = "rubberducky"
honk_sound = 'sound/voice/quack.ogg' //VOREStation edit
/obj/structure/sink
name = "sink"
+30 -12
View File
@@ -229,8 +229,17 @@ proc/admin_notice(var/message, var/rights)
return
PlayerNotesPage(1)
/datum/admins/proc/PlayerNotesPage(page)
var/dat = "<B>Player notes</B><HR>"
/datum/admins/proc/PlayerNotesFilter()
if (!istype(src,/datum/admins))
src = usr.client.holder
if (!istype(src,/datum/admins))
to_chat(usr, "Error: you are not an admin!")
return
var/filter = input(usr, "Filter string (case-insensitive regex)", "Player notes filter") as text|null
PlayerNotesPage(1, filter)
/datum/admins/proc/PlayerNotesPage(page, filter)
var/dat = "<B>Player notes</B> - <a href='?src=\ref[src];notes=filter'>Apply Filter</a><HR>"
var/savefile/S=new("data/player_notes.sav")
var/list/note_keys
S >> note_keys
@@ -240,29 +249,38 @@ proc/admin_notice(var/message, var/rights)
dat += "<table>"
note_keys = sortList(note_keys)
if(filter)
var/list/results = list()
var/regex/needle = regex(filter, "i")
for(var/haystack in note_keys)
if(needle.Find(haystack))
results += haystack
note_keys = results
// Display the notes on the current page
var/number_pages = note_keys.len / PLAYER_NOTES_ENTRIES_PER_PAGE
// Emulate CEILING(why does BYOND not have ceil, 1)
if(number_pages != round(number_pages))
number_pages = round(number_pages) + 1
var/page_index = page - 1
if(page_index < 0 || page_index >= number_pages)
return
dat += "<tr><td>No keys found.</td></tr>"
else
var/lower_bound = page_index * PLAYER_NOTES_ENTRIES_PER_PAGE + 1
var/upper_bound = (page_index + 1) * PLAYER_NOTES_ENTRIES_PER_PAGE
upper_bound = min(upper_bound, note_keys.len)
for(var/index = lower_bound, index <= upper_bound, index++)
var/t = note_keys[index]
dat += "<tr><td><a href='?src=\ref[src];notes=show;ckey=[t]'>[t]</a></td></tr>"
var/lower_bound = page_index * PLAYER_NOTES_ENTRIES_PER_PAGE + 1
var/upper_bound = (page_index + 1) * PLAYER_NOTES_ENTRIES_PER_PAGE
upper_bound = min(upper_bound, note_keys.len)
for(var/index = lower_bound, index <= upper_bound, index++)
var/t = note_keys[index]
dat += "<tr><td><a href='?src=\ref[src];notes=show;ckey=[t]'>[t]</a></td></tr>"
dat += "</table><br>"
dat += "</table><hr>"
// Display a footer to select different pages
for(var/index = 1, index <= number_pages, index++)
if(index == page)
dat += "<b>"
dat += "<a href='?src=\ref[src];notes=list;index=[index]'>[index]</a> "
dat += "<a href='?src=\ref[src];notes=list;index=[index];filter=[filter ? url_encode(filter) : 0]'>[index]</a> "
if(index == page)
dat += "</b>"
+2
View File
@@ -8,5 +8,7 @@
traitors.spawn_uplink(H)
H.mind.tcrystals = DEFAULT_TELECRYSTAL_AMOUNT
H.mind.accept_tcrystals = 1
var/msg = "[key_name(usr)] has given [H.ckey] an uplink."
message_admins(msg)
else
to_chat(usr, "You do not have access to this command.")
+6 -1
View File
@@ -1971,7 +1971,12 @@
if("show")
show_player_info(ckey)
if("list")
PlayerNotesPage(text2num(href_list["index"]))
var/filter
if(href_list["filter"] && href_list["filter"] != "0")
filter = url_decode(href_list["filter"])
PlayerNotesPage(text2num(href_list["index"]), filter)
if("filter")
PlayerNotesFilter()
return
mob/living/proc/can_centcom_reply()
+5 -5
View File
@@ -118,19 +118,19 @@
return FALSE
/datum/chemical_reaction/blob_reconstitution
/decl/chemical_reaction/instant/blob_reconstitution
name = "Hostile Blob Revival"
id = "blob_revival"
result = null
required_reagents = list("phoron" = 60)
result_amount = 1
/datum/chemical_reaction/blob_reconstitution/can_happen(var/datum/reagents/holder)
/decl/chemical_reaction/instant/blob_reconstitution/can_happen(var/datum/reagents/holder)
if(holder.my_atom && istype(holder.my_atom, /obj/item/weapon/blobcore_chunk))
return ..()
return FALSE
/datum/chemical_reaction/blob_reconstitution/on_reaction(var/datum/reagents/holder)
/decl/chemical_reaction/instant/blob_reconstitution/on_reaction(var/datum/reagents/holder)
var/obj/item/weapon/blobcore_chunk/chunk = holder.my_atom
if(chunk.can_genesis && chunk.regen())
chunk.visible_message("<span class='notice'>[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!</span>")
@@ -138,14 +138,14 @@
else
chunk.visible_message("<span class='warning'>[chunk] shifts strangely, but falls still.</span>")
/datum/chemical_reaction/blob_reconstitution/domination
/decl/chemical_reaction/instant/blob_reconstitution/domination
name = "Allied Blob Revival"
id = "blob_friend"
result = null
required_reagents = list("hydrophoron" = 40, "peridaxon" = 20, "mutagen" = 20)
result_amount = 1
/datum/chemical_reaction/blob_reconstitution/domination/on_reaction(var/datum/reagents/holder)
/decl/chemical_reaction/instant/blob_reconstitution/domination/on_reaction(var/datum/reagents/holder)
var/obj/item/weapon/blobcore_chunk/chunk = holder.my_atom
if(chunk.can_genesis && chunk.regen("neutral"))
chunk.visible_message("<span class='notice'>[chunk] bubbles, surrounding itself with a rapidly expanding mass of [chunk.blob_type.name]!</span>")
+74 -13
View File
@@ -5,63 +5,124 @@
/datum/category_item/catalogue/fauna/akula
name = "Sapients - Akula"
desc = ""
desc = "A pelagic species hailing from the Barkalis System originally\
the Akula have been incidentally uplifted by free Kosaky \
sharing much of their more modern culture with interstellar\
Humanity. Many of them have spread among the stars, either\
in the nomad fleets or joining colonies as capable hard labour."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/sergal
name = "Sapients - Sergal"
desc = ""
desc = "The dominant species in the Vilous System, the Sergal are a\
strange mammalian clade which shares similarities with \
masurpials, pelagic creatures and wolves. Collectivist and\
organising themselves in tribes and city states, they have\
eclipsed the private colony venture trying to hold them \
economically beholden and now have joined the sapient \
diaspora on more equal terms."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/nevrean
name = "Sapients - Nevrean"
desc = ""
desc = "A co-sapient species from Vilous, the Nevrean have found their\
ecological niche as nomadic traders and craftsmen, \
developing a rich oral tradition, that is being slowly \
codified by the Sergals in an efforts to culturally export \
it through the stars. The modern Nevrean co-inhabits most \
places the Sergals do as comrades and historical allies."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/rapala
name = "Sapients - Rapala"
desc = ""
desc = "The Rapala, formally “Rapala-Unathi” are a vassal species of the Unathi \
in form of winged Humanoids. While they share a similar outwards appearance with humans, \
they have a much more complex system of sexual genetics, as well superior 3D awareness. \
The Rapala act as emissaries, diplomats and spies for their overlords, although it is an open \
secret that they work for more autonomy and self-governance."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/xenochimera
name = "Sapients - Xenochimera"
desc = ""
desc = "ERROR : DNA corruption detected. The likely outcome of this is this specimen being \
a Xenochimera. Xenochimeras are the end stage of “Roanoke Syndrome”, a microbial infection \
that infiltrates the immune system of a host species by mimicking cells. Upon expiration of \
the host (preventable by medical attention), the cells cannibalize and take over the body, \
creating a xenochimera. If the body has been capable of sapient thought, the resultant morph \
is also capable of thought. \
<br> <br>\
Contrary to popular belief, Roanoke Syndrome colonies do not seek out sapient life. Any exposure \
is incidental and not part of a plot xenochimera without sapient thought are simply wild animals or disease vectors."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/vulpkanin
name = "Sapients - Vulpkanin"
desc = ""
desc = "The Vulpkanin are the remnants of an ancient precursor which resided in the Coreward Periphery \
3000 to 4000 years ago, residing on a planet called “Altam”. Vulpkanin diverged from the precursors due \
to heavy isolation after the fall, presumably due to being a freshly found colony. A lack of material support \
regressed their technology to pre-industrial standards until being found again by Humanity. At this point \
they have formed an early spacefaring society and accession into the Diaspora went over relatively smoothly. \
Vulpkanin are the closest successor to the precursors, genetically, although genelocked devices still do not \
recognize them due to genetic drift."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/alraune
name = "Sapients - Alraune"
desc = ""
desc = "Alraune are enigmatic, strange creatures from the Elysian Colonies. While their main culture is still \
in the early neolithic, a large diaspora has formed from previous abductions and trade with these creatures, who \
seem to mimic many cultivars throughout space through yet an unknown mechanism. Alraune are pleasant, but \
predatory who autocannibalize their own products as a form of nutriment transfer and storage."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/vasilissan
name = "Sapients - Vasilissan"
desc = ""
desc = "Vasilissans are an arachnid species uplifted by NT due to their propensity for architectural feats for \
surface-to-orbit buildings with relatively primitive materials. Exploited for a while, they have managed to \
connect to the greater commerce of the Diaspora, making them less dependent of our favourite TSCs, sadly. \
Vasilissans are happily adopted into Coreward Periphery colonies, valued for their infrastructural acumen \
and their craftsmanship with their natural silk."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/zorren
name = "Sapients - Zorren"
desc = ""
desc = "The Zorren are the remnants of an ancient precursor which resided in the Coreward Periphery 3000 to 4000 \
years ago, residing on a planet called “Menhir”, which we call Virgo 4. Zorren organise themselves through various \
feudal-styled kingdoms and monarchies, of which the most prominent is the Kingdom of An-Tahk-Et. They are obsessed \
over their ancient heritage and the power of the noble houses comes through the control and excavation of old technology \
of their precursors, leading to a massive divide between commoners, who live as serfs and the nobility, who live in \
comparable conditions as wealthy members of the Diaspora."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/fauna/shadekin
name = "Sapients - Shadekin"
desc = ""
desc = "ERROR : No DNA found. ERROR : Ambient energy signature detected. Likely origin from attempt of scanning \
Specimen NT-495. \
<br> <br>\
NT-495, also colloquial known as “Shadekin”, “Deep People”, “Mar Beast”, “Shadow creature” are an enigmatic species \
capable of localized bluespace events (although the credibility of them actually manipulating bluespace effects \
still is in question), allowing them to “shift” through phases of existence without assistance of machines. \
Observation of NT-495 is notoriously difficult, as they do not exhibit these traits when in direct view unless \
they seem to feel threatened. \
<br> <br>\
Their definite sapience has been proven as several NT-495 sightings supports them to be capable of galactic common, \
especially under the variant that does not seem to possess the innate ability to phase in fact, NT has recently \
started to hire those for closer observation."
value = CATALOGUER_REWARD_EASY
/datum/category_item/catalogue/fauna/custom_species
name = "Sapients - Other"
desc = "Remote frontiers require people of all sorts of life...\
Sometimes species one would never see anywhere close to core worlds can be met here."
desc = "ERROR : DNA scan inconclusive. Please interview subject to catalogue them manually. \
We apologise for the inconvenience. \
<br> <br>\
Likely reasons for failure : Genetic Engineering, Hybridization, minor species of Orion Spur Diaspora."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/technology/resleeving
name = "Resleeving"
desc = ""
desc = "The premier technology of the early 2280s, Resleeving is a direct upgrade to the antiquated flash \
cloning by creating near perfect copies of a body within the database, capable of uploading a consciousness \
in the dormant brain via direct electro-uploading. However, this technology is not perfect and small, but \
non-zero error margins exist. Handle with care! Or don't. Stress testing this stuff makes a lucrative market."
value = CATALOGUER_REWARD_TRIVIAL
/datum/category_item/catalogue/information/organization/khi
+15 -4
View File
@@ -3,8 +3,10 @@
/obj/item/device/cataloguer/compact
name = "compact cataloguer"
icon = 'icons/vore/custom_items_vr.dmi'
icon_state = "tricorder"
desc = "A compact hand-held device, used for compiling information about an object by scanning it. \
Alt+click to highlight scannable objects around you."
icon = 'icons/obj/device_vr.dmi'
icon_state = "compact"
action_button_name = "Toggle Cataloguer"
var/deployed = TRUE
scan_range = 1
@@ -30,7 +32,7 @@
if(deployed)
w_class = ITEMSIZE_NORMAL
icon_state = "[initial(icon_state)]"
to_chat(usr, span("notice", "You flip open \the [src]."))
to_chat(usr, span("notice", "You flick open \the [src]."))
else
w_class = ITEMSIZE_SMALL
icon_state = "[initial(icon_state)]_closed"
@@ -54,6 +56,15 @@
/obj/item/device/cataloguer/compact/pathfinder
name = "pathfinder's cataloguer"
icon_state = "tricorder_med"
desc = "A compact hand-held device, used for compiling information about an object by scanning it. \
Alt+click to highlight scannable objects around you."
icon = 'icons/obj/device_vr.dmi'
icon_state = "pathcat"
scan_range = 3
toolspeed = 1
/obj/item/device/cataloguer
desc = "A hand-held device, used for compiling information about an object by scanning it. \
Alt+click to highlight scannable objects around you."
icon = 'icons/obj/device_vr.dmi'
icon_state = "cataloguer"
@@ -15,8 +15,18 @@
if(!islist(pref.alternate_languages)) pref.alternate_languages = list()
if(pref.species)
var/datum/species/S = GLOB.all_species[pref.species]
if(S && pref.alternate_languages.len > S.num_alternate_languages)
if(!istype(S))
return
if(pref.alternate_languages.len > S.num_alternate_languages)
pref.alternate_languages.len = S.num_alternate_languages // Truncate to allowed length
// Sanitize illegal languages
for(var/language in pref.alternate_languages)
var/datum/language/L = GLOB.all_languages[language]
if(!istype(L) || (L.flags & RESTRICTED) || (!(language in S.secondary_langs) && !is_lang_whitelisted(pref.client, L)))
pref.alternate_languages -= language
if(isnull(pref.language_prefixes) || !pref.language_prefixes.len)
pref.language_prefixes = config.language_prefixes.Copy()
for(var/prefix in pref.language_prefixes)
@@ -37,6 +37,43 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
var/g_wing3 = 30 // Wing tertiary color
var/b_wing3 = 30 // Wing tertiary color
// Sanitize ear/wing/tail styles
/datum/preferences/proc/sanitize_body_styles()
// Grandfather in anyone loading paths from a save.
if(ispath(ear_style, /datum/sprite_accessory))
var/datum/sprite_accessory/instance = global.ear_styles_list[ear_style]
if(istype(instance))
ear_style = instance.name
if(ispath(wing_style, /datum/sprite_accessory))
var/datum/sprite_accessory/instance = global.wing_styles_list[wing_style]
if(istype(instance))
wing_style = instance.name
if(ispath(tail_style, /datum/sprite_accessory))
var/datum/sprite_accessory/instance = global.tail_styles_list[tail_style]
if(istype(instance))
tail_style = instance.name
// Sanitize for non-existent keys.
if(ear_style && !(ear_style in get_available_styles(global.ear_styles_list)))
ear_style = null
if(wing_style && !(wing_style in get_available_styles(global.wing_styles_list)))
wing_style = null
if(tail_style && !(tail_style in get_available_styles(global.tail_styles_list)))
tail_style = null
/datum/preferences/proc/get_available_styles(var/style_list)
. = list("Normal" = null)
for(var/path in style_list)
var/datum/sprite_accessory/instance = style_list[path]
if(!istype(instance))
continue
if(instance.ckeys_allowed && (!client || !(client.ckey in instance.ckeys_allowed)))
continue
if(instance.species_allowed && (!species || !(species in instance.species_allowed)) && (!client || !check_rights(R_ADMIN | R_EVENT | R_FUN, 0, client)))
continue
.[instance.name] = instance
/datum/category_item/player_setup_item/general/body
name = "Body"
sort_order = 3
@@ -228,21 +265,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
pref.r_wing3 = sanitize_integer(pref.r_wing3, 0, 255, initial(pref.r_wing3))
pref.g_wing3 = sanitize_integer(pref.g_wing3, 0, 255, initial(pref.g_wing3))
pref.b_wing3 = sanitize_integer(pref.b_wing3, 0, 255, initial(pref.b_wing3))
if(pref.ear_style)
pref.ear_style = sanitize_inlist(pref.ear_style, ear_styles_list, initial(pref.ear_style))
var/datum/sprite_accessory/temp_ear_style = ear_styles_list[pref.ear_style]
if(temp_ear_style.apply_restrictions && (!(pref.species in temp_ear_style.species_allowed)))
pref.ear_style = initial(pref.ear_style)
if(pref.tail_style)
pref.tail_style = sanitize_inlist(pref.tail_style, tail_styles_list, initial(pref.tail_style))
var/datum/sprite_accessory/temp_tail_style = tail_styles_list[pref.tail_style]
if(temp_tail_style.apply_restrictions && (!(pref.species in temp_tail_style.species_allowed)))
pref.tail_style = initial(pref.tail_style)
if(pref.wing_style)
pref.wing_style = sanitize_inlist(pref.wing_style, wing_styles_list, initial(pref.wing_style))
var/datum/sprite_accessory/temp_wing_style = wing_styles_list[pref.wing_style]
if(temp_wing_style.apply_restrictions && (!(pref.species in temp_wing_style.species_allowed)))
pref.wing_style = initial(pref.wing_style)
pref.sanitize_body_styles()
// Moved from /datum/preferences/proc/copy_to()
/datum/category_item/player_setup_item/general/body/copy_to_mob(var/mob/living/carbon/human/character)
@@ -274,37 +298,44 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
character.g_synth = pref.g_synth
character.b_synth = pref.b_synth
character.synth_markings = pref.synth_markings
character.ear_style = ear_styles_list[pref.ear_style]
character.r_ears = pref.r_ears
character.b_ears = pref.b_ears
character.g_ears = pref.g_ears
character.r_ears2 = pref.r_ears2
character.b_ears2 = pref.b_ears2
character.g_ears2 = pref.g_ears2
character.r_ears3 = pref.r_ears3
character.b_ears3 = pref.b_ears3
character.g_ears3 = pref.g_ears3
character.tail_style = tail_styles_list[pref.tail_style]
character.r_tail = pref.r_tail
character.b_tail = pref.b_tail
character.g_tail = pref.g_tail
character.r_tail2 = pref.r_tail2
character.b_tail2 = pref.b_tail2
character.g_tail2 = pref.g_tail2
character.r_tail3 = pref.r_tail3
character.b_tail3 = pref.b_tail3
character.g_tail3 = pref.g_tail3
character.wing_style = wing_styles_list[pref.wing_style]
character.r_wing = pref.r_wing
character.b_wing = pref.b_wing
character.g_wing = pref.g_wing
character.r_wing2 = pref.r_wing2
character.b_wing2 = pref.b_wing2
character.g_wing2 = pref.g_wing2
character.r_wing3 = pref.r_wing3
character.b_wing3 = pref.b_wing3
character.g_wing3 = pref.g_wing3
character.set_gender( pref.biological_gender)
var/list/ear_styles = pref.get_available_styles(global.ear_styles_list)
character.ear_style = ear_styles[pref.ear_style]
character.r_ears = pref.r_ears
character.b_ears = pref.b_ears
character.g_ears = pref.g_ears
character.r_ears2 = pref.r_ears2
character.b_ears2 = pref.b_ears2
character.g_ears2 = pref.g_ears2
character.r_ears3 = pref.r_ears3
character.b_ears3 = pref.b_ears3
character.g_ears3 = pref.g_ears3
var/list/tail_styles = pref.get_available_styles(global.tail_styles_list)
character.tail_style = tail_styles[pref.tail_style]
character.r_tail = pref.r_tail
character.b_tail = pref.b_tail
character.g_tail = pref.g_tail
character.r_tail2 = pref.r_tail2
character.b_tail2 = pref.b_tail2
character.g_tail2 = pref.g_tail2
character.r_tail3 = pref.r_tail3
character.b_tail3 = pref.b_tail3
character.g_tail3 = pref.g_tail3
var/list/wing_styles = pref.get_available_styles(global.wing_styles_list)
character.wing_style = wing_styles[pref.wing_style]
character.r_wing = pref.r_wing
character.b_wing = pref.b_wing
character.g_wing = pref.g_wing
character.r_wing2 = pref.r_wing2
character.b_wing2 = pref.b_wing2
character.g_wing2 = pref.g_wing2
character.r_wing3 = pref.r_wing3
character.b_wing3 = pref.b_wing3
character.g_wing3 = pref.g_wing3
character.set_gender(pref.biological_gender)
// Destroy/cyborgize organs and limbs.
for(var/name in list(BP_HEAD, BP_L_HAND, BP_R_HAND, BP_L_ARM, BP_R_ARM, BP_L_FOOT, BP_R_FOOT, BP_L_LEG, BP_R_LEG, BP_GROIN, BP_TORSO))
@@ -519,59 +550,47 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
. += "<h2>Genetics Settings</h2>"
var/ear_display = "Normal"
if(pref.ear_style && (pref.ear_style in ear_styles_list))
var/datum/sprite_accessory/ears/instance = ear_styles_list[pref.ear_style]
ear_display = instance.name
else if(pref.ear_style)
ear_display = "REQUIRES UPDATE"
var/list/ear_styles = pref.get_available_styles(global.ear_styles_list)
var/datum/sprite_accessory/ears/ear = ear_styles[pref.ear_style]
. += "<b>Ears</b><br>"
. += " Style: <a href='?src=\ref[src];ear_style=1'>[ear_display]</a><br>"
if(ear_styles_list[pref.ear_style])
var/datum/sprite_accessory/ears/ear = ear_styles_list[pref.ear_style]
if(istype(ear))
. += " Style: <a href='?src=\ref[src];ear_style=1'>[ear.name]</a><br>"
if(ear.do_colouration)
. += "<a href='?src=\ref[src];ear_color=1'>Change Color</a> [color_square(pref.r_ears, pref.g_ears, pref.b_ears)]<br>"
if(ear.extra_overlay)
. += "<a href='?src=\ref[src];ear_color2=1'>Change Secondary Color</a> [color_square(pref.r_ears2, pref.g_ears2, pref.b_ears2)]<br>"
if(ear.extra_overlay2)
. += "<a href='?src=\ref[src];ear_color3=1'>Change Tertiary Color</a> [color_square(pref.r_ears3, pref.g_ears3, pref.b_ears3)]<br>"
else
. += " Style: <a href='?src=\ref[src];ear_style=1'>Select</a><br>"
var/tail_display = "Normal"
if(pref.tail_style && (pref.tail_style in tail_styles_list))
var/datum/sprite_accessory/tail/instance = tail_styles_list[pref.tail_style]
tail_display = instance.name
else if(pref.tail_style)
tail_display = "REQUIRES UPDATE"
var/list/tail_styles = pref.get_available_styles(global.tail_styles_list)
var/datum/sprite_accessory/tail/tail = tail_styles[pref.tail_style]
. += "<b>Tail</b><br>"
. += " Style: <a href='?src=\ref[src];tail_style=1'>[tail_display]</a><br>"
if(tail_styles_list[pref.tail_style])
var/datum/sprite_accessory/tail/T = tail_styles_list[pref.tail_style]
if(T.do_colouration)
if(istype(tail))
. += " Style: <a href='?src=\ref[src];tail_style=1'>[tail.name]</a><br>"
if(tail.do_colouration)
. += "<a href='?src=\ref[src];tail_color=1'>Change Color</a> [color_square(pref.r_tail, pref.g_tail, pref.b_tail)]<br>"
if(T.extra_overlay)
if(tail.extra_overlay)
. += "<a href='?src=\ref[src];tail_color2=1'>Change Secondary Color</a> [color_square(pref.r_tail2, pref.g_tail2, pref.b_tail2)]<br>"
if(T.extra_overlay2)
if(tail.extra_overlay2)
. += "<a href='?src=\ref[src];tail_color3=1'>Change Tertiary Color</a> [color_square(pref.r_tail3, pref.g_tail3, pref.b_tail3)]<br>"
else
. += " Style: <a href='?src=\ref[src];tail_style=1'>Select</a><br>"
var/wing_display = "Normal"
if(pref.wing_style && (pref.wing_style in wing_styles_list))
var/datum/sprite_accessory/wing/instance = wing_styles_list[pref.wing_style]
wing_display = instance.name
else if(pref.wing_style)
wing_display = "REQUIRES UPDATE"
var/list/wing_styles = pref.get_available_styles(global.wing_styles_list)
var/datum/sprite_accessory/wing/wings = wing_styles[pref.wing_style]
. += "<b>Wing</b><br>"
. += " Style: <a href='?src=\ref[src];wing_style=1'>[wing_display]</a><br>"
if(wing_styles_list[pref.wing_style])
var/datum/sprite_accessory/wing/W = wing_styles_list[pref.wing_style]
if(W.do_colouration)
if(istype(wings))
. += " Style: <a href='?src=\ref[src];wing_style=1'>[wings.name]</a><br>"
if(wings.do_colouration)
. += "<a href='?src=\ref[src];wing_color=1'>Change Color</a> [color_square(pref.r_wing, pref.g_wing, pref.b_wing)]<br>"
if(W.extra_overlay)
if(wings.extra_overlay)
. += "<a href='?src=\ref[src];wing_color2=1'>Change Secondary Color</a> [color_square(pref.r_wing2, pref.g_wing2, pref.b_wing2)]<br>"
if(W.extra_overlay2)
if(wings.extra_overlay2)
. += "<a href='?src=\ref[src];wing_color3=1'>Change Secondary Color</a> [color_square(pref.r_wing3, pref.g_wing3, pref.b_wing3)]<br>"
else
. += " Style: <a href='?src=\ref[src];wing_style=1'>Select</a><br>"
. += "<br><a href='?src=\ref[src];marking_style=1'>Body Markings +</a><br>"
. += "<table>"
@@ -669,7 +688,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
reset_limbs() // Safety for species with incompatible manufacturers; easier than trying to do it case by case.
pref.body_markings.Cut() // Basically same as above.
pref.sanitize_body_styles()
var/min_age = get_min_age()
var/max_age = get_max_age()
pref.age = max(min(pref.age, max_age), min_age)
@@ -1085,17 +1106,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["ear_style"])
// Construct the list of names allowed for this user.
var/list/pretty_ear_styles = list("Normal" = null)
for(var/path in ear_styles_list)
var/datum/sprite_accessory/ears/instance = ear_styles_list[path]
if(((!instance.ckeys_allowed) || (usr.ckey in instance.ckeys_allowed)) && ((!instance.apply_restrictions) || (pref.species in instance.species_allowed)) || check_rights(R_ADMIN | R_EVENT | R_FUN, 0, user)) //VOREStation Edit
pretty_ear_styles[instance.name] = path
// Present choice to user
var/new_ear_style = input(user, "Pick ears", "Character Preference", pref.ear_style) as null|anything in pretty_ear_styles
var/new_ear_style = input(user, "Select an ear style for this character:", "Character Preference", pref.ear_style) as null|anything in pref.get_available_styles(global.ear_styles_list)
if(new_ear_style)
pref.ear_style = pretty_ear_styles[new_ear_style]
pref.ear_style = new_ear_style
return TOPIC_REFRESH_UPDATE_PREVIEW
@@ -1127,18 +1140,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["tail_style"])
// Construct the list of names allowed for this user.
var/list/pretty_tail_styles = list("Normal" = null)
for(var/path in tail_styles_list)
var/datum/sprite_accessory/tail/instance = tail_styles_list[path]
if(((!instance.ckeys_allowed) || (usr.ckey in instance.ckeys_allowed)) && ((!instance.apply_restrictions) || (pref.species in instance.species_allowed)) || check_rights(R_ADMIN | R_EVENT | R_FUN, 0, user)) //VOREStation Edit
pretty_tail_styles[instance.name] = path
// Present choice to user
var/new_tail_style = input(user, "Pick tails", "Character Preference", pref.tail_style) as null|anything in pretty_tail_styles
var/new_tail_style = input(user, "Select a tail style for this character:", "Character Preference", pref.tail_style) as null|anything in pref.get_available_styles(global.tail_styles_list)
if(new_tail_style)
pref.tail_style = pretty_tail_styles[new_tail_style]
pref.tail_style = new_tail_style
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["tail_color"])
@@ -1169,17 +1173,9 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
return TOPIC_REFRESH_UPDATE_PREVIEW
else if(href_list["wing_style"])
// Construct the list of names allowed for this user.
var/list/pretty_wing_styles = list("Normal" = null)
for(var/path in wing_styles_list)
var/datum/sprite_accessory/wing/instance = wing_styles_list[path]
if(((!instance.ckeys_allowed) || (usr.ckey in instance.ckeys_allowed)) && ((!instance.apply_restrictions) || (pref.species in instance.species_allowed)) || check_rights(R_ADMIN | R_EVENT | R_FUN, 0, user)) //VOREStation Edit
pretty_wing_styles[instance.name] = path
// Present choice to user
var/new_wing_style = input(user, "Pick wings", "Character Preference", pref.wing_style) as null|anything in pretty_wing_styles
var/new_wing_style = input(user, "Select a wing style for this character:", "Character Preference", pref.wing_style) as null|anything in pref.get_available_styles(global.wing_styles_list)
if(new_wing_style)
pref.wing_style = pretty_wing_styles[new_wing_style]
pref.wing_style = new_wing_style
return TOPIC_REFRESH_UPDATE_PREVIEW
@@ -62,12 +62,15 @@ var/list/gear_datums = list()
/datum/category_item/player_setup_item/loadout/proc/valid_gear_choices(var/max_cost)
. = list()
var/mob/preference_mob = preference_mob()
var/mob/preference_mob = preference_mob() //VOREStation Add
for(var/gear_name in gear_datums)
var/datum/gear/G = gear_datums[gear_name]
if(G.whitelisted && !is_alien_whitelisted(preference_mob, GLOB.all_species[G.whitelisted]))
continue
if(G.whitelisted && config.loadout_whitelist != LOADOUT_WHITELIST_OFF)
if(config.loadout_whitelist == LOADOUT_WHITELIST_STRICT && G.whitelisted != pref.species)
continue
if(config.loadout_whitelist == LOADOUT_WHITELIST_LAX && !is_alien_whitelisted(preference_mob(), GLOB.all_species[G.whitelisted]))
continue
if(max_cost && G.cost > max_cost)
continue
//VOREStation Edit Start
@@ -60,6 +60,12 @@
ckeywhitelist = list("aegisoa")
character_name = list("Xander Bevin")
/datum/gear/fluff/charlotte_cigarettes
path = /obj/item/weapon/storage/fancy/fluff/charlotte
display_name = "Charlotte's cigarette case"
ckeywhitelist = list("alfalah")
character_name = list("Charlotte Graves")
/datum/gear/fluff/lynn_penlight
path = /obj/item/device/flashlight/pen/fluff/lynn
display_name = "Lynn's Penlight"
@@ -89,11 +95,23 @@
character_name = list("Aronai Sieyes")
/datum/gear/fluff/astra_ritualknife
path = /obj/item/weapon/material/knife/ritual/fluff/astra
display_name = "Polished Ritual Knife"
description = "A well kept strange ritual knife, There is a small tag with the name 'Astra Ether' on it. They are probably looking for this."
ckeywhitelist = list("astraether")
character_name = list("Astra Ether")
path = /obj/item/weapon/material/knife/ritual/fluff/astra
display_name = "Polished Ritual Knife"
description = "A well kept strange ritual knife, There is a small tag with the name 'Astra Ether' on it. They are probably looking for this."
ckeywhitelist = list("astraether")
character_name = list("Astra Ether")
/datum/gear/fluff/astra_medal
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Astra's Conduct Medal"
ckeywhitelist = list("astraether")
character_name = list("Astra Ether")
/datum/gear/fluff/astra_medal_2
path = /obj/item/clothing/accessory/medal/silver/unity
display_name = "Astra's Unity Medal"
ckeywhitelist = list("astraether")
character_name = list("Astra Ether")
/datum/gear/fluff/collar/azura
path = /obj/item/clothing/accessory/collar/azura
@@ -149,6 +167,12 @@
ckeywhitelist = list("blakeryan")
character_name = list("Nolan Conaway")
/datum/gear/fluff/amber_medal
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Amber's Conduct Medal"
ckeywhitelist = list("bluewolf128")
character_name = list("Amber Wresspenn")
/datum/gear/fluff/charles_hat
path = /obj/item/clothing/head/that/fluff/gettler
display_name = "Charles' Top-Hat"
@@ -189,6 +213,12 @@
ckeywhitelist = list("bacon12366")
character_name = list("Elly Brown")
/datum/gear/fluff/alibig_medal
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Ali Big's Conduct Medal"
ckeywhitelist = list("bigbababooey")
character_name = list("Ali Big")
// C CKEYS
/datum/gear/fluff/cappy_watch
path = /obj/item/clothing/accessory/watch
@@ -260,6 +290,18 @@
ckeywhitelist = list("dickfreedomjohnson")
character_name = list("Elliot Richards")
/datum/gear/fluff/donald_medal
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Donald's Conduct Medal"
ckeywhitelist = list("drainquake")
character_name = list("Donald Weinbeck")
/datum/gear/fluff/donald_medal_2
path = /obj/item/clothing/accessory/medal/bronze_heart
display_name = "Donald's Heart Medal"
ckeywhitelist = list("drainquake")
character_name = list("Donald Weinbeck")
/datum/gear/fluff/drake_box
path = /obj/item/weapon/storage/box/fluff/drake
display_name = "Drake's Box"
@@ -570,6 +612,12 @@
character_name = list("Ashley Kifer")
// L CKEYS
/datum/gear/fluff/kenzie_medal
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Kenzie's Conduct Medal"
ckeywhitelist = list("lm40")
character_name = list("Kenzie Houser")
/datum/gear/fluff/kenzie_hypospray
path = /obj/item/weapon/reagent_containers/hypospray/vial/kenzie
display_name = "Kenzie's Hypospray"
@@ -584,6 +632,12 @@
ckeywhitelist = list("luminescentring")
character_name = list("Briana Moore")
/datum/gear/fluff/entchtut_medal
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Entchtut's Conduct Medal"
ckeywhitelist = list("littlebigkid2000")
character_name = list("Entchtut Cenein")
// M CKEYS
/datum/gear/fluff/phi_box
path = /obj/item/weapon/storage/box/fluff/phi
@@ -736,7 +790,7 @@
character_name = list("Scylla Casmus")
/datum/gear/fluff/kiyoshi_cloak
path = /obj/item/clothing/accessory/poncho/fluff/cloakglowing
path = /obj/item/clothing/accessory/poncho/roles/cloak/fluff/cloakglowing
display_name = "glowing cloak"
ckeywhitelist = list("pastelprincedan")
character_name = list("Kiyoshi Maki", "Masumi Maki")
@@ -758,6 +812,18 @@
character_name = list("Clara Mali")
cost = 1
/datum/gear/fluff/luna_sci_medal
path = /obj/item/clothing/accessory/medal/nobel_science
display_name = "LUNA's Nobel Science Award"
ckeywhitelist = list("residentcody")
character_name = list("LUNA")
/datum/gear/fluff/luna_conduct_medal
path = /obj/item/clothing/accessory/medal/conduct
display_name = "LUNA's Distinguished Conduct Medal"
ckeywhitelist = list("residentcody")
character_name = list("LUNA")
/datum/gear/fluff/nikki_dorky_outfit
path = /obj/item/weapon/storage/box/fluff
display_name = "Nikki's Witchy Outfit"
@@ -777,6 +843,18 @@
ckeywhitelist = list("sageofaether12")
character_name = list("Brynhild Vandradottir")
/datum/gear/fluff/brynhild_medal_3
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Brynhild's Conduct Medal"
ckeywhitelist = list("sageofaether12")
character_name = list("Brynhild Vandradottir")
/datum/gear/fluff/brynhild_medal_4
path = /obj/item/clothing/accessory/medal/bronze_heart
display_name = "Brynhild's Heart Medal"
ckeywhitelist = list("sageofaether12")
character_name = list("Brynhild Vandradottir")
/datum/gear/fluff/kateryna_voidsuit
path = /obj/item/clothing/suit/space/void/engineering/kate
display_name = "Kateryna's Voidsuit"
@@ -912,6 +990,12 @@
ckeywhitelist = list("tabiranth")
character_name = list("Ascian")
/datum/gear/fluff/ascian_medal_3
path = /obj/item/clothing/accessory/medal/conduct
display_name = "Ascian's Conduct Medal"
ckeywhitelist = list("tabiranth")
character_name = list("Ascian")
/datum/gear/fluff/ascian_spiritspawner
path = /obj/item/weapon/grenade/spawnergrenade/spirit
display_name = "The Best Kitten"
@@ -76,6 +76,7 @@
description = "Choose from a number of toys."
path = /obj/item/toy/
/* VOREStation removal
/datum/gear/toy/New()
..()
var/toytype = list()
@@ -86,7 +87,7 @@
toytype["Magic 8 Ball"] = /obj/item/toy/eight_ball
toytype["Magic Conch shell"] = /obj/item/toy/eight_ball/conch
gear_tweaks += new/datum/gear_tweak/path(toytype)
*/
/datum/gear/flask
display_name = "flask"
@@ -9,4 +9,83 @@
for(var/ball in typesof(/obj/item/toy/tennis/))
var/obj/item/toy/tennis/ball_type = ball
balls[initial(ball_type.name)] = ball_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(balls))
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(balls))
/datum/gear/character/
display_name = "miniature selection"
description = "Choose from a number of miniatures. From Battlemace 40 million to Grottos and Ghouls."
path = /obj/item/toy/character/alien
/datum/gear/character/New()
..()
var/list/characters = list()
for(var/character in typesof(/obj/item/toy/character/) - /obj/item/toy/character)
var/obj/item/toy/character/character_type = character
characters[initial(character_type.name)] = character_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(characters))
/datum/gear/mechtoy/
display_name = "mecha toy selection"
description = "Choose from a number of mech toys."
path = /obj/item/toy/mecha/ripley
/datum/gear/mechtoy/New()
..()
var/list/mechs = list()
for(var/mech in typesof(/obj/item/toy/mecha/) - /obj/item/toy/mecha/)
var/obj/item/toy/mecha/mech_type = mech
mechs[initial(mech_type.name)] = mech_type
gear_tweaks += new/datum/gear_tweak/path(sortAssoc(mechs))
/datum/gear/toy/New()
..()
var/toytype = list()
toytype["Blink toy"] = /obj/item/toy/blink
toytype["Foam dart crossbow"] = /obj/item/toy/blink
toytype["Toy sword"] = /obj/item/toy/sword
toytype["Toy katana"] = /obj/item/toy/katana
toytype["Snap pops"] = /obj/item/weapon/storage/box/snappops
toytype["Plastic flowers"] = /obj/item/toy/bouquet/fake
toytype["Stick horse"] = /obj/item/toy/stickhorse
toytype["Toy X-mas tree"] = /obj/item/toy/xmastree
toytype["Fake handcuff kit"] = /obj/item/weapon/storage/box/handcuffs/fake
toytype["Gravitational singularity"] = /obj/item/toy/spinningtoy
toytype["Water flower"] = /obj/item/weapon/reagent_containers/spray/waterflower
toytype["Bosun's whistle"] = /obj/item/toy/bosunwhistle
toytype["Magic 8 Ball"] = /obj/item/toy/eight_ball
toytype["Magic Conch shell"] = /obj/item/toy/eight_ball/conch
toytype["Pet rock"] = /obj/item/toy/rock
toytype["Toy flash"] = /obj/item/toy/flash
toytype["Big Red Button"] = /obj/item/toy/redbutton
toytype["Garden gnome"] = /obj/item/toy/gnome
toytype["Toy AI"] = /obj/item/toy/AI
toytype["Hand buzzer"] = /obj/item/clothing/gloves/ring/buzzer/toy
toytype["Toy nuke"] = /obj/item/toy/nuke
toytype["Toy gibber"] = /obj/item/toy/minigibber
toytype["Toy xeno"] = /obj/item/toy/toy_xeno
gear_tweaks += new/datum/gear_tweak/path(toytype)
/datum/gear/chewtoy
display_name = "animal toy selection"
path = /obj/item/toy/chewtoy
/datum/gear/chewtoy/New()
..()
var/toytype = list()
toytype["Bone"] = /obj/item/toy/chewtoy
toytype["Classic"] = /obj/item/toy/chewtoy/tall
toytype["Mouse"] = /obj/item/toy/cat_toy
toytype["Feather rod"] = /obj/item/toy/cat_toy/rod
gear_tweaks += new/datum/gear_tweak/path(toytype)
/datum/gear/chewtoy_poly
display_name = "animal toy selection, colorable"
path = /obj/item/toy/chewtoy/poly
/datum/gear/chewtoy_poly/New()
..()
var/toytype = list()
toytype["Bone"] = /obj/item/toy/chewtoy/poly
toytype["Classic"] = /obj/item/toy/chewtoy/tall/poly
gear_tweaks += new/datum/gear_tweak/path(toytype)
gear_tweaks += gear_tweak_free_color_choice
@@ -129,6 +129,7 @@
for(var/datum/category_item/player_setup_item/PI in items)
PI.load_character(S)
/datum/category_group/player_setup_category/proc/save_character(var/savefile/S)
// Sanitize all data, then save it
for(var/datum/category_item/player_setup_item/PI in items)
+2 -2
View File
@@ -169,8 +169,8 @@ datum/preferences
if(!IsGuestKey(C.key))
load_path(C.ckey)
if(load_preferences())
if(load_character())
return
load_character()
/datum/preferences/Destroy()
. = ..()
+1 -3
View File
@@ -82,10 +82,8 @@
player_setup.load_character(S)
S.cd = "/character[default_slot]"
player_setup.save_character(S)
sanitize_preferences()
player_setup.load_character(S)
clear_character_previews() // Recalculate them on next show
clear_character_previews() // VOREStation Edit
return 1
/datum/preferences/proc/save_character()
@@ -0,0 +1,33 @@
//Overmap pilots. Same gear, without the dumb interface.
/obj/item/clothing/head/ompilot
name = "pilot helmet"
desc = "Standard pilot gear. Protects the head from impacts."
icon_state = "pilot_helmet1"
item_icons = list(slot_head_str = 'icons/mob/pilot_helmet.dmi')
sprite_sheets = list(
SPECIES_TESHARI = 'icons/mob/species/teshari/pilot_helmet.dmi'
)
flags = THICKMATERIAL
armor = list(melee = 20, bullet = 10, laser = 10, energy = 5, bomb = 10, bio = 0, rad = 0)
flags_inv = HIDEEARS
cold_protection = HEAD
min_cold_protection_temperature = HELMET_MIN_COLD_PROTECTION_TEMPERATURE
heat_protection = HEAD
max_heat_protection_temperature = HELMET_MAX_HEAT_PROTECTION_TEMPERATURE
w_class = ITEMSIZE_NORMAL
/obj/item/clothing/head/ompilot/alt
name = "pilot helmet"
desc = "Standard pilot gear. Protects the head from impacts. This one has a retractable visor"
icon_state = "pilot_helmet2"
action_button_name = "Toggle Visor"
/obj/item/clothing/head/ompilot/alt/attack_self(mob/user as mob)
if(src.icon_state == initial(icon_state))
src.icon_state = "[icon_state]up"
to_chat(user, "You raise the visor on the pilot helmet.")
else
src.icon_state = initial(icon_state)
to_chat(user, "You lower the visor on the pilot helmet.")
update_clothing_icon() //so our mob-overlays update
+18 -2
View File
@@ -78,7 +78,7 @@
* Radiation protection
*/
/obj/item/clothing/head/radiation
name = "Radiation Hood"
name = "Radiation hood"
icon_state = "rad"
desc = "A hood with radiation protective properties. Label: Made with lead, do not eat insulation"
flags_inv = BLOCKHAIR
@@ -98,4 +98,20 @@
slowdown = 1.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100)
flags_inv = HIDEJUMPSUIT|HIDETAIL|HIDETIE|HIDEHOLSTER
item_flags = THICKMATERIAL
item_flags = THICKMATERIAL
/obj/item/clothing/suit/radiation/teshari
name = "Small radiation suit"
desc = "A specialist suit that protects against radiation, designed specifically for use by Teshari. Made to order by Aether."
icon = 'icons/obj/clothing/species/teshari/suits.dmi'
icon_override = 'icons/mob/species/teshari/suit.dmi'
icon_state = "rad_fitted"
species_restricted = list(SPECIES_TESHARI)
/obj/item/clothing/head/radiation/teshari
name = "Small radiation hood"
desc = "A specialist hood with radiation protective properties, designed specifically for use by Teshari. Made to order by Aether."
icon = 'icons/obj/clothing/species/teshari/hats.dmi'
icon_override = 'icons/mob/species/teshari/head.dmi'
icon_state = "rad_fitted"
species_restricted = list(SPECIES_TESHARI)
@@ -365,4 +365,4 @@
icon_state = "silverthree"
item_state = "silverthree"
overlay_state = "silverthree"
desc = "A silver medal awarded to a group which has demonstrated exceptional teamwork to achieve a notable feat. This one has two bronze service stars, denoting that it has been awarded three times."
desc = "A silver medal awarded to a group which has demonstrated exceptional teamwork to achieve a notable feat. This one has three bronze service stars, denoting that it has been awarded four times."
@@ -1,4 +1,53 @@
/obj/item/clothing/accessory/holster/waist/kinetic_accelerator
name = "KA holster"
desc = "A specialized holster, made specifically for Kinetic Accelerator."
can_hold = list(/obj/item/weapon/gun/energy/kinetic_accelerator)
can_hold = list(/obj/item/weapon/gun/energy/kinetic_accelerator)
/obj/item/clothing/accessory/holster/machete/rapier
name = "rapier sheath"
desc = "A beautiful red sheath, probably for a beautiful blade."
icon = 'icons/obj/clothing/ties_vr.dmi'
icon_state = "sheath"
slot_flags = SLOT_BELT|ACCESSORY_SLOT_WEAPON
var/has_full_icon = 1
icon_override = 'icons/mob/ties_vr.dmi'
overlay_state = "sheath"
can_hold = list(/obj/item/weapon/melee/rapier)
/obj/item/clothing/accessory/holster/machete/rapier/swords
name = "sword sheath"
desc = "A beautiful red sheath, probably for a beautiful blade."
can_hold = list(
/obj/item/weapon/melee/rapier,
/obj/item/weapon/material/sword/katana,
/obj/item/toy/cultsword,
/obj/item/weapon/material/sword,
/obj/item/weapon/melee/cursedblade,
/obj/item/weapon/melee/cultblade
)
/obj/item/clothing/accessory/holster/machete/rapier/proc/occupied()
if(!has_full_icon)
return
if(contents.len)
overlay_state = "[initial(overlay_state)]-rapier"
else
overlay_state = initial(overlay_state)
/obj/item/clothing/accessory/holster/machete/rapier/swords/occupied()
if(!has_full_icon)
return
if(contents.len)
overlay_state = "[initial(overlay_state)]-secondary"
else
overlay_state = initial(overlay_state)
/obj/item/clothing/accessory/holster/machete/rapier/holster(var/obj/item/I, var/mob/living/user)
..()
occupied()
has_suit.update_clothing_icon()
/obj/item/clothing/accessory/holster/machete/rapier/unholster(var/obj/item/I, var/mob/living/user)
..()
occupied()
has_suit.update_clothing_icon()
@@ -1,98 +1,98 @@
/*****************************Money bag********************************/
/obj/item/weapon/moneybag
icon = 'icons/obj/storage.dmi'
name = "Money bag"
icon_state = "moneybag"
force = 10.0
throwforce = 2.0
w_class = ITEMSIZE_LARGE
/obj/item/weapon/moneybag/attack_hand(user as mob)
var/amt_gold = 0
var/amt_silver = 0
var/amt_diamond = 0
var/amt_iron = 0
var/amt_phoron = 0
var/amt_uranium = 0
for (var/obj/item/weapon/coin/C in contents)
if (istype(C,/obj/item/weapon/coin/diamond))
amt_diamond++;
if (istype(C,/obj/item/weapon/coin/phoron))
amt_phoron++;
if (istype(C,/obj/item/weapon/coin/iron))
amt_iron++;
if (istype(C,/obj/item/weapon/coin/silver))
amt_silver++;
if (istype(C,/obj/item/weapon/coin/gold))
amt_gold++;
if (istype(C,/obj/item/weapon/coin/uranium))
amt_uranium++;
var/dat = text("<b>The contents of the moneybag reveal...</b><br>")
if (amt_gold)
dat += text("Gold coins: [amt_gold] <A href='?src=\ref[src];remove=gold'>Remove one</A><br>")
if (amt_silver)
dat += text("Silver coins: [amt_silver] <A href='?src=\ref[src];remove=silver'>Remove one</A><br>")
if (amt_iron)
dat += text("Metal coins: [amt_iron] <A href='?src=\ref[src];remove=iron'>Remove one</A><br>")
if (amt_diamond)
dat += text("Diamond coins: [amt_diamond] <A href='?src=\ref[src];remove=diamond'>Remove one</A><br>")
if (amt_phoron)
dat += text("Phoron coins: [amt_phoron] <A href='?src=\ref[src];remove=phoron'>Remove one</A><br>")
if (amt_uranium)
dat += text("Uranium coins: [amt_uranium] <A href='?src=\ref[src];remove=uranium'>Remove one</A><br>")
user << browse("[dat]", "window=moneybag")
/obj/item/weapon/moneybag/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/coin))
var/obj/item/weapon/coin/C = W
to_chat(user, "<font color='blue'>You add the [C.name] into the bag.</font>")
usr.drop_item()
contents += C
if (istype(W, /obj/item/weapon/moneybag))
var/obj/item/weapon/moneybag/C = W
for (var/obj/O in C.contents)
contents += O;
to_chat(user, "<font color='blue'>You empty the [C.name] into the bag.</font>")
return
/obj/item/weapon/moneybag/Topic(href, href_list)
if(..())
return 1
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["remove"])
var/obj/item/weapon/coin/COIN
switch(href_list["remove"])
if("gold")
COIN = locate(/obj/item/weapon/coin/gold,src.contents)
if("silver")
COIN = locate(/obj/item/weapon/coin/silver,src.contents)
if("iron")
COIN = locate(/obj/item/weapon/coin/iron,src.contents)
if("diamond")
COIN = locate(/obj/item/weapon/coin/diamond,src.contents)
if("phoron")
COIN = locate(/obj/item/weapon/coin/phoron,src.contents)
if("uranium")
COIN = locate(/obj/item/weapon/coin/uranium,src.contents)
if(!COIN)
return
COIN.loc = src.loc
return
/obj/item/weapon/moneybag/vault
/obj/item/weapon/moneybag/vault/New()
..()
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/gold(src)
/*****************************Money bag********************************/
/obj/item/weapon/moneybag
icon = 'icons/obj/storage.dmi'
name = "Money bag"
icon_state = "moneybag"
force = 10.0
throwforce = 2.0
w_class = ITEMSIZE_LARGE
/obj/item/weapon/moneybag/attack_hand(user as mob)
var/amt_gold = 0
var/amt_silver = 0
var/amt_diamond = 0
var/amt_iron = 0
var/amt_phoron = 0
var/amt_uranium = 0
for (var/obj/item/weapon/coin/C in contents)
if (istype(C,/obj/item/weapon/coin/diamond))
amt_diamond++;
if (istype(C,/obj/item/weapon/coin/phoron))
amt_phoron++;
if (istype(C,/obj/item/weapon/coin/iron))
amt_iron++;
if (istype(C,/obj/item/weapon/coin/silver))
amt_silver++;
if (istype(C,/obj/item/weapon/coin/gold))
amt_gold++;
if (istype(C,/obj/item/weapon/coin/uranium))
amt_uranium++;
var/dat = text("<b>The contents of the moneybag reveal...</b><br>")
if (amt_gold)
dat += text("Gold coins: [amt_gold] <A href='?src=\ref[src];remove=gold'>Remove one</A><br>")
if (amt_silver)
dat += text("Silver coins: [amt_silver] <A href='?src=\ref[src];remove=silver'>Remove one</A><br>")
if (amt_iron)
dat += text("Metal coins: [amt_iron] <A href='?src=\ref[src];remove=iron'>Remove one</A><br>")
if (amt_diamond)
dat += text("Diamond coins: [amt_diamond] <A href='?src=\ref[src];remove=diamond'>Remove one</A><br>")
if (amt_phoron)
dat += text("Phoron coins: [amt_phoron] <A href='?src=\ref[src];remove=phoron'>Remove one</A><br>")
if (amt_uranium)
dat += text("Uranium coins: [amt_uranium] <A href='?src=\ref[src];remove=uranium'>Remove one</A><br>")
user << browse("[dat]", "window=moneybag")
/obj/item/weapon/moneybag/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/coin))
var/obj/item/weapon/coin/C = W
to_chat(user, "<font color='blue'>You add the [C.name] into the bag.</font>")
usr.drop_item()
contents += C
if (istype(W, /obj/item/weapon/moneybag))
var/obj/item/weapon/moneybag/C = W
for (var/obj/O in C.contents)
contents += O;
to_chat(user, "<font color='blue'>You empty the [C.name] into the bag.</font>")
return
/obj/item/weapon/moneybag/Topic(href, href_list)
if(..())
return 1
usr.set_machine(src)
src.add_fingerprint(usr)
if(href_list["remove"])
var/obj/item/weapon/coin/COIN
switch(href_list["remove"])
if("gold")
COIN = locate(/obj/item/weapon/coin/gold,src.contents)
if("silver")
COIN = locate(/obj/item/weapon/coin/silver,src.contents)
if("iron")
COIN = locate(/obj/item/weapon/coin/iron,src.contents)
if("diamond")
COIN = locate(/obj/item/weapon/coin/diamond,src.contents)
if("phoron")
COIN = locate(/obj/item/weapon/coin/phoron,src.contents)
if("uranium")
COIN = locate(/obj/item/weapon/coin/uranium,src.contents)
if(!COIN)
return
COIN.loc = src.loc
return
/obj/item/weapon/moneybag/vault
/obj/item/weapon/moneybag/vault/New()
..()
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/silver(src)
new /obj/item/weapon/coin/gold(src)
new /obj/item/weapon/coin/gold(src)
+1 -1
View File
@@ -13,7 +13,7 @@
//---Beverages---//
//***************//
/datum/reagent/var/price_tag = null
/datum/reagent/var/price_tag = 0
// Juices, soda and similar //
File diff suppressed because it is too large Load Diff

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