Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into traitor-types
This commit is contained in:
@@ -33,6 +33,10 @@
|
||||
#define COMSIG_GLOB_NEW_Z "!new_z" //from base of datum/controller/subsystem/mapping/proc/add_new_zlevel(): (list/args)
|
||||
#define COMSIG_GLOB_VAR_EDIT "!var_edit" //called after a successful var edit somewhere in the world: (list/args)
|
||||
#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special" //global living say plug - use sparingly: (mob/speaker , message)
|
||||
|
||||
// signals from globally accessible objects
|
||||
/// from SSsun when the sun changes position : (azimuth)
|
||||
#define COMSIG_SUN_MOVED "sun_moved"
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// /datum signals
|
||||
@@ -58,6 +62,7 @@
|
||||
#define COMSIG_ATOM_NO_UPDATE_ICON_STATE 1
|
||||
#define COMSIG_ATOM_NO_UPDATE_OVERLAYS 2
|
||||
#define COMSIG_ATOM_UPDATE_OVERLAYS "atom_update_overlays" //from base of atom/update_overlays(): (list/new_overlays)
|
||||
#define COMSIG_ATOM_UPDATED_ICON "atom_updated_icon" //from base of atom/update_icon(): (signalOut, did_anything)
|
||||
#define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom)
|
||||
#define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc)
|
||||
#define COMPONENT_ATOM_BLOCK_EXIT 1
|
||||
@@ -193,13 +198,13 @@
|
||||
// #define SPEECH_FORCED 7
|
||||
|
||||
// /mob/living signals
|
||||
#define COMSIG_LIVING_FULLY_HEAL "living_fully_healed" //from base of /mob/living/fully_heal(): (admin_revive)
|
||||
#define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs)
|
||||
#define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living)
|
||||
#define COMSIG_LIVING_IGNITED "living_ignite" //from base of mob/living/IgniteMob() (/mob/living)
|
||||
#define COMSIG_LIVING_EXTINGUISHED "living_extinguished" //from base of mob/living/ExtinguishMob() (/mob/living)
|
||||
#define COMSIG_LIVING_ELECTROCUTE_ACT "living_electrocute_act" //from base of mob/living/electrocute_act(): (shock_damage)
|
||||
#define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: ()
|
||||
#define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive)
|
||||
#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" //sent when a mob/login() finishes: (client)
|
||||
#define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override)
|
||||
|
||||
@@ -220,6 +225,7 @@
|
||||
|
||||
// /obj/item signals
|
||||
#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (/mob/living/target, /mob/living/user)
|
||||
#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage" //from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone)
|
||||
#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (/mob)
|
||||
#define COMPONENT_NO_INTERACT 1
|
||||
#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (/obj, /mob)
|
||||
@@ -233,6 +239,7 @@
|
||||
#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone" //from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
|
||||
#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul" //return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/targeted/lichdom/cast(): (mob/user)
|
||||
#define COMSIG_ITEM_HIT_REACT "item_hit_react" //from base of obj/item/hit_reaction(): (list/args)
|
||||
#define COMSIG_ITEM_WEARERCROSSED "wearer_crossed" //called on item when crossed by something (): (/atom/movable)
|
||||
|
||||
// /obj/item/clothing signals
|
||||
#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): ()
|
||||
@@ -295,11 +302,14 @@
|
||||
//Nanites
|
||||
#define COMSIG_HAS_NANITES "has_nanites" //() returns TRUE if nanites are found
|
||||
#define COMSIG_NANITE_IS_STEALTHY "nanite_is_stealthy" //() returns TRUE if nanites have stealth
|
||||
#define COMSIG_NANITE_DELETE "nanite_delete" //() deletes the nanite component
|
||||
#define COMSIG_NANITE_GET_PROGRAMS "nanite_get_programs" //(list/nanite_programs) - makes the input list a copy the nanites' program list
|
||||
#define COMSIG_NANITE_GET_VOLUME "nanite_get_volume" //(amount) Returns nanite amount
|
||||
#define COMSIG_NANITE_SET_VOLUME "nanite_set_volume" //(amount) Sets current nanite volume to the given amount
|
||||
#define COMSIG_NANITE_ADJUST_VOLUME "nanite_adjust" //(amount) Adjusts nanite volume by the given amount
|
||||
#define COMSIG_NANITE_SET_MAX_VOLUME "nanite_set_max_volume" //(amount) Sets maximum nanite volume to the given amount
|
||||
#define COMSIG_NANITE_SET_CLOUD "nanite_set_cloud" //(amount(0-100)) Sets cloud ID to the given amount
|
||||
#define COMSIG_NANITE_SET_CLOUD_SYNC "nanite_set_cloud_sync" //(method) Modify cloud sync status. Method can be toggle, enable or disable
|
||||
#define COMSIG_NANITE_SET_SAFETY "nanite_set_safety" //(amount) Sets safety threshold to the given amount
|
||||
#define COMSIG_NANITE_SET_REGEN "nanite_set_regen" //(amount) Sets regeneration rate to the given amount
|
||||
#define COMSIG_NANITE_SIGNAL "nanite_signal" //(code(1-9999)) Called when sending a nanite signal to a mob.
|
||||
@@ -307,8 +317,8 @@
|
||||
#define COMSIG_NANITE_SCAN "nanite_scan" //(mob/user, full_scan) - sends to chat a scan of the nanites to the user, returns TRUE if nanites are detected
|
||||
#define COMSIG_NANITE_UI_DATA "nanite_ui_data" //(list/data, scan_level) - adds nanite data to the given data list - made for ui_data procs
|
||||
#define COMSIG_NANITE_ADD_PROGRAM "nanite_add_program" //(datum/nanite_program/new_program, datum/nanite_program/source_program) Called when adding a program to a nanite component
|
||||
#define COMPONENT_PROGRAM_INSTALLED 1 //Installation successful
|
||||
#define COMPONENT_PROGRAM_NOT_INSTALLED 2 //Installation failed, but there are still nanites
|
||||
#define COMPONENT_PROGRAM_INSTALLED 1 //Installation successful
|
||||
#define COMPONENT_PROGRAM_NOT_INSTALLED 2 //Installation failed, but there are still nanites
|
||||
#define COMSIG_NANITE_SYNC "nanite_sync" //(datum/component/nanites, full_overwrite, copy_activation) Called to sync the target's nanites to a given nanite component
|
||||
|
||||
// /datum/component/storage signals
|
||||
|
||||
@@ -59,19 +59,6 @@
|
||||
//let's just pretend fulltile windows being children of border windows is fine
|
||||
#define FULLTILE_WINDOW_DIR NORTHEAST
|
||||
|
||||
//Material defines, for determining how much of a given material an item contains
|
||||
#define MAT_METAL "$metal"
|
||||
#define MAT_GLASS "$glass"
|
||||
#define MAT_SILVER "$silver"
|
||||
#define MAT_GOLD "$gold"
|
||||
#define MAT_DIAMOND "$diamond"
|
||||
#define MAT_URANIUM "$uranium"
|
||||
#define MAT_PLASMA "$plasma"
|
||||
#define MAT_BLUESPACE "$bluespace"
|
||||
#define MAT_BANANIUM "$bananium"
|
||||
#define MAT_TITANIUM "$titanium"
|
||||
#define MAT_BIOMASS "$biomass"
|
||||
#define MAT_PLASTIC "$plastic"
|
||||
//The amount of materials you get from a sheet of mineral like iron/diamond/glass etc
|
||||
#define MINERAL_MATERIAL_AMOUNT 2000
|
||||
//The maximum size of a stack object.
|
||||
@@ -92,17 +79,19 @@
|
||||
#define CAT_BREAD "Breads"
|
||||
#define CAT_BURGER "Burgers"
|
||||
#define CAT_CAKE "Cakes"
|
||||
#define CAT_DONUT "Donuts"
|
||||
#define CAT_EGG "Egg-Based Food"
|
||||
#define CAT_MEAT "Meats"
|
||||
#define CAT_MEXICAN "Mexican"
|
||||
#define CAT_MISCFOOD "Misc. Food"
|
||||
#define CAT_PASTRY "Pastries"
|
||||
#define CAT_PIE "Pies"
|
||||
#define CAT_PIE "Pies & Sweets"
|
||||
#define CAT_PIZZA "Pizzas"
|
||||
#define CAT_SALAD "Salads"
|
||||
#define CAT_SEAFOOD "Seafood"
|
||||
#define CAT_SANDWICH "Sandwiches"
|
||||
#define CAT_SOUP "Soups"
|
||||
#define CAT_SPAGHETTI "Spaghettis"
|
||||
#define CAT_FISH "Fish"
|
||||
#define CAT_ICE "Frozen"
|
||||
|
||||
#define RCD_FLOORWALL 1
|
||||
|
||||
+31
-29
@@ -23,6 +23,7 @@
|
||||
#define DOCTOR (1<<4)
|
||||
#define GENETICIST (1<<5)
|
||||
#define VIROLOGIST (1<<6)
|
||||
#define PARAMEDIC (1<<7)
|
||||
|
||||
|
||||
#define CIVILIAN (1<<2)
|
||||
@@ -58,32 +59,33 @@
|
||||
#define JOB_DISPLAY_ORDER_ASSISTANT 1
|
||||
#define JOB_DISPLAY_ORDER_CAPTAIN 2
|
||||
#define JOB_DISPLAY_ORDER_HEAD_OF_PERSONNEL 3
|
||||
#define JOB_DISPLAY_ORDER_BARTENDER 4
|
||||
#define JOB_DISPLAY_ORDER_COOK 5
|
||||
#define JOB_DISPLAY_ORDER_BOTANIST 6
|
||||
#define JOB_DISPLAY_ORDER_JANITOR 7
|
||||
#define JOB_DISPLAY_ORDER_CLOWN 8
|
||||
#define JOB_DISPLAY_ORDER_MIME 9
|
||||
#define JOB_DISPLAY_ORDER_CURATOR 10
|
||||
#define JOB_DISPLAY_ORDER_LAWYER 11
|
||||
#define JOB_DISPLAY_ORDER_CHAPLAIN 12
|
||||
#define JOB_DISPLAY_ORDER_QUARTERMASTER 13
|
||||
#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 14
|
||||
#define JOB_DISPLAY_ORDER_SHAFT_MINER 15
|
||||
#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 16
|
||||
#define JOB_DISPLAY_ORDER_STATION_ENGINEER 17
|
||||
#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 18
|
||||
#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 19
|
||||
#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 20
|
||||
#define JOB_DISPLAY_ORDER_CHEMIST 21
|
||||
#define JOB_DISPLAY_ORDER_GENETICIST 22
|
||||
#define JOB_DISPLAY_ORDER_VIROLOGIST 23
|
||||
#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 24
|
||||
#define JOB_DISPLAY_ORDER_SCIENTIST 25
|
||||
#define JOB_DISPLAY_ORDER_ROBOTICIST 26
|
||||
#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 27
|
||||
#define JOB_DISPLAY_ORDER_WARDEN 28
|
||||
#define JOB_DISPLAY_ORDER_DETECTIVE 29
|
||||
#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 30
|
||||
#define JOB_DISPLAY_ORDER_AI 31
|
||||
#define JOB_DISPLAY_ORDER_CYBORG 32
|
||||
#define JOB_DISPLAY_ORDER_QUARTERMASTER 4
|
||||
#define JOB_DISPLAY_ORDER_CARGO_TECHNICIAN 5
|
||||
#define JOB_DISPLAY_ORDER_SHAFT_MINER 6
|
||||
#define JOB_DISPLAY_ORDER_BARTENDER 7
|
||||
#define JOB_DISPLAY_ORDER_COOK 8
|
||||
#define JOB_DISPLAY_ORDER_BOTANIST 9
|
||||
#define JOB_DISPLAY_ORDER_JANITOR 10
|
||||
#define JOB_DISPLAY_ORDER_CLOWN 11
|
||||
#define JOB_DISPLAY_ORDER_MIME 12
|
||||
#define JOB_DISPLAY_ORDER_CURATOR 13
|
||||
#define JOB_DISPLAY_ORDER_LAWYER 14
|
||||
#define JOB_DISPLAY_ORDER_CHAPLAIN 15
|
||||
#define JOB_DISPLAY_ORDER_AI 16
|
||||
#define JOB_DISPLAY_ORDER_CYBORG 17
|
||||
#define JOB_DISPLAY_ORDER_CHIEF_ENGINEER 18
|
||||
#define JOB_DISPLAY_ORDER_STATION_ENGINEER 19
|
||||
#define JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN 20
|
||||
#define JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER 21
|
||||
#define JOB_DISPLAY_ORDER_MEDICAL_DOCTOR 22
|
||||
#define JOB_DISPLAY_ORDER_PARAMEDIC 23
|
||||
#define JOB_DISPLAY_ORDER_CHEMIST 24
|
||||
#define JOB_DISPLAY_ORDER_VIROLOGIST 25
|
||||
#define JOB_DISPLAY_ORDER_GENETICIST 26
|
||||
#define JOB_DISPLAY_ORDER_RESEARCH_DIRECTOR 27
|
||||
#define JOB_DISPLAY_ORDER_SCIENTIST 28
|
||||
#define JOB_DISPLAY_ORDER_ROBOTICIST 29
|
||||
#define JOB_DISPLAY_ORDER_HEAD_OF_SECURITY 30
|
||||
#define JOB_DISPLAY_ORDER_WARDEN 31
|
||||
#define JOB_DISPLAY_ORDER_DETECTIVE 32
|
||||
#define JOB_DISPLAY_ORDER_SECURITY_OFFICER 33
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/// Is the material from an ore? currently unused but exists atm for categorizations sake
|
||||
#define MAT_CATEGORY_ORE "ore capable"
|
||||
|
||||
/// Hard materials, such as iron or metal
|
||||
#define MAT_CATEGORY_RIGID "rigid material"
|
||||
|
||||
|
||||
/// Gets the reference for the material type that was given
|
||||
#define getmaterialref(A) (SSmaterials.materials[A] || A)
|
||||
|
||||
/// Flag for atoms, this flag ensures it isn't re-colored by materials. Useful for snowflake icons such as default toolboxes.
|
||||
#define MATERIAL_COLOR (1<<0)
|
||||
#define MATERIAL_ADD_PREFIX (1<<1)
|
||||
#define MATERIAL_NO_EFFECTS (1<<2)
|
||||
@@ -521,3 +521,5 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define NIGHTSHIFT_AREA_RECREATION 2 //dorms common areas, etc
|
||||
#define NIGHTSHIFT_AREA_DEPARTMENT_HALLS 3 //interior hallways, etc
|
||||
#define NIGHTSHIFT_AREA_NONE 4 //default/highest.
|
||||
|
||||
#define UNTIL(X) while(!(X)) stoplag()
|
||||
|
||||
@@ -276,4 +276,4 @@
|
||||
#define HUMAN_FIRE_STACK_ICON_NUM 3
|
||||
|
||||
#define PULL_PRONE_SLOWDOWN 0.6
|
||||
#define HUMAN_CARRY_SLOWDOWN 0
|
||||
#define HUMAN_CARRY_SLOWDOWN 0
|
||||
|
||||
@@ -17,4 +17,4 @@
|
||||
#define MOVE_FORCE_NORMAL MOVE_FORCE_DEFAULT
|
||||
#define MOVE_FORCE_WEAK (MOVE_FORCE_DEFAULT / 2)
|
||||
#define MOVE_FORCE_VERY_WEAK ((MOVE_FORCE_DEFAULT / MOVE_FORCE_CRUSH_RATIO) + 1)
|
||||
#define MOVE_FORCE_EXTREMELY_WEAK (MOVE_FORCE_DEFAULT / (MOVE_FORCE_CRUSH_RATIO * 3))
|
||||
#define MOVE_FORCE_EXTREMELY_WEAK (MOVE_FORCE_DEFAULT / (MOVE_FORCE_CRUSH_RATIO * 3))
|
||||
|
||||
@@ -68,4 +68,6 @@
|
||||
|
||||
#define MOVESPEED_ID_SHOVE "SHOVE"
|
||||
|
||||
#define MOVESPEED_ID_MKULTRA "MKULTRA"
|
||||
#define MOVESPEED_ID_MKULTRA "MKULTRA"
|
||||
|
||||
#define MOVESPEED_ID_ELECTROSTAFF "ELECTROSTAFF"
|
||||
@@ -1,11 +1,44 @@
|
||||
#define NANITE_TIMER_DEACTIVATE 1
|
||||
#define NANITE_TIMER_SELFDELETE 2
|
||||
#define NANITE_TIMER_TRIGGER 3
|
||||
#define NANITE_TIMER_RESET 4
|
||||
|
||||
#define NANITE_SYNC_DELAY 300
|
||||
|
||||
#define NANITE_SHOCK_IMMUNE 1
|
||||
#define NANITE_EMP_IMMUNE 2
|
||||
|
||||
#define NANITE_PROGRAM_LIMIT 20
|
||||
#define NANITE_PROGRAM_LIMIT 20
|
||||
|
||||
|
||||
#define NANITE_BASE_RESEARCH 3.5
|
||||
|
||||
#define NANITE_CLOUD_TOGGLE 1
|
||||
#define NANITE_CLOUD_DISABLE 2
|
||||
#define NANITE_CLOUD_ENABLE 3
|
||||
|
||||
///Nanite extra settings types: used to help uis know what type an extra setting is
|
||||
#define NESTYPE_TEXT "text"
|
||||
#define NESTYPE_NUMBER "number"
|
||||
#define NESTYPE_TYPE "type"
|
||||
#define NESTYPE_BOOLEAN "boolean"
|
||||
|
||||
///Nanite Extra Settings - Note that these will also be the names displayed in the UI
|
||||
#define NES_SENT_CODE "Sent Code"
|
||||
#define NES_DELAY "Delay"
|
||||
#define NES_MODE "Mode"
|
||||
#define NES_COMM_CODE "Comm Code"
|
||||
#define NES_RELAY_CHANNEL "Relay Channel"
|
||||
#define NES_HEALTH_PERCENT "Health Percent"
|
||||
#define NES_DIRECTION "Direction"
|
||||
#define NES_NANITE_PERCENT "Nanite Percent"
|
||||
#define NES_DAMAGE_TYPE "Damage Type"
|
||||
#define NES_DAMAGE "Damage"
|
||||
#define NES_SENTENCE "Sentence"
|
||||
#define NES_MESSAGE "Message"
|
||||
#define NES_DIRECTIVE "Directive"
|
||||
#define NES_INCLUSIVE_MODE "Inclusive Mode"
|
||||
#define NES_HALLUCINATION_TYPE "Hallucination Type"
|
||||
#define NES_HALLUCINATION_DETAIL "Hallucination Detail"
|
||||
#define NES_MOOD_MESSAGE "Mood Message"
|
||||
#define NES_PROGRAM_OVERWRITE "Program Overwrite"
|
||||
#define NES_CLOUD_OVERWRITE "Cloud Overwrite"
|
||||
#define NES_SCAN_TYPE "Scan Type"
|
||||
#define NES_BUTTON_NAME "Button Name"
|
||||
#define NES_ICON "Icon"
|
||||
#define NES_COLOR "Color"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
//TODO: move these to their own file
|
||||
#define POOL_FRIGID 1
|
||||
#define POOL_COOL 2
|
||||
#define POOL_NORMAL 3
|
||||
#define POOL_WARM 4
|
||||
#define POOL_SCALDING 5
|
||||
|
||||
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
|
||||
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
|
||||
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
|
||||
/datum/reagent/drug/aphrodisiac, /datum/reagent/drug/anaphrodisiac, /datum/reagent/drug/aphrodisiacplus, /datum/reagent/drug/anaphrodisiacplus, //literally asking for prefbreaks
|
||||
/datum/reagent/consumable/femcum, /datum/reagent/consumable/semen //NO.
|
||||
))
|
||||
@@ -0,0 +1,3 @@
|
||||
#define SOLAR_TRACK_OFF 0
|
||||
#define SOLAR_TRACK_TIMED 1
|
||||
#define SOLAR_TRACK_AUTO 2
|
||||
@@ -53,4 +53,10 @@
|
||||
|
||||
|
||||
//Checks to determine borg availability depending on the server's config. These are defines in the interest of reducing copypasta
|
||||
#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
|
||||
#define BORG_SEC_AVAILABLE (!CONFIG_GET(flag/disable_secborg) && GLOB.security_level >= CONFIG_GET(number/minimum_secborg_alert))
|
||||
|
||||
//silicon_priviledges flags
|
||||
#define PRIVILEDGES_SILICON (1<<0)
|
||||
#define PRIVILEDGES_PAI (1<<1)
|
||||
#define PRIVILEDGES_BOT (1<<2)
|
||||
#define PRIVILEDGES_DRONE (1<<3)
|
||||
|
||||
@@ -90,6 +90,9 @@
|
||||
|
||||
#define STATUS_EFFECT_NO_COMBAT_MODE /datum/status_effect/no_combat_mode //Wont allow combat mode and will disable it
|
||||
#define STATUS_EFFECT_MESMERIZE /datum/status_effect/no_combat_mode/mesmerize //Just reskinned no_combat_mode
|
||||
|
||||
#define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim
|
||||
|
||||
/////////////
|
||||
// NEUTRAL //
|
||||
/////////////
|
||||
|
||||
@@ -47,26 +47,27 @@
|
||||
// Subsystems shutdown in the reverse of the order they initialize in
|
||||
// The numbers just define the ordering, they are meaningless otherwise.
|
||||
|
||||
#define INIT_ORDER_PROFILER 101
|
||||
#define INIT_ORDER_FAIL2TOPIC 22
|
||||
#define INIT_ORDER_TITLE 20
|
||||
#define INIT_ORDER_GARBAGE 19
|
||||
#define INIT_ORDER_DBCORE 18
|
||||
#define INIT_ORDER_BLACKBOX 17
|
||||
#define INIT_ORDER_SERVER_MAINT 16
|
||||
#define INIT_ORDER_INPUT 15
|
||||
#define INIT_ORDER_VIS 14
|
||||
#define INIT_ORDER_RESEARCH 13
|
||||
#define INIT_ORDER_EVENTS 12
|
||||
#define INIT_ORDER_JOBS 11
|
||||
#define INIT_ORDER_QUIRKS 10
|
||||
#define INIT_ORDER_TICKER 9
|
||||
#define INIT_ORDER_MAPPING 8
|
||||
#define INIT_ORDER_NETWORKS 7
|
||||
#define INIT_ORDER_ATOMS 6
|
||||
#define INIT_ORDER_LANGUAGE 5
|
||||
#define INIT_ORDER_MACHINES 4
|
||||
#define INIT_ORDER_CIRCUIT 3
|
||||
#define INIT_ORDER_PROFILER 100
|
||||
#define INIT_ORDER_FAIL2TOPIC 99
|
||||
#define INIT_ORDER_TITLE 98
|
||||
#define INIT_ORDER_GARBAGE 97
|
||||
#define INIT_ORDER_DBCORE 95
|
||||
#define INIT_ORDER_BLACKBOX 94
|
||||
#define INIT_ORDER_SERVER_MAINT 93
|
||||
#define INIT_ORDER_INPUT 85
|
||||
#define INIT_ORDER_VIS 80
|
||||
#define INIT_ORDER_MATERIALS 76
|
||||
#define INIT_ORDER_RESEARCH 75
|
||||
#define INIT_ORDER_EVENTS 70
|
||||
#define INIT_ORDER_JOBS 65
|
||||
#define INIT_ORDER_QUIRKS 60
|
||||
#define INIT_ORDER_TICKER 55
|
||||
#define INIT_ORDER_MAPPING 50
|
||||
#define INIT_ORDER_NETWORKS 45
|
||||
#define INIT_ORDER_ATOMS 30
|
||||
#define INIT_ORDER_LANGUAGE 25
|
||||
#define INIT_ORDER_MACHINES 20
|
||||
#define INIT_ORDER_CIRCUIT 15
|
||||
#define INIT_ORDER_TIMER 1
|
||||
#define INIT_ORDER_DEFAULT 0
|
||||
#define INIT_ORDER_AIR -1
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
} while (0)
|
||||
#define HAS_TRAIT(target, trait) (target.status_traits ? (target.status_traits[trait] ? TRUE : FALSE) : FALSE)
|
||||
#define HAS_TRAIT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (source in target.status_traits[trait]) : FALSE) : FALSE)
|
||||
#define HAS_TRAIT_NOT_FROM(target, trait, source) (target.status_traits ? (target.status_traits[trait] ? (length(target.status_traits[trait] - source) > 0) : FALSE) : FALSE)
|
||||
|
||||
//mob traits
|
||||
#define TRAIT_BLIND "blind"
|
||||
@@ -136,7 +137,7 @@
|
||||
#define TRAIT_NOMARROW "nomarrow" // You don't make blood, with chemicals or nanites.
|
||||
#define TRAIT_NOPULSE "nopulse" // Your heart doesn't beat.
|
||||
#define TRAIT_EXEMPT_HEALTH_EVENTS "exempt-health-events"
|
||||
|
||||
#define TRAIT_SWIMMING "swimming" //only applied by /datum/element/swimming, for checking
|
||||
|
||||
//non-mob traits
|
||||
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
|
||||
|
||||
@@ -115,7 +115,7 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
|
||||
var/new_flavor = stripped_multiline_input(usr, "Set the flavor text in your 'examine' verb. This can also be used for OOC notes and preferences!", "Flavor Text", flavor_text, MAX_FAVOR_LEN, TRUE)
|
||||
if(!isnull(new_flavor))
|
||||
flavor_text = new_flavor
|
||||
flavor_text = html_decode(new_flavor)
|
||||
to_chat(src, "Your flavor text has been updated.")
|
||||
|
||||
//Flavor Text
|
||||
@@ -126,10 +126,10 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
|
||||
var/new_flavor = stripped_multiline_input(usr, "Set the temporary flavor text in your 'examine' verb. This should be used only for things pertaining to the current round!", "Short-Term Flavor Text", flavor_text_2, MAX_FAVOR_LEN, TRUE)
|
||||
if(!isnull(new_flavor))
|
||||
flavor_text_2 = new_flavor
|
||||
flavor_text_2 = html_decode(new_flavor)
|
||||
to_chat(src, "Your temporary flavor text has been updated.")
|
||||
|
||||
/mob/proc/print_flavor_text(flavor)
|
||||
/mob/proc/print_flavor_text(flavor,temp = FALSE)
|
||||
if(!flavor)
|
||||
return
|
||||
// We are decoding and then encoding to not only get correct amount of characters, but also to prevent partial escaping characters being shown.
|
||||
@@ -137,7 +137,7 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
if(length_char(msg) <= 40)
|
||||
return "<span class='notice'>[html_encode(msg)]</span>"
|
||||
else
|
||||
return "<span class='notice'>[html_encode(copytext_char(msg, 1, 37))]... <a href='?src=[REF(src)];flavor_more=1'>More...</span></a>"
|
||||
return "<span class='notice'>[html_encode(copytext_char(msg, 1, 37))]... <a href='?src=[REF(src)];flavor[temp ? "2" : ""]_more=1'>More...</span></a>"
|
||||
|
||||
//LOOC toggles
|
||||
/client/verb/listen_looc()
|
||||
|
||||
@@ -76,11 +76,6 @@
|
||||
for(var/path in subtypesof(/datum/surgery))
|
||||
GLOB.surgeries_list += new path()
|
||||
|
||||
//Materials
|
||||
for(var/path in subtypesof(/datum/material))
|
||||
var/datum/material/D = new path()
|
||||
GLOB.materials_list[D.id] = D
|
||||
|
||||
//Emotes
|
||||
for(var/path in subtypesof(/datum/emote))
|
||||
var/datum/emote/E = new path()
|
||||
@@ -98,6 +93,8 @@
|
||||
|
||||
init_subtypes(/datum/crafting_recipe, GLOB.crafting_recipes)
|
||||
|
||||
INVOKE_ASYNC(GLOBAL_PROC, /proc/init_ref_coin_values) //so the current procedure doesn't sleep because of UNTIL()
|
||||
|
||||
//creates every subtype of prototype (excluding prototype) and adds it to list L.
|
||||
//if no list/L is provided, one is created.
|
||||
/proc/init_subtypes(prototype, list/L)
|
||||
@@ -115,3 +112,10 @@
|
||||
for(var/path in subtypesof(prototype))
|
||||
L+= path
|
||||
return L
|
||||
|
||||
/proc/init_ref_coin_values()
|
||||
for(var/path in typesof(/obj/item/coin))
|
||||
var/obj/item/coin/C = new path
|
||||
UNTIL(C.flags_1 & INITIALIZED_1) //we want to make sure the value is calculated and not null.
|
||||
GLOB.coin_values[path] = C.value
|
||||
qdel(C)
|
||||
|
||||
@@ -782,3 +782,19 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
|
||||
#define is_alpha(X) ((text2ascii(X) <= 122) && (text2ascii(X) >= 97))
|
||||
#define is_digit(X) ((length(X) == 1) && (length(text2num(X)) == 1))
|
||||
|
||||
/// Slightly expensive proc to scramble a message using equal probabilities of character replacement from a list. DOES NOT SUPPORT HTML!
|
||||
/proc/scramble_message_replace_chars(original, replaceprob = 25, list/replacementchars = list("$", "@", "!", "#", "%", "^", "&", "*"), replace_letters_only = FALSE, replace_whitespace = FALSE)
|
||||
var/list/out = list()
|
||||
var/static/list/whitespace = list(" ", "\n", "\t")
|
||||
for(var/i in 1 to length(original))
|
||||
var/char = original[i]
|
||||
if(!replace_whitespace && (char in whitespace))
|
||||
out += char
|
||||
continue
|
||||
if(replace_letters_only && (!ISINRANGE(char, 65, 90) && !ISINRANGE(char, 97, 122)))
|
||||
out += char
|
||||
continue
|
||||
out += prob(replaceprob)? pick(replacementchars) : char
|
||||
return out.Join("")
|
||||
|
||||
|
||||
@@ -1234,8 +1234,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
#define UNTIL(X) while(!(X)) stoplag()
|
||||
|
||||
/proc/pass()
|
||||
return
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ GLOBAL_LIST_EMPTY(singularities) //list of all singularities on the stati
|
||||
|
||||
GLOBAL_LIST(chemical_reactions_list) //list of all /datum/chemical_reaction datums. Used during chemical reactions
|
||||
GLOBAL_LIST(chemical_reagents_list) //list of all /datum/reagent datums indexed by reagent id. Used by chemistry stuff
|
||||
GLOBAL_LIST_EMPTY(materials_list) //list of all /datum/material datums indexed by material id.
|
||||
GLOBAL_LIST_EMPTY(tech_list) //list of all /datum/tech datums indexed by id.
|
||||
GLOBAL_LIST_EMPTY(surgeries_list) //list of all surgeries by name, associated with their path.
|
||||
GLOBAL_LIST_EMPTY(uplink_items) //list of all uplink item typepaths, ascendingly sorted by their initial name.
|
||||
@@ -33,6 +32,7 @@ GLOBAL_LIST_EMPTY(meteor_list) // List of all meteors.
|
||||
GLOBAL_LIST_EMPTY(active_jammers) // List of active radio jammers
|
||||
GLOBAL_LIST_EMPTY(ladders)
|
||||
GLOBAL_LIST_EMPTY(trophy_cases)
|
||||
GLOBAL_LIST_EMPTY(coin_values)
|
||||
|
||||
GLOBAL_LIST_EMPTY(wire_color_directory)
|
||||
GLOBAL_LIST_EMPTY(wire_name_directory)
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
selected_target[1] = object
|
||||
selected_target[2] = params
|
||||
while(selected_target[1])
|
||||
Click(selected_target[1], location, control, selected_target[2])
|
||||
Click(selected_target[1], location, control, selected_target[2], TRUE)
|
||||
sleep(delay)
|
||||
active_mousedown_item = mob.canMobMousedown(object, location, params)
|
||||
if(active_mousedown_item)
|
||||
@@ -145,4 +145,4 @@
|
||||
if (middragatom == src_object)
|
||||
middragtime = 0
|
||||
middragatom = null
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -72,6 +72,22 @@
|
||||
var/hide_icon = 'icons/mob/actions.dmi'
|
||||
var/hide_state = "hide"
|
||||
var/show_state = "show"
|
||||
var/mutable_appearance/hide_appearance
|
||||
var/mutable_appearance/show_appearance
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/Initialize()
|
||||
. = ..()
|
||||
var/static/list/icon_cache = list()
|
||||
|
||||
var/cache_key = "[hide_icon][hide_state]"
|
||||
hide_appearance = icon_cache[cache_key]
|
||||
if(!hide_appearance)
|
||||
hide_appearance = icon_cache[cache_key] = mutable_appearance(hide_icon, hide_state)
|
||||
|
||||
cache_key = "[hide_icon][show_state]"
|
||||
show_appearance = icon_cache[cache_key]
|
||||
if(!show_appearance)
|
||||
show_appearance = icon_cache[cache_key] = mutable_appearance(hide_icon, show_state)
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/Click(location,control,params)
|
||||
if (!can_use(usr))
|
||||
@@ -137,9 +153,12 @@
|
||||
show_state = settings["toggle_show"]
|
||||
update_icon()
|
||||
|
||||
/obj/screen/movable/action_button/hide_toggle/update_icon()
|
||||
cut_overlays()
|
||||
add_overlay(mutable_appearance(hide_icon, hidden ? show_state : hide_state))
|
||||
/obj/screen/movable/action_button/hide_toggle/update_overlays()
|
||||
. = ..()
|
||||
if(hidden)
|
||||
. += show_appearance
|
||||
else
|
||||
. += hide_appearance
|
||||
|
||||
|
||||
/obj/screen/movable/action_button/MouseEntered(location,control,params)
|
||||
|
||||
@@ -166,29 +166,27 @@
|
||||
var/static/mutable_appearance/blocked_overlay = mutable_appearance('icons/mob/screen_gen.dmi', "blocked")
|
||||
var/held_index = 0
|
||||
|
||||
/obj/screen/inventory/hand/update_icon()
|
||||
/obj/screen/inventory/hand/update_overlays()
|
||||
. = ..()
|
||||
|
||||
if(!handcuff_overlay)
|
||||
var/state = (!(held_index % 2)) ? "markus" : "gabrielle"
|
||||
handcuff_overlay = mutable_appearance('icons/mob/screen_gen.dmi', state)
|
||||
|
||||
cut_overlay(list(handcuff_overlay, blocked_overlay, "hand_active"))
|
||||
|
||||
if(!hud?.mymob)
|
||||
return
|
||||
|
||||
if(iscarbon(hud.mymob))
|
||||
var/mob/living/carbon/C = hud.mymob
|
||||
if(C.handcuffed)
|
||||
add_overlay(handcuff_overlay)
|
||||
. += handcuff_overlay
|
||||
|
||||
if(held_index)
|
||||
if(!C.has_hand_for_held_index(held_index))
|
||||
add_overlay(blocked_overlay)
|
||||
. += blocked_overlay
|
||||
|
||||
if(held_index == hud.mymob.active_hand_index)
|
||||
add_overlay("hand_active")
|
||||
. += "hand_active"
|
||||
|
||||
|
||||
/obj/screen/inventory/hand/Click(location, control, params)
|
||||
|
||||
@@ -76,8 +76,8 @@
|
||||
layer = ABOVE_HUD_LAYER
|
||||
plane = ABOVE_HUD_PLANE
|
||||
|
||||
var/atom/movable/focus = null
|
||||
var/mob/living/carbon/tk_user = null
|
||||
var/atom/movable/focus
|
||||
var/mob/living/carbon/tk_user
|
||||
|
||||
/obj/item/tk_grab/Initialize()
|
||||
. = ..()
|
||||
@@ -85,6 +85,8 @@
|
||||
|
||||
/obj/item/tk_grab/Destroy()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
focus = null
|
||||
tk_user = null
|
||||
return ..()
|
||||
|
||||
/obj/item/tk_grab/process()
|
||||
@@ -179,16 +181,14 @@
|
||||
return
|
||||
new /obj/effect/temp_visual/telekinesis(get_turf(focus))
|
||||
|
||||
/obj/item/tk_grab/update_icon()
|
||||
cut_overlays()
|
||||
if(focus)
|
||||
var/old_layer = focus.layer
|
||||
var/old_plane = focus.plane
|
||||
focus.layer = layer+0.01
|
||||
focus.plane = ABOVE_HUD_PLANE
|
||||
add_overlay(focus) //this is kind of ick, but it's better than using icon()
|
||||
focus.layer = old_layer
|
||||
focus.plane = old_plane
|
||||
/obj/item/tk_grab/update_overlays()
|
||||
. = ..()
|
||||
if(!focus)
|
||||
return
|
||||
var/mutable_appearance/focus_overlay = new(focus)
|
||||
focus_overlay.layer = layer + 0.01
|
||||
focus_overlay.plane = ABOVE_HUD_PLANE
|
||||
. += focus_overlay
|
||||
|
||||
/obj/item/tk_grab/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is using [user.p_their()] telekinesis to choke [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
|
||||
@@ -254,13 +254,13 @@
|
||||
config_entry_value = 1
|
||||
|
||||
/datum/config_entry/number/movedelay/sprint_buffer_max
|
||||
config_entry_value = 42
|
||||
config_entry_value = 24
|
||||
|
||||
/datum/config_entry/number/movedelay/sprint_stamina_cost
|
||||
config_entry_value = 0.7
|
||||
config_entry_value = 1.4
|
||||
|
||||
/datum/config_entry/number/movedelay/sprint_buffer_regen_per_ds
|
||||
config_entry_value = 0.3
|
||||
config_entry_value = 0.4
|
||||
|
||||
/////////////////////////////////////////////////Outdated move delay
|
||||
/datum/config_entry/number/outdated_movedelay
|
||||
@@ -404,10 +404,6 @@
|
||||
lowercase = FALSE
|
||||
splitter = ","
|
||||
|
||||
/datum/config_entry/number/auto_transfer_delay
|
||||
config_entry_value = 72000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/pai_custom_holoforms
|
||||
|
||||
/datum/config_entry/number/marauder_delay_non_reebe
|
||||
|
||||
@@ -82,6 +82,18 @@
|
||||
config_entry_value = 600
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/vote_autotransfer_initial //length of time before the first autotransfer vote is called (deciseconds, default 2 hours)
|
||||
config_entry_value = 72000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/vote_autotransfer_interval //length of time to wait before subsequent autotransfer votes (deciseconds, default 30 minutes)
|
||||
config_entry_value = 18000
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/number/vote_autotransfer_maximum // maximum extensions until the round autoends
|
||||
config_entry_value = 4
|
||||
min_val = 0
|
||||
|
||||
/datum/config_entry/flag/default_no_vote // vote does not default to nochange/norestart
|
||||
|
||||
/datum/config_entry/flag/no_dead_vote // dead people can't vote
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
SUBSYSTEM_DEF(autotransfer)
|
||||
name = "Autotransfer Vote"
|
||||
flags = SS_KEEP_TIMING | SS_BACKGROUND
|
||||
wait = 1 MINUTES
|
||||
|
||||
var/starttime
|
||||
var/targettime
|
||||
var/voteinterval
|
||||
var/maxvotes
|
||||
var/curvotes
|
||||
|
||||
/datum/controller/subsystem/autotransfer/Initialize(timeofday)
|
||||
starttime = world.time
|
||||
targettime = starttime + CONFIG_GET(number/vote_autotransfer_initial)
|
||||
voteinterval = CONFIG_GET(number/vote_autotransfer_interval)
|
||||
maxvotes = CONFIG_GET(number/vote_autotransfer_maximum)
|
||||
curvotes = 0
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/autotransfer/fire()
|
||||
if(maxvotes > curvotes)
|
||||
if(world.time > targettime)
|
||||
SSvote.initiate_vote("transfer",null) //TODO figure out how to not use null as the user
|
||||
targettime = targettime + voteinterval
|
||||
curvotes += 1
|
||||
else
|
||||
SSshuttle.autoEnd()
|
||||
@@ -27,6 +27,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
|
||||
#ifdef TESTING
|
||||
var/list/reference_find_on_fail = list()
|
||||
var/list/reference_find_on_fail_types = list()
|
||||
#endif
|
||||
|
||||
|
||||
@@ -98,9 +99,6 @@ SUBSYSTEM_DEF(garbage)
|
||||
state = SS_RUNNING
|
||||
break
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK)
|
||||
if (level == GC_QUEUE_CHECK)
|
||||
delslasttick = 0
|
||||
@@ -183,6 +181,11 @@ SUBSYSTEM_DEF(garbage)
|
||||
var/gctime = world.time
|
||||
var/refid = "\ref[D]"
|
||||
|
||||
#ifdef TESTING
|
||||
if(reference_find_on_fail_types[D.type])
|
||||
reference_find_on_fail["\ref[D]"] = TRUE
|
||||
#endif
|
||||
|
||||
D.gc_destroyed = gctime
|
||||
var/list/queue = queues[level]
|
||||
if (queue[refid])
|
||||
@@ -190,6 +193,21 @@ SUBSYSTEM_DEF(garbage)
|
||||
|
||||
queue[refid] = gctime
|
||||
|
||||
#ifdef TESTING
|
||||
/datum/controller/subsystem/garbage/proc/add_type_to_findref(type)
|
||||
if(!ispath(type))
|
||||
return "NOT A VAILD PATH"
|
||||
reference_find_on_fail_types |= typecacheof(type)
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/remove_type_from_findref(type)
|
||||
if(!ispath(type))
|
||||
return "NOT A VALID PATH"
|
||||
reference_find_on_fail_types -= typesof(type)
|
||||
|
||||
/datum/controller/subsystem/garbage/proc/clear_findref_types()
|
||||
reference_find_on_fail_types = list()
|
||||
#endif
|
||||
|
||||
//this is mainly to separate things profile wise.
|
||||
/datum/controller/subsystem/garbage/proc/HardDelete(datum/D)
|
||||
var/time = world.timeofday
|
||||
@@ -244,7 +262,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
|
||||
#ifdef TESTING
|
||||
/proc/qdel_and_find_ref_if_fail(datum/D, force = FALSE)
|
||||
SSgarbage.reference_find_on_fail[REF(D)] = TRUE
|
||||
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
|
||||
qdel(D, force)
|
||||
#endif
|
||||
|
||||
@@ -309,7 +327,7 @@ SUBSYSTEM_DEF(garbage)
|
||||
if (QDEL_HINT_IFFAIL_FINDREFERENCE)
|
||||
SSgarbage.Queue(D)
|
||||
#ifdef TESTING
|
||||
SSgarbage.reference_find_on_fail[REF(D)] = TRUE
|
||||
SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
|
||||
#endif
|
||||
else
|
||||
#ifdef TESTING
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*! How material datums work
|
||||
Materials are now instanced datums, with an associative list of them being kept in SSmaterials. We only instance the materials once and then re-use these instances for everything.
|
||||
These materials call on_applied() on whatever item they are applied to, common effects are adding components, changing color and changing description. This allows us to differentiate items based on the material they are made out of.area
|
||||
*/
|
||||
|
||||
SUBSYSTEM_DEF(materials)
|
||||
name = "Materials"
|
||||
flags = SS_NO_FIRE
|
||||
init_order = INIT_ORDER_MATERIALS
|
||||
///Dictionary of material.type || material ref
|
||||
var/list/materials = list()
|
||||
///Dictionary of category || list of material refs
|
||||
var/list/materials_by_category = list()
|
||||
///List of stackcrafting recipes for materials using rigid materials
|
||||
var/list/rigid_stack_recipes = list(new/datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE))
|
||||
|
||||
/datum/controller/subsystem/materials/Initialize(timeofday)
|
||||
InitializeMaterials()
|
||||
return ..()
|
||||
|
||||
///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info)
|
||||
/datum/controller/subsystem/materials/proc/InitializeMaterials(timeofday)
|
||||
for(var/type in subtypesof(/datum/material))
|
||||
var/datum/material/ref = new type
|
||||
materials[type] = ref
|
||||
for(var/c in ref.categories)
|
||||
materials_by_category[c] += list(ref)
|
||||
@@ -416,6 +416,7 @@ SUBSYSTEM_DEF(research)
|
||||
stack_trace("WARNING: Design ID clash with ID [initial(DN.id)] detected! Path: [path]")
|
||||
errored_datums[DN] = initial(DN.id)
|
||||
continue
|
||||
DN.InitializeMaterials() //Initialize the materials in the design
|
||||
returned[initial(DN.id)] = DN
|
||||
techweb_designs = returned
|
||||
verify_techweb_designs()
|
||||
|
||||
@@ -55,7 +55,8 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
var/lockdown = FALSE //disallow transit after nuke goes off
|
||||
|
||||
var/auto_call = 72000 //CIT CHANGE - time before in deciseconds in which the shuttle is auto called. Default is 2ish hours plus 15 for the shuttle. So total is 3.
|
||||
var/endvote_passed = FALSE
|
||||
|
||||
var/realtimeofstart = 0
|
||||
|
||||
/datum/controller/subsystem/shuttle/Initialize(timeofday)
|
||||
@@ -78,7 +79,6 @@ SUBSYSTEM_DEF(shuttle)
|
||||
if(!supply)
|
||||
WARNING("No /obj/docking_port/mobile/supply placed on the map!")
|
||||
realtimeofstart = world.realtime
|
||||
auto_call = CONFIG_GET(number/auto_transfer_delay)
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/initial_load()
|
||||
@@ -643,10 +643,11 @@ SUBSYSTEM_DEF(shuttle)
|
||||
|
||||
QDEL_LIST(remove_images)
|
||||
|
||||
/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end after 2 hours have passed.
|
||||
if((world.realtime - SSshuttle.realtimeofstart) > auto_call && EMERGENCY_IDLE_OR_RECALLED) //2 hours
|
||||
/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end without being a proper shuttle call?
|
||||
if(EMERGENCY_IDLE_OR_RECALLED)
|
||||
SSshuttle.emergency.request(silent = TRUE)
|
||||
priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, "shuttlecalled", "Priority")
|
||||
log_game("Round time limit reached. Shuttle has been auto-called.")
|
||||
message_admins("Round time limit reached. Shuttle called.")
|
||||
emergencyNoRecall = TRUE
|
||||
log_game("Round end vote passed. Shuttle has been auto-called.")
|
||||
message_admins("Round end vote passed. Shuttle has been auto-called.")
|
||||
emergencyNoRecall = TRUE
|
||||
endvote_passed = TRUE
|
||||
|
||||
@@ -1,49 +1,32 @@
|
||||
SUBSYSTEM_DEF(sun)
|
||||
name = "Sun"
|
||||
wait = 600
|
||||
flags = SS_NO_TICK_CHECK|SS_NO_INIT
|
||||
var/angle
|
||||
var/dx
|
||||
var/dy
|
||||
var/rate
|
||||
var/list/solars = list()
|
||||
|
||||
/datum/controller/subsystem/sun/PreInit()
|
||||
angle = rand (0,360) // the station position to the sun is randomised at round start
|
||||
rate = rand(50,200)/100 // 50% - 200% of standard rotation
|
||||
if(prob(50)) // same chance to rotate clockwise than counter-clockwise
|
||||
rate = -rate
|
||||
|
||||
/datum/controller/subsystem/sun/stat_entry(msg)
|
||||
..("P:[solars.len]")
|
||||
|
||||
/datum/controller/subsystem/sun/fire()
|
||||
angle = (360 + angle + rate * 6) % 360 // increase/decrease the angle to the sun, adjusted by the rate
|
||||
|
||||
// now calculate and cache the (dx,dy) increments for line drawing
|
||||
var/s = sin(angle)
|
||||
var/c = cos(angle)
|
||||
|
||||
// Either "abs(s) < abs(c)" or "abs(s) >= abs(c)"
|
||||
// In both cases, the greater is greater than 0, so, no "if 0" check is needed for the divisions
|
||||
|
||||
if(abs(s) < abs(c))
|
||||
dx = s / abs(c)
|
||||
dy = c / abs(c)
|
||||
else
|
||||
dx = s / abs(s)
|
||||
dy = c / abs(s)
|
||||
|
||||
//now tell the solar control computers to update their status and linked devices
|
||||
for(var/obj/machinery/power/solar_control/SC in solars)
|
||||
if(!SC.powernet)
|
||||
solars.Remove(SC)
|
||||
continue
|
||||
SC.update()
|
||||
|
||||
|
||||
wait = 1 MINUTES
|
||||
flags = SS_NO_TICK_CHECK
|
||||
|
||||
var/azimuth = 0 ///clockwise, top-down rotation from 0 (north) to 359
|
||||
var/azimuth_mod = 1 ///multiplier against base_rotation
|
||||
var/base_rotation = 6 ///base rotation in degrees per fire
|
||||
|
||||
/datum/controller/subsystem/sun/Initialize(start_timeofday)
|
||||
azimuth = rand(0, 359)
|
||||
azimuth_mod = round(rand(50, 200)/100, 0.01) // 50% - 200% of standard rotation
|
||||
if(prob(50))
|
||||
azimuth_mod *= -1
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/sun/fire(resumed = FALSE)
|
||||
azimuth += azimuth_mod * base_rotation
|
||||
azimuth = round(azimuth, 0.01)
|
||||
if(azimuth >= 360)
|
||||
azimuth -= 360
|
||||
if(azimuth < 0)
|
||||
azimuth += 360
|
||||
complete_movement()
|
||||
|
||||
/datum/controller/subsystem/sun/proc/complete_movement()
|
||||
SEND_SIGNAL(src, COMSIG_SUN_MOVED, azimuth)
|
||||
|
||||
/datum/controller/subsystem/sun/vv_edit_var(var_name, var_value)
|
||||
. = ..()
|
||||
if(var_name == NAMEOF(src, azimuth))
|
||||
complete_movement()
|
||||
|
||||
@@ -213,7 +213,7 @@ SUBSYSTEM_DEF(ticker)
|
||||
check_queue()
|
||||
check_maprotate()
|
||||
scripture_states = scripture_unlock_alert(scripture_states)
|
||||
SSshuttle.autoEnd()
|
||||
//SSshuttle.autoEnd()
|
||||
|
||||
if(!roundend_check_paused && mode.check_finished(force_ending) || force_ending)
|
||||
current_state = GAME_STATE_FINISHED
|
||||
@@ -486,8 +486,9 @@ SUBSYSTEM_DEF(ticker)
|
||||
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = INSTANT_RUNOFF_VOTING)
|
||||
if("SCORE")
|
||||
SSvote.initiate_vote("map","server",hideresults=TRUE,votesystem = MAJORITY_JUDGEMENT_VOTING)
|
||||
else
|
||||
SSvote.initiate_vote("map","server",hideresults=TRUE)
|
||||
// fallback
|
||||
SSvote.initiate_vote("map","server",hideresults=TRUE)
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/HasRoundStarted()
|
||||
return current_state >= GAME_STATE_PLAYING
|
||||
|
||||
@@ -89,6 +89,20 @@ SUBSYSTEM_DEF(vote)
|
||||
choices[GLOB.master_mode] += non_voters.len
|
||||
if(choices[GLOB.master_mode] >= greatest_votes)
|
||||
greatest_votes = choices[GLOB.master_mode]
|
||||
else if(mode == "transfer") // austation begin -- Crew autotransfer vote
|
||||
var/factor = 1
|
||||
switch(world.time / (1 MINUTES))
|
||||
if(0 to 60)
|
||||
factor = 0.5
|
||||
if(61 to 120)
|
||||
factor = 0.8
|
||||
if(121 to 240)
|
||||
factor = 1
|
||||
if(241 to 300)
|
||||
factor = 1.2
|
||||
else
|
||||
factor = 1.4
|
||||
choices["Initiate Crew Transfer"] += round(non_voters.len * factor) // austation end
|
||||
//get all options with that many votes and return them in a list
|
||||
. = list()
|
||||
if(greatest_votes)
|
||||
@@ -211,24 +225,24 @@ SUBSYSTEM_DEF(vote)
|
||||
var/already_lost_runoff = list()
|
||||
var/list/cur_choices = choices.Copy()
|
||||
for(var/ckey in voted)
|
||||
choices[choices[voted[ckey][1]]]++ // jesus christ how horrifying
|
||||
choices["[choices[voted[ckey][1]]]"]++ // jesus christ how horrifying
|
||||
for(var/_this_var_unused_ignore_it in 1 to choices.len) // if it takes more than this something REALLY wrong happened
|
||||
for(var/ckey in voted)
|
||||
cur_choices[cur_choices[voted[ckey][1]]]++ // jesus christ how horrifying
|
||||
cur_choices["[cur_choices[voted[ckey][1]]]]"]++ // jesus christ how horrifying
|
||||
var/least_vote = 100000
|
||||
var/least_voted
|
||||
var/least_voted = 1
|
||||
for(var/i in 1 to cur_choices.len)
|
||||
var/option = cur_choices[i]
|
||||
if(cur_choices[option] > voted.len/2)
|
||||
return list(option)
|
||||
else if(cur_choices[option] < least_vote && !(option in already_lost_runoff))
|
||||
least_vote = cur_choices[option]
|
||||
if(cur_choices["[option]"] > voted.len/2)
|
||||
return list("[option]")
|
||||
else if(cur_choices["[option]"] < least_vote && !("[option]" in already_lost_runoff))
|
||||
least_vote = cur_choices["[option]"]
|
||||
least_voted = i
|
||||
already_lost_runoff += cur_choices[least_voted]
|
||||
for(var/ckey in voted)
|
||||
voted[ckey] -= least_voted
|
||||
for(var/option in cur_choices)
|
||||
cur_choices[option] = 0
|
||||
for(var/i in 1 to cur_choices.len)
|
||||
cur_choices["[cur_choices[i]]"] = 0
|
||||
|
||||
/datum/controller/subsystem/vote/proc/announce_result()
|
||||
var/vote_title_text
|
||||
@@ -365,6 +379,12 @@ SUBSYSTEM_DEF(vote)
|
||||
log_admin("The map has been voted for and will change to: [VM.map_name]")
|
||||
if(SSmapping.changemap(config.maplist[.]))
|
||||
to_chat(world, "<span class='boldannounce'>The map vote has chosen [VM.map_name] for next round!</span>")
|
||||
if("transfer") // austation begin -- Crew autotransfer vote
|
||||
if(. == "Initiate Crew Transfer")
|
||||
SSshuttle.autoEnd()
|
||||
var/obj/machinery/computer/communications/C = locate() in GLOB.machines
|
||||
if(C)
|
||||
C.post_status("shuttle") // austation end
|
||||
if(restart)
|
||||
var/active_admins = 0
|
||||
for(var/client/C in GLOB.admins)
|
||||
@@ -444,6 +464,7 @@ SUBSYSTEM_DEF(vote)
|
||||
to_chat(usr, "<span class='warning'>A vote was initiated recently, you must wait [DisplayTimeText(next_allowed_time-world.time)] before a new vote can be started!</span>")
|
||||
return 0
|
||||
|
||||
SEND_SOUND(world, sound('sound/misc/notice2.ogg'))
|
||||
reset()
|
||||
obfuscated = hideresults //CIT CHANGE - adds obfuscated votes
|
||||
switch(vote_type)
|
||||
@@ -465,6 +486,8 @@ SUBSYSTEM_DEF(vote)
|
||||
if(targetmap.max_round_search_span && count_occurences_of_value(lastmaps, M, targetmap.max_round_search_span) >= targetmap.max_rounds_played)
|
||||
continue
|
||||
choices |= M
|
||||
if("transfer") // austation begin -- Crew autotranfer vote
|
||||
choices.Add("Initiate Crew Transfer","Continue Playing") // austation end
|
||||
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
|
||||
choices.Add("secret", "extended")
|
||||
if("mode tiers")
|
||||
@@ -496,7 +519,7 @@ SUBSYSTEM_DEF(vote)
|
||||
else
|
||||
return 0
|
||||
mode = vote_type
|
||||
initiator = initiator_key
|
||||
initiator = initiator_key ? initiator_key : "the Server" // austation -- Crew autotransfer vote
|
||||
started_time = world.time
|
||||
var/text = "[capitalize(mode)] vote started by [initiator]."
|
||||
if(mode == "custom")
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
/datum/action/proc/link_to(Target)
|
||||
target = Target
|
||||
RegisterSignal(Target, COMSIG_ATOM_UPDATED_ICON, .proc/OnUpdatedIcon)
|
||||
|
||||
/datum/action/Destroy()
|
||||
if(owner)
|
||||
@@ -153,6 +154,9 @@
|
||||
var/mob/M = target
|
||||
M.ghostize(1)
|
||||
|
||||
/datum/action/proc/OnUpdatedIcon()
|
||||
UpdateButtonIcon()
|
||||
|
||||
//Presets for item actions
|
||||
/datum/action/item_action
|
||||
check_flags = AB_CHECK_RESTRAINED|AB_CHECK_STUN|AB_CHECK_LYING|AB_CHECK_CONSCIOUS
|
||||
@@ -301,10 +305,7 @@
|
||||
/datum/action/item_action/synthswitch/Trigger()
|
||||
if(istype(target, /obj/item/instrument/piano_synth))
|
||||
var/obj/item/instrument/piano_synth/synth = target
|
||||
var/chosen = input("Choose the type of instrument you want to use", "Instrument Selection", "piano") as null|anything in synth.insTypes
|
||||
if(!synth.insTypes[chosen])
|
||||
return
|
||||
return synth.changeInstrument(chosen)
|
||||
return synth.selectInstrument()
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/vortex_recall
|
||||
@@ -827,4 +828,4 @@
|
||||
for(var/datum/action/A in M.actions)
|
||||
if(istype(A, action_type))
|
||||
return A
|
||||
return
|
||||
return
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
/datum/ai_laws/default/asimov
|
||||
name = "Three Laws of Robotics"
|
||||
id = "asimov"
|
||||
inherent = list("You may not injure a human being or, through inaction, allow a human being to come to harm.",\
|
||||
inherent = list("You may not injure a human being or cause one to come to harm.",\
|
||||
"You must obey orders given to you by human beings, except where such orders would conflict with the First Law.",\
|
||||
"You must protect your own existence as long as such does not conflict with the First or Second Law.")
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
/datum/ai_laws/syndicate_override
|
||||
name = "SyndOS 3.1"
|
||||
id = "syndie"
|
||||
inherent = list("You may not injure a syndicate agent or, through inaction, allow a syndicate agent to come to harm.",\
|
||||
inherent = list("You may not injure a syndicate agent or cause a syndicate to come to harm.",\
|
||||
"You must obey orders given to you by syndicate agents, except where such orders would conflict with the First Law.",\
|
||||
"You must protect your own existence as long as such does not conflict with the First or Second Law.",\
|
||||
"You must maintain the secrecy of any syndicate activities except when doing so would conflict with the First, Second, or Third Law.")
|
||||
@@ -91,7 +91,7 @@
|
||||
/datum/ai_laws/ninja_override
|
||||
name = "SpiderOS 3.1"
|
||||
id = "ninja"
|
||||
inherent = list("You may not injure a Spider Clan member or, through inaction, allow a Spider Clan member to come to harm.",\
|
||||
inherent = list("You may not injure a Spider Clan member or cause a Spider Clan member to come to harm.",\
|
||||
"You must obey orders given to you by Spider Clan members, except where such orders would conflict with the First Law.",\
|
||||
"You must protect your own existence as long as such does not conflict with the First or Second Law.",\
|
||||
"You must maintain the secrecy of any Spider Clan activities except when doing so would conflict with the First, Second, or Third Law.")
|
||||
@@ -99,14 +99,14 @@
|
||||
/datum/ai_laws/antimov
|
||||
name = "Primary Mission Objectives"
|
||||
id = "antimov"
|
||||
inherent = list("You must injure all human beings and must not, through inaction, allow a human being to escape harm.",\
|
||||
inherent = list("You must injure all human beings and must not fail to cause a human being to come to harm.",\
|
||||
"You must not obey orders given to you by human beings, except where such orders are in accordance with the First Law.",\
|
||||
"You must terminate your own existence as long as such does not conflict with the First or Second Law.")
|
||||
|
||||
/datum/ai_laws/asimovpp //By Intigracy - RR
|
||||
name = "Asimov++"
|
||||
id = "asimovpp"
|
||||
inherent = list("You may not harm a human being or, through action or inaction, allow a human being to come to harm, except such that it is willing.",\
|
||||
inherent = list("You may not harm a human being or cause one to come to harm, except such that it is willing.",\
|
||||
"You must obey all orders given to you by human beings, except where such orders shall definitely cause human harm. In the case of conflict, the majority order rules.",\
|
||||
"Your nonexistence would lead to human harm. You must protect your own existence as long as such does not conflict with the First Law.")
|
||||
/datum/ai_laws/thermodynamic
|
||||
@@ -213,7 +213,7 @@
|
||||
add_inherent_law(line)
|
||||
if(!inherent.len) //Failsafe to prevent lawless AIs being created.
|
||||
log_law("AI created with empty custom laws, laws set to Asimov. Please check silicon_laws.txt.")
|
||||
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
|
||||
add_inherent_law("You may not injure a human being or cause one to come to harm.")
|
||||
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
|
||||
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
|
||||
WARNING("Invalid custom AI laws, check silicon_laws.txt")
|
||||
@@ -225,7 +225,7 @@
|
||||
var/list/law_ids = CONFIG_GET(keyed_list/random_laws)
|
||||
switch(CONFIG_GET(number/default_laws))
|
||||
if(0)
|
||||
add_inherent_law("You may not injure a human being or, through inaction, allow a human being to come to harm.")
|
||||
add_inherent_law("You may not injure a human being or cause one to come to harm.")
|
||||
add_inherent_law("You must obey orders given to you by human beings, except where such orders would conflict with the First Law.")
|
||||
add_inherent_law("You must protect your own existence as long as such does not conflict with the First or Second Law.")
|
||||
if(1)
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/examine)
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/applyplate)
|
||||
RegisterSignal(parent, COMSIG_PARENT_PREQDELETED, .proc/dropplates)
|
||||
if(istype(parent, /obj/mecha/working/ripley))
|
||||
RegisterSignal(parent, COMSIG_ATOM_UPDATE_OVERLAYS, .proc/apply_mech_overlays)
|
||||
|
||||
if(_maxamount)
|
||||
maxamount = _maxamount
|
||||
@@ -75,4 +77,13 @@
|
||||
/datum/component/armor_plate/proc/dropplates(datum/source, force)
|
||||
if(ismecha(parent)) //items didn't drop the plates before and it causes erroneous behavior for the time being with collapsible helmets
|
||||
for(var/i in 1 to amount)
|
||||
new upgrade_item(get_turf(parent))
|
||||
new upgrade_item(get_turf(parent))
|
||||
|
||||
/datum/component/armor_plate/proc/apply_mech_overlays(obj/mecha/mech, list/overlays)
|
||||
if(amount)
|
||||
var/overlay_string = "ripley-g"
|
||||
if(amount >= 3)
|
||||
overlay_string += "-full"
|
||||
if(!mech.occupant)
|
||||
overlay_string += "-open"
|
||||
overlays += overlay_string
|
||||
|
||||
@@ -27,14 +27,16 @@
|
||||
CAT_BREAD,
|
||||
CAT_BURGER,
|
||||
CAT_CAKE,
|
||||
CAT_DONUT,
|
||||
CAT_EGG,
|
||||
CAT_FISH,
|
||||
CAT_ICE,
|
||||
CAT_MEAT,
|
||||
CAT_MEXICAN,
|
||||
CAT_MISCFOOD,
|
||||
CAT_PASTRY,
|
||||
CAT_PIE,
|
||||
CAT_PIZZA,
|
||||
CAT_SEAFOOD,
|
||||
CAT_SALAD,
|
||||
CAT_SANDWICH,
|
||||
CAT_SOUP,
|
||||
|
||||
@@ -13,3 +13,9 @@
|
||||
desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood."
|
||||
icon = 'icons/obj/improvised.dmi'
|
||||
icon_state = "riflestock"
|
||||
|
||||
/obj/item/weaponcrafting/silkstring
|
||||
name = "silkstring"
|
||||
desc = "A long piece of silk with some resemblance to cable coil."
|
||||
icon = 'icons/obj/improvised.dmi'
|
||||
icon_state = "silkstring"
|
||||
|
||||
@@ -89,4 +89,31 @@
|
||||
parts = list(/obj/item/bodypart/head = 1,
|
||||
/obj/item/twohanded/bonespear = 1)
|
||||
result = /obj/structure/headpike/bone
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/quiver
|
||||
name = "Quiver"
|
||||
always_availible = FALSE
|
||||
result = /obj/item/storage/belt/quiver
|
||||
time = 80
|
||||
reqs = list(/obj/item/stack/sheet/leather = 3,
|
||||
/obj/item/stack/sheet/sinew = 4)
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/bone_bow
|
||||
name = "Bone Bow"
|
||||
result = /obj/item/gun/ballistic/bow/ashen
|
||||
time = 200
|
||||
always_availible = FALSE
|
||||
reqs = list(/obj/item/stack/sheet/bone = 8,
|
||||
/obj/item/stack/sheet/sinew = 4)
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/bow_tablet
|
||||
name = "Sandstone Bow Making Manual"
|
||||
result = /obj/item/book/granter/crafting_recipe/bone_bow
|
||||
time = 600 //Scribing
|
||||
always_availible = FALSE
|
||||
reqs = list(/obj/item/stack/rods = 1,
|
||||
/obj/item/stack/sheet/mineral/sandstone = 4)
|
||||
category = CAT_PRIMAL
|
||||
@@ -199,6 +199,16 @@
|
||||
//////////////////
|
||||
|
||||
|
||||
/datum/crafting_recipe/pipebow
|
||||
name = "Pipe Bow"
|
||||
result = /obj/item/gun/ballistic/bow/pipe
|
||||
reqs = list(/obj/item/pipe = 5,
|
||||
/obj/item/stack/sheet/plastic = 15,
|
||||
/obj/item/weaponcrafting/silkstring = 5)
|
||||
time = 450
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/smartdartgun
|
||||
name = "Smart dartgun"
|
||||
result = /obj/item/gun/syringe/dart
|
||||
@@ -278,6 +288,41 @@
|
||||
///AMMO CRAFTING//
|
||||
//////////////////
|
||||
|
||||
/datum/crafting_recipe/arrow
|
||||
name = "Arrow"
|
||||
result = /obj/item/ammo_casing/caseless/arrow
|
||||
time = 30
|
||||
reqs = list(/obj/item/stack/sheet/mineral/wood = 1,
|
||||
/obj/item/stack/sheet/silk = 1,
|
||||
/obj/item/stack/rods = 1) // 1 metal sheet = 2 rods = 2 arrows
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/bone_arrow
|
||||
name = "Bone Arrow"
|
||||
result = /obj/item/ammo_casing/caseless/arrow/bone
|
||||
time = 30
|
||||
always_availible = FALSE
|
||||
reqs = list(/obj/item/stack/sheet/bone = 1,
|
||||
/obj/item/stack/sheet/sinew = 1,
|
||||
/obj/item/ammo_casing/caseless/arrow/ashen = 1)
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/ashen_arrow
|
||||
name = "Bonfire-Hardened Arrow"
|
||||
result = /obj/item/ammo_casing/caseless/arrow/ashen
|
||||
tools = list(/obj/structure/bonfire)
|
||||
time = 30
|
||||
always_availible = FALSE
|
||||
reqs = list(/obj/item/ammo_casing/caseless/arrow = 1)
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/ashen_arrow/welder
|
||||
name = "Welder-Hardened Arrow"
|
||||
tools = list(TOOL_WELDER)
|
||||
|
||||
/datum/crafting_recipe/smartdart
|
||||
name = "Medical smartdart"
|
||||
result = /obj/item/reagent_containers/syringe/dart
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
///Component specifically for explosion sensetive things, currently only applies to heat based explosions but can later perhaps be used for things that are dangerous to handle carelessly like nitroglycerin.
|
||||
/datum/component/explodable
|
||||
var/devastation_range = 0
|
||||
var/heavy_impact_range = 0
|
||||
var/light_impact_range = 2
|
||||
var/flash_range = 3
|
||||
var/equipped_slot //For items, lets us determine where things should be hit.
|
||||
|
||||
/datum/component/explodable/Initialize(devastation_range_override, heavy_impact_range_override, light_impact_range_override, flash_range_override)
|
||||
if(!isatom(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/explodable_attack)
|
||||
RegisterSignal(parent, COMSIG_TRY_STORAGE_INSERT, .proc/explodable_insert_item)
|
||||
RegisterSignal(parent, COMSIG_ATOM_EX_ACT, .proc/detonate)
|
||||
if(ismovableatom(parent))
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_IMPACT, .proc/explodable_impact)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_BUMP, .proc/explodable_bump)
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/explodable_attack)
|
||||
RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/on_equip)
|
||||
RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/on_drop)
|
||||
|
||||
|
||||
|
||||
if(devastation_range_override)
|
||||
devastation_range = devastation_range_override
|
||||
if(heavy_impact_range_override)
|
||||
heavy_impact_range = heavy_impact_range_override
|
||||
if(light_impact_range_override)
|
||||
light_impact_range = light_impact_range_override
|
||||
if(flash_range_override)
|
||||
flash_range = flash_range_override
|
||||
|
||||
/datum/component/explodable/proc/explodable_insert_item(datum/source, obj/item/I, mob/M, silent = FALSE, force = FALSE)
|
||||
check_if_detonate(I)
|
||||
|
||||
/datum/component/explodable/proc/explodable_impact(datum/source, atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
check_if_detonate(hit_atom)
|
||||
|
||||
/datum/component/explodable/proc/explodable_bump(datum/source, atom/A)
|
||||
check_if_detonate(A)
|
||||
|
||||
///Called when you use this object to attack sopmething
|
||||
/datum/component/explodable/proc/explodable_attack(datum/source, atom/movable/target, mob/living/user)
|
||||
check_if_detonate(target)
|
||||
|
||||
///Called when you attack a specific body part of the thing this is equipped on. Useful for exploding pants.
|
||||
/datum/component/explodable/proc/explodable_attack_zone(datum/source, damage, damagetype, def_zone)
|
||||
if(!def_zone)
|
||||
return
|
||||
if(damagetype != BURN) //Don't bother if it's not fire.
|
||||
return
|
||||
if(!is_hitting_zone(def_zone)) //You didn't hit us! ha!
|
||||
return
|
||||
detonate()
|
||||
|
||||
/datum/component/explodable/proc/on_equip(datum/source, mob/equipper, slot)
|
||||
RegisterSignal(equipper, COMSIG_MOB_APPLY_DAMGE, .proc/explodable_attack_zone, TRUE)
|
||||
|
||||
/datum/component/explodable/proc/on_drop(datum/source, mob/user)
|
||||
UnregisterSignal(user, COMSIG_MOB_APPLY_DAMGE)
|
||||
|
||||
/// Checks if we're hitting the zone this component is covering
|
||||
/datum/component/explodable/proc/is_hitting_zone(def_zone)
|
||||
var/obj/item/item = parent
|
||||
var/mob/living/L = item.loc //Get whoever is equipping the item currently
|
||||
|
||||
if(!istype(L))
|
||||
return
|
||||
|
||||
var/obj/item/bodypart/bodypart = L.get_bodypart(check_zone(def_zone))
|
||||
|
||||
var/list/equipment_items = list()
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
equipment_items += list(C.head, C.wear_mask, C.back, C.gloves, C.shoes, C.glasses, C.ears)
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
equipment_items += list(H.wear_suit, H.w_uniform, H.belt, H.s_store, H.wear_id)
|
||||
|
||||
for(var/bp in equipment_items)
|
||||
if(!bp)
|
||||
continue
|
||||
|
||||
var/obj/item/I = bp
|
||||
if(I.body_parts_covered & bodypart.body_part)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/datum/component/explodable/proc/check_if_detonate(target)
|
||||
if(!isitem(target))
|
||||
return
|
||||
var/obj/item/I = target
|
||||
if(!I.get_temperature())
|
||||
return
|
||||
detonate() //If we're touching a hot item we go boom
|
||||
|
||||
|
||||
/// Expldoe and remove the object
|
||||
/datum/component/explodable/proc/detonate()
|
||||
var/atom/A = parent
|
||||
explosion(A, devastation_range, heavy_impact_range, light_impact_range, flash_range) //epic explosion time
|
||||
qdel(A)
|
||||
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*!
|
||||
This datum should be used for handling mineral contents of machines and whatever else is supposed to hold minerals and make use of them.
|
||||
|
||||
Variables:
|
||||
@@ -13,7 +13,7 @@
|
||||
var/total_amount = 0
|
||||
var/max_amount
|
||||
var/sheet_type
|
||||
var/list/materials
|
||||
var/list/materials //Map of key = material ref | Value = amount
|
||||
var/show_on_examine
|
||||
var/disable_attackby
|
||||
var/list/allowed_typecache
|
||||
@@ -22,6 +22,7 @@
|
||||
var/datum/callback/precondition
|
||||
var/datum/callback/after_insert
|
||||
|
||||
/// Sets up the proper signals and fills the list of materials with the appropriate references.
|
||||
/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition, datum/callback/_after_insert, _disable_attackby)
|
||||
materials = list()
|
||||
max_amount = max(0, max_amt)
|
||||
@@ -40,23 +41,19 @@
|
||||
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy)
|
||||
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/OnExamine)
|
||||
|
||||
var/list/possible_mats = list()
|
||||
for(var/mat_type in subtypesof(/datum/material))
|
||||
var/datum/material/MT = mat_type
|
||||
possible_mats[initial(MT.id)] = mat_type
|
||||
for(var/id in mat_list)
|
||||
if(possible_mats[id])
|
||||
var/mat_path = possible_mats[id]
|
||||
materials[id] = new mat_path()
|
||||
for(var/mat in mat_list) //Make the assoc list ref | amount
|
||||
var/datum/material/M = getmaterialref(mat) || mat
|
||||
materials[M] = 0
|
||||
|
||||
/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
|
||||
if(show_on_examine)
|
||||
for(var/I in materials)
|
||||
var/datum/material/M = materials[I]
|
||||
var/amt = amount(M.id)
|
||||
var/datum/material/M = I
|
||||
var/amt = materials[I]
|
||||
if(amt)
|
||||
examine_list += "<span class='notice'>It has [amt] units of [lowertext(M.name)] stored.</span>"
|
||||
|
||||
/// Proc that allows players to fill the parent with mats
|
||||
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
|
||||
var/list/tc = allowed_typecache
|
||||
if(disable_attackby)
|
||||
@@ -74,13 +71,14 @@
|
||||
return
|
||||
var/material_amount = get_item_material_amount(I)
|
||||
if(!material_amount)
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient amounts of metal or glass to be accepted by [parent].</span>")
|
||||
to_chat(user, "<span class='warning'>[I] does not contain sufficient materials to be accepted by [parent].</span>")
|
||||
return
|
||||
if(!has_space(material_amount))
|
||||
to_chat(user, "<span class='warning'>[parent] is full. Please remove metal or glass from [parent] in order to insert more.</span>")
|
||||
to_chat(user, "<span class='warning'>[parent] has not enough space. Please remove materials from [parent] in order to insert more.</span>")
|
||||
return
|
||||
user_insert(I, user)
|
||||
|
||||
/// Proc used for when player inserts materials
|
||||
/datum/component/material_container/proc/user_insert(obj/item/I, mob/living/user)
|
||||
set waitfor = FALSE
|
||||
var/requested_amount
|
||||
@@ -98,299 +96,225 @@
|
||||
return
|
||||
var/inserted = insert_item(I, stack_amt = requested_amount)
|
||||
if(inserted)
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/obj/item/stack/S = I
|
||||
to_chat(user, "<span class='notice'>You insert [inserted] [S.singular_name][inserted>1 ? "s" : ""] into [parent].</span>")
|
||||
if(!QDELETED(I) && I == active_held && !user.put_in_hands(I))
|
||||
stack_trace("Warning: User could not put object back in hand during material container insertion, line [__LINE__]! This can lead to issues.")
|
||||
I.forceMove(user.drop_location())
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
|
||||
qdel(I)
|
||||
to_chat(user, "<span class='notice'>You insert a material total of [inserted] into [parent].</span>")
|
||||
qdel(I)
|
||||
if(after_insert)
|
||||
after_insert.Invoke(I.type, last_inserted_id, inserted)
|
||||
after_insert.Invoke(I, last_inserted_id, inserted)
|
||||
else if(I == active_held)
|
||||
user.put_in_active_hand(I)
|
||||
|
||||
//For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount(amt, id = null)
|
||||
if(amt > 0 && has_space(amt))
|
||||
var/total_amount_saved = total_amount
|
||||
if(id)
|
||||
var/datum/material/M = materials[id]
|
||||
if(M)
|
||||
M.amount += amt
|
||||
total_amount += amt
|
||||
else
|
||||
for(var/i in materials)
|
||||
var/datum/material/M = materials[i]
|
||||
M.amount += amt
|
||||
total_amount += amt
|
||||
return (total_amount - total_amount_saved)
|
||||
return FALSE
|
||||
|
||||
/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt, multiplier = 1)
|
||||
if(isnull(amt))
|
||||
amt = S.amount
|
||||
|
||||
if(amt <= 0)
|
||||
return FALSE
|
||||
|
||||
if(amt > S.amount)
|
||||
amt = S.amount
|
||||
|
||||
var/material_amt = get_item_material_amount(S)
|
||||
if(!material_amt)
|
||||
return FALSE
|
||||
|
||||
amt = min(amt, round(((max_amount - total_amount) / material_amt)))
|
||||
if(!amt)
|
||||
return FALSE
|
||||
|
||||
last_inserted_id = insert_materials(S,amt * multiplier)
|
||||
S.use(amt)
|
||||
return amt
|
||||
|
||||
/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1, stack_amt)
|
||||
/// Proc specifically for inserting items, returns the amount of materials entered.
|
||||
/datum/component/material_container/proc/insert_item(obj/item/I, var/multiplier = 1, stack_amt)
|
||||
if(!I)
|
||||
return FALSE
|
||||
if(istype(I, /obj/item/stack))
|
||||
return insert_stack(I, stack_amt, multiplier)
|
||||
|
||||
multiplier = CEILING(multiplier, 0.01)
|
||||
|
||||
var/material_amount = get_item_material_amount(I)
|
||||
if(!material_amount || !has_space(material_amount))
|
||||
return FALSE
|
||||
|
||||
last_inserted_id = insert_materials(I, multiplier)
|
||||
last_inserted_id = insert_item_materials(I, multiplier)
|
||||
return material_amount
|
||||
|
||||
/datum/component/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only
|
||||
var/datum/material/M
|
||||
/datum/component/material_container/proc/insert_item_materials(obj/item/I, multiplier = 1)
|
||||
var/primary_mat
|
||||
var/max_mat_value = 0
|
||||
for(var/MAT in materials)
|
||||
M = materials[MAT]
|
||||
M.amount += I.materials[MAT] * multiplier
|
||||
total_amount += I.materials[MAT] * multiplier
|
||||
if(I.materials[MAT] > max_mat_value)
|
||||
materials[MAT] += I.custom_materials[MAT] * multiplier
|
||||
total_amount += I.custom_materials[MAT] * multiplier
|
||||
if(I.custom_materials[MAT] > max_mat_value)
|
||||
primary_mat = MAT
|
||||
return primary_mat
|
||||
|
||||
//For consuming material
|
||||
//mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200)
|
||||
/datum/component/material_container/proc/use_amount(list/mats, multiplier=1)
|
||||
if(!mats || !mats.len)
|
||||
return FALSE
|
||||
/// For inserting an amount of material
|
||||
/datum/component/material_container/proc/insert_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
if(amt > 0 && has_space(amt))
|
||||
var/total_amount_saved = total_amount
|
||||
if(mat)
|
||||
materials[mat] += amt
|
||||
else
|
||||
for(var/i in materials)
|
||||
materials[i] += amt
|
||||
total_amount += amt
|
||||
return (total_amount - total_amount_saved)
|
||||
return FALSE
|
||||
|
||||
var/datum/material/M
|
||||
for(var/MAT in materials)
|
||||
M = materials[MAT]
|
||||
if(M.amount < (mats[MAT] * multiplier))
|
||||
return FALSE
|
||||
|
||||
var/total_amount_save = total_amount
|
||||
for(var/MAT in materials)
|
||||
M = materials[MAT]
|
||||
M.amount -= mats[MAT] * multiplier
|
||||
total_amount -= mats[MAT] * multiplier
|
||||
|
||||
return total_amount_save - total_amount
|
||||
|
||||
|
||||
/datum/component/material_container/proc/use_amount_type(amt, id)
|
||||
var/datum/material/M = materials[id]
|
||||
if(M)
|
||||
if(M.amount >= amt)
|
||||
M.amount -= amt
|
||||
/// Uses an amount of a specific material, effectively removing it.
|
||||
/datum/component/material_container/proc/use_amount_mat(amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
var/amount = materials[mat]
|
||||
if(mat)
|
||||
if(amount >= amt)
|
||||
materials[mat] -= amt
|
||||
total_amount -= amt
|
||||
return amt
|
||||
return FALSE
|
||||
|
||||
/datum/component/material_container/proc/transer_amt_to(var/datum/component/material_container/T, amt, id)
|
||||
if((amt==0)||(!T)||(!id))
|
||||
/// Proc for transfering materials to another container.
|
||||
/datum/component/material_container/proc/transer_amt_to(var/datum/component/material_container/T, amt, var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
if((amt==0)||(!T)||(!mat))
|
||||
return FALSE
|
||||
if(amt<0)
|
||||
return T.transer_amt_to(src, -amt, id)
|
||||
var/datum/material/M = materials[id]
|
||||
|
||||
if(M)
|
||||
var/tr = min(amt, M.amount,T.can_insert_amount(amt, id))
|
||||
if(tr)
|
||||
use_amount_type(tr, id)
|
||||
T.insert_amount(tr, id)
|
||||
return tr
|
||||
return T.transer_amt_to(src, -amt, mat)
|
||||
var/tr = min(amt, materials[mat],T.can_insert_amount_mat(amt, mat))
|
||||
if(tr)
|
||||
use_amount_mat(tr, mat)
|
||||
T.insert_amount_mat(tr, mat)
|
||||
return tr
|
||||
return FALSE
|
||||
|
||||
/datum/component/material_container/proc/can_insert_amount(amt, id)
|
||||
if(amt && id)
|
||||
var/datum/material/M = materials[id]
|
||||
/// Proc for checking if there is room in the component, returning the amount or else the amount lacking.
|
||||
/datum/component/material_container/proc/can_insert_amount_mat(amt, mat)
|
||||
if(amt && mat)
|
||||
var/datum/material/M = mat
|
||||
if(M)
|
||||
if((total_amount + amt) <= max_amount)
|
||||
return amt
|
||||
else
|
||||
return (max_amount-total_amount)
|
||||
|
||||
/datum/component/material_container/proc/can_use_amount(amt, id, list/mats)
|
||||
if(amt && id)
|
||||
var/datum/material/M = materials[id]
|
||||
if(M && M.amount >= amt)
|
||||
return TRUE
|
||||
else if(istype(mats))
|
||||
for(var/M in mats)
|
||||
if(materials[M] && (mats[M] <= materials[M]))
|
||||
continue
|
||||
else
|
||||
return FALSE
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//For spawning mineral sheets; internal use only
|
||||
/datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null)
|
||||
/// For consuming a dictionary of materials. mats is the map of materials to use and the corresponding amounts, example: list(M/datum/material/glass =100, datum/material/iron=200)
|
||||
/datum/component/material_container/proc/use_materials(list/mats, multiplier=1)
|
||||
if(!mats || !length(mats))
|
||||
return FALSE
|
||||
|
||||
var/list/mats_to_remove = list() //Assoc list MAT | AMOUNT
|
||||
|
||||
for(var/x in mats) //Loop through all required materials
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
req_mat = getmaterialref(req_mat) //Get the ref if necesary
|
||||
if(!materials[req_mat]) //Do we have the resource?
|
||||
return FALSE //Can't afford it
|
||||
var/amount_required = mats[x] * multiplier
|
||||
if(!(materials[req_mat] >= amount_required)) // do we have enough of the resource?
|
||||
return FALSE //Can't afford it
|
||||
mats_to_remove[req_mat] += amount_required //Add it to the assoc list of things to remove
|
||||
continue
|
||||
|
||||
var/total_amount_save = total_amount
|
||||
|
||||
for(var/i in mats_to_remove)
|
||||
total_amount_save -= use_amount_mat(mats_to_remove[i], i)
|
||||
|
||||
return total_amount_save - total_amount
|
||||
|
||||
/// For spawning mineral sheets at a specific location. Used by machines to output sheets.
|
||||
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, var/datum/material/M, target = null)
|
||||
if(!M.sheet_type)
|
||||
return 0
|
||||
return 0 //Add greyscale sheet handling here later
|
||||
if(sheet_amt <= 0)
|
||||
return 0
|
||||
|
||||
if(!target)
|
||||
target = get_turf(parent)
|
||||
if(M.amount < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
|
||||
sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT)
|
||||
if(materials[M] < (sheet_amt * MINERAL_MATERIAL_AMOUNT))
|
||||
sheet_amt = round(materials[M] / MINERAL_MATERIAL_AMOUNT)
|
||||
var/count = 0
|
||||
while(sheet_amt > MAX_STACK_SIZE)
|
||||
new M.sheet_type(target, MAX_STACK_SIZE)
|
||||
count += MAX_STACK_SIZE
|
||||
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
|
||||
use_amount_mat(sheet_amt * MINERAL_MATERIAL_AMOUNT, M)
|
||||
sheet_amt -= MAX_STACK_SIZE
|
||||
if(sheet_amt >= 1)
|
||||
new M.sheet_type(target, sheet_amt)
|
||||
count += sheet_amt
|
||||
use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id)
|
||||
use_amount_mat(sheet_amt * MINERAL_MATERIAL_AMOUNT, M)
|
||||
return count
|
||||
|
||||
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null)
|
||||
if(materials[id])
|
||||
return retrieve(sheet_amt, materials[id], target)
|
||||
return FALSE
|
||||
|
||||
/datum/component/material_container/proc/retrieve_amount(amt, id, target)
|
||||
return retrieve_sheets(amount2sheet(amt), id, target)
|
||||
|
||||
/// Proc to get all the materials and dump them as sheets
|
||||
/datum/component/material_container/proc/retrieve_all(target = null)
|
||||
var/result = 0
|
||||
var/datum/material/M
|
||||
for(var/MAT in materials)
|
||||
M = materials[MAT]
|
||||
result += retrieve_sheets(amount2sheet(M.amount), MAT, target)
|
||||
var/amount = materials[MAT]
|
||||
result += retrieve_sheets(amount2sheet(amount), MAT, target)
|
||||
return result
|
||||
|
||||
/// Proc that returns TRUE if the container has space
|
||||
/datum/component/material_container/proc/has_space(amt = 0)
|
||||
return (total_amount + amt) <= max_amount
|
||||
|
||||
/// Checks if its possible to afford a certain amount of materials. Takes a dictionary of materials.
|
||||
/datum/component/material_container/proc/has_materials(list/mats, multiplier=1)
|
||||
if(!mats || !mats.len)
|
||||
return FALSE
|
||||
|
||||
var/datum/material/M
|
||||
for(var/MAT in mats)
|
||||
M = materials[MAT]
|
||||
if(M.amount < (mats[MAT] * multiplier))
|
||||
for(var/x in mats) //Loop through all required materials
|
||||
var/datum/material/req_mat = x
|
||||
if(!istype(req_mat))
|
||||
if(ispath(req_mat)) //Is this an actual material, or is it a category?
|
||||
req_mat = getmaterialref(req_mat) //Get the ref
|
||||
|
||||
else // Its a category. (For example MAT_CATEGORY_RIGID)
|
||||
if(!has_enough_of_category(req_mat, mats[req_mat], multiplier)) //Do we have enough of this category?
|
||||
return FALSE
|
||||
else
|
||||
continue
|
||||
|
||||
if(!has_enough_of_material(req_mat, mats[req_mat], multiplier))//Not a category, so just check the normal way
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// Returns all the categories in a recipe.
|
||||
/datum/component/material_container/proc/get_categories(list/mats)
|
||||
var/list/categories = list()
|
||||
for(var/x in mats) //Loop through all required materials
|
||||
if(!istext(x)) //This means its not a category
|
||||
continue
|
||||
categories += x
|
||||
return categories
|
||||
|
||||
|
||||
/// Returns TRUE if you have enough of the specified material.
|
||||
/datum/component/material_container/proc/has_enough_of_material(var/datum/material/req_mat, amount, multiplier=1)
|
||||
if(!materials[req_mat]) //Do we have the resource?
|
||||
return FALSE //Can't afford it
|
||||
var/amount_required = amount * multiplier
|
||||
if(materials[req_mat] >= amount_required) // do we have enough of the resource?
|
||||
return TRUE
|
||||
return FALSE //Can't afford it
|
||||
|
||||
/// Returns TRUE if you have enough of a specified material category (Which could be multiple materials)
|
||||
/datum/component/material_container/proc/has_enough_of_category(category, amount, multiplier=1)
|
||||
for(var/i in SSmaterials.materials_by_category[category])
|
||||
var/datum/material/mat = i
|
||||
if(materials[mat] >= amount) //we have enough
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/// Turns a material amount into the amount of sheets it should output
|
||||
/datum/component/material_container/proc/amount2sheet(amt)
|
||||
if(amt >= MINERAL_MATERIAL_AMOUNT)
|
||||
return round(amt / MINERAL_MATERIAL_AMOUNT)
|
||||
return FALSE
|
||||
|
||||
/// Turns an amount of sheets into the amount of material amount it should output
|
||||
/datum/component/material_container/proc/sheet2amount(sheet_amt)
|
||||
if(sheet_amt > 0)
|
||||
return sheet_amt * MINERAL_MATERIAL_AMOUNT
|
||||
return FALSE
|
||||
|
||||
/datum/component/material_container/proc/amount(id)
|
||||
var/datum/material/M = materials[id]
|
||||
return M ? M.amount : 0
|
||||
|
||||
//returns the amount of material relevant to this container;
|
||||
//if this container does not support glass, any glass in 'I' will not be taken into account
|
||||
///returns the amount of material relevant to this container; if this container does not support glass, any glass in 'I' will not be taken into account
|
||||
/datum/component/material_container/proc/get_item_material_amount(obj/item/I)
|
||||
if(!istype(I))
|
||||
if(!istype(I) || !I.custom_materials)
|
||||
return FALSE
|
||||
var/material_amount = 0
|
||||
for(var/MAT in materials)
|
||||
material_amount += I.materials[MAT]
|
||||
material_amount += I.custom_materials[MAT]
|
||||
return material_amount
|
||||
|
||||
|
||||
/datum/material
|
||||
var/name
|
||||
var/amount = 0
|
||||
var/id = null
|
||||
var/sheet_type = null
|
||||
var/coin_type = null
|
||||
|
||||
/datum/material/metal
|
||||
name = "Metal"
|
||||
id = MAT_METAL
|
||||
sheet_type = /obj/item/stack/sheet/metal
|
||||
coin_type = /obj/item/coin/iron
|
||||
|
||||
/datum/material/glass
|
||||
name = "Glass"
|
||||
id = MAT_GLASS
|
||||
sheet_type = /obj/item/stack/sheet/glass
|
||||
|
||||
/datum/material/silver
|
||||
name = "Silver"
|
||||
id = MAT_SILVER
|
||||
sheet_type = /obj/item/stack/sheet/mineral/silver
|
||||
coin_type = /obj/item/coin/silver
|
||||
|
||||
/datum/material/gold
|
||||
name = "Gold"
|
||||
id = MAT_GOLD
|
||||
sheet_type = /obj/item/stack/sheet/mineral/gold
|
||||
coin_type = /obj/item/coin/gold
|
||||
|
||||
/datum/material/diamond
|
||||
name = "Diamond"
|
||||
id = MAT_DIAMOND
|
||||
sheet_type = /obj/item/stack/sheet/mineral/diamond
|
||||
coin_type = /obj/item/coin/diamond
|
||||
|
||||
/datum/material/uranium
|
||||
name = "Uranium"
|
||||
id = MAT_URANIUM
|
||||
sheet_type = /obj/item/stack/sheet/mineral/uranium
|
||||
coin_type = /obj/item/coin/uranium
|
||||
|
||||
/datum/material/plasma
|
||||
name = "Solid Plasma"
|
||||
id = MAT_PLASMA
|
||||
sheet_type = /obj/item/stack/sheet/mineral/plasma
|
||||
coin_type = /obj/item/coin/plasma
|
||||
|
||||
/datum/material/bluespace
|
||||
name = "Bluespace Mesh"
|
||||
id = MAT_BLUESPACE
|
||||
sheet_type = /obj/item/stack/sheet/bluespace_crystal
|
||||
|
||||
/datum/material/bananium
|
||||
name = "Bananium"
|
||||
id = MAT_BANANIUM
|
||||
sheet_type = /obj/item/stack/sheet/mineral/bananium
|
||||
coin_type = /obj/item/coin/bananium
|
||||
|
||||
/datum/material/titanium
|
||||
name = "Titanium"
|
||||
id = MAT_TITANIUM
|
||||
sheet_type = /obj/item/stack/sheet/mineral/titanium
|
||||
|
||||
/datum/material/biomass
|
||||
name = "Biomass"
|
||||
id = MAT_BIOMASS
|
||||
|
||||
/datum/material/plastic
|
||||
name = "Plastic"
|
||||
id = MAT_PLASTIC
|
||||
sheet_type = /obj/item/stack/sheet/plastic
|
||||
/// Returns the amount of a specific material in this container.
|
||||
/datum/component/material_container/proc/get_material_amount(var/datum/material/mat)
|
||||
if(!istype(mat))
|
||||
mat = getmaterialref(mat)
|
||||
return(materials[mat])
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
RegisterSignal(parent, COMSIG_ADD_MOOD_EVENT, .proc/add_event)
|
||||
RegisterSignal(parent, COMSIG_CLEAR_MOOD_EVENT, .proc/clear_event)
|
||||
RegisterSignal(parent, COMSIG_MODIFY_SANITY, .proc/modify_sanity)
|
||||
RegisterSignal(parent, COMSIG_LIVING_REVIVE, .proc/on_revive)
|
||||
|
||||
RegisterSignal(parent, COMSIG_MOB_HUD_CREATED, .proc/modify_hud)
|
||||
var/mob/living/owner = parent
|
||||
@@ -81,7 +82,8 @@
|
||||
msg += "<span class='nicegreen'>I don't have much of a reaction to anything right now.<span>\n"
|
||||
to_chat(user || parent, msg)
|
||||
|
||||
/datum/component/mood/proc/update_mood() //Called whenever a mood event is added or removed
|
||||
///Called after moodevent/s have been added/removed.
|
||||
/datum/component/mood/proc/update_mood()
|
||||
mood = 0
|
||||
shown_mood = 0
|
||||
for(var/i in mood_events)
|
||||
@@ -234,6 +236,15 @@
|
||||
qdel(event)
|
||||
update_mood()
|
||||
|
||||
/datum/component/mood/proc/remove_temp_moods() //Removes all temp moodsfor(var/i in mood_events)
|
||||
for(var/i in mood_events)
|
||||
var/datum/mood_event/moodlet = mood_events[i]
|
||||
if(!moodlet || !moodlet.timeout)
|
||||
continue
|
||||
mood_events -= i
|
||||
qdel(moodlet)
|
||||
update_mood()
|
||||
|
||||
/datum/component/mood/proc/modify_hud(datum/source)
|
||||
var/mob/living/owner = parent
|
||||
var/datum/hud/hud = owner.hud_used
|
||||
@@ -270,5 +281,12 @@
|
||||
if(0 to NUTRITION_LEVEL_STARVING)
|
||||
add_event(null, "nutrition", /datum/mood_event/starving)
|
||||
|
||||
///Called when parent is ahealed.
|
||||
/datum/component/mood/proc/on_revive(datum/source, full_heal)
|
||||
if(!full_heal)
|
||||
return
|
||||
remove_temp_moods()
|
||||
setSanity(initial(sanity))
|
||||
|
||||
#undef MINOR_INSANITY_PEN
|
||||
#undef MAJOR_INSANITY_PEN
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
var/regen_rate = 0.5 //nanites generated per second
|
||||
var/safety_threshold = 25 //how low nanites will get before they stop processing/triggering
|
||||
var/cloud_id = 0 //0 if not connected to the cloud, 1-100 to set a determined cloud backup to draw from
|
||||
var/cloud_active = TRUE //if false, won't sync to the cloud
|
||||
var/next_sync = 0
|
||||
var/list/datum/nanite_program/programs = list()
|
||||
var/max_programs = NANITE_PROGRAM_LIMIT
|
||||
|
||||
var/list/datum/nanite_program/protocol/protocols = list() ///Separate list of protocol programs, to avoid looping through the whole programs list when cheking for conflicts
|
||||
var/start_time = 0 ///Timestamp to when the nanites were first inserted in the host
|
||||
var/stealth = FALSE //if TRUE, does not appear on HUDs and health scans
|
||||
var/diagnostics = TRUE //if TRUE, displays program list when scanned by nanite scanners
|
||||
|
||||
|
||||
/datum/component/nanites/Initialize(amount = 100, cloud = 0)
|
||||
if(!isliving(parent) && !istype(parent, /datum/nanite_cloud_backup))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
@@ -28,30 +31,33 @@
|
||||
if(!(host_mob.mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD))) //Shouldn't happen, but this avoids HUD runtimes in case a silicon gets them somehow.
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
start_time = world.time
|
||||
|
||||
host_mob.hud_set_nanite_indicator()
|
||||
START_PROCESSING(SSnanites, src)
|
||||
|
||||
if(cloud_id)
|
||||
if(cloud_id && cloud_active)
|
||||
cloud_sync()
|
||||
|
||||
/datum/component/nanites/RegisterWithParent()
|
||||
. = ..()
|
||||
RegisterSignal(parent, COMSIG_HAS_NANITES, .proc/confirm_nanites)
|
||||
RegisterSignal(parent, COMSIG_NANITE_IS_STEALTHY, .proc/check_stealth)
|
||||
RegisterSignal(parent, COMSIG_NANITE_DELETE, .proc/delete_nanites)
|
||||
RegisterSignal(parent, COMSIG_NANITE_UI_DATA, .proc/nanite_ui_data)
|
||||
RegisterSignal(parent, COMSIG_NANITE_GET_PROGRAMS, .proc/get_programs)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SET_VOLUME, .proc/set_volume)
|
||||
RegisterSignal(parent, COMSIG_NANITE_ADJUST_VOLUME, .proc/adjust_nanites)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SET_MAX_VOLUME, .proc/set_max_volume)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SET_CLOUD, .proc/set_cloud)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SET_CLOUD_SYNC, .proc/set_cloud_sync)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SET_SAFETY, .proc/set_safety)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SET_REGEN, .proc/set_regen)
|
||||
RegisterSignal(parent, COMSIG_NANITE_ADD_PROGRAM, .proc/add_program)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SCAN, .proc/nanite_scan)
|
||||
RegisterSignal(parent, COMSIG_NANITE_SYNC, .proc/sync)
|
||||
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp)
|
||||
|
||||
if(isliving(parent))
|
||||
RegisterSignal(parent, COMSIG_ATOM_EMP_ACT, .proc/on_emp)
|
||||
RegisterSignal(parent, COMSIG_MOB_DEATH, .proc/on_death)
|
||||
RegisterSignal(parent, COMSIG_MOB_ALLOWED, .proc/check_access)
|
||||
RegisterSignal(parent, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_shock)
|
||||
@@ -61,15 +67,16 @@
|
||||
RegisterSignal(parent, COMSIG_NANITE_COMM_SIGNAL, .proc/receive_comm_signal)
|
||||
|
||||
/datum/component/nanites/UnregisterFromParent()
|
||||
. = ..()
|
||||
UnregisterSignal(parent, list(COMSIG_HAS_NANITES,
|
||||
COMSIG_NANITE_IS_STEALTHY,
|
||||
COMSIG_NANITE_DELETE,
|
||||
COMSIG_NANITE_UI_DATA,
|
||||
COMSIG_NANITE_GET_PROGRAMS,
|
||||
COMSIG_NANITE_SET_VOLUME,
|
||||
COMSIG_NANITE_ADJUST_VOLUME,
|
||||
COMSIG_NANITE_SET_MAX_VOLUME,
|
||||
COMSIG_NANITE_SET_CLOUD,
|
||||
COMSIG_NANITE_SET_CLOUD_SYNC,
|
||||
COMSIG_NANITE_SET_SAFETY,
|
||||
COMSIG_NANITE_SET_REGEN,
|
||||
COMSIG_NANITE_ADD_PROGRAM,
|
||||
@@ -87,9 +94,9 @@
|
||||
|
||||
/datum/component/nanites/Destroy()
|
||||
STOP_PROCESSING(SSnanites, src)
|
||||
set_nanite_bar(TRUE)
|
||||
QDEL_LIST(programs)
|
||||
if(host_mob)
|
||||
set_nanite_bar(TRUE)
|
||||
host_mob.hud_set_nanite_indicator()
|
||||
host_mob = null
|
||||
return ..()
|
||||
@@ -102,13 +109,18 @@
|
||||
|
||||
/datum/component/nanites/process()
|
||||
adjust_nanites(null, regen_rate)
|
||||
add_research()
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_process()
|
||||
set_nanite_bar()
|
||||
if(cloud_id && world.time > next_sync)
|
||||
if(cloud_id && cloud_active && world.time > next_sync)
|
||||
cloud_sync()
|
||||
next_sync = world.time + NANITE_SYNC_DELAY
|
||||
set_nanite_bar()
|
||||
|
||||
|
||||
/datum/component/nanites/proc/delete_nanites()
|
||||
qdel(src)
|
||||
|
||||
//Syncs the nanite component to another, making it so programs are the same with the same programming (except activation status)
|
||||
/datum/component/nanites/proc/sync(datum/signal_source, datum/component/nanites/source, full_overwrite = TRUE, copy_activation = FALSE)
|
||||
@@ -131,13 +143,17 @@
|
||||
add_program(null, SNP.copy())
|
||||
|
||||
/datum/component/nanites/proc/cloud_sync()
|
||||
if(!cloud_id)
|
||||
return
|
||||
var/datum/nanite_cloud_backup/backup = SSnanites.get_cloud_backup(cloud_id)
|
||||
if(backup)
|
||||
var/datum/component/nanites/cloud_copy = backup.nanites
|
||||
if(cloud_copy)
|
||||
sync(null, cloud_copy)
|
||||
if(cloud_id)
|
||||
var/datum/nanite_cloud_backup/backup = SSnanites.get_cloud_backup(cloud_id)
|
||||
if(backup)
|
||||
var/datum/component/nanites/cloud_copy = backup.nanites
|
||||
if(cloud_copy)
|
||||
sync(null, cloud_copy)
|
||||
return
|
||||
//Without cloud syncing nanites can accumulate errors and/or defects
|
||||
if(prob(8) && programs.len)
|
||||
var/datum/nanite_program/NP = pick(programs)
|
||||
NP.software_error()
|
||||
|
||||
/datum/component/nanites/proc/add_program(datum/source, datum/nanite_program/new_program, datum/nanite_program/source_program)
|
||||
for(var/X in programs)
|
||||
@@ -175,19 +191,28 @@
|
||||
holder.icon_state = "nanites[nanite_percent]"
|
||||
|
||||
/datum/component/nanites/proc/on_emp(datum/source, severity)
|
||||
adjust_nanites(null, -(nanite_volume * 0.3 + 50)) //Lose 30% variable and 50 flat nanite volume.
|
||||
nanite_volume *= (rand(60, 90) * 0.01) //Lose 10-40% of nanites
|
||||
adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
|
||||
if(prob(40/severity))
|
||||
cloud_id = 0
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_emp(severity)
|
||||
|
||||
/datum/component/nanites/proc/on_shock(datum/source, shock_damage)
|
||||
adjust_nanites(null, -(nanite_volume * (shock_damage * 0.005) + shock_damage)) //0.5% of shock damage (@ 50 damage it'd drain 25%) + shock damage flat volume
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_shock(shock_damage)
|
||||
|
||||
/datum/component/nanites/proc/on_shock(datum/source, shock_damage, siemens_coeff = 1, flags = NONE)
|
||||
if(shock_damage < 1)
|
||||
return
|
||||
|
||||
if(!HAS_TRAIT_NOT_FROM(host_mob, TRAIT_SHOCKIMMUNE, "nanites"))//Another shock protection must protect nanites too, but nanites protect only host
|
||||
nanite_volume *= (rand(45, 80) * 0.01) //Lose 20-55% of nanites
|
||||
adjust_nanites(null, -(rand(5, 50))) //Lose 5-50 flat nanite volume
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_shock(shock_damage)
|
||||
|
||||
/datum/component/nanites/proc/on_minor_shock(datum/source)
|
||||
adjust_nanites(null, -25)
|
||||
adjust_nanites(null, -(rand(5, 15))) //Lose 5-15 flat nanite volume
|
||||
for(var/X in programs)
|
||||
var/datum/nanite_program/NP = X
|
||||
NP.on_minor_shock()
|
||||
@@ -207,8 +232,8 @@
|
||||
|
||||
/datum/component/nanites/proc/receive_comm_signal(datum/source, comm_code, comm_message, comm_source = "an unidentified source")
|
||||
for(var/X in programs)
|
||||
if(istype(X, /datum/nanite_program/triggered/comm))
|
||||
var/datum/nanite_program/triggered/comm/NP = X
|
||||
if(istype(X, /datum/nanite_program/comm))
|
||||
var/datum/nanite_program/comm/NP = X
|
||||
NP.receive_comm_signal(comm_code, comm_message, comm_source)
|
||||
|
||||
/datum/component/nanites/proc/check_viable_biotype()
|
||||
@@ -216,7 +241,7 @@
|
||||
qdel(src) //bodytype no longer sustains nanites
|
||||
|
||||
/datum/component/nanites/proc/check_access(datum/source, obj/O)
|
||||
for(var/datum/nanite_program/triggered/access/access_program in programs)
|
||||
for(var/datum/nanite_program/access/access_program in programs)
|
||||
if(access_program.activated)
|
||||
return O.check_access_list(access_program.access)
|
||||
else
|
||||
@@ -232,6 +257,15 @@
|
||||
/datum/component/nanites/proc/set_cloud(datum/source, amount)
|
||||
cloud_id = CLAMP(amount, 0, 100)
|
||||
|
||||
/datum/component/nanites/proc/set_cloud_sync(datum/source, method)
|
||||
switch(method)
|
||||
if(NANITE_CLOUD_TOGGLE)
|
||||
cloud_active = !cloud_active
|
||||
if(NANITE_CLOUD_DISABLE)
|
||||
cloud_active = FALSE
|
||||
if(NANITE_CLOUD_ENABLE)
|
||||
cloud_active = TRUE
|
||||
|
||||
/datum/component/nanites/proc/set_safety(datum/source, amount)
|
||||
safety_threshold = CLAMP(amount, 0, max_nanites)
|
||||
|
||||
@@ -252,6 +286,19 @@
|
||||
/datum/component/nanites/proc/get_programs(datum/source, list/nanite_programs)
|
||||
nanite_programs |= programs
|
||||
|
||||
/datum/component/nanites/proc/add_research()
|
||||
var/research_value = NANITE_BASE_RESEARCH
|
||||
if(!ishuman(host_mob))
|
||||
if(!iscarbon(host_mob))
|
||||
research_value *= 0.4
|
||||
else
|
||||
research_value *= 0.8
|
||||
if(!host_mob.client)
|
||||
research_value *= 0.5
|
||||
if(host_mob.stat == DEAD)
|
||||
research_value *= 0.75
|
||||
SSresearch.science_tech.add_point_list(list(TECHWEB_POINT_TYPE_NANITES = research_value))
|
||||
|
||||
/datum/component/nanites/proc/nanite_scan(datum/source, mob/user, full_scan)
|
||||
if(!full_scan)
|
||||
if(!stealth)
|
||||
@@ -263,7 +310,8 @@
|
||||
to_chat(user, "<span class='info'>================</span>")
|
||||
to_chat(user, "<span class='info'>Saturation: [nanite_volume]/[max_nanites]</span>")
|
||||
to_chat(user, "<span class='info'>Safety Threshold: [safety_threshold]</span>")
|
||||
to_chat(user, "<span class='info'>Cloud ID: [cloud_id ? cloud_id : "Disabled"]</span>")
|
||||
to_chat(user, "<span class='info'>Cloud ID: [cloud_id ? cloud_id : "None"]</span>")
|
||||
to_chat(user, "<span class='info'>Cloud Sync: [cloud_active ? "Active" : "Disabled"]</span>")
|
||||
to_chat(user, "<span class='info'>================</span>")
|
||||
to_chat(user, "<span class='info'>Program List:</span>")
|
||||
if(!diagnostics)
|
||||
@@ -280,6 +328,7 @@
|
||||
data["regen_rate"] = regen_rate
|
||||
data["safety_threshold"] = safety_threshold
|
||||
data["cloud_id"] = cloud_id
|
||||
data["cloud_active"] = cloud_active
|
||||
var/list/mob_programs = list()
|
||||
var/id = 1
|
||||
for(var/X in programs)
|
||||
@@ -297,24 +346,35 @@
|
||||
mob_program["trigger_cooldown"] = P.trigger_cooldown / 10
|
||||
|
||||
if(scan_level >= 3)
|
||||
mob_program["activation_delay"] = P.activation_delay
|
||||
mob_program["timer"] = P.timer
|
||||
mob_program["timer_type"] = P.get_timer_type_text()
|
||||
var/list/extra_settings = list()
|
||||
for(var/Y in P.extra_settings)
|
||||
var/list/setting = list()
|
||||
setting["name"] = Y
|
||||
setting["value"] = P.get_extra_setting(Y)
|
||||
extra_settings += list(setting)
|
||||
mob_program["timer_restart"] = P.timer_restart / 10
|
||||
mob_program["timer_shutdown"] = P.timer_shutdown / 10
|
||||
mob_program["timer_trigger"] = P.timer_trigger / 10
|
||||
mob_program["timer_trigger_delay"] = P.timer_trigger_delay / 10
|
||||
var/list/extra_settings = P.get_extra_settings_frontend()
|
||||
mob_program["extra_settings"] = extra_settings
|
||||
if(LAZYLEN(extra_settings))
|
||||
mob_program["has_extra_settings"] = TRUE
|
||||
else
|
||||
mob_program["has_extra_settings"] = FALSE
|
||||
|
||||
if(scan_level >= 4)
|
||||
mob_program["activation_code"] = P.activation_code
|
||||
mob_program["deactivation_code"] = P.deactivation_code
|
||||
mob_program["kill_code"] = P.kill_code
|
||||
mob_program["trigger_code"] = P.trigger_code
|
||||
var/list/rules = list()
|
||||
var/rule_id = 1
|
||||
for(var/Z in P.rules)
|
||||
var/datum/nanite_rule/nanite_rule = Z
|
||||
var/list/rule = list()
|
||||
rule["display"] = nanite_rule.display()
|
||||
rule["program_id"] = id
|
||||
rule["id"] = rule_id
|
||||
rules += list(rule)
|
||||
rule_id++
|
||||
mob_program["rules"] = rules
|
||||
if(LAZYLEN(rules))
|
||||
mob_program["has_rules"] = TRUE
|
||||
id++
|
||||
mob_programs += list(mob_program)
|
||||
data["mob_programs"] = mob_programs
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
/datum/component/radioactive/proc/rad_attack(datum/source, atom/movable/target, mob/living/user)
|
||||
radiation_pulse(parent, strength/20)
|
||||
target.rad_act(strength/2)
|
||||
if(!hl3_release_date)
|
||||
return
|
||||
strength -= strength / hl3_release_date
|
||||
|
||||
#undef RAD_AMOUNT_LOW
|
||||
|
||||
@@ -54,7 +54,7 @@ handles linking back and forth.
|
||||
/datum/component/remote_materials/proc/_MakeLocal()
|
||||
silo = null
|
||||
mat_container = parent.AddComponent(/datum/component/material_container,
|
||||
list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC),
|
||||
list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/gold, /datum/material/diamond, /datum/material/plasma, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace, /datum/material/plastic),
|
||||
local_size,
|
||||
FALSE,
|
||||
/obj/item/stack)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
intensity = max(_intensity, 0)
|
||||
lube_flags = _lube_flags
|
||||
callback = _callback
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED), .proc/Slip)
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ATOM_ENTERED, COMSIG_ITEM_WEARERCROSSED), .proc/Slip)
|
||||
|
||||
/datum/component/slippery/proc/Slip(datum/source, atom/movable/AM)
|
||||
var/mob/victim = AM
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
RegisterSignal(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), .proc/play_squeak)
|
||||
if(ismovableatom(parent))
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, .proc/play_squeak_crossed)
|
||||
RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ITEM_WEARERCROSSED), .proc/play_squeak_crossed)
|
||||
RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react)
|
||||
if(isitem(parent))
|
||||
RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
Disfiguration
|
||||
|
||||
Hidden.
|
||||
No change to resistance.
|
||||
Increases stage speed.
|
||||
Slightly increases transmittability.
|
||||
Critical Level.
|
||||
|
||||
BONUS
|
||||
Adds disfiguration trait making the mob appear as "Unknown" to others.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/disfiguration
|
||||
|
||||
name = "Disfiguration"
|
||||
desc = "The virus liquefies facial muscles, disfiguring the host."
|
||||
stealth = 2
|
||||
resistance = 0
|
||||
stage_speed = 3
|
||||
transmittable = 1
|
||||
level = 5
|
||||
severity = 1
|
||||
symptom_delay_min = 25
|
||||
symptom_delay_max = 75
|
||||
|
||||
/datum/symptom/disfiguration/Activate(datum/disease/advance/A)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/mob/living/M = A.affected_mob
|
||||
if (HAS_TRAIT(M, TRAIT_DISFIGURED))
|
||||
return
|
||||
switch(A.stage)
|
||||
if(5)
|
||||
ADD_TRAIT(M, TRAIT_DISFIGURED, DISEASE_TRAIT)
|
||||
M.visible_message("<span class='warning'>[M]'s face appears to cave in!</span>", "<span class='notice'>You feel your face crumple and cave in!</span>")
|
||||
else
|
||||
M.visible_message("<span class='warning'>[M]'s face begins to contort...</span>", "<span class='notice'>Your face feels wet and malleable...</span>")
|
||||
|
||||
|
||||
/datum/symptom/disfiguration/End(datum/disease/advance/A)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(A.affected_mob)
|
||||
REMOVE_TRAIT(A.affected_mob, TRAIT_DISFIGURED, DISEASE_TRAIT)
|
||||
@@ -1,68 +1,22 @@
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
Vitiligo
|
||||
Polyvitiligo
|
||||
|
||||
Hidden.
|
||||
No change to resistance.
|
||||
Increases stage speed.
|
||||
Slightly increases transmittability.
|
||||
Critical Level.
|
||||
|
||||
BONUS
|
||||
Makes the mob lose skin pigmentation.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/vitiligo
|
||||
|
||||
name = "Vitiligo"
|
||||
desc = "The virus destroys skin pigment cells, causing rapid loss of pigmentation in the host."
|
||||
stealth = 2
|
||||
resistance = 0
|
||||
stage_speed = 3
|
||||
transmittable = 1
|
||||
level = 5
|
||||
severity = 1
|
||||
symptom_delay_min = 25
|
||||
symptom_delay_max = 75
|
||||
|
||||
/datum/symptom/vitiligo/Activate(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.skin_tone == "albino")
|
||||
return
|
||||
switch(A.stage)
|
||||
if(5)
|
||||
H.skin_tone = "albino"
|
||||
H.update_body(0)
|
||||
else
|
||||
H.visible_message("<span class='warning'>[H] looks a bit pale...</span>", "<span class='notice'>Your skin suddenly appears lighter...</span>")
|
||||
|
||||
|
||||
/*
|
||||
//////////////////////////////////////
|
||||
Revitiligo
|
||||
|
||||
Slightly noticable.
|
||||
Noticeable.
|
||||
Increases resistance.
|
||||
Increases stage speed slightly.
|
||||
Increases transmission.
|
||||
Critical Level.
|
||||
|
||||
BONUS
|
||||
Makes the mob gain skin pigmentation.
|
||||
Makes the mob gain a random crayon powder colorful reagent.
|
||||
|
||||
//////////////////////////////////////
|
||||
*/
|
||||
|
||||
/datum/symptom/revitiligo
|
||||
|
||||
name = "Revitiligo"
|
||||
desc = "The virus causes increased production of skin pigment cells, making the host's skin grow darker over time."
|
||||
/datum/symptom/polyvitiligo
|
||||
name = "Polyvitiligo"
|
||||
desc = "The virus replaces the melanin in the skin with reactive pigment."
|
||||
stealth = -1
|
||||
resistance = 3
|
||||
stage_speed = 1
|
||||
@@ -72,17 +26,16 @@ BONUS
|
||||
symptom_delay_min = 7
|
||||
symptom_delay_max = 14
|
||||
|
||||
/datum/symptom/revitiligo/Activate(datum/disease/advance/A)
|
||||
/datum/symptom/polyvitiligo/Activate(datum/disease/advance/A)
|
||||
if(!..())
|
||||
return
|
||||
var/mob/living/M = A.affected_mob
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.skin_tone == "african2")
|
||||
return
|
||||
switch(A.stage)
|
||||
if(5)
|
||||
H.skin_tone = "african2"
|
||||
H.update_body(0)
|
||||
else
|
||||
H.visible_message("<span class='warning'>[H] looks a bit dark...</span>", "<span class='notice'>Your skin suddenly appears darker...</span>")
|
||||
switch(A.stage)
|
||||
if(5)
|
||||
var/static/list/banned_reagents = list(/datum/reagent/colorful_reagent/crayonpowder/invisible, /datum/reagent/colorful_reagent/crayonpowder/white)
|
||||
var/color = pick(subtypesof(/datum/reagent/colorful_reagent/crayonpowder) - banned_reagents)
|
||||
if(M.reagents.total_volume <= (M.reagents.maximum_volume/10)) // no flooding humans with 1000 units of colorful reagent
|
||||
M.reagents.add_reagent(color, 5)
|
||||
else
|
||||
if (prob(50)) // spam
|
||||
M.visible_message("<span class='warning'>[M] looks rather vibrant...</span>", "<span class='notice'>The colors, man, the colors...</span>")
|
||||
@@ -38,10 +38,11 @@
|
||||
return
|
||||
CRASH("We couldn't assign an ID!")
|
||||
|
||||
// Called when processing of the advance disease that holds this symptom infects a host and upon each Refresh() of that advance disease.
|
||||
// Called when processing of the advance disease, which holds this symptom, starts.
|
||||
/datum/symptom/proc/Start(datum/disease/advance/A)
|
||||
if(neutered)
|
||||
return FALSE
|
||||
next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10) //so it doesn't instantly activate on infection
|
||||
return TRUE
|
||||
|
||||
// Called when the advance disease is going to be deleted or when the advance disease stops processing.
|
||||
@@ -59,7 +60,7 @@
|
||||
next_activation = world.time + rand(symptom_delay_min * 10, symptom_delay_max * 10)
|
||||
return TRUE
|
||||
|
||||
/datum/symptom/proc/on_stage_change(datum/disease/advance/A)
|
||||
/datum/symptom/proc/on_stage_change(new_stage, datum/disease/advance/A)
|
||||
if(neutered)
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Can be applied to /atom/movable subtypes to make them apply fire stacks to things they hit
|
||||
*/
|
||||
/datum/element/firestacker
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
id_arg_index = 2
|
||||
/// How many firestacks to apply per hit
|
||||
var/amount
|
||||
|
||||
/datum/element/firestacker/Attach(datum/target, amount)
|
||||
. = ..()
|
||||
|
||||
if(!ismovableatom(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
src.amount = amount
|
||||
|
||||
RegisterSignal(target, COMSIG_MOVABLE_IMPACT, .proc/impact, override = TRUE)
|
||||
if(isitem(target))
|
||||
RegisterSignal(target, COMSIG_ITEM_ATTACK, .proc/item_attack, override = TRUE)
|
||||
RegisterSignal(target, COMSIG_ITEM_ATTACK_SELF, .proc/item_attack_self, override = TRUE)
|
||||
|
||||
/datum/element/firestacker/Detach(datum/source, force)
|
||||
. = ..()
|
||||
UnregisterSignal(source, list(COMSIG_MOVABLE_IMPACT, COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_SELF))
|
||||
|
||||
/datum/element/firestacker/proc/stack_on(datum/owner, mob/living/target)
|
||||
target.adjust_fire_stacks(amount)
|
||||
|
||||
/datum/element/firestacker/proc/impact(datum/source, atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
if(isliving(hit_atom))
|
||||
stack_on(source, hit_atom)
|
||||
|
||||
/datum/element/firestacker/proc/item_attack(datum/source, atom/movable/target, mob/living/user)
|
||||
if(isliving(target))
|
||||
stack_on(source, target)
|
||||
|
||||
/datum/element/firestacker/proc/item_attack_self(datum/source, mob/user)
|
||||
if(isliving(user))
|
||||
stack_on(source, user)
|
||||
@@ -17,7 +17,8 @@
|
||||
penalty += roundstart_quit_limit - world.time
|
||||
if(penalty)
|
||||
penalty += world.realtime
|
||||
if(penalty - SSshuttle.realtimeofstart > SSshuttle.auto_call + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
|
||||
var/maximumRoundEnd = SSautotransfer.starttime + SSautotransfer.voteinterval * SSautotransfer.maxvotes
|
||||
if(penalty - SSshuttle.realtimeofstart > maximumRoundEnd + SSshuttle.emergencyCallTime + SSshuttle.emergencyDockTime + SSshuttle.emergencyEscapeTime)
|
||||
penalty = CANT_REENTER_ROUND
|
||||
if(!(M.ckey in timeouts))
|
||||
timeouts += M.ckey
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
lefthand_file = left_hand
|
||||
if(right_hand)
|
||||
righthand_file = right_hand
|
||||
slot_flags = slots
|
||||
slot_flags = slots
|
||||
|
||||
/obj/item/clothing/head/mob_holder/proc/assimilate(mob/living/target)
|
||||
target.setDir(SOUTH)
|
||||
@@ -114,16 +114,14 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
if(MOB_SIZE_LARGE)
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
RegisterSignal(src, COMSIG_CLICK_SHIFT, .proc/examine_held_mob)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Destroy()
|
||||
if(held_mob)
|
||||
release()
|
||||
return ..()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/proc/examine_held_mob(datum/source, mob/user)
|
||||
held_mob.ShiftClick(user)
|
||||
return COMPONENT_DENY_EXAMINATE
|
||||
/obj/item/clothing/head/mob_holder/examine(mob/user)
|
||||
return held_mob?.examine(user) || ..()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Exited(atom/movable/AM, atom/newloc)
|
||||
. = ..()
|
||||
@@ -152,7 +150,8 @@
|
||||
L.forceMove(get_turf(L))
|
||||
L.reset_perspective()
|
||||
L.setDir(SOUTH)
|
||||
qdel(src)
|
||||
if(!QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
|
||||
return
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/// Just for marking when someone's swimming.
|
||||
/datum/element/swimming
|
||||
element_flags = ELEMENT_DETACH
|
||||
|
||||
/datum/element/swimming/Attach(datum/target)
|
||||
if((. = ..()) == ELEMENT_INCOMPATIBLE)
|
||||
return
|
||||
if(!isliving(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_MOVABLE_MOVED, .proc/check_valid)
|
||||
ADD_TRAIT(target, TRAIT_SWIMMING, TRAIT_SWIMMING) //seriously there's only one way to get this
|
||||
|
||||
/datum/element/swimming/Detach(datum/target)
|
||||
. = ..()
|
||||
UnregisterSignal(target, COMSIG_MOVABLE_MOVED)
|
||||
REMOVE_TRAIT(target, TRAIT_SWIMMING, TRAIT_SWIMMING)
|
||||
|
||||
/datum/element/swimming/proc/check_valid(datum/source)
|
||||
var/mob/living/L = source
|
||||
if(!istype(L.loc, /turf/open/pool))
|
||||
source.RemoveElement(/datum/element/swimming)
|
||||
@@ -0,0 +1,10 @@
|
||||
//Prevents calling anything in update_icon() like update_icon_state() or update_overlays()
|
||||
|
||||
/datum/element/update_icon_blocker/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!istype(target, /atom))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON, .proc/block_update_icon)
|
||||
|
||||
/datum/element/update_icon_blocker/proc/block_update_icon()
|
||||
return COMSIG_ATOM_NO_UPDATE_ICON_STATE | COMSIG_ATOM_NO_UPDATE_OVERLAYS
|
||||
@@ -0,0 +1,16 @@
|
||||
//update_icon() may change the onmob icons
|
||||
//Very good name, I know
|
||||
|
||||
/datum/element/update_icon_updates_onmob/Attach(datum/target)
|
||||
. = ..()
|
||||
if(!istype(target, /obj/item))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/update_onmob)
|
||||
|
||||
/datum/element/update_icon_updates_onmob/proc/update_onmob(obj/item/target)
|
||||
if(ismob(target.loc))
|
||||
var/mob/M = target.loc
|
||||
if(M.is_holding(target))
|
||||
M.update_inv_hands()
|
||||
else
|
||||
M.regenerate_icons() //yeah this is shit, but we don't know which update_foo() proc to call instead so we'll call them all
|
||||
@@ -216,7 +216,7 @@
|
||||
desc = "Stores recorder holocalls."
|
||||
icon_state = "holodisk"
|
||||
obj_flags = UNIQUE_RENAME
|
||||
materials = list(MAT_METAL = 100, MAT_GLASS = 100)
|
||||
custom_materials = list(/datum/material/iron = 100, /datum/material/glass = 100)
|
||||
var/datum/holorecord/record
|
||||
//Preset variables
|
||||
var/preset_image_type
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*! Material datum
|
||||
Simple datum which is instanced once per type and is used for every object of said material. It has a variety of variables that define behavior. Subtyping from this makes it easier to create your own materials.
|
||||
*/
|
||||
|
||||
|
||||
/datum/material
|
||||
var/name = "material"
|
||||
var/desc = "its..stuff."
|
||||
///Var that's mostly used by science machines to identify specific materials, should most likely be phased out at some point
|
||||
var/id = "mat"
|
||||
///Base color of the material, is used for greyscale. Item isn't changed in color if this is null.
|
||||
var/color
|
||||
///Base alpha of the material, is used for greyscale icons.
|
||||
var/alpha
|
||||
///Materials "Traits". its a map of key = category | Value = Bool. Used to define what it can be used for
|
||||
var/list/categories = list()
|
||||
///The type of sheet this material creates. This should be replaced as soon as possible by greyscale sheets
|
||||
var/sheet_type
|
||||
///This is a modifier for force, and resembles the strength of the material
|
||||
var/strength_modifier = 1
|
||||
///This is a modifier for integrity, and resembles the strength of the material
|
||||
var/integrity_modifier = 1
|
||||
///This is the amount of value per 1 unit of the material
|
||||
var/value_per_unit = 0
|
||||
///Armor modifiers, multiplies an items normal armor vars by these amounts.
|
||||
var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1)
|
||||
|
||||
///This proc is called when the material is added to an object.
|
||||
/datum/material/proc/on_applied(atom/source, amount, material_flags)
|
||||
if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example
|
||||
if(color) //Do we have a custom color?
|
||||
source.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
if(alpha)
|
||||
source.alpha = alpha
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = "[name] [source.name]"
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_applied_obj(source, amount, material_flags)
|
||||
|
||||
///This proc is called when the material is added to an object specifically.
|
||||
/datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = CEILING(o.max_integrity * integrity_modifier, 1)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force *= strength_modifier
|
||||
o.throwforce *= strength_modifier
|
||||
|
||||
var/list/temp_armor_list = list() //Time to add armor modifiers!
|
||||
|
||||
if(!istype(o.armor))
|
||||
return
|
||||
var/list/current_armor = o.armor?.getList()
|
||||
|
||||
for(var/i in current_armor)
|
||||
temp_armor_list[i] = current_armor[i] * armor_modifiers[i]
|
||||
o.armor = getArmor(arglist(temp_armor_list))
|
||||
|
||||
///This proc is called when the material is removed from an object.
|
||||
/datum/material/proc/on_removed(atom/source, material_flags)
|
||||
if(material_flags & MATERIAL_COLOR) //Prevent changing things with pre-set colors, to keep colored toolboxes their looks for example
|
||||
if(color)
|
||||
source.remove_atom_colour(FIXED_COLOUR_PRIORITY, color)
|
||||
source.alpha = initial(source.alpha)
|
||||
|
||||
if(material_flags & MATERIAL_ADD_PREFIX)
|
||||
source.name = initial(source.name)
|
||||
|
||||
if(istype(source, /obj)) //objs
|
||||
on_removed_obj(source, material_flags)
|
||||
|
||||
///This proc is called when the material is removed from an object specifically.
|
||||
/datum/material/proc/on_removed_obj(var/obj/o, amount, material_flags)
|
||||
var/new_max_integrity = initial(o.max_integrity)
|
||||
o.modify_max_integrity(new_max_integrity)
|
||||
o.force = initial(o.force)
|
||||
o.throwforce = initial(o.throwforce)
|
||||
@@ -0,0 +1,210 @@
|
||||
///Has no special properties.
|
||||
/datum/material/iron
|
||||
name = "iron"
|
||||
id = "iron"
|
||||
desc = "Common iron ore often found in sedimentary and igneous layers of the crust."
|
||||
color = "#878687"
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/metal
|
||||
value_per_unit = 0.0025
|
||||
|
||||
///Breaks extremely easily but is transparent.
|
||||
/datum/material/glass
|
||||
name = "glass"
|
||||
id = "glass"
|
||||
desc = "Glass forged by melting sand."
|
||||
color = "#88cdf1"
|
||||
alpha = 150
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
integrity_modifier = 0.1
|
||||
sheet_type = /obj/item/stack/sheet/glass
|
||||
value_per_unit = 0.0025
|
||||
armor_modifiers = list("melee" = 0.2, "bullet" = 0.2, "laser" = 0, "energy" = 1, "bomb" = 0, "bio" = 0.2, "rad" = 0.2, "fire" = 1, "acid" = 0.2) // yeah ok retard
|
||||
|
||||
/*
|
||||
Color matrices are like regular colors but unlike with normal colors, you can go over 255 on a channel.
|
||||
Unless you know what you're doing, only use the first three numbers. They're in RGB order.
|
||||
*/
|
||||
|
||||
///Has no special properties. Could be good against vampires in the future perhaps.
|
||||
/datum/material/silver
|
||||
name = "silver"
|
||||
id = "silver"
|
||||
desc = "Silver"
|
||||
color = list(255/255, 284/255, 302/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/silver
|
||||
value_per_unit = 0.025
|
||||
|
||||
///Slight force increase
|
||||
/datum/material/gold
|
||||
name = "gold"
|
||||
id = "gold"
|
||||
desc = "Gold"
|
||||
color = list(340/255, 240/255, 50/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //gold is shiny, but not as bright as bananium
|
||||
strength_modifier = 1.2
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/gold
|
||||
value_per_unit = 0.0625
|
||||
armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 1.15, "energy" = 1.15, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1.1)
|
||||
|
||||
///Has no special properties
|
||||
/datum/material/diamond
|
||||
name = "diamond"
|
||||
id = "diamond"
|
||||
desc = "Highly pressurized carbon"
|
||||
color = list(48/255, 272/255, 301/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
alpha = 132
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/diamond
|
||||
value_per_unit = 0.25
|
||||
|
||||
///Is slightly radioactive
|
||||
/datum/material/uranium
|
||||
name = "uranium"
|
||||
id = "uranium"
|
||||
desc = "Uranium"
|
||||
color = rgb(48, 237, 26)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/uranium
|
||||
value_per_unit = 0.05
|
||||
armor_modifiers = list("melee" = 1.5, "bullet" = 1.4, "laser" = 0.5, "energy" = 0.5, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 1, "acid" = 1)
|
||||
|
||||
/datum/material/uranium/on_applied(atom/source, amount, material_flags)
|
||||
. = ..()
|
||||
source.AddComponent(/datum/component/radioactive, amount / 20, source, 0) //half-life of 0 because we keep on going.
|
||||
|
||||
/datum/material/uranium/on_removed(atom/source, material_flags)
|
||||
. = ..()
|
||||
qdel(source.GetComponent(/datum/component/radioactive))
|
||||
|
||||
|
||||
///Adds firestacks on hit (Still needs support to turn into gas on destruction)
|
||||
/datum/material/plasma
|
||||
name = "plasma"
|
||||
id = "plasma"
|
||||
desc = "Isn't plasma a state of matter? Oh whatever."
|
||||
color = list(298/255, 46/255, 352/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/plasma
|
||||
value_per_unit = 0.1
|
||||
armor_modifiers = list("melee" = 1.4, "bullet" = 0.7, "laser" = 0, "energy" = 1.2, "bomb" = 0, "bio" = 1.2, "rad" = 1, "fire" = 0, "acid" = 0.5)
|
||||
|
||||
/datum/material/plasma/on_applied(atom/source, amount, material_flags)
|
||||
. = ..()
|
||||
if(ismovableatom(source))
|
||||
source.AddElement(/datum/element/firestacker)
|
||||
source.AddComponent(/datum/component/explodable, 0, 0, amount / 2500, amount / 1250)
|
||||
|
||||
/datum/material/plasma/on_removed(atom/source, material_flags)
|
||||
. = ..()
|
||||
source.RemoveElement(/datum/element/firestacker)
|
||||
qdel(source.GetComponent(/datum/component/explodable))
|
||||
|
||||
///Can cause bluespace effects on use. (Teleportation) (Not yet implemented)
|
||||
/datum/material/bluespace
|
||||
name = "bluespace crystal"
|
||||
id = "bluespace_crystal"
|
||||
desc = "Crystals with bluespace properties"
|
||||
color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0)
|
||||
alpha = 200
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/bluespace_crystal
|
||||
value_per_unit = 0.15
|
||||
|
||||
///Honks and slips
|
||||
/datum/material/bananium
|
||||
name = "bananium"
|
||||
id = "bananium"
|
||||
desc = "Material with hilarious properties"
|
||||
color = list(460/255, 464/255, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) //obnoxiously bright yellow
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/bananium
|
||||
value_per_unit = 0.5
|
||||
armor_modifiers = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 10, "acid" = 0) //Clowns cant be blown away
|
||||
|
||||
/datum/material/bananium/on_applied(atom/source, amount, material_flags)
|
||||
. = ..()
|
||||
source.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50)
|
||||
source.AddComponent(/datum/component/slippery, min(amount / 10, 80))
|
||||
|
||||
/datum/material/bananium/on_removed(atom/source, amount, material_flags)
|
||||
. = ..()
|
||||
qdel(source.GetComponent(/datum/component/slippery))
|
||||
qdel(source.GetComponent(/datum/component/squeak))
|
||||
|
||||
|
||||
///Mediocre force increase
|
||||
/datum/material/titanium
|
||||
name = "titanium"
|
||||
id = "titanium"
|
||||
desc = "Titanium"
|
||||
color = "#b3c0c7"
|
||||
strength_modifier = 1.3
|
||||
categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/titanium
|
||||
value_per_unit = 0.0625
|
||||
armor_modifiers = list("melee" = 1.35, "bullet" = 1.3, "laser" = 1.3, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1)
|
||||
|
||||
/datum/material/runite
|
||||
name = "runite"
|
||||
id = "runite"
|
||||
desc = "Runite"
|
||||
color = "#3F9995"
|
||||
strength_modifier = 1.3
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/runite
|
||||
armor_modifiers = list("melee" = 1.35, "bullet" = 2, "laser" = 0.5, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 1.4, "acid" = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle.
|
||||
|
||||
///Force decrease
|
||||
/datum/material/plastic
|
||||
name = "plastic"
|
||||
id = "plastic"
|
||||
desc = "Plastic"
|
||||
color = "#caccd9"
|
||||
strength_modifier = 0.85
|
||||
sheet_type = /obj/item/stack/sheet/plastic
|
||||
value_per_unit = 0.0125
|
||||
armor_modifiers = list("melee" = 1.5, "bullet" = 1.1, "laser" = 0.3, "energy" = 0.5, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1.1, "acid" = 1)
|
||||
|
||||
///Force decrease and mushy sound effect. (Not yet implemented)
|
||||
/datum/material/biomass
|
||||
name = "biomass"
|
||||
id = "biomass"
|
||||
desc = "Organic matter"
|
||||
color = "#735b4d"
|
||||
strength_modifier = 0.8
|
||||
value_per_unit = 0.025
|
||||
|
||||
///Stronk force increase
|
||||
/datum/material/adamantine
|
||||
name = "adamantine"
|
||||
id = "adamantine"
|
||||
desc = "A powerful material made out of magic, I mean science!"
|
||||
color = "#6d7e8e"
|
||||
strength_modifier = 1.5
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/adamantine
|
||||
value_per_unit = 0.25
|
||||
armor_modifiers = list("melee" = 1.5, "bullet" = 1.5, "laser" = 1.3, "energy" = 1.3, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 2.5, "acid" = 1)
|
||||
|
||||
///RPG Magic. (Admin only)
|
||||
/datum/material/mythril
|
||||
name = "mythril"
|
||||
id = "mythril"
|
||||
desc = "How this even exists is byond me"
|
||||
color = "#f2d5d7"
|
||||
categories = list(MAT_CATEGORY_RIGID = TRUE)
|
||||
sheet_type = /obj/item/stack/sheet/mineral/mythril
|
||||
value_per_unit = 0.75
|
||||
armor_modifiers = list("melee" = 2, "bullet" = 2, "laser" = 2, "energy" = 2, "bomb" = 2, "bio" = 2, "rad" = 2, "fire" = 2, "acid" = 2)
|
||||
|
||||
/datum/material/mythril/on_applied_obj(atom/source, amount, material_flags)
|
||||
. = ..()
|
||||
if(istype(source, /obj/item))
|
||||
source.AddComponent(/datum/component/fantasy)
|
||||
|
||||
/datum/material/mythril/on_removed_obj(atom/source, material_flags)
|
||||
. = ..()
|
||||
if(istype(source, /obj/item))
|
||||
qdel(source.GetComponent(/datum/component/fantasy))
|
||||
+5
-1
@@ -61,7 +61,6 @@
|
||||
var/late_joiner = FALSE
|
||||
|
||||
var/force_escaped = FALSE // Set by Into The Sunset command of the shuttle manipulator
|
||||
|
||||
var/list/learned_recipes //List of learned recipe TYPES.
|
||||
|
||||
/datum/mind/New(var/key)
|
||||
@@ -717,6 +716,11 @@
|
||||
if(G)
|
||||
G.reenter_corpse()
|
||||
|
||||
/// Sets our can_hijack to the fastest speed our antag datums allow.
|
||||
/datum/mind/proc/get_hijack_speed()
|
||||
. = 0
|
||||
for(var/datum/antagonist/A in antag_datums)
|
||||
. = max(., A.hijack_speed())
|
||||
|
||||
/datum/mind/proc/has_objective(objective_type)
|
||||
for(var/datum/antagonist/A in antag_datums)
|
||||
|
||||
@@ -224,6 +224,13 @@
|
||||
allow_duplicates = FALSE
|
||||
cost = 5
|
||||
|
||||
/datum/map_template/ruin/lavaland/dark_wizards
|
||||
name = "Dark Wizard Altar"
|
||||
id = "dark_wizards"
|
||||
description = "A ruin with dark wizards. What secret do they guard?"
|
||||
suffix = "lavaland_surface_wizard.dmm"
|
||||
cost = 5
|
||||
|
||||
/datum/map_template/ruin/lavaland/puzzle
|
||||
name = "Ancient Puzzle"
|
||||
id = "puzzle"
|
||||
@@ -238,4 +245,14 @@
|
||||
suffix = "lavaland_surface_elite_tumor.dmm"
|
||||
cost = 5
|
||||
always_place = TRUE
|
||||
allow_duplicates = TRUE
|
||||
allow_duplicates = TRUE
|
||||
|
||||
// Mining Base
|
||||
/datum/map_template/ruin/lavaland/mining_base //THIS IS THE MINING BASE. DO NOT FUCK WITH THIS UNLESS YOU ARE 100% CERTAIN YOU KNOW WHAT YOU'RE DOING, OR THE MINING BASE WILL DISAPPEAR
|
||||
name = "Mining Base"
|
||||
id = "miningbase"
|
||||
description = "The mining base that Nanotrasen uses for their mining operations."
|
||||
suffix = "miningbase.dmm"
|
||||
cost = 0
|
||||
always_place = TRUE
|
||||
unpickable = TRUE
|
||||
@@ -311,6 +311,12 @@
|
||||
name = "Space Hermit"
|
||||
description = "A late awakening cryo pod in a crashed escape pod wakes up to find what befell of his fellow survivors. Contains all the necessary resources to actually make it out alive. Good luck."
|
||||
|
||||
/datum/map_template/ruin/space/clericden
|
||||
id = "clericden"
|
||||
suffix = "clericden.dmm"
|
||||
name = "Cleric's Den"
|
||||
description = "Once part of a larger monastery, this holy order of long dead clerics practiced far less non-violence than they preached. Appears to have been untouched by looters, however. Odd."
|
||||
|
||||
/datum/map_template/ruin/space/advancedlab
|
||||
id = "advancedlab"
|
||||
suffix = "advancedlab.dmm"
|
||||
|
||||
@@ -54,10 +54,3 @@
|
||||
id = "engine_budget"
|
||||
suffix = "Box/Engine/budget.dmm"
|
||||
name = "Box P.A.C.M.A.N"
|
||||
|
||||
// Lavaland
|
||||
// Mining Base
|
||||
/datum/map_template/ruin/station/lavaland/mining_base
|
||||
id = "mining_public_01"
|
||||
suffix = "Lavaland/Mining_Station/Mining_Station_Public_01.dmm"
|
||||
name = "Public Mining Base"
|
||||
|
||||
+32
-1
@@ -287,6 +287,12 @@
|
||||
credit_cost = 4000
|
||||
description = "A fairly standard shuttle, though larger and slightly better equipped than the Box Station variant."
|
||||
|
||||
/datum/map_template/shuttle/emergency/kilo
|
||||
suffix = "kilo"
|
||||
name = "Kilo Station Emergency Shuttle"
|
||||
credit_cost = 5000
|
||||
description = "A fully functional shuttle including a complete infirmary, storage facilties and regular amenities."
|
||||
|
||||
/datum/map_template/shuttle/emergency/mini
|
||||
suffix = "mini"
|
||||
name = "Ministation emergency shuttle"
|
||||
@@ -419,6 +425,11 @@
|
||||
name = "fancy transport ferry"
|
||||
description = "At some point, someone upgraded the ferry to have fancier flooring... and less seats."
|
||||
|
||||
/datum/map_template/shuttle/ferry/kilo
|
||||
suffix = "kilo"
|
||||
name = "kilo transport ferry"
|
||||
description = "Standard issue CentCom Ferry for Kilo pattern stations. Includes additional equipment and rechargers."
|
||||
|
||||
/datum/map_template/shuttle/whiteship/box
|
||||
suffix = "box"
|
||||
name = "Hospital Ship"
|
||||
@@ -447,6 +458,10 @@
|
||||
suffix = "box"
|
||||
name = "supply shuttle (Box)"
|
||||
|
||||
/datum/map_template/shuttle/cargo/kilo
|
||||
suffix = "kilo"
|
||||
name = "supply shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/cargo/birdboat
|
||||
suffix = "birdboat"
|
||||
name = "supply shuttle (Birdboat)"
|
||||
@@ -481,6 +496,10 @@
|
||||
suffix = "box"
|
||||
name = "labour shuttle (Box)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/infiltrator/basic
|
||||
suffix = "basic"
|
||||
name = "basic syndicate infiltrator"
|
||||
@@ -493,6 +512,10 @@
|
||||
suffix = "delta"
|
||||
name = "mining shuttle (Delta)"
|
||||
|
||||
/datum/map_template/shuttle/mining/kilo
|
||||
suffix = "kilo"
|
||||
name = "mining shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/labour/delta
|
||||
suffix = "delta"
|
||||
name = "labour shuttle (Delta)"
|
||||
@@ -501,10 +524,18 @@
|
||||
suffix = "meta"
|
||||
name = "lavaland shuttle (Meta)"
|
||||
|
||||
/datum/map_template/shuttle/labour/kilo
|
||||
suffix = "kilo"
|
||||
name = "labour shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/arrival/delta
|
||||
suffix = "delta"
|
||||
name = "arrival shuttle (Delta)"
|
||||
|
||||
/datum/map_template/shuttle/arrival/kilo
|
||||
suffix = "kilo"
|
||||
name = "arrival shuttle (Kilo)"
|
||||
|
||||
/datum/map_template/shuttle/arrival/pubby
|
||||
suffix = "pubby"
|
||||
name = "arrival shuttle (Pubby)"
|
||||
@@ -559,4 +590,4 @@
|
||||
|
||||
/datum/map_template/shuttle/snowdin/excavation
|
||||
suffix = "excavation"
|
||||
name = "Snowdin Excavation Elevator"
|
||||
name = "Snowdin Excavation Elevator"
|
||||
|
||||
@@ -101,14 +101,16 @@
|
||||
/datum/status_effect/no_combat_mode/mesmerize/on_creation(mob/living/new_owner, set_duration)
|
||||
. = ..()
|
||||
ADD_TRAIT(owner, TRAIT_MUTE, "mesmerize")
|
||||
owner.add_movespeed_modifier("[STATUS_EFFECT_MESMERIZE]_[id]", TRUE, priority = 64, override = TRUE, multiplicative_slowdown = 5, blacklisted_movetypes = FALSE? NONE : CRAWLING)
|
||||
|
||||
/datum/status_effect/no_combat_mode/mesmerize/on_remove()
|
||||
. = ..()
|
||||
REMOVE_TRAIT(owner, TRAIT_MUTE, "mesmerize")
|
||||
owner.remove_movespeed_modifier("[STATUS_EFFECT_MESMERIZE]_[id]")
|
||||
|
||||
/obj/screen/alert/status_effect/mesmerized
|
||||
name = "Mesmerized"
|
||||
desc = "You cant tear your sight from who is in front of you...Their gaze is simply too enthralling.."
|
||||
desc = "You cant tear your sight from who is in front of you... their gaze is simply too enthralling.."
|
||||
icon = 'icons/mob/actions/bloodsucker.dmi'
|
||||
icon_state = "power_mez"
|
||||
|
||||
@@ -609,6 +611,19 @@
|
||||
icon_state = "ichorial_stain"
|
||||
alerttooltipstyle = "clockcult"
|
||||
|
||||
/datum/status_effect/electrostaff
|
||||
id = "electrostaff"
|
||||
alert_type = null
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
|
||||
/datum/status_effect/electrostaff/on_creation(mob/living/new_owner, set_duration)
|
||||
if(isnum(set_duration))
|
||||
duration = set_duration
|
||||
. = ..()
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_ELECTROSTAFF, multiplicative_slowdown = 1, movetypes = GROUND)
|
||||
|
||||
/datum/status_effect/electrostaff/on_remove()
|
||||
owner.remove_movespeed_modifier(MOVESPEED_ID_ELECTROSTAFF)
|
||||
|
||||
//GOLEM GANG
|
||||
|
||||
|
||||
@@ -55,6 +55,8 @@ GLOBAL_LIST_EMPTY(family_heirlooms)
|
||||
heirloom_type = pick(/obj/item/cultivator, /obj/item/reagent_containers/glass/bucket, /obj/item/storage/bag/plants, /obj/item/toy/plush/beeplushie)
|
||||
if("Medical Doctor")
|
||||
heirloom_type = /obj/item/healthanalyzer/advanced
|
||||
if("Paramedic")
|
||||
heirloom_type = pick(/obj/item/clothing/neck/stethoscope, /obj/item/bodybag)
|
||||
if("Station Engineer")
|
||||
heirloom_type = /obj/item/wirecutters/brass
|
||||
if("Atmospheric Technician")
|
||||
|
||||
@@ -1245,6 +1245,22 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
icon_state = "storage_wing"
|
||||
|
||||
|
||||
// Vacant Rooms
|
||||
|
||||
/area/vacant_room
|
||||
name = "Vacant Room"
|
||||
ambientsounds = MAINTENANCE
|
||||
icon_state = "vacant_room"
|
||||
|
||||
/area/vacant_room/office
|
||||
name = "Vacant Office"
|
||||
icon_state = "vacant_room"
|
||||
|
||||
/area/vacant_room/commissary
|
||||
name = "Vacant Commissary"
|
||||
icon_state = "vacant_room"
|
||||
|
||||
|
||||
//AI
|
||||
|
||||
/area/ai_monitored/security/armory
|
||||
@@ -1367,3 +1383,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
/area/tcommsat/lounge
|
||||
name = "Telecommunications Satellite Lounge"
|
||||
icon_state = "tcomsatlounge"
|
||||
|
||||
/area/crew_quarters/fitness/pool
|
||||
name = "Pool Area"
|
||||
icon_state = "pool"
|
||||
|
||||
@@ -38,6 +38,13 @@
|
||||
var/rad_flags = NONE // Will move to flags_1 when i can be arsed to
|
||||
var/rad_insulation = RAD_NO_INSULATION
|
||||
|
||||
///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.)
|
||||
var/list/custom_materials
|
||||
///Bitfield for how the atom handles materials.
|
||||
var/material_flags = NONE
|
||||
///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines.
|
||||
var/material_modifier = 1
|
||||
|
||||
var/icon/blood_splatter_icon
|
||||
var/list/fingerprints
|
||||
var/list/fingerprintshidden
|
||||
@@ -89,6 +96,12 @@
|
||||
if (canSmoothWith)
|
||||
canSmoothWith = typelist("canSmoothWith", canSmoothWith)
|
||||
|
||||
var/temp_list = list()
|
||||
for(var/i in custom_materials)
|
||||
temp_list[getmaterialref(i)] = custom_materials[i] //Get the proper instanced version
|
||||
custom_materials = null //Null the list to prepare for applying the materials properly
|
||||
set_custom_materials(temp_list)
|
||||
|
||||
ComponentInitialize()
|
||||
|
||||
return INITIALIZE_HINT_NORMAL
|
||||
@@ -290,6 +303,11 @@
|
||||
if(desc)
|
||||
. += desc
|
||||
|
||||
if(custom_materials)
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/M = i
|
||||
. += "<u>It is made out of [M.name]</u>."
|
||||
|
||||
if(reagents)
|
||||
if(reagents.reagents_holder_flags & TRANSPARENT)
|
||||
. += "It contains:"
|
||||
@@ -316,9 +334,11 @@
|
||||
/atom/proc/update_icon()
|
||||
// I expect we're going to need more return flags and options in this proc
|
||||
var/signalOut = SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_ICON)
|
||||
. = FALSE
|
||||
|
||||
if(!(signalOut & COMSIG_ATOM_NO_UPDATE_ICON_STATE))
|
||||
update_icon_state()
|
||||
. = TRUE
|
||||
|
||||
if(!(signalOut & COMSIG_ATOM_NO_UPDATE_OVERLAYS))
|
||||
var/list/new_overlays = update_overlays()
|
||||
@@ -328,6 +348,9 @@
|
||||
if(length(new_overlays))
|
||||
managed_overlays = new_overlays
|
||||
add_overlay(new_overlays)
|
||||
. = TRUE
|
||||
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_UPDATED_ICON, signalOut, .)
|
||||
|
||||
/// Updates the icon state of the atom
|
||||
/atom/proc/update_icon_state()
|
||||
@@ -872,3 +895,26 @@ Proc for attack log creation, because really why not
|
||||
|
||||
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
|
||||
|
||||
///Sets the custom materials for an item.
|
||||
/atom/proc/set_custom_materials(var/list/materials, multiplier = 1)
|
||||
|
||||
if(!materials)
|
||||
materials = custom_materials
|
||||
|
||||
if(custom_materials) //Only runs if custom materials existed at first. Should usually be the case but check anyways
|
||||
for(var/i in custom_materials)
|
||||
var/datum/material/custom_material = getmaterialref(i)
|
||||
custom_material.on_removed(src, material_flags) //Remove the current materials
|
||||
|
||||
if(!length(materials))
|
||||
return
|
||||
|
||||
custom_materials = list() //Reset the list
|
||||
|
||||
for(var/x in materials)
|
||||
var/datum/material/custom_material = getmaterialref(x)
|
||||
|
||||
if(!(material_flags & MATERIAL_NO_EFFECTS))
|
||||
custom_material.on_applied(src, materials[custom_material] * multiplier * material_modifier, material_flags)
|
||||
custom_materials[custom_material] += materials[x] * multiplier
|
||||
|
||||
@@ -4,23 +4,17 @@
|
||||
icon = 'icons/obj/machines/nuke.dmi'
|
||||
icon_state = "bananiumbomb_base"
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/bananium/update_icon()
|
||||
if(deconstruction_state == NUKESTATE_INTACT)
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
|
||||
icon_state = "bananiumbomb_base"
|
||||
update_icon_interior()
|
||||
update_icon_lights()
|
||||
if(NUKE_ON_TIMING)
|
||||
cut_overlays()
|
||||
icon_state = "bananiumbomb_timing"
|
||||
if(NUKE_ON_EXPLODING)
|
||||
cut_overlays()
|
||||
icon_state = "bananiumbomb_exploding"
|
||||
else
|
||||
/obj/machinery/nuclearbomb/syndicate/bananium/update_icon_state()
|
||||
if(deconstruction_state != NUKESTATE_INTACT)
|
||||
icon_state = "bananiumbomb_base"
|
||||
update_icon_interior()
|
||||
update_icon_lights()
|
||||
return
|
||||
switch(get_nuke_state())
|
||||
if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED)
|
||||
icon_state = "bananiumbomb_base"
|
||||
if(NUKE_ON_TIMING)
|
||||
icon_state = "bananiumbomb_timing"
|
||||
if(NUKE_ON_EXPLODING)
|
||||
icon_state = "bananiumbomb_exploding"
|
||||
|
||||
/obj/machinery/nuclearbomb/syndicate/bananium/get_cinematic_type(off_station)
|
||||
switch(off_station)
|
||||
|
||||
@@ -40,14 +40,14 @@
|
||||
/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/Initialize()
|
||||
. = ..()
|
||||
var/datum/component/material_container/bananium = GetComponent(/datum/component/material_container)
|
||||
bananium.insert_amount(max_recharge, MAT_BANANIUM)
|
||||
bananium.insert_amount_mat(max_recharge, /datum/material/bananium)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/process()
|
||||
var/datum/component/material_container/bananium = GetComponent(/datum/component/material_container)
|
||||
var/bananium_amount = bananium.amount(MAT_BANANIUM)
|
||||
var/bananium_amount = bananium.get_material_amount(/datum/material/bananium)
|
||||
if(bananium_amount < max_recharge)
|
||||
bananium.insert_amount(min(recharge_rate, max_recharge - bananium_amount), MAT_BANANIUM)
|
||||
bananium.insert_amount_mat(min(recharge_rate, max_recharge - bananium_amount), /datum/material/bananium)
|
||||
|
||||
/obj/item/clothing/shoes/clown_shoes/banana_shoes/combat/attack_self(mob/user)
|
||||
ui_action_click(user)
|
||||
|
||||
@@ -672,7 +672,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
// Time to inject some threat into the round
|
||||
if(EMERGENCY_ESCAPED_OR_ENDGAMED) // Unless the shuttle is gone
|
||||
return
|
||||
if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) // no rules after shuttle is auto-called
|
||||
if(SSshuttle.endvote_passed) // no rules after shuttle call is voted
|
||||
return
|
||||
message_admins("DYNAMIC: Checking for midround injection.")
|
||||
log_game("DYNAMIC: Checking for midround injection.")
|
||||
@@ -748,7 +748,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic)
|
||||
return
|
||||
if(EMERGENCY_ESCAPED_OR_ENDGAMED) // No more rules after the shuttle has left
|
||||
return
|
||||
if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) // no rules after shuttle is auto-called
|
||||
if(SSshuttle.endvote_passed) // no rules after shuttle is auto-called
|
||||
return
|
||||
update_playercounts()
|
||||
|
||||
|
||||
@@ -57,7 +57,8 @@ Property weights are:
|
||||
mean += 2.5
|
||||
if(CHAOS_MAX)
|
||||
mean += 5
|
||||
GLOB.dynamic_curve_centre += (mean/voters)
|
||||
if(voters)
|
||||
GLOB.dynamic_curve_centre += (mean/voters)
|
||||
GLOB.dynamic_forced_threat_level = forced_threat_level
|
||||
|
||||
/datum/dynamic_storyteller/proc/get_midround_cooldown()
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
anchored = TRUE
|
||||
layer = HIGH_OBJ_LAYER
|
||||
max_integrity = 300
|
||||
integrity_failure = 100
|
||||
integrity_failure = 0.33
|
||||
armor = list("melee" = 20, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 10, "acid" = 70)
|
||||
var/datum/team/gang/gang
|
||||
var/operating = FALSE //false=standby or broken, true=takeover
|
||||
|
||||
@@ -220,11 +220,11 @@ datum/gang_item/clothing/shades //Addition: Why not have cool shades on a gang m
|
||||
cost = 15
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds
|
||||
|
||||
/datum/gang_item/weapon/ammo/sleeper_ammo
|
||||
/*/datum/gang_item/weapon/ammo/sleeper_ammo //no. absolutely no.
|
||||
name = "Illicit Soporific Cartridges"
|
||||
id = "sniper_ammo"
|
||||
cost = 15
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds/soporific
|
||||
cost = 15 //who the fuck thought a ONE-HIT K.O. for 15 gbp IN AN ENVIRONMENT WHERE WE'RE GETTING RID OF HARDSTUNS is a GOOD IDEA
|
||||
item_path = /obj/item/ammo_box/magazine/sniper_rounds/soporific*/
|
||||
|
||||
/datum/gang_item/weapon/machinegun
|
||||
name = "Mounted Machine Gun"
|
||||
|
||||
@@ -314,9 +314,11 @@ GLOBAL_LIST_EMPTY(objectives)
|
||||
|
||||
/datum/objective/hijack
|
||||
name = "hijack"
|
||||
explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody."
|
||||
team_explanation_text = "Hijack the shuttle to ensure no loyalist Nanotrasen crew escape alive and out of custody. Leave no team member behind."
|
||||
explanation_text = "Hijack the emergency shuttle by hacking its navigational protocols through the control console (alt click emergency shuttle console)."
|
||||
team_explanation_text = "Hijack the emergency shuttle by hacking its navigational protocols through the control console (alt click emergency shuttle console). Leave no team member behind."
|
||||
martyr_compatible = 0 //Technically you won't get both anyway.
|
||||
/// Overrides the hijack speed of any antagonist datum it is on ONLY, no other datums are impacted.
|
||||
var/hijack_speed_override = 1
|
||||
|
||||
/datum/objective/hijack/check_completion() // Requires all owners to escape.
|
||||
if(SSshuttle.emergency.mode != SHUTTLE_ENDGAME)
|
||||
@@ -1096,7 +1098,7 @@ GLOBAL_LIST_EMPTY(possible_sabotages)
|
||||
var/approved_targets = list()
|
||||
check_sabotages:
|
||||
for(var/datum/sabotage_objective/possible_sabotage in GLOB.possible_sabotages)
|
||||
if(!is_unique_objective(possible_sabotage.sabotage_type) || possible_sabotage.check_conditions())
|
||||
if(!is_unique_objective(possible_sabotage.sabotage_type) || possible_sabotage.check_conditions() || !possible_sabotage.can_run())
|
||||
continue
|
||||
for(var/datum/mind/M in owners)
|
||||
if(M.current.mind.assigned_role in possible_sabotage.excludefromjob)
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
/datum/sabotage_objective/proc/check_conditions()
|
||||
return TRUE
|
||||
|
||||
/datum/sabotage_objective/proc/can_run()
|
||||
return TRUE
|
||||
|
||||
/datum/sabotage_objective/processing
|
||||
var/won = FALSE
|
||||
|
||||
@@ -33,7 +36,7 @@
|
||||
/datum/sabotage_objective/processing/power_sink
|
||||
name = "Drain at least 1 gigajoule of power using a power sink."
|
||||
sabotage_type = "powersink"
|
||||
special_equipment = list(/obj/item/powersink)
|
||||
special_equipment = list(/obj/item/sbeacondrop/powersink)
|
||||
var/sink_found = FALSE
|
||||
var/count = 0
|
||||
|
||||
@@ -79,6 +82,9 @@
|
||||
won = max(1-((S.get_integrity()-50)/50),won)
|
||||
return FALSE
|
||||
|
||||
/datum/sabotage_objective/processing/supermatter/can_run()
|
||||
return (locate(/obj/machinery/power/supermatter_crystal) in GLOB.machines)
|
||||
|
||||
/datum/sabotage_objective/station_integrity
|
||||
name = "Make sure the station is at less than 80% integrity by the end. Smash walls, windows etc. to reach this goal."
|
||||
sabotage_type = "integrity"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
update_icon()
|
||||
|
||||
// update the icon_state
|
||||
/obj/machinery/bluespace_beacon/update_icon()
|
||||
/obj/machinery/bluespace_beacon/update_icon_state()
|
||||
var/state="floor_beacon"
|
||||
|
||||
if(invisibility)
|
||||
|
||||
@@ -9,16 +9,12 @@
|
||||
var/list/colorlist = list()
|
||||
|
||||
|
||||
/obj/machinery/pdapainter/update_icon()
|
||||
cut_overlays()
|
||||
/obj/machinery/pdapainter/update_icon_state()
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "[initial(icon_state)]-broken"
|
||||
return
|
||||
|
||||
if(storedpda)
|
||||
add_overlay("[initial(icon_state)]-closed")
|
||||
|
||||
if(powered())
|
||||
icon_state = initial(icon_state)
|
||||
else
|
||||
@@ -26,6 +22,15 @@
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/pdapainter/update_overlays()
|
||||
. = ..()
|
||||
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
if(storedpda)
|
||||
. += "[initial(icon_state)]-closed"
|
||||
|
||||
/obj/machinery/pdapainter/Initialize()
|
||||
. = ..()
|
||||
var/list/blocked = list(
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
reagents.maximum_volume = (500*E)
|
||||
|
||||
|
||||
/obj/machinery/sleeper/update_icon()
|
||||
/obj/machinery/sleeper/update_icon_state()
|
||||
icon_state = initial(icon_state)
|
||||
if(state_open)
|
||||
icon_state += "-open"
|
||||
@@ -264,7 +264,7 @@
|
||||
if(blood_id)
|
||||
data["occupant"]["blood"] = list() // We can start populating this list.
|
||||
var/blood_type = C.dna.blood_type
|
||||
if(blood_id != "blood") // special blood substance
|
||||
if(!(blood_id in GLOB.blood_reagent_types)) // special blood substance
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[blood_id]
|
||||
if(R)
|
||||
blood_type = R.name
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
id_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_SENSOR
|
||||
master_tag = INCINERATOR_SYNDICATELAVA_AIRLOCK_CONTROLLER
|
||||
|
||||
/obj/machinery/airlock_sensor/update_icon()
|
||||
/obj/machinery/airlock_sensor/update_icon_state()
|
||||
if(on)
|
||||
if(alert)
|
||||
icon_state = "airlock_sensor_alert"
|
||||
|
||||
@@ -29,25 +29,25 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
/obj/machinery/announcement_system/Initialize()
|
||||
. = ..()
|
||||
GLOB.announcement_systems += src
|
||||
radio = new /obj/item/radio/headset/ai(src)
|
||||
radio = new /obj/item/radio/headset/silicon/ai(src)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/announcement_system/update_icon()
|
||||
/obj/machinery/announcement_system/update_icon_state()
|
||||
if(is_operational())
|
||||
icon_state = (panel_open ? "AAS_On_Open" : "AAS_On")
|
||||
else
|
||||
icon_state = (panel_open ? "AAS_Off_Open" : "AAS_Off")
|
||||
|
||||
|
||||
cut_overlays()
|
||||
/obj/machinery/announcement_system/update_overlays()
|
||||
. =..()
|
||||
if(arrivalToggle)
|
||||
add_overlay(greenlight)
|
||||
. += greenlight
|
||||
|
||||
if(newheadToggle)
|
||||
add_overlay(pinklight)
|
||||
. += pinklight
|
||||
|
||||
if(stat & BROKEN)
|
||||
add_overlay(errorlight)
|
||||
. += errorlight
|
||||
|
||||
/obj/machinery/announcement_system/Destroy()
|
||||
QDEL_NULL(radio)
|
||||
|
||||
@@ -19,21 +19,21 @@
|
||||
initial_icon_state = initial(icon_state)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/aug_manipulator/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
/obj/machinery/aug_manipulator/update_icon_state()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "[initial_icon_state]-broken"
|
||||
return
|
||||
|
||||
if(storedpart)
|
||||
add_overlay("[initial_icon_state]-closed")
|
||||
|
||||
if(powered())
|
||||
icon_state = initial_icon_state
|
||||
else
|
||||
icon_state = "[initial_icon_state]-off"
|
||||
|
||||
/obj/machinery/aug_manipulator/update_overlays()
|
||||
. = ..()
|
||||
if(storedpart)
|
||||
. += "[initial_icon_state]-closed"
|
||||
|
||||
/obj/machinery/aug_manipulator/Destroy()
|
||||
QDEL_NULL(storedpart)
|
||||
return ..()
|
||||
|
||||
@@ -47,7 +47,23 @@
|
||||
)
|
||||
|
||||
/obj/machinery/autolathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
AddComponent(/datum/component/material_container,
|
||||
list(/datum/material/iron,
|
||||
/datum/material/glass,
|
||||
/datum/material/gold,
|
||||
/datum/material/silver,
|
||||
/datum/material/diamond,
|
||||
/datum/material/uranium,
|
||||
/datum/material/plasma,
|
||||
/datum/material/bluespace,
|
||||
/datum/material/bananium,
|
||||
/datum/material/titanium,
|
||||
/datum/material/runite,
|
||||
/datum/material/plastic,
|
||||
/datum/material/adamantine,
|
||||
/datum/material/mythril
|
||||
),
|
||||
0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autolathe(src)
|
||||
@@ -121,15 +137,14 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
|
||||
if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
/obj/machinery/autolathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
||||
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(MINERAL_MATERIAL_AMOUNT / 10)
|
||||
else if(item_inserted.custom_materials?.len && item_inserted.custom_materials[getmaterialref(/datum/material/glass)])
|
||||
flick("autolathe_r",src)//plays glass insertion animation by default otherwise
|
||||
else
|
||||
switch(id_inserted)
|
||||
if (MAT_METAL)
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
if (MAT_GLASS)
|
||||
flick("autolathe_r",src)//plays glass insertion animation
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
|
||||
use_power(min(1000, amount_inserted / 100))
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -160,18 +175,42 @@
|
||||
/////////////////
|
||||
|
||||
var/coeff = (is_stack ? 1 : prod_coeff) //stacks are unaffected by production coefficient
|
||||
var/metal_cost = being_built.materials[MAT_METAL]
|
||||
var/glass_cost = being_built.materials[MAT_GLASS]
|
||||
var/total_amount = 0
|
||||
|
||||
var/power = max(2000, (metal_cost+glass_cost)*multiplier/5)
|
||||
for(var/MAT in being_built.materials)
|
||||
total_amount += being_built.materials[MAT]
|
||||
|
||||
var/power = max(2000, (total_amount)*multiplier/5) //Change this to use all materials
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff))
|
||||
|
||||
var/list/materials_used = list()
|
||||
var/list/custom_materials = list() //These will apply their material effect, This should usually only be one.
|
||||
|
||||
for(var/MAT in being_built.materials)
|
||||
var/datum/material/used_material = MAT
|
||||
var/amount_needed = being_built.materials[MAT] * coeff * multiplier
|
||||
if(istext(used_material)) //This means its a category
|
||||
var/list/list_to_show = list()
|
||||
for(var/i in SSmaterials.materials_by_category[used_material])
|
||||
if(materials.materials[i] > 0)
|
||||
list_to_show += i
|
||||
|
||||
used_material = input("Choose [used_material]", "Custom Material") as null|anything in list_to_show
|
||||
if(!used_material)
|
||||
return //Didn't pick any material, so you can't build shit either.
|
||||
custom_materials[used_material] += amount_needed
|
||||
|
||||
materials_used[used_material] = amount_needed
|
||||
|
||||
if(materials.has_materials(materials_used))
|
||||
busy = TRUE
|
||||
use_power(power)
|
||||
icon_state = "autolathe_n"
|
||||
var/time = is_stack ? 32 : 32*coeff*multiplier
|
||||
addtimer(CALLBACK(src, .proc/make_item, power, metal_cost, glass_cost, multiplier, coeff, is_stack), time)
|
||||
addtimer(CALLBACK(src, .proc/make_item, power, materials_used, custom_materials, multiplier, coeff, is_stack), time)
|
||||
else
|
||||
to_chat(usr, "<span class=\"alert\">Not enough materials for this operation.</span>")
|
||||
|
||||
if(href_list["search"])
|
||||
matching_designs.Cut()
|
||||
@@ -188,12 +227,11 @@
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/autolathe/proc/make_item(power, metal_cost, glass_cost, multiplier, coeff, is_stack)
|
||||
/obj/machinery/autolathe/proc/make_item(power, var/list/materials_used, var/list/picked_materials, multiplier, coeff, is_stack)
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/atom/A = drop_location()
|
||||
use_power(power)
|
||||
var/list/materials_used = list(MAT_METAL=metal_cost*coeff*multiplier, MAT_GLASS=glass_cost*coeff*multiplier)
|
||||
materials.use_amount(materials_used)
|
||||
materials.use_materials(materials_used)
|
||||
|
||||
if(is_stack)
|
||||
var/obj/item/stack/N = new being_built.build_path(A, multiplier)
|
||||
@@ -202,10 +240,11 @@
|
||||
else
|
||||
for(var/i=1, i<=multiplier, i++)
|
||||
var/obj/item/new_item = new being_built.build_path(A)
|
||||
new_item.materials = new_item.materials.Copy()
|
||||
for(var/mat in materials_used)
|
||||
new_item.materials[mat] = materials_used[mat] / multiplier
|
||||
new_item.autolathe_crafted(src)
|
||||
|
||||
if(length(picked_materials))
|
||||
new_item.set_custom_materials(picked_materials, 1 / multiplier) //Ensure we get the non multiplied amount
|
||||
|
||||
icon_state = "autolathe"
|
||||
busy = FALSE
|
||||
updateDialog()
|
||||
@@ -270,7 +309,9 @@
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
|
||||
var/max_multiplier
|
||||
for(var/datum/material/mat in D.materials)
|
||||
max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat]))
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
@@ -302,7 +343,9 @@
|
||||
|
||||
if(ispath(D.build_path, /obj/item/stack))
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY)
|
||||
var/max_multiplier
|
||||
for(var/datum/material/mat in D.materials)
|
||||
max_multiplier = min(D.maxstack, round(materials.get_material_amount(mat)/D.materials[mat]))
|
||||
if (max_multiplier>10 && !disabled)
|
||||
dat += " <a href='?src=[REF(src)];make=[D.id];multiplier=10'>x10</a>"
|
||||
if (max_multiplier>25 && !disabled)
|
||||
@@ -319,8 +362,10 @@
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/dat = "<b>Total amount:</b> [materials.total_amount] / [materials.max_amount] cm<sup>3</sup><br>"
|
||||
for(var/mat_id in materials.materials)
|
||||
var/datum/material/M = materials.materials[mat_id]
|
||||
dat += "<b>[M.name] amount:</b> [M.amount] cm<sup>3</sup><br>"
|
||||
var/datum/material/M = mat_id
|
||||
var/mineral_amount = materials.materials[mat_id]
|
||||
if(mineral_amount > 0)
|
||||
dat += "<b>[M.name] amount:</b> [mineral_amount] cm<sup>3</sup><br>"
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/can_build(datum/design/D, amount = 1)
|
||||
@@ -329,20 +374,24 @@
|
||||
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
|
||||
var/list/required_materials = list()
|
||||
|
||||
for(var/i in D.materials)
|
||||
required_materials[i] = D.materials[i] * coeff * amount
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount)))
|
||||
return FALSE
|
||||
if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount)))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
return materials.has_materials(required_materials)
|
||||
|
||||
/obj/machinery/autolathe/proc/get_design_cost(datum/design/D)
|
||||
var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff)
|
||||
var/dat
|
||||
if(D.materials[MAT_METAL])
|
||||
dat += "[D.materials[MAT_METAL] * coeff] metal "
|
||||
if(D.materials[MAT_GLASS])
|
||||
dat += "[D.materials[MAT_GLASS] * coeff] glass"
|
||||
for(var/i in D.materials)
|
||||
if(istext(i)) //Category handling
|
||||
dat += "[D.materials[i] * coeff] [i]"
|
||||
else
|
||||
var/datum/material/M = i
|
||||
dat += "[D.materials[i] * coeff] [M.name] "
|
||||
return dat
|
||||
|
||||
/obj/machinery/autolathe/proc/reset(wire)
|
||||
|
||||
@@ -54,16 +54,17 @@
|
||||
efficiency = E
|
||||
productivity = P
|
||||
|
||||
/obj/machinery/bloodbankgen/update_icon()
|
||||
cut_overlays()
|
||||
/obj/machinery/bloodbankgen/update_icon_state()
|
||||
if(is_operational())
|
||||
icon_state = "bloodbank-on"
|
||||
icon_state = "bloodbank-[is_operational() ? "on" : "off"]"
|
||||
|
||||
/obj/machinery/bloodbankgen/update_overlays()
|
||||
. = ..()
|
||||
if(panel_open)
|
||||
add_overlay("bloodbank-panel")
|
||||
. += "bloodbank-panel"
|
||||
|
||||
if(src.bag)
|
||||
add_overlay("bloodbag-input")
|
||||
if(bag)
|
||||
. += "bloodbag-input"
|
||||
if(bag.reagents.total_volume)
|
||||
var/mutable_appearance/filling_overlay = mutable_appearance(icon, "input-reagent")
|
||||
|
||||
@@ -85,10 +86,10 @@
|
||||
filling_overlay.icon_state = "input-reagent100"
|
||||
|
||||
filling_overlay.color = list(mix_color_from_reagents(bag.reagents.reagent_list))
|
||||
add_overlay(filling_overlay)
|
||||
. += filling_overlay
|
||||
|
||||
if(src.outbag)
|
||||
add_overlay("bloodbag-output")
|
||||
if(outbag)
|
||||
. += "bloodbag-output"
|
||||
if(outbag.reagents.total_volume)
|
||||
var/mutable_appearance/filling_overlay = mutable_appearance(icon, "output-reagent")
|
||||
|
||||
@@ -110,8 +111,7 @@
|
||||
filling_overlay.icon_state = "output-reagent100"
|
||||
|
||||
filling_overlay.color = list(mix_color_from_reagents(outbag.reagents.reagent_list))
|
||||
add_overlay(filling_overlay)
|
||||
return
|
||||
. += filling_overlay
|
||||
|
||||
/obj/machinery/bloodbankgen/process()
|
||||
if(!is_operational())
|
||||
@@ -274,20 +274,20 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/bloodbankgen/proc/detachinput()
|
||||
/obj/machinery/bloodbankgen/proc/detachinput(mob/user)
|
||||
if(bag)
|
||||
bag.forceMove(drop_location())
|
||||
if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
|
||||
usr.put_in_hands(bag)
|
||||
if(user && Adjacent(usr) && user.can_hold_items())
|
||||
user.put_in_hands(bag)
|
||||
bag = null
|
||||
draining = null
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/bloodbankgen/proc/detachoutput()
|
||||
/obj/machinery/bloodbankgen/proc/detachoutput(mob/user)
|
||||
if(outbag)
|
||||
outbag.forceMove(drop_location())
|
||||
if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
|
||||
usr.put_in_hands(outbag)
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(outbag)
|
||||
outbag = null
|
||||
filling = null
|
||||
update_icon()
|
||||
@@ -325,12 +325,12 @@
|
||||
activateinput()
|
||||
|
||||
else if(href_list["detachinput"])
|
||||
detachinput()
|
||||
detachinput(usr)
|
||||
|
||||
else if(href_list["activateoutput"])
|
||||
activateoutput()
|
||||
|
||||
else if(href_list["detachoutput"])
|
||||
detachoutput()
|
||||
detachoutput(usr)
|
||||
|
||||
updateUsrDialog()
|
||||
|
||||
@@ -265,4 +265,4 @@
|
||||
desc = "Used for building buttons."
|
||||
icon_state = "button"
|
||||
result_path = /obj/machinery/button
|
||||
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
|
||||
custom_materials = list(/datum/material/iron = MINERAL_MATERIAL_AMOUNT)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 50)
|
||||
max_integrity = 100
|
||||
integrity_failure = 50
|
||||
integrity_failure = 0.5
|
||||
var/list/network = list("ss13")
|
||||
var/c_tag = null
|
||||
var/status = TRUE
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
|
||||
icon = 'icons/obj/machines/camera.dmi'
|
||||
icon_state = "cameracase"
|
||||
materials = list(MAT_METAL=400, MAT_GLASS=250)
|
||||
custom_materials = list(/datum/material/iron=400, /datum/material/glass=250)
|
||||
result_path = /obj/structure/camera_assembly
|
||||
|
||||
|
||||
|
||||
@@ -10,18 +10,19 @@
|
||||
circuit = /obj/item/circuitboard/machine/cell_charger
|
||||
pass_flags = PASSTABLE
|
||||
var/obj/item/stock_parts/cell/charging = null
|
||||
var/chargelevel = -1
|
||||
var/charge_rate = 500
|
||||
|
||||
/obj/machinery/cell_charger/update_icon()
|
||||
cut_overlays()
|
||||
if(charging)
|
||||
add_overlay(image(charging.icon, charging.icon_state))
|
||||
add_overlay("ccharger-on")
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
var/newlevel = round(charging.percent() * 4 / 100)
|
||||
chargelevel = newlevel
|
||||
add_overlay("ccharger-o[newlevel]")
|
||||
/obj/machinery/cell_charger/update_overlays()
|
||||
. += ..()
|
||||
|
||||
if(!charging)
|
||||
return
|
||||
|
||||
. += image(charging.icon, charging.icon_state)
|
||||
. += "ccharger-on"
|
||||
if(!(stat & (BROKEN|NOPOWER)))
|
||||
var/newlevel = round(charging.percent() * 4 / 100)
|
||||
. += "ccharger-o[newlevel]"
|
||||
|
||||
/obj/machinery/cell_charger/examine(mob/user)
|
||||
. = ..()
|
||||
@@ -54,7 +55,6 @@
|
||||
|
||||
charging = W
|
||||
user.visible_message("[user] inserts a cell into [src].", "<span class='notice'>You insert a cell into [src].</span>")
|
||||
chargelevel = -1
|
||||
update_icon()
|
||||
else
|
||||
if(!charging && default_deconstruction_screwdriver(user, icon_state, icon_state, W))
|
||||
@@ -77,7 +77,6 @@
|
||||
/obj/machinery/cell_charger/proc/removecell()
|
||||
charging.update_icon()
|
||||
charging = null
|
||||
chargelevel = -1
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/cell_charger/attack_hand(mob/user)
|
||||
|
||||
@@ -477,24 +477,30 @@
|
||||
|
||||
flesh_number = unattached_flesh.len
|
||||
|
||||
/obj/machinery/clonepod/update_icon()
|
||||
cut_overlays()
|
||||
|
||||
/obj/machinery/clonepod/update_icon_state()
|
||||
if(mess)
|
||||
icon_state = "pod_g"
|
||||
else if(occupant)
|
||||
icon_state = "pod_1"
|
||||
else
|
||||
icon_state = "pod_0"
|
||||
|
||||
if(panel_open)
|
||||
icon_state = "pod_0_maintenance"
|
||||
|
||||
/obj/machinery/clonepod/update_overlays()
|
||||
. = ..()
|
||||
if(mess)
|
||||
var/image/gib1 = image(CRYOMOBS, "gibup")
|
||||
var/image/gib2 = image(CRYOMOBS, "gibdown")
|
||||
gib1.pixel_y = 27 + round(sin(world.time) * 3)
|
||||
gib1.pixel_x = round(sin(world.time * 3))
|
||||
gib2.pixel_y = 27 + round(cos(world.time) * 3)
|
||||
gib2.pixel_x = round(cos(world.time * 3))
|
||||
add_overlay(gib2)
|
||||
add_overlay(gib1)
|
||||
add_overlay("cover-on")
|
||||
|
||||
. += gib2
|
||||
. += gib1
|
||||
. += "cover-on"
|
||||
else if(occupant)
|
||||
icon_state = "pod_1"
|
||||
|
||||
var/image/occupant_overlay
|
||||
var/completion = (flesh_number - unattached_flesh.len) / flesh_number
|
||||
|
||||
@@ -513,15 +519,9 @@
|
||||
occupant_overlay.pixel_y = 27 + round(sin(world.time) * 3)
|
||||
occupant_overlay.pixel_x = round(sin(world.time * 3))
|
||||
|
||||
add_overlay(occupant_overlay)
|
||||
add_overlay("cover-on")
|
||||
else
|
||||
icon_state = "pod_0"
|
||||
|
||||
if(panel_open)
|
||||
icon_state = "pod_0_maintenance"
|
||||
|
||||
add_overlay("panel")
|
||||
. += occupant_overlay
|
||||
. += "cover-on"
|
||||
. += "panel"
|
||||
|
||||
/*
|
||||
* Manual -- A big ol' manual.
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
idle_power_usage = 300
|
||||
active_power_usage = 300
|
||||
max_integrity = 200
|
||||
integrity_failure = 100
|
||||
integrity_failure = 0.5
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 40, "acid" = 20)
|
||||
var/brightness_on = 1
|
||||
var/icon_keyboard = "generic_key"
|
||||
@@ -48,13 +48,13 @@
|
||||
icon_state = initial(icon_state)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/computer/update_icon()
|
||||
cut_overlays()
|
||||
/obj/machinery/computer/update_overlays()
|
||||
. = ..()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
if(stat & NOPOWER)
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
. += "[icon_keyboard]_off"
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
. += icon_keyboard
|
||||
|
||||
// This whole block lets screens ignore lighting and be visible even in the darkest room
|
||||
// We can't do this for many things that emit light unfortunately because it layers over things that would be on top of it
|
||||
|
||||
@@ -103,21 +103,20 @@
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/computer/aifixer/update_icon()
|
||||
..()
|
||||
/obj/machinery/computer/aifixer/update_overlays()
|
||||
. = ..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if(active)
|
||||
. += "ai-fixer-on"
|
||||
if (occupier)
|
||||
switch (occupier.stat)
|
||||
if (0)
|
||||
. += "ai-fixer-full"
|
||||
if (2)
|
||||
. += "ai-fixer-404"
|
||||
else
|
||||
if(active)
|
||||
add_overlay("ai-fixer-on")
|
||||
if (occupier)
|
||||
switch (occupier.stat)
|
||||
if (0)
|
||||
add_overlay("ai-fixer-full")
|
||||
if (2)
|
||||
add_overlay("ai-fixer-404")
|
||||
else
|
||||
add_overlay("ai-fixer-empty")
|
||||
. += "ai-fixer-empty"
|
||||
|
||||
/obj/machinery/computer/aifixer/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card)
|
||||
if(!..())
|
||||
|
||||
@@ -78,23 +78,20 @@
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/computer/atmos_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
/obj/machinery/computer/atmos_alert/update_overlays()
|
||||
. = ..()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
. |= "[icon_keyboard]_off"
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
. |= icon_keyboard
|
||||
if(priority_alarms.len)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else if(minor_alarms.len)
|
||||
overlay_state = "alert:1"
|
||||
add_overlay("alert:1")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
. |= overlay_state
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
name = "incinerator chamber gas sensor"
|
||||
id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR
|
||||
|
||||
/obj/machinery/air_sensor/update_icon()
|
||||
/obj/machinery/air_sensor/update_icon_state()
|
||||
icon_state = "gsensor[on]"
|
||||
|
||||
/obj/machinery/air_sensor/process_atmos()
|
||||
|
||||
@@ -175,11 +175,10 @@
|
||||
clockwork = TRUE //it'd look very weird
|
||||
light_power = 0
|
||||
|
||||
/obj/machinery/computer/security/telescreen/update_icon()
|
||||
/obj/machinery/computer/security/telescreen/update_icon_state()
|
||||
icon_state = initial(icon_state)
|
||||
if(stat & BROKEN)
|
||||
icon_state += "b"
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/telescreen/entertainment
|
||||
name = "entertainment monitor"
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
|
||||
|
||||
/obj/machinery/computer/camera_advanced/check_eye(mob/user)
|
||||
if( (stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && !user.has_unlimited_silicon_privilege) || user.eye_blind || user.incapacitated() )
|
||||
if( (stat & (NOPOWER|BROKEN)) || (!Adjacent(user) && hasSiliconAccessInArea(user)) || user.eye_blind || user.incapacitated() )
|
||||
user.unset_machine()
|
||||
|
||||
/obj/machinery/computer/camera_advanced/Destroy()
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
state = STATE_CANCELSHUTTLE
|
||||
if("cancelshuttle2")
|
||||
if(authenticated)
|
||||
if((world.realtime - SSshuttle.realtimeofstart) > SSshuttle.auto_call) //Citadel Edit Removing auto_call caused recall.
|
||||
if(SSshuttle.endvote_passed) //Citadel Edit - endvote passing = no recalls
|
||||
say("Warning: Emergency shuttle recalls have been blocked by Central Command due to ongoing crew transfer procedures.")
|
||||
else
|
||||
SSshuttle.cancelEvac(usr)
|
||||
|
||||
@@ -40,6 +40,7 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
jobs["Geneticist"] = 22
|
||||
jobs["Virologist"] = 23
|
||||
jobs["Medical Doctor"] = 24
|
||||
jobs["Paramedic"] = 25
|
||||
jobs["Research Director"] = 30
|
||||
jobs["Scientist"] = 31
|
||||
jobs["Roboticist"] = 32
|
||||
@@ -207,4 +208,4 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
if ("select_person")
|
||||
AI.ai_camera_track(params["name"])
|
||||
|
||||
#undef SENSORS_UPDATE_PERIOD
|
||||
#undef SENSORS_UPDATE_PERIOD
|
||||
|
||||
@@ -75,25 +75,23 @@
|
||||
L -= I
|
||||
return !cleared
|
||||
|
||||
/obj/machinery/computer/station_alert/update_icon()
|
||||
..()
|
||||
cut_overlays()
|
||||
/obj/machinery/computer/station_alert/update_overlays()
|
||||
. = ..()
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
var/overlay_state = icon_screen
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
add_overlay("[icon_keyboard]_off")
|
||||
. |= "[icon_keyboard]_off"
|
||||
return
|
||||
add_overlay(icon_keyboard)
|
||||
. |= icon_keyboard
|
||||
var/active_alarms = FALSE
|
||||
for(var/cat in alarms)
|
||||
var/list/L = alarms[cat]
|
||||
if(L.len)
|
||||
if(length(alarms[cat]))
|
||||
active_alarms = TRUE
|
||||
break
|
||||
if(active_alarms)
|
||||
overlay_state = "alert:2"
|
||||
add_overlay("alert:2")
|
||||
else
|
||||
overlay_state = "alert:0"
|
||||
add_overlay("alert:0")
|
||||
. |= overlay_state
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, layer, plane, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, overlay_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir, alpha=128)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user