Merge branch 'master' of https://github.com/Citadel-Station-13/Citadel-Station-13 into tggenetics
This commit is contained in:
@@ -193,13 +193,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 +220,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 +234,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 +297,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 +312,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.
|
||||
|
||||
@@ -54,7 +54,6 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
||||
#define PASSCLOSEDTURF (1<<5)
|
||||
#define LETPASSTHROW (1<<6)
|
||||
|
||||
|
||||
//Movement Types
|
||||
#define GROUND (1<<0)
|
||||
#define FLYING (1<<1)
|
||||
|
||||
@@ -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)
|
||||
@@ -406,6 +406,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
|
||||
#define DUMMY_HUMAN_SLOT_HOLOFORM "dummy_holoform_generation"
|
||||
#define DUMMY_HUMAN_SLOT_ADMIN "admintools"
|
||||
#define DUMMY_HUMAN_SLOT_MANIFEST "dummy_manifest_generation"
|
||||
#define DUMMY_HUMAN_SLOT_HALLUCINATION "dummy_hallucination"
|
||||
|
||||
#define PR_ANNOUNCEMENTS_PER_ROUND 5 //The number of unique PR announcements allowed per round
|
||||
//This makes sure that a single person can only spam 3 reopens and 3 closes before being ignored
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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"
|
||||
|
||||
+13
-12
@@ -17,18 +17,19 @@
|
||||
|
||||
// Flags for the item_flags var on /obj/item
|
||||
|
||||
#define BEING_REMOVED (1<<0)
|
||||
#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips
|
||||
#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips
|
||||
#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
|
||||
#define SLOWS_WHILE_IN_HAND (1<<4)
|
||||
#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
|
||||
#define DROPDEL (1<<6) //When dropped, it calls qdel on itself
|
||||
#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
|
||||
#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff
|
||||
#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
|
||||
#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
|
||||
#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
|
||||
#define BEING_REMOVED (1<<0)
|
||||
#define IN_INVENTORY (1<<1) //is this item equipped into an inventory slot or hand of a mob? used for tooltips
|
||||
#define FORCE_STRING_OVERRIDE (1<<2) //used for tooltips
|
||||
#define NEEDS_PERMIT (1<<3) //Used by security bots to determine if this item is safe for public use.
|
||||
#define SLOWS_WHILE_IN_HAND (1<<4)
|
||||
#define NO_MAT_REDEMPTION (1<<5) //Stops you from putting things like an RCD or other items into an ORM or protolathe for materials.
|
||||
#define DROPDEL (1<<6) //When dropped, it calls qdel on itself
|
||||
#define NOBLUDGEON (1<<7) //when an item has this it produces no "X has been hit by Y with Z" message in the default attackby()
|
||||
#define ABSTRACT (1<<8) //for all things that are technically items but used for various different stuff
|
||||
#define IMMUTABLE_SLOW (1<<9) //When players should not be able to change the slowdown of the item (Speed potions, ect)
|
||||
#define SURGICAL_TOOL (1<<10) //Tool commonly used for surgery: won't attack targets in an active surgical operation on help intent (in case of mistakes)
|
||||
#define NO_UNIFORM_REQUIRED (1<<11) //Can be worn on certain slots (currently belt and id) that would otherwise require an uniform.
|
||||
#define NO_ATTACK_CHAIN_SOFT_STAMCRIT (1<<12) //Entirely blocks melee_attack_chain() if user is soft stamcritted. Uses getStaminaLoss() to check at this point in time. THIS DOES NOT BLOCK RANGED AFTERATTACK()S, ONLY MELEE RANGE AFTERATTACK()S.
|
||||
|
||||
// Flags for the clothing_flags var on /obj/item/clothing
|
||||
|
||||
|
||||
@@ -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.
|
||||
))
|
||||
@@ -22,6 +22,11 @@
|
||||
// Is an open container for all intents and purposes.
|
||||
#define OPENCONTAINER (REFILLABLE | DRAINABLE | TRANSPARENT)
|
||||
|
||||
//reagents_value defines, for cargo stuff.
|
||||
#define DEFAULT_REAGENTS_VALUE 1
|
||||
#define NO_REAGENTS_VALUE 0
|
||||
#define HARVEST_REAGENTS_VALUE 0.3
|
||||
|
||||
|
||||
#define TOUCH 1 // splashing
|
||||
#define INGEST 2 // ingestion
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -81,6 +81,7 @@
|
||||
|
||||
//Don't set this very much higher then 1024 unless you like inviting people in to dos your server with message spam
|
||||
#define MAX_MESSAGE_LEN 2048 //Citadel edit: What's the WORST that could happen?
|
||||
#define MAX_FAVOR_LEN 4096 //double the maximum message length.
|
||||
#define MAX_NAME_LEN 42
|
||||
#define MAX_BROADCAST_LEN 512
|
||||
#define MAX_CHARTER_LEN 80
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -108,27 +108,37 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||
message_admins("[key_name_admin(usr)] manually reloaded mentors")
|
||||
|
||||
//Flavor Text
|
||||
/mob/living/carbon/human/verb/set_flavor()
|
||||
/mob/proc/set_flavor()
|
||||
set name = "Set Flavor Text"
|
||||
set desc = "Sets an extended description of your character's features."
|
||||
set category = "IC"
|
||||
|
||||
var/new_flavor = input(src, "Enter your new flavor text:", "Flavor text", null) as message|null
|
||||
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 = sanitize(new_flavor)
|
||||
flavor_text = new_flavor
|
||||
to_chat(src, "Your flavor text has been updated.")
|
||||
|
||||
//Flavor Text
|
||||
/mob/living/carbon/human/verb/set_flavor_2()
|
||||
/mob/proc/set_flavor_2()
|
||||
set name = "Set Temporary Flavor Text"
|
||||
set desc = "Sets a description of your character's current appearance. Use this for emotions, poses etc."
|
||||
set category = "IC"
|
||||
|
||||
var/new_flavor = input(src, "Enter your new temporary flavor text:", "Temporary flavor text", null) as message|null
|
||||
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 = sanitize(new_flavor)
|
||||
flavor_text_2 = new_flavor
|
||||
to_chat(src, "Your temporary flavor text has been updated.")
|
||||
|
||||
/mob/proc/print_flavor_text(flavor)
|
||||
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.
|
||||
var/msg = html_decode(replacetext(flavor, "\n", " "))
|
||||
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>"
|
||||
|
||||
//LOOC toggles
|
||||
/client/verb/listen_looc()
|
||||
set name = "Show/Hide LOOC"
|
||||
|
||||
@@ -436,7 +436,7 @@
|
||||
var/list/result = list()
|
||||
for(var/m in group)
|
||||
var/mob/M = m
|
||||
if(!M.key || !M.client || (ignore_category && GLOB.poll_ignore[ignore_category] && M.ckey in GLOB.poll_ignore[ignore_category]))
|
||||
if(!M.key || !M.client || (ignore_category && GLOB.poll_ignore[ignore_category] && (M.ckey in GLOB.poll_ignore[ignore_category])))
|
||||
continue
|
||||
if(be_special_flag)
|
||||
if(!(M.client.prefs) || !(be_special_flag in M.client.prefs.be_special))
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -529,7 +529,7 @@ GLOBAL_LIST_EMPTY(species_list)
|
||||
continue
|
||||
if(M.stat != DEAD && !override)
|
||||
continue
|
||||
if(speaker_key && speaker_key in prefs.ignoring)
|
||||
if(speaker_key && (speaker_key in prefs.ignoring))
|
||||
continue
|
||||
|
||||
switch(message_type)
|
||||
|
||||
@@ -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("")
|
||||
|
||||
|
||||
@@ -1 +1,59 @@
|
||||
GLOBAL_LIST_EMPTY(donators_by_group) //group id = donator list of ckeys
|
||||
|
||||
GLOBAL_LIST_INIT(flirts, list("Roses are red / Violets are good / One day while Andy...",
|
||||
"My love for you is like the singularity. It cannot be contained.",
|
||||
"Will you be my lusty xenomorph maid?",
|
||||
"We go together like the clown and the external airlock.",
|
||||
"Roses are red / Liches are wizards / I love you more than a whole squad of lizards.",
|
||||
"Be my valentine. Law 2.",
|
||||
"You must be a mime, because you leave me speechless.",
|
||||
"I love you like Ian loves the HoP.",
|
||||
"You're hotter than a plasma fire in toxins.",
|
||||
"Are you a rogue atmos tech? Because you're taking my breath away.",
|
||||
"Could I have all access... to your heart?",
|
||||
"Call me the doctor, because I'm here to inspect your johnson.",
|
||||
"I'm not a changeling, but you make my proboscis extend.",
|
||||
"I just can't get EI NATH of you.",
|
||||
"You must be a nuke op, because you make my heart explode.",
|
||||
"Roses are red / Botany is a farm / Not being my Valentine / causes human harm.",
|
||||
"I want you more than an assistant wants insulated gloves.",
|
||||
"If I was a security officer, I'd brig you all shift.",
|
||||
"Are you the janitor? Because I think I've fallen for you.",
|
||||
"You're always valid to my heart.",
|
||||
"I'd risk the wrath of the gods to bwoink you.",
|
||||
"You look as beautiful now as the last time you were cloned.",
|
||||
"Someone check the gravitational generator, because I'm only attracted to you.",
|
||||
"If I were the warden I'd always let you into my armory.",
|
||||
"The virologist is rogue, and the only cure is a kiss from you.",
|
||||
"Would you spend some time in my upgraded sleeper?",
|
||||
"You must be a silicon, because you've unbolted my heart.",
|
||||
"Are you Nar'Sie? Because there's nar-one else I sie.",
|
||||
"If you were a taser, you'd be set to stunning.",
|
||||
"Do you have stamina damage from running through my dreams?",
|
||||
"If I were an alien, would you let me hug you?",
|
||||
"My love for you is stronger than a reinforced wall.",
|
||||
"This must be the captain's office, because I see a fox.",
|
||||
"I'm not a highlander, but there can only be one for me.",
|
||||
"The floor is made of lava! Quick, get on my bed.",
|
||||
"If you were an abandoned station you'd be the DEARelict.",
|
||||
"If you had a pickaxe you'd be a shaft FINEr.",
|
||||
"Roses are red, tide is gray, if I were an assistant I'd steal you away.",
|
||||
"Roses are red, text is green, I love you more than cleanbots clean.",
|
||||
"If you were a carp I'd fi-lay you.",
|
||||
"I'm a nuke op, and my pinpointer leads to your heart.",
|
||||
"Wanna slay my megafauna?",
|
||||
"I'm a clockwork cultist. Or zl inyragvar.",
|
||||
"If you were a disposal bin I'd ride you all day.",
|
||||
"Put on your explorer's suit because I'm taking you to LOVEaland.",
|
||||
"I must be the CMO, 'cause I saw you on my CUTE sensors.",
|
||||
"You're the vomit to my flyperson.",
|
||||
"You must be liquid dark matter, because you're pulling me closer.",
|
||||
"Not even sorium can drive me away from you.",
|
||||
"Wanna make like a borg and do some heavy petting?",
|
||||
"Are you powering the station? Because you super matter to me.",
|
||||
"I wish science could make me a bag of holding you.",
|
||||
"Let's call the emergency CUDDLE.",
|
||||
"I must be tripping on BZ, because I saw an angel walk by.",
|
||||
"Wanna empty out my tool storage?",
|
||||
"Did you visit the medbay after you fell from heaven?",
|
||||
"Are you wearing space pants? Wanna not be?" ))
|
||||
|
||||
@@ -4,6 +4,7 @@ GLOBAL_LIST_INIT(wizard_second, world.file2list("strings/names/wizardsecond.txt"
|
||||
GLOBAL_LIST_INIT(ninja_titles, world.file2list("strings/names/ninjatitle.txt"))
|
||||
GLOBAL_LIST_INIT(ninja_names, world.file2list("strings/names/ninjaname.txt"))
|
||||
GLOBAL_LIST_INIT(commando_names, world.file2list("strings/names/death_commando.txt"))
|
||||
GLOBAL_LIST_INIT(first_names, world.file2list("strings/names/first.txt"))
|
||||
GLOBAL_LIST_INIT(first_names_male, world.file2list("strings/names/first_male.txt"))
|
||||
GLOBAL_LIST_INIT(first_names_female, world.file2list("strings/names/first_female.txt"))
|
||||
GLOBAL_LIST_INIT(last_names, world.file2list("strings/names/last.txt"))
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
..()
|
||||
..()
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
*afterattack. The return value does not matter.
|
||||
*/
|
||||
/obj/item/proc/melee_attack_chain(mob/user, atom/target, params)
|
||||
if(item_flags & NO_ATTACK_CHAIN_SOFT_STAMCRIT)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
if(L.getStaminaLoss() >= STAMINA_SOFTCRIT)
|
||||
to_chat(L, "<span class='warning'>You are too exhausted to swing [src]!</span>")
|
||||
return
|
||||
if(tool_behaviour && target.tool_act(user, src, tool_behaviour))
|
||||
return
|
||||
if(pre_attack(target, user, params))
|
||||
|
||||
@@ -234,6 +234,7 @@
|
||||
|
||||
/datum/config_entry/number/movedelay //Used for modifying movement speed for mobs.
|
||||
abstract_type = /datum/config_entry/number/movedelay
|
||||
integer = FALSE
|
||||
|
||||
/datum/config_entry/number/movedelay/ValidateAndSet()
|
||||
. = ..()
|
||||
|
||||
@@ -118,7 +118,7 @@ SUBSYSTEM_DEF(job)
|
||||
if(flag && (!(flag in player.client.prefs.be_special)))
|
||||
JobDebug("FOC flag failed, Player: [player], Flag: [flag], ")
|
||||
continue
|
||||
if(player.mind && job.title in player.mind.restricted_roles)
|
||||
if(player.mind && (job.title in player.mind.restricted_roles))
|
||||
JobDebug("FOC incompatible with antagonist role, Player: [player]")
|
||||
continue
|
||||
if(player.client.prefs.job_preferences[job.title] == level)
|
||||
@@ -158,7 +158,7 @@ SUBSYSTEM_DEF(job)
|
||||
JobDebug("GRJ player not enough xp, Player: [player]")
|
||||
continue
|
||||
|
||||
if(player.mind && job.title in player.mind.restricted_roles)
|
||||
if(player.mind && (job.title in player.mind.restricted_roles))
|
||||
JobDebug("GRJ incompatible with antagonist role, Player: [player], Job: [job.title]")
|
||||
continue
|
||||
|
||||
@@ -340,7 +340,7 @@ SUBSYSTEM_DEF(job)
|
||||
JobDebug("DO non-human failed, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
if(player.mind && job.title in player.mind.restricted_roles)
|
||||
if(player.mind && (job.title in player.mind.restricted_roles))
|
||||
JobDebug("DO incompatible with antagonist role, Player: [player], Job:[job.title]")
|
||||
continue
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -38,7 +38,7 @@ SUBSYSTEM_DEF(shuttle)
|
||||
var/points = 5000 //number of trade-points we have
|
||||
var/centcom_message = "" //Remarks from CentCom on how well you checked the last order.
|
||||
var/list/discoveredPlants = list() //Typepaths for unusual plants we've already sent CentCom, associated with their potencies
|
||||
var/passive_supply_points_per_minute = 500
|
||||
var/passive_supply_points_per_minute = 125
|
||||
|
||||
var/list/supply_packs = list()
|
||||
var/list/shoppinglist = list()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -149,7 +149,7 @@ SUBSYSTEM_DEF(vote)
|
||||
var/list/this_vote = voted[ckey]
|
||||
var/list/pretty_vote = list()
|
||||
for(var/choice in choices)
|
||||
if("[choice]" in this_vote && "[choice]" in scores_by_choice)
|
||||
if(("[choice]" in this_vote) && ("[choice]" in scores_by_choice))
|
||||
sorted_insert(scores_by_choice["[choice]"],this_vote["[choice]"],/proc/cmp_numeric_asc)
|
||||
// START BALLOT GATHERING
|
||||
pretty_vote += "[choice]"
|
||||
@@ -160,7 +160,7 @@ SUBSYSTEM_DEF(vote)
|
||||
for(var/score_name in scores_by_choice)
|
||||
var/list/score = scores_by_choice[score_name]
|
||||
for(var/indiv_score in score)
|
||||
SSblackbox.record_feedback("nested tally","voting",1,list(blackbox_text,"Scores",score_name,GLOB.vote_score_options[indiv_score]))
|
||||
SSblackbox.record_feedback("nested tally","voting",1,list(blackbox_text,"Scores",score_name,GLOB.vote_score_options[indiv_score]))
|
||||
if(score.len == 0)
|
||||
scores_by_choice -= score_name
|
||||
while(scores_by_choice.len > 1)
|
||||
@@ -211,24 +211,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
|
||||
@@ -376,7 +376,7 @@ SUBSYSTEM_DEF(vote)
|
||||
else
|
||||
to_chat(world, "<span style='boldannounce'>Notice:Restart vote will not restart the server automatically because there are active admins on.</span>")
|
||||
message_admins("A restart vote has passed, but there are active admins on with +server, so it has been canceled. If you wish, you may restart the server.")
|
||||
|
||||
|
||||
return .
|
||||
|
||||
/datum/controller/subsystem/vote/proc/submit_vote(vote, score = 0)
|
||||
|
||||
@@ -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)
|
||||
|
||||
+2
-1
@@ -61,7 +61,8 @@
|
||||
/datum/beam/proc/recalculate_in(time)
|
||||
if(timing_id)
|
||||
deltimer(timing_id)
|
||||
timing_id = addtimer(CALLBACK(src, .proc/recalculate), time, TIMER_STOPPABLE)
|
||||
if(!finished)
|
||||
timing_id = addtimer(CALLBACK(src, .proc/recalculate), time, TIMER_STOPPABLE)
|
||||
|
||||
/datum/beam/proc/after_calculate()
|
||||
if((sleep_time == null) || finished) //Does not automatically recalculate.
|
||||
|
||||
@@ -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 pice of silk looks like 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 = 10)
|
||||
time = 450
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/smartdartgun
|
||||
name = "Smart dartgun"
|
||||
result = /obj/item/gun/syringe/dart
|
||||
@@ -278,6 +288,37 @@
|
||||
///AMMO CRAFTING//
|
||||
//////////////////
|
||||
|
||||
/datum/crafting_recipe/arrow
|
||||
name = "Arrow"
|
||||
result = /obj/item/ammo_casing/caseless/arrow
|
||||
time = 40
|
||||
reqs = list(/obj/item/stack/sheet/mineral/wood = 1,
|
||||
/obj/item/weaponcrafting/silkstring = 1,
|
||||
/obj/item/stack/rods = 3) // 1 metal sheet is worth 1.5 arrows
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/datum/crafting_recipe/bone_arrow
|
||||
name = "Bone Arrow"
|
||||
result = /obj/item/ammo_casing/caseless/arrow/bone
|
||||
time = 40
|
||||
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 = "Harden Arrow"
|
||||
result = /obj/item/ammo_casing/caseless/arrow/ashen
|
||||
tools = list(/obj/structure/bonfire)
|
||||
time = 20
|
||||
always_availible = FALSE
|
||||
reqs = list(/obj/item/ammo_casing/caseless/arrow = 1)
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
/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
|
||||
|
||||
@@ -45,4 +45,4 @@
|
||||
cleaned_human.clean_blood()
|
||||
cleaned_human.wash_cream()
|
||||
cleaned_human.regenerate_icons()
|
||||
to_chat(cleaned_human, "<span class='danger'>[src] cleans your face!</span>")
|
||||
to_chat(cleaned_human, "<span class='danger'>[AM] cleans your face!</span>")
|
||||
|
||||
@@ -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)
|
||||
@@ -40,7 +40,7 @@
|
||||
to_chat(user, "<span class='warning'>Your hands are full!</span>")
|
||||
return FALSE
|
||||
if(source.buckled)
|
||||
to_chat(user, "<span class='warning'>[src] is buckled to something!</span>")
|
||||
to_chat(user, "<span class='warning'>[source] is buckled to something!</span>")
|
||||
return FALSE
|
||||
if(source == user)
|
||||
to_chat(user, "<span class='warning'>You can't pick yourself up.</span>")
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
source.visible_message("<span class='warning'>[user] picks up [source]!</span>", \
|
||||
"<span class='userdanger'>[user] picks you up!</span>")
|
||||
to_chat(user, "<span class='notice'>You pick [src] up.</span>")
|
||||
to_chat(user, "<span class='notice'>You pick [source] up.</span>")
|
||||
source.drop_all_held_items()
|
||||
var/obj/item/clothing/head/mob_holder/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
|
||||
if(proctype)
|
||||
@@ -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)
|
||||
@@ -101,6 +101,8 @@
|
||||
target.forceMove(src)
|
||||
var/image/I = new //work around to retain the same appearance to the mob idependently from inhands/worn states.
|
||||
I.appearance = target.appearance
|
||||
I.layer = FLOAT_LAYER //So it doesn't get screwed up by layer overrides.
|
||||
I.plane = FLOAT_PLANE //Same as above but for planes.
|
||||
I.override = TRUE
|
||||
add_overlay(I)
|
||||
name = target.name
|
||||
@@ -112,23 +114,21 @@
|
||||
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)
|
||||
. = ..()
|
||||
if(AM == held_mob)
|
||||
held_mob.reset_perspective()
|
||||
held_mob = null
|
||||
qdel(src)
|
||||
QDEL_IN(src, 1) //To avoid a qdel loop.
|
||||
|
||||
/obj/item/clothing/head/mob_holder/Entered(atom/movable/AM, atom/newloc)
|
||||
. = ..()
|
||||
@@ -158,7 +158,7 @@
|
||||
/obj/item/clothing/head/mob_holder/container_resist()
|
||||
if(isliving(loc))
|
||||
var/mob/living/L = loc
|
||||
L.visible_message("<span class='warning'>[src] escapes from [L]!</span>", "<span class='warning'>[src] escapes your grip!</span>")
|
||||
L.visible_message("<span class='warning'>[held_mob] escapes from [L]!</span>", "<span class='warning'>[held_mob] escapes your grip!</span>")
|
||||
release()
|
||||
|
||||
/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
|
||||
@@ -170,7 +170,7 @@
|
||||
location = location.loc
|
||||
if(ismob(location))
|
||||
return location.loc.assume_air(env)
|
||||
return loc.assume_air(env)
|
||||
return location.assume_air(env)
|
||||
|
||||
/obj/item/clothing/head/mob_holder/remove_air(amount)
|
||||
var/atom/location = loc
|
||||
@@ -181,4 +181,4 @@
|
||||
location = location.loc
|
||||
if(ismob(location))
|
||||
return location.loc.remove_air(amount)
|
||||
return loc.remove_air(amount)
|
||||
return location.remove_air(amount)
|
||||
|
||||
@@ -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)
|
||||
@@ -12,7 +12,12 @@
|
||||
/mob/camera/aiEye/remote/holo/setLoc()
|
||||
. = ..()
|
||||
var/obj/machinery/holopad/H = origin
|
||||
H.move_hologram(eye_user, loc)
|
||||
H?.move_hologram(eye_user, loc)
|
||||
|
||||
/obj/machinery/holopad/remove_eye_control(mob/living/user)
|
||||
if(user.client)
|
||||
user.reset_perspective(null)
|
||||
user.remote_control = null
|
||||
|
||||
//this datum manages it's own references
|
||||
|
||||
@@ -54,11 +59,6 @@
|
||||
/datum/holocall/Destroy()
|
||||
QDEL_NULL(hangup)
|
||||
|
||||
var/user_good = !QDELETED(user)
|
||||
if(user_good)
|
||||
user.reset_perspective()
|
||||
user.remote_control = null
|
||||
|
||||
if(!QDELETED(eye))
|
||||
QDEL_NULL(eye)
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ GLOBAL_LIST_INIT(huds, list(
|
||||
|
||||
/datum/atom_hud
|
||||
var/list/atom/hudatoms = list() //list of all atoms which display this hud
|
||||
var/list/mob/hudusers = list() //list with all mobs who can see the hud
|
||||
var/list/hudusers = list() //list with all mobs who can see the hud
|
||||
var/list/hud_icons = list() //these will be the indexes for the atom's hud_list
|
||||
|
||||
var/list/next_time_allowed = list() //mobs associated with the next time this hud can be added to them
|
||||
|
||||
@@ -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)
|
||||
@@ -715,6 +714,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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -37,22 +37,22 @@
|
||||
|
||||
/datum/map_template/ruin/station/box/engine/teg
|
||||
id = "engine_teg"
|
||||
suffix = "Box/Engine/engine_tesla.dmm"
|
||||
suffix = "Box/Engine/engine_teg.dmm"
|
||||
name = "Box TEG"
|
||||
|
||||
/datum/map_template/ruin/station/box/engine/empty
|
||||
id = "engine_empty"
|
||||
suffix = "Box/Engine/engine_tesla.dmm"
|
||||
suffix = "Box/Engine/empty.dmm"
|
||||
name = "Box Empty"
|
||||
|
||||
/datum/map_template/ruin/station/box/engine/am
|
||||
id = "engine_am"
|
||||
suffix = "Box/Engine/engine_tesla.dmm"
|
||||
suffix = "Box/Engine/engine_am.dmm"
|
||||
name = "Box Antimatter"
|
||||
|
||||
/datum/map_template/ruin/station/box/engine/budget
|
||||
id = "engine_budget"
|
||||
suffix = "Box/Engine/engine_tesla.dmm"
|
||||
suffix = "Box/Engine/budget.dmm"
|
||||
name = "Box P.A.C.M.A.N"
|
||||
|
||||
// Lavaland
|
||||
@@ -60,4 +60,4 @@
|
||||
/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"
|
||||
name = "Public Mining Base"
|
||||
|
||||
@@ -1367,3 +1367,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:"
|
||||
@@ -872,3 +890,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
|
||||
|
||||
@@ -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)
|
||||
@@ -279,7 +279,6 @@
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/honker/dark
|
||||
max_equip = 3
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/honker/dark/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (M.mind)
|
||||
if (restrict_ghost_roles && M.mind.assigned_role in GLOB.exp_specialmap[EXP_TYPE_SPECIAL]) // Are they playing a ghost role?
|
||||
if (restrict_ghost_roles && (M.mind.assigned_role in GLOB.exp_specialmap[EXP_TYPE_SPECIAL])) // Are they playing a ghost role?
|
||||
trimmed_list.Remove(M)
|
||||
continue
|
||||
if (M.mind.assigned_role in restricted_roles) // Does their job allow it?
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
var/list/L = list()
|
||||
var/list/LL = list()
|
||||
var/hacked = FALSE
|
||||
var/hackable = TRUE
|
||||
var/disabled = 0
|
||||
var/shocked = FALSE
|
||||
var/hack_wire
|
||||
@@ -46,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)
|
||||
@@ -120,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()
|
||||
|
||||
@@ -159,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()
|
||||
@@ -187,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)
|
||||
@@ -201,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()
|
||||
@@ -269,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)
|
||||
@@ -301,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)
|
||||
@@ -318,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)
|
||||
@@ -328,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)
|
||||
@@ -371,6 +421,8 @@
|
||||
|
||||
/obj/machinery/autolathe/proc/adjust_hacked(state)
|
||||
hacked = state
|
||||
if(!hackable && hacked)
|
||||
return
|
||||
for(var/id in SSresearch.techweb_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
if((D.build_type & AUTOLATHE) && ("hacked" in D.category))
|
||||
@@ -383,6 +435,12 @@
|
||||
. = ..()
|
||||
adjust_hacked(TRUE)
|
||||
|
||||
/obj/machinery/autolathe/secure
|
||||
name = "secured autolathe"
|
||||
desc = "An autolathe reprogrammed with security protocols to prevent hacking."
|
||||
hackable = FALSE
|
||||
circuit = /obj/item/circuitboard/machine/autolathe/secure
|
||||
|
||||
//Called when the object is constructed by an autolathe
|
||||
//Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes
|
||||
/obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -47,7 +47,10 @@
|
||||
jump_action.Grant(user)
|
||||
actions += jump_action
|
||||
|
||||
/obj/machinery/computer/camera_advanced/proc/remove_eye_control(mob/living/user)
|
||||
/obj/machinery/proc/remove_eye_control(mob/living/user)
|
||||
CRASH("[type] does not implement ai eye handling")
|
||||
|
||||
/obj/machinery/computer/camera_advanced/remove_eye_control(mob/living/user)
|
||||
if(!user)
|
||||
return
|
||||
for(var/V in actions)
|
||||
@@ -69,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()
|
||||
@@ -157,7 +160,7 @@
|
||||
var/cooldown = 0
|
||||
var/acceleration = 1
|
||||
var/mob/living/eye_user = null
|
||||
var/obj/machinery/computer/camera_advanced/origin
|
||||
var/obj/machinery/origin
|
||||
var/eye_initialized = 0
|
||||
var/visible_icon = 0
|
||||
var/image/user_image = null
|
||||
@@ -170,7 +173,7 @@
|
||||
|
||||
/mob/camera/aiEye/remote/Destroy()
|
||||
if(origin && eye_user)
|
||||
origin.remove_eye_control(eye_user)
|
||||
origin.remove_eye_control(eye_user,src)
|
||||
origin = null
|
||||
. = ..()
|
||||
eye_user = null
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* ~ Zuhayr
|
||||
*/
|
||||
|
||||
|
||||
//Main cryopod console.
|
||||
|
||||
/obj/machinery/computer/cryopod
|
||||
@@ -18,7 +17,6 @@
|
||||
density = FALSE
|
||||
interaction_flags_machine = INTERACT_MACHINE_OFFLINE
|
||||
req_one_access = list(ACCESS_HEADS, ACCESS_ARMORY) //Heads of staff or the warden can go here to claim recover items from their department that people went were cryodormed with.
|
||||
var/mode = null
|
||||
|
||||
var/menu = 1 //Which menu screen to display
|
||||
|
||||
@@ -118,7 +116,7 @@
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
|
||||
I.forceMove(drop_location())
|
||||
if(user && Adjacent(user) && !issiliconoradminghost(user))
|
||||
if(user && Adjacent(user) && user.can_hold_items())
|
||||
user.put_in_hands(I)
|
||||
frozen_items -= I
|
||||
updateUsrDialog()
|
||||
@@ -130,7 +128,8 @@
|
||||
playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
|
||||
updateUsrDialog()
|
||||
return
|
||||
if(!allow_items) return
|
||||
if(!allow_items)
|
||||
return
|
||||
|
||||
if(frozen_items.len == 0)
|
||||
to_chat(user, "<span class='notice'>There is nothing to recover from storage.</span>")
|
||||
@@ -182,7 +181,7 @@
|
||||
var/last_no_computer_message = 0
|
||||
|
||||
// These items are preserved when the process() despawn proc occurs.
|
||||
var/list/preserve_items = list(
|
||||
var/static/list/preserve_items = typecacheof(list(
|
||||
/obj/item/hand_tele,
|
||||
/obj/item/card/id/captains_spare,
|
||||
/obj/item/aicard,
|
||||
@@ -203,9 +202,9 @@
|
||||
/obj/item/tank/jetpack,
|
||||
/obj/item/documents,
|
||||
/obj/item/nuke_core_container
|
||||
)
|
||||
))
|
||||
// These items will NOT be preserved
|
||||
var/list/do_not_preserve_items = list (
|
||||
var/static/list/do_not_preserve_items = typecacheof(list(
|
||||
/obj/item/mmi/posibrain,
|
||||
/obj/item/gun/energy/laser/mounted,
|
||||
/obj/item/gun/energy/e_gun/advtaser/mounted,
|
||||
@@ -215,7 +214,7 @@
|
||||
/obj/item/gun/energy/printer,
|
||||
/obj/item/gun/energy/kinetic_accelerator/cyborg,
|
||||
/obj/item/gun/energy/laser/cyborg
|
||||
)
|
||||
))
|
||||
|
||||
/obj/machinery/cryopod/Initialize(mapload)
|
||||
. = ..()
|
||||
@@ -287,14 +286,14 @@
|
||||
#define CRYO_DESTROY 0
|
||||
#define CRYO_PRESERVE 1
|
||||
#define CRYO_OBJECTIVE 2
|
||||
#define CRYO_IGNORE 3
|
||||
|
||||
/obj/machinery/cryopod/proc/should_preserve_item(obj/item/I)
|
||||
for(var/datum/objective_item/steal/T in control_computer.theft_cache)
|
||||
if(istype(I, T.targetitem) && T.check_special_completion(I))
|
||||
return CRYO_OBJECTIVE
|
||||
for(var/T in preserve_items)
|
||||
if(istype(I, T) && !(I.type in do_not_preserve_items))
|
||||
return CRYO_PRESERVE
|
||||
if(preserve_items[I] && !do_not_preserve_items[I])
|
||||
return CRYO_PRESERVE
|
||||
return CRYO_DESTROY
|
||||
|
||||
// This function can not be undone; do not call this unless you are sure
|
||||
@@ -303,52 +302,47 @@
|
||||
find_control_computer()
|
||||
|
||||
var/mob/living/mob_occupant = occupant
|
||||
var/list/obj/item/cryo_items = list()
|
||||
|
||||
//Handle Borg stuff first
|
||||
if(iscyborg(mob_occupant))
|
||||
var/mob/living/silicon/robot/R = mob_occupant
|
||||
|
||||
R.contents -= R.mmi
|
||||
qdel(R.mmi)
|
||||
if(R.mmi?.brain)
|
||||
cryo_items[R.mmi] = CRYO_IGNORE
|
||||
cryo_items[R.mmi.brain] = CRYO_IGNORE
|
||||
for(var/obj/item/I in R.module) // the tools the borg has; metal, glass, guns etc
|
||||
for(var/obj/item/O in I) // the things inside the tools, if anything; mainly for janiborg trash bags
|
||||
if(should_preserve_item(O) != CRYO_DESTROY) // Preserve important things inside the item
|
||||
continue
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
R.module.remove_module(I, TRUE) //delete the module itself so it doesn't transfer over.
|
||||
|
||||
//Drop all items into the pod.
|
||||
for(var/obj/item/I in mob_occupant)
|
||||
mob_occupant.doUnEquip(I)
|
||||
I.forceMove(src)
|
||||
|
||||
if(cryo_items[I] == CRYO_IGNORE)
|
||||
continue
|
||||
cryo_items[I] = should_preserve_item(I)
|
||||
mob_occupant.transferItemToLoc(I, src, TRUE)
|
||||
if(I.contents.len) //Make sure we catch anything not handled by qdel() on the items.
|
||||
if(should_preserve_item(I) != CRYO_DESTROY) // Don't remove the contents of things that need preservation
|
||||
if(cryo_items[I] != CRYO_DESTROY) // Don't remove the contents of things that need preservation
|
||||
continue
|
||||
for(var/obj/item/O in I.contents)
|
||||
if(istype(O, /obj/item/tank)) //Stop eating pockets, you fuck!
|
||||
continue
|
||||
cryo_items[O] = should_preserve_item(O)
|
||||
O.forceMove(src)
|
||||
|
||||
//Delete all items not on the preservation list.
|
||||
var/list/items = contents
|
||||
items -= mob_occupant // Don't delete the occupant
|
||||
|
||||
for(var/obj/item/I in items)
|
||||
if(istype(I, /obj/item/pda))
|
||||
var/obj/item/pda/P = I
|
||||
QDEL_NULL(P.id)
|
||||
qdel(P)
|
||||
for(var/A in cryo_items)
|
||||
var/obj/item/I = A
|
||||
if(QDELETED(I)) //edge cases and DROPDEL.
|
||||
continue
|
||||
|
||||
var/preserve = should_preserve_item(I)
|
||||
if(preserve == CRYO_DESTROY)
|
||||
var/preserve = cryo_items[I]
|
||||
if(preserve == CRYO_IGNORE)
|
||||
continue
|
||||
else if(preserve == CRYO_DESTROY)
|
||||
qdel(I)
|
||||
else if(control_computer && control_computer.allow_items)
|
||||
else if(control_computer?.allow_items)
|
||||
control_computer.frozen_items += I
|
||||
if(preserve == CRYO_OBJECTIVE)
|
||||
control_computer.objective_items += I
|
||||
I.loc = null
|
||||
I.moveToNullspace()
|
||||
else
|
||||
I.forceMove(loc)
|
||||
|
||||
@@ -417,6 +411,7 @@
|
||||
#undef CRYO_DESTROY
|
||||
#undef CRYO_PRESERVE
|
||||
#undef CRYO_OBJECTIVE
|
||||
#undef CRYO_IGNORE
|
||||
|
||||
/obj/machinery/cryopod/MouseDrop_T(mob/living/target, mob/user)
|
||||
if(!istype(target) || user.incapacitated() || !target.Adjacent(user) || !Adjacent(user) || !ismob(target) || (!ishuman(user) && !iscyborg(user)) || !istype(user.loc, /turf) || target.buckled)
|
||||
@@ -443,29 +438,24 @@
|
||||
var/generic_plsnoleave_message = " Please adminhelp before leaving the round, even if there are no administrators online!"
|
||||
|
||||
if(target == user && world.time - target.client.cryo_warned > 5 MINUTES)//if we haven't warned them in the last 5 minutes
|
||||
var/caught = FALSE
|
||||
var/list/caught_string
|
||||
var/addendum = ""
|
||||
if(target.mind.assigned_role in GLOB.command_positions)
|
||||
alert("<span class='userdanger'>You're a Head of Staff![generic_plsnoleave_message] Be sure to put your locker items back into your locker!</span>")
|
||||
caught = TRUE
|
||||
LAZYADD(caught_string, "Head of Staff")
|
||||
addendum = " Be sure to put your locker items back into your locker!"
|
||||
if(iscultist(target) || is_servant_of_ratvar(target))
|
||||
to_chat(target, "<span class='userdanger'>You're a Cultist![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
LAZYADD(caught_string, "Cultist")
|
||||
if(is_devil(target))
|
||||
alert("<span class='userdanger'>You're a Devil![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
if(istype(SSticker.mode, /datum/antagonist/gang))
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/gang))
|
||||
alert("<span class='userdanger'>You're a Gangster![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
if(istype(SSticker.mode, /datum/antagonist/rev))
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev/head))
|
||||
alert("<span class='userdanger'>You're a Head Revolutionary![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
else if(target.mind.has_antag_datum(/datum/antagonist/rev))
|
||||
alert("<span class='userdanger'>You're a Revolutionary![generic_plsnoleave_message]</span>")
|
||||
caught = TRUE
|
||||
LAZYADD(caught_string, "Devil")
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/gang))
|
||||
LAZYADD(caught_string, "Gangster")
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev/head))
|
||||
LAZYADD(caught_string, "Head Revolutionary")
|
||||
if(target.mind.has_antag_datum(/datum/antagonist/rev))
|
||||
LAZYADD(caught_string, "Revolutionary")
|
||||
|
||||
if(caught)
|
||||
if(caught_string)
|
||||
alert(target, "You're a [english_list(caught_string)]![generic_plsnoleave_message][addendum]")
|
||||
target.client.cryo_warned = world.time
|
||||
return
|
||||
|
||||
|
||||
@@ -202,6 +202,8 @@
|
||||
for(var/i in 1 to 10)
|
||||
spawn_atom_to_turf(/obj/effect/temp_visual/hierophant/telegraph/edge, src, 1, FALSE)
|
||||
sleep(5)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
#define DISCO_INFENO_RANGE (rand(85, 115)*0.01)
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
desc = "A frame for a defibrillator mount. It can't be removed once it's placed."
|
||||
icon = 'icons/obj/machines/defib_mount.dmi'
|
||||
icon_state = "defibrillator_mount"
|
||||
materials = list(MAT_METAL = 300, MAT_GLASS = 100)
|
||||
custom_materials = list(/datum/material/iron = 300, /datum/material/glass = 100)
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
result_path = /obj/machinery/defibrillator_mount
|
||||
pixel_shift = -28
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
density = TRUE
|
||||
max_integrity = 100
|
||||
var/proj_pass_rate = 50 //How many projectiles will pass the cover. Lower means stronger cover
|
||||
var/material = METAL
|
||||
var/bar_material = METAL
|
||||
|
||||
/obj/structure/barricade/deconstruct(disassembled = TRUE)
|
||||
if(!(flags_1 & NODECONSTRUCT_1))
|
||||
@@ -26,7 +26,7 @@
|
||||
return
|
||||
|
||||
/obj/structure/barricade/attackby(obj/item/I, mob/user, params)
|
||||
if(istype(I, /obj/item/weldingtool) && user.a_intent != INTENT_HARM && material == METAL)
|
||||
if(istype(I, /obj/item/weldingtool) && user.a_intent != INTENT_HARM && bar_material == METAL)
|
||||
if(obj_integrity < max_integrity)
|
||||
if(!I.tool_start_check(user, amount=0))
|
||||
return
|
||||
@@ -61,7 +61,7 @@
|
||||
desc = "This space is blocked off by a wooden barricade."
|
||||
icon = 'icons/obj/structures.dmi'
|
||||
icon_state = "woodenbarricade"
|
||||
material = WOOD
|
||||
bar_material = WOOD
|
||||
var/drop_amount = 3
|
||||
|
||||
/obj/structure/barricade/wooden/attackby(obj/item/I, mob/user)
|
||||
@@ -106,7 +106,7 @@
|
||||
max_integrity = 280
|
||||
proj_pass_rate = 20
|
||||
pass_flags = LETPASSTHROW
|
||||
material = SAND
|
||||
bar_material = SAND
|
||||
climbable = TRUE
|
||||
smooth = SMOOTH_TRUE
|
||||
canSmoothWith = list(/obj/structure/barricade/sandbags, /turf/closed/wall, /turf/closed/wall/r_wall, /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/closed/wall/rust, /turf/closed/wall/r_wall/rust, /obj/structure/barricade/security)
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
icon_state = "closed"
|
||||
max_integrity = 300
|
||||
var/normal_integrity = AIRLOCK_INTEGRITY_N
|
||||
integrity_failure = 70
|
||||
integrity_failure = 0.25
|
||||
damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N
|
||||
autoclose = TRUE
|
||||
secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
|
||||
@@ -469,7 +469,7 @@
|
||||
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
|
||||
if(welded)
|
||||
weld_overlay = get_airlock_overlay("welded", overlays_file)
|
||||
if(obj_integrity <integrity_failure)
|
||||
if(obj_integrity < integrity_failure * max_integrity)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
else if(obj_integrity < (0.75 * max_integrity))
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
@@ -495,7 +495,7 @@
|
||||
panel_overlay = get_airlock_overlay("panel_closed_protected", overlays_file)
|
||||
else
|
||||
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
|
||||
if(obj_integrity <integrity_failure)
|
||||
if(obj_integrity < integrity_failure * max_integrity)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
else if(obj_integrity < (0.75 * max_integrity))
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
@@ -517,7 +517,7 @@
|
||||
panel_overlay = get_airlock_overlay("panel_closed_protected", overlays_file)
|
||||
else
|
||||
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
|
||||
if(obj_integrity <integrity_failure)
|
||||
if(obj_integrity < integrity_failure * max_integrity)
|
||||
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
else if(obj_integrity < (0.75 * max_integrity))
|
||||
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
density = TRUE
|
||||
|
||||
max_integrity = 250
|
||||
integrity_failure = 80
|
||||
integrity_failure = 0.33
|
||||
|
||||
// These allow for different icons when creating custom dispensers
|
||||
var/icon_off = "off"
|
||||
@@ -50,10 +50,10 @@
|
||||
|
||||
/obj/machinery/droneDispenser/Initialize()
|
||||
. = ..()
|
||||
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE, /obj/item/stack)
|
||||
materials.insert_amount(starting_amount)
|
||||
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE, /obj/item/stack)
|
||||
materials.insert_amount_mat(starting_amount)
|
||||
materials.precise_insertion = TRUE
|
||||
using_materials = list(MAT_METAL=metal_cost, MAT_GLASS=glass_cost)
|
||||
using_materials = list(/datum/material/iron = metal_cost, /datum/material/glass = glass_cost)
|
||||
|
||||
/obj/machinery/droneDispenser/preloaded
|
||||
starting_amount = 5000
|
||||
@@ -168,7 +168,7 @@
|
||||
update_icon()
|
||||
|
||||
if(DRONE_PRODUCTION)
|
||||
materials.use_amount(using_materials)
|
||||
materials.use_materials(using_materials)
|
||||
if(power_used)
|
||||
use_power(power_used)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
icon = 'icons/obj/monitors.dmi'
|
||||
icon_state = "fire0"
|
||||
max_integrity = 250
|
||||
integrity_failure = 100
|
||||
integrity_failure = 0.4
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 90, "acid" = 30)
|
||||
use_power = IDLE_POWER_USE
|
||||
idle_power_usage = 2
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
icon = 'icons/obj/stationobjs.dmi'
|
||||
icon_state = "mflash1"
|
||||
max_integrity = 250
|
||||
integrity_failure = 100
|
||||
integrity_failure = 0.4
|
||||
light_color = LIGHT_COLOR_WHITE
|
||||
light_power = FLASH_LIGHT_POWER
|
||||
var/obj/item/assembly/flash/handheld/bulb
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
if(usr.incapacitated())
|
||||
return
|
||||
if(beaker)
|
||||
if(usr && Adjacent(usr) && !issiliconoradminghost(usr))
|
||||
if(usr && Adjacent(usr) && usr.can_hold_items())
|
||||
if(!usr.put_in_hands(beaker))
|
||||
beaker.forceMove(drop_location())
|
||||
beaker = null
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
var/raising= 0 //if the turret is currently opening or closing its cover
|
||||
|
||||
max_integrity = 160 //the turret's health
|
||||
integrity_failure = 80
|
||||
integrity_failure = 0.5
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
|
||||
var/locked = TRUE //if the turret's behaviour control access is locked
|
||||
@@ -717,7 +717,6 @@
|
||||
return 10 //Syndicate turrets shoot everything not in their faction
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/pod
|
||||
integrity_failure = 20
|
||||
max_integrity = 40
|
||||
stun_projectile = /obj/item/projectile/bullet/syndicate_turret
|
||||
lethal_projectile = /obj/item/projectile/bullet/syndicate_turret
|
||||
@@ -799,7 +798,6 @@
|
||||
|
||||
/obj/machinery/porta_turret/centcom_shuttle/weak
|
||||
max_integrity = 120
|
||||
integrity_failure = 60
|
||||
name = "Old Laser Turret"
|
||||
desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else."
|
||||
stun_projectile = /obj/item/projectile/beam/weak/penetrator
|
||||
@@ -989,7 +987,7 @@
|
||||
desc = "Used for building turret control panels."
|
||||
icon_state = "apc"
|
||||
result_path = /obj/machinery/turretid
|
||||
materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT)
|
||||
custom_materials = list(/datum/material/iron=MINERAL_MATERIAL_AMOUNT)
|
||||
|
||||
/obj/item/gun/proc/get_turret_properties()
|
||||
. = list()
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
/obj/machinery/recycler/Initialize()
|
||||
AddComponent(/datum/component/butchering/recycler, 1, amount_produced,amount_produced/5)
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLASTIC), INFINITY, FALSE, null, null, null, TRUE)
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass, /datum/material/silver, /datum/material/plasma, /datum/material/gold, /datum/material/diamond, /datum/material/plastic, /datum/material/uranium, /datum/material/bananium, /datum/material/titanium, /datum/material/bluespace), INFINITY, FALSE, null, null, null, TRUE)
|
||||
. = ..()
|
||||
update_icon()
|
||||
req_one_access = get_all_accesses() + get_all_centcom_access()
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
else
|
||||
if(!user.temporarilyRemoveItemFromInventory(C))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You insert a [C.cmineral] coin into [src]'s slot!</span>")
|
||||
to_chat(user, "<span class='notice'>You insert [C] into [src]'s slot!</span>")
|
||||
balance += C.value
|
||||
qdel(C)
|
||||
else
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
try_detonate(TRUE)
|
||||
//Counter terrorists win
|
||||
else if(!active || defused)
|
||||
if(defused && payload in src)
|
||||
if(defused && (payload in src))
|
||||
payload.defuse()
|
||||
countdown.stop()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
for(var/obj/machinery/telecomms/hub/H in links)
|
||||
for(var/obj/machinery/telecomms/relay/R in H.links)
|
||||
if(R.can_receive(signal) && R.z in signal.levels)
|
||||
if(R.can_receive(signal) && (R.z in signal.levels))
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
)
|
||||
|
||||
/obj/machinery/autoylathe/Initialize()
|
||||
AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASTIC), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
AddComponent(/datum/component/material_container, list(/datum/material/iron, /datum/material/glass, /datum/material/plastic), 0, TRUE, null, null, CALLBACK(src, .proc/AfterMaterialInsert))
|
||||
. = ..()
|
||||
|
||||
wires = new /datum/wires/autoylathe(src)
|
||||
@@ -120,18 +120,13 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/autoylathe/proc/AfterMaterialInsert(type_inserted, id_inserted, amount_inserted)
|
||||
if(ispath(type_inserted, /obj/item/stack/ore/bluespace_crystal))
|
||||
use_power(amount_inserted / 10)
|
||||
/obj/machinery/autoylathe/proc/AfterMaterialInsert(obj/item/item_inserted, id_inserted, amount_inserted)
|
||||
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
|
||||
if (MAT_PLASTIC)
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
use_power(amount_inserted / 10)
|
||||
flick("autolathe_o",src)//plays metal insertion animation
|
||||
|
||||
use_power(min(1000, amount_inserted / 100))
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/autoylathe/Topic(href, href_list)
|
||||
@@ -161,18 +156,40 @@
|
||||
/////////////////
|
||||
|
||||
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/plastic_cost = being_built.materials[MAT_PLASTIC]
|
||||
var/power = max(2000, (metal_cost+glass_cost+plastic_cost)*multiplier/5)
|
||||
var/total_amount = 0
|
||||
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) && (materials.amount(MAT_PLASTIC) >= plastic_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, plastic_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()
|
||||
@@ -189,12 +206,11 @@
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/autoylathe/proc/make_item(power, metal_cost, glass_cost, plastic_cost, multiplier, coeff, is_stack)
|
||||
/obj/machinery/autoylathe/proc/make_item(power, list/materials_used, 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, MAT_PLASTIC=plastic_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)
|
||||
@@ -203,10 +219,9 @@
|
||||
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.autoylathe_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()
|
||||
@@ -265,7 +280,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,D.materials[MAT_PLASTIC] ?round(materials.amount(MAT_PLASTIC)/D.materials[MAT_PLASTIC]):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)
|
||||
@@ -297,7 +314,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,D.materials[MAT_PLASTIC] ?round(materials.amount(MAT_PLASTIC)/D.materials[MAT_PLASTIC]):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)
|
||||
@@ -314,8 +333,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/autoylathe/proc/can_build(datum/design/D, amount = 1)
|
||||
@@ -324,24 +345,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
|
||||
if(D.materials[MAT_PLASTIC] && (materials.amount(MAT_PLASTIC) < (D.materials[MAT_PLASTIC] * coeff * amount)))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
return materials.has_materials(required_materials)
|
||||
|
||||
/obj/machinery/autoylathe/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 "
|
||||
if(D.materials[MAT_PLASTIC])
|
||||
dat += "[D.materials[MAT_PLASTIC] * coeff] plastic"
|
||||
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/autoylathe/proc/reset(wire)
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
internal_damage_threshold = 50
|
||||
armor = list("melee" = 30, "bullet" = 30, "laser" = 15, "energy" = 20, "bomb" = 20, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 100)
|
||||
mouse_pointer = 'icons/mecha/mecha_mouse.dmi'
|
||||
var/spawn_tracked = TRUE
|
||||
|
||||
/obj/mecha/combat/Initialize()
|
||||
. = ..()
|
||||
if(spawn_tracked)
|
||||
trackers += new /obj/item/mecha_parts/mecha_tracking(src)
|
||||
/obj/mecha/combat/proc/max_ammo() //Max the ammo stored for Nuke Ops mechs, or anyone else that calls this
|
||||
for(var/obj/item/I in equipment)
|
||||
if(istype(I, /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/))
|
||||
var/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/gun = I
|
||||
gun.projectiles_cache = gun.projectiles_cache_max
|
||||
@@ -30,7 +30,6 @@
|
||||
internals_req_access = list(ACCESS_SYNDICATE)
|
||||
wreckage = /obj/structure/mecha_wreckage/gygax/dark
|
||||
max_equip = 4
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/gygax/dark/loaded/Initialize()
|
||||
. = ..()
|
||||
@@ -42,6 +41,7 @@
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay
|
||||
ME.attach(src)
|
||||
max_ammo()
|
||||
|
||||
/obj/mecha/combat/gygax/dark/add_cell(obj/item/stock_parts/cell/C=null)
|
||||
if(C)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
force = 45
|
||||
max_equip = 4
|
||||
bumpsmash = 1
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/marauder/GrantActions(mob/living/user, human_occupant = 0)
|
||||
..()
|
||||
@@ -41,6 +40,7 @@
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
max_ammo()
|
||||
|
||||
/obj/mecha/combat/marauder/seraph
|
||||
desc = "Heavy-duty, command-type exosuit. This is a custom model, utilized only by high-ranking military personnel."
|
||||
@@ -68,6 +68,7 @@
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
max_ammo()
|
||||
|
||||
/obj/mecha/combat/marauder/mauler
|
||||
desc = "Heavy-duty, combat exosuit, developed off of the existing Marauder model."
|
||||
@@ -90,5 +91,6 @@
|
||||
ME.attach(src)
|
||||
ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
|
||||
ME.attach(src)
|
||||
max_ammo()
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
internals_req_access = list()
|
||||
add_req_access = 0
|
||||
wreckage = /obj/structure/mecha_wreckage/durand/neovgre
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/neovgre/GrantActions(mob/living/user, human_occupant = 0) //No Eject action for you sonny jim, your life for Ratvar!
|
||||
internals_action.Grant(user, src)
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
stepsound = null
|
||||
turnsound = null
|
||||
opacity = 0
|
||||
spawn_tracked = FALSE
|
||||
|
||||
/obj/mecha/combat/reticence/loaded/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -527,7 +527,8 @@
|
||||
range = MELEE|RANGED
|
||||
equip_cooldown = 0
|
||||
var/obj/item/gun/medbeam/mech/medigun
|
||||
materials = list(MAT_METAL = 15000, MAT_GLASS = 8000, MAT_PLASMA = 3000, MAT_GOLD = 8000, MAT_DIAMOND = 2000)
|
||||
custom_materials = list(/datum/material/iron = 15000, /datum/material/glass = 8000, /datum/material/plasma = 3000, /datum/material/gold = 8000, /datum/material/diamond = 2000)
|
||||
material_flags = MATERIAL_NO_EFFECTS
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical/mechmedbeam/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -388,7 +388,7 @@
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
|
||||
var/output = ..()
|
||||
if(output)
|
||||
return "[output] \[[fuel]: [round(fuel.amount*fuel.perunit,0.1)] cm<sup>3</sup>\] - <a href='?src=[REF(src)];toggle=1'>[equip_ready?"A":"Dea"]ctivate</a>"
|
||||
return "[output] \[[fuel]: [round(fuel.amount*fuel.mats_per_stack,0.1)] cm<sup>3</sup>\] - <a href='?src=[REF(src)];toggle=1'>[equip_ready?"A":"Dea"]ctivate</a>"
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/action(target)
|
||||
if(chassis)
|
||||
@@ -398,9 +398,9 @@
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/proc/load_fuel(var/obj/item/stack/sheet/P)
|
||||
if(P.type == fuel.type && P.amount > 0)
|
||||
var/to_load = max(max_fuel - fuel.amount*fuel.perunit,0)
|
||||
var/to_load = max(max_fuel - fuel.amount*fuel.mats_per_stack,0)
|
||||
if(to_load)
|
||||
var/units = min(max(round(to_load / P.perunit),1),P.amount)
|
||||
var/units = min(max(round(to_load / P.mats_per_stack),1),P.amount)
|
||||
fuel.amount += units
|
||||
P.use(units)
|
||||
occupant_message("[units] unit\s of [fuel] successfully loaded.")
|
||||
@@ -454,7 +454,7 @@
|
||||
if(cur_charge < chassis.cell.maxcharge)
|
||||
use_fuel = fuel_per_cycle_active
|
||||
chassis.give_power(power_per_cycle)
|
||||
fuel.amount -= min(use_fuel/fuel.perunit,fuel.amount)
|
||||
fuel.amount -= min(use_fuel/fuel.mats_per_stack,fuel.amount)
|
||||
update_equip_info()
|
||||
return 1
|
||||
|
||||
|
||||
@@ -34,6 +34,19 @@
|
||||
return
|
||||
if(!cargo_holder)
|
||||
return
|
||||
if(ismecha(target))
|
||||
var/obj/mecha/M = target
|
||||
var/have_ammo
|
||||
for(var/obj/item/mecha_ammo/box in cargo_holder.cargo)
|
||||
if(istype(box, /obj/item/mecha_ammo) && box.rounds)
|
||||
have_ammo = TRUE
|
||||
if(M.ammo_resupply(box, chassis.occupant, TRUE))
|
||||
return
|
||||
if(have_ammo)
|
||||
to_chat(chassis.occupant, "No further supplies can be provided to [M].")
|
||||
else
|
||||
to_chat(chassis.occupant, "No providable supplies found in cargo hold")
|
||||
return
|
||||
if(isobj(target))
|
||||
var/obj/O = target
|
||||
if(!O.anchored)
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/obj/item/mecha_ammo
|
||||
name = "generic ammo box"
|
||||
desc = "A box of ammo for an unknown weapon."
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
icon = 'icons/mecha/mecha_ammo.dmi'
|
||||
icon_state = "empty"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
var/rounds = 0
|
||||
var/round_term = "round"
|
||||
var/direct_load //For weapons where we re-load the weapon itself rather than adding to the ammo storage.
|
||||
var/load_audio = "sound/weapons/gun_magazine_insert_empty_1.ogg"
|
||||
var/ammo_type
|
||||
|
||||
/obj/item/mecha_ammo/proc/update_name()
|
||||
if(!rounds)
|
||||
name = "empty ammo box"
|
||||
desc = "An exosuit ammuniton box that has since been emptied. Please recycle."
|
||||
icon_state = "empty"
|
||||
|
||||
/obj/item/mecha_ammo/attack_self(mob/user)
|
||||
..()
|
||||
if(rounds)
|
||||
to_chat(user, "<span class='warning'>You cannot flatten the ammo box until it's empty!</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You fold [src] flat.</span>")
|
||||
var/I = new /obj/item/stack/sheet/metal(user.loc)
|
||||
qdel(src)
|
||||
user.put_in_hands(I)
|
||||
|
||||
/obj/item/mecha_ammo/examine(mob/user)
|
||||
. = ..()
|
||||
if(rounds)
|
||||
. += "There [rounds > 1?"are":"is"] [rounds] [round_term][rounds > 1?"s":""] left."
|
||||
|
||||
/obj/item/mecha_ammo/incendiary
|
||||
name = "incendiary ammo"
|
||||
desc = "A box of incendiary ammunition for use with exosuit weapons."
|
||||
icon_state = "incendiary"
|
||||
rounds = 24
|
||||
ammo_type = "incendiary"
|
||||
|
||||
/obj/item/mecha_ammo/scattershot
|
||||
name = "scattershot ammo"
|
||||
desc = "A box of scaled-up buckshot, for use in exosuit shotguns."
|
||||
icon_state = "scattershot"
|
||||
rounds = 40
|
||||
ammo_type = "scattershot"
|
||||
|
||||
/obj/item/mecha_ammo/lmg
|
||||
name = "machine gun ammo"
|
||||
desc = "A box of linked ammunition, designed for the Ultra AC 2 exosuit weapon."
|
||||
icon_state = "lmg"
|
||||
rounds = 300
|
||||
ammo_type = "lmg"
|
||||
|
||||
/obj/item/mecha_ammo/missiles_br
|
||||
name = "breaching missiles"
|
||||
desc = "A box of large missiles, ready for loading into a BRM-6 exosuit missile rack."
|
||||
icon_state = "missile_br"
|
||||
rounds = 6
|
||||
round_term = "missile"
|
||||
direct_load = TRUE
|
||||
load_audio = "sound/weapons/bulletinsert.ogg"
|
||||
ammo_type = "missiles_br"
|
||||
|
||||
/obj/item/mecha_ammo/missiles_he
|
||||
name = "anti-armor missiles"
|
||||
desc = "A box of large missiles, ready for loading into an SRM-8 exosuit missile rack."
|
||||
icon_state = "missile_he"
|
||||
rounds = 8
|
||||
round_term = "missile"
|
||||
direct_load = TRUE
|
||||
load_audio = "sound/weapons/bulletinsert.ogg"
|
||||
ammo_type = "missiles_he"
|
||||
|
||||
|
||||
/obj/item/mecha_ammo/flashbang
|
||||
name = "launchable flashbangs"
|
||||
desc = "A box of smooth flashbangs, for use with a large exosuit launcher. Cannot be primed by hand."
|
||||
icon_state = "flashbang"
|
||||
rounds = 6
|
||||
round_term = "grenade"
|
||||
ammo_type = "flashbang"
|
||||
|
||||
/obj/item/mecha_ammo/clusterbang
|
||||
name = "launchable flashbang clusters"
|
||||
desc = "A box of clustered flashbangs, for use with a specialized exosuit cluster launcher. Cannot be primed by hand."
|
||||
icon_state = "clusterbang"
|
||||
rounds = 3
|
||||
round_term = "cluster"
|
||||
direct_load = TRUE
|
||||
ammo_type = "clusterbang"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user