done hopefully
This commit is contained in:
+40
-33
@@ -327,6 +327,7 @@
|
||||
/obj/effect/turf_decal/tile/brown{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/closet/secure_closet/miner,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/production)
|
||||
"fU" = (
|
||||
@@ -716,13 +717,13 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/laborcamp/security)
|
||||
"mN" = (
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/obj/structure/cable{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-4"
|
||||
},
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/turf/open/floor/plating,
|
||||
/area/mine/production)
|
||||
"nm" = (
|
||||
@@ -812,6 +813,16 @@
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/mine/production)
|
||||
"ou" = (
|
||||
/obj/effect/turf_decal/tile/brown{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/tile/brown{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/closet/secure_closet/miner,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/production)
|
||||
"ow" = (
|
||||
/obj/machinery/door/airlock/medical/glass{
|
||||
name = "Infirmary"
|
||||
@@ -1160,13 +1171,6 @@
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/living_quarters)
|
||||
"tJ" = (
|
||||
/obj/item/beacon,
|
||||
/obj/effect/turf_decal/tile/purple{
|
||||
dir = 8
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/production)
|
||||
"tK" = (
|
||||
/obj/structure/closet/crate,
|
||||
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
|
||||
@@ -1569,10 +1573,10 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/living_quarters)
|
||||
"Bc" = (
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-8"
|
||||
},
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/turf/open/floor/plating,
|
||||
/area/mine/production)
|
||||
"Be" = (
|
||||
@@ -2226,6 +2230,7 @@
|
||||
/obj/structure/cable{
|
||||
icon_state = "1-2"
|
||||
},
|
||||
/obj/item/beacon,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/production)
|
||||
"KO" = (
|
||||
@@ -2296,10 +2301,10 @@
|
||||
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
|
||||
/area/lavaland/surface/outdoors)
|
||||
"Lc" = (
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-4"
|
||||
},
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/turf/open/floor/plating,
|
||||
/area/mine/production)
|
||||
"Le" = (
|
||||
@@ -2370,7 +2375,8 @@
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3,
|
||||
/obj/machinery/door/airlock/mining/glass{
|
||||
name = "Processing Area";
|
||||
req_access_txt = "48"
|
||||
req_access_txt = "48";
|
||||
security_level = 6
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "1-2"
|
||||
@@ -2520,6 +2526,7 @@
|
||||
/obj/effect/turf_decal/tile/purple{
|
||||
dir = 8
|
||||
},
|
||||
/obj/structure/closet/secure_closet/miner,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/production)
|
||||
"Nk" = (
|
||||
@@ -3008,13 +3015,13 @@
|
||||
/turf/open/floor/plasteel,
|
||||
/area/mine/production)
|
||||
"Vo" = (
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/obj/structure/cable{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj/structure/cable{
|
||||
icon_state = "0-8"
|
||||
},
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/turf/open/floor/plating,
|
||||
/area/mine/production)
|
||||
"Vs" = (
|
||||
@@ -5458,7 +5465,7 @@ JY
|
||||
JY
|
||||
jJ
|
||||
jJ
|
||||
JY
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
wz
|
||||
@@ -5514,8 +5521,8 @@ JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
wz
|
||||
@@ -5569,9 +5576,9 @@ JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
@@ -5625,8 +5632,8 @@ JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
@@ -5681,8 +5688,8 @@ JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
Lm
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
@@ -5737,8 +5744,8 @@ JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
Lm
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
@@ -5793,8 +5800,8 @@ JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
@@ -5848,9 +5855,9 @@ JY
|
||||
Lm
|
||||
VT
|
||||
VT
|
||||
JY
|
||||
JY
|
||||
JY
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
@@ -5906,8 +5913,8 @@ VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
Lm
|
||||
Lm
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
VT
|
||||
Lm
|
||||
@@ -6598,7 +6605,7 @@ VT
|
||||
VT
|
||||
Cd
|
||||
Ed
|
||||
tJ
|
||||
Wf
|
||||
II
|
||||
Jo
|
||||
Ed
|
||||
@@ -6661,7 +6668,7 @@ wX
|
||||
Wf
|
||||
YM
|
||||
GN
|
||||
II
|
||||
ou
|
||||
Nf
|
||||
mN
|
||||
Aj
|
||||
|
||||
+13
-12
@@ -24,18 +24,19 @@
|
||||
#define LOG_SAY (1 << 1)
|
||||
#define LOG_WHISPER (1 << 2)
|
||||
#define LOG_EMOTE (1 << 3)
|
||||
#define LOG_DSAY (1 << 4)
|
||||
#define LOG_PDA (1 << 5)
|
||||
#define LOG_CHAT (1 << 6)
|
||||
#define LOG_COMMENT (1 << 7)
|
||||
#define LOG_TELECOMMS (1 << 8)
|
||||
#define LOG_OOC (1 << 9)
|
||||
#define LOG_ADMIN (1 << 10)
|
||||
#define LOG_OWNERSHIP (1 << 11)
|
||||
#define LOG_GAME (1 << 12)
|
||||
#define LOG_ADMIN_PRIVATE (1 << 13)
|
||||
#define LOG_ASAY (1 << 14)
|
||||
#define LOG_VIRUS (1 << 15)
|
||||
#define LOG_SUBTLER (1 << 4)
|
||||
#define LOG_DSAY (1 << 5)
|
||||
#define LOG_PDA (1 << 6)
|
||||
#define LOG_CHAT (1 << 7)
|
||||
#define LOG_COMMENT (1 << 8)
|
||||
#define LOG_TELECOMMS (1 << 9)
|
||||
#define LOG_OOC (1 << 10)
|
||||
#define LOG_ADMIN (1 << 11)
|
||||
#define LOG_OWNERSHIP (1 << 12)
|
||||
#define LOG_GAME (1 << 13)
|
||||
#define LOG_ADMIN_PRIVATE (1 << 14)
|
||||
#define LOG_ASAY (1 << 15)
|
||||
#define LOG_VIRUS (1 << 16)
|
||||
|
||||
//Individual logging panel pages
|
||||
#define INDIVIDUAL_ATTACK_LOG (LOG_ATTACK)
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
#define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman.
|
||||
#define TRAIT_FREESPRINT "free_sprinting"
|
||||
#define TRAIT_NO_TELEPORT "no-teleport" //you just can't
|
||||
#define TRAIT_NO_INTERNALS "no-internals"
|
||||
#define TRAIT_NO_ALCOHOL "alcohol_intolerance"
|
||||
|
||||
// common trait sources
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
if (CONFIG_GET(flag/log_adminchat))
|
||||
WRITE_LOG(GLOB.world_game_log, "ADMIN: DSAY: [text]")
|
||||
|
||||
/proc/log_consent(text)
|
||||
WRITE_LOG(GLOB.world_game_log,"CONSENT: [text]")
|
||||
|
||||
/* All other items are public. */
|
||||
/proc/log_game(text)
|
||||
@@ -94,6 +96,10 @@
|
||||
if (CONFIG_GET(flag/log_emote))
|
||||
WRITE_LOG(GLOB.world_game_log, "EMOTE: [text]")
|
||||
|
||||
/proc/log_subtler(text)
|
||||
if (CONFIG_GET(flag/log_emote))
|
||||
WRITE_LOG(GLOB.world_game_log, "EMOTE (SUBTLER): [text]")
|
||||
|
||||
/proc/log_prayer(text)
|
||||
if (CONFIG_GET(flag/log_prayer))
|
||||
WRITE_LOG(GLOB.world_game_log, "PRAY: [text]")
|
||||
|
||||
@@ -291,6 +291,9 @@
|
||||
icon_state = "internal0"
|
||||
else
|
||||
if(!C.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
if(HAS_TRAIT(C, TRAIT_NO_INTERNALS))
|
||||
to_chat(C, "<span class='warning'>Due to cumbersome equipment or anatomy, you are currently unable to use internals!</span>")
|
||||
return
|
||||
var/obj/item/clothing/check
|
||||
var/internals = FALSE
|
||||
|
||||
|
||||
@@ -431,3 +431,7 @@
|
||||
/datum/config_entry/flag/log_pictures
|
||||
|
||||
/datum/config_entry/flag/picture_logging_camera
|
||||
|
||||
/datum/config_entry/number/max_bunker_days
|
||||
config_entry_value = 7
|
||||
min_val = 1
|
||||
|
||||
@@ -39,6 +39,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
if(CONFIG_GET(flag/use_antag_rep))
|
||||
LoadAntagReputation()
|
||||
LoadRandomizedRecipes()
|
||||
LoadPanicBunker()
|
||||
return ..()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadSatchels()
|
||||
@@ -259,6 +260,15 @@ SUBSYSTEM_DEF(persistence)
|
||||
if(CONFIG_GET(flag/use_antag_rep))
|
||||
CollectAntagReputation()
|
||||
SaveRandomizedRecipes()
|
||||
SavePanicBunker()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
||||
var/bunker_path = file("data/bunker_passthrough.json")
|
||||
if(fexists(bunker_path))
|
||||
GLOB.bunker_passthrough = json_decode(file2text(bunker_path))
|
||||
for(var/ckey in GLOB.bunker_passthrough)
|
||||
if(daysSince(GLOB.bunker_passthrough[ckey]) >= CONFIG_GET(number/max_bunker_days))
|
||||
GLOB.bunker_passthrough -= ckey
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/GetPhotoAlbums()
|
||||
var/album_path = file("data/photo_albums.json")
|
||||
@@ -381,6 +391,13 @@ SUBSYSTEM_DEF(persistence)
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SavePanicBunker()
|
||||
var/json_file = file("data/bunker_passthrough.json")
|
||||
var/list/file_data = list()
|
||||
file_data["data"] = GLOB.bunker_passthrough
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file,json_encode(file_data))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/remove_duplicate_trophies(list/trophies)
|
||||
var/list/ukeys = list()
|
||||
. = list()
|
||||
|
||||
@@ -16,41 +16,43 @@
|
||||
var/viewing_category = 1 //typical powergamer starting on the Weapons tab
|
||||
var/viewing_subcategory = 1
|
||||
var/list/categories = list(
|
||||
CAT_WEAPONRY,
|
||||
CAT_ROBOT,
|
||||
CAT_MISC,
|
||||
CAT_PRIMAL,
|
||||
CAT_FOOD,
|
||||
CAT_CLOTHING)
|
||||
var/list/subcategories = list(
|
||||
list( //Weapon subcategories
|
||||
CAT_WEAPON,
|
||||
CAT_AMMO),
|
||||
CAT_NONE, //Robot subcategories
|
||||
CAT_NONE, //Misc subcategories
|
||||
CAT_NONE, //Tribal subcategories
|
||||
list( //Food subcategories
|
||||
CAT_BREAD,
|
||||
CAT_BURGER,
|
||||
CAT_CAKE,
|
||||
CAT_EGG,
|
||||
CAT_FISH,
|
||||
CAT_ICE, //Called Frozen
|
||||
CAT_MEAT,
|
||||
CAT_MISCFOOD,
|
||||
CAT_PASTRY,
|
||||
CAT_PIE,
|
||||
CAT_PIZZA,
|
||||
CAT_SALAD,
|
||||
CAT_SANDWICH,
|
||||
CAT_SOUP,
|
||||
CAT_SPAGHETTI),
|
||||
CAT_NONE) //Clothing subcategories
|
||||
CAT_WEAPONRY = list(
|
||||
CAT_WEAPON,
|
||||
CAT_AMMO,
|
||||
),
|
||||
CAT_ROBOT = CAT_NONE,
|
||||
CAT_MISC = CAT_NONE,
|
||||
CAT_PRIMAL = CAT_NONE,
|
||||
CAT_FOOD = list(
|
||||
CAT_BREAD,
|
||||
CAT_BURGER,
|
||||
CAT_CAKE,
|
||||
CAT_EGG,
|
||||
CAT_FISH,
|
||||
CAT_ICE,
|
||||
CAT_MEAT,
|
||||
CAT_MISCFOOD,
|
||||
CAT_PASTRY,
|
||||
CAT_PIE,
|
||||
CAT_PIZZA,
|
||||
CAT_SALAD,
|
||||
CAT_SANDWICH,
|
||||
CAT_SOUP,
|
||||
CAT_SPAGHETTI,
|
||||
),
|
||||
CAT_DRINK = CAT_NONE,
|
||||
CAT_CLOTHING = CAT_NONE,
|
||||
)
|
||||
|
||||
var/cur_category = CAT_NONE
|
||||
var/cur_subcategory = CAT_NONE
|
||||
var/datum/action/innate/crafting/button
|
||||
var/display_craftable_only = FALSE
|
||||
var/display_compact = TRUE
|
||||
|
||||
|
||||
|
||||
|
||||
/* This is what procs do:
|
||||
get_environment - gets a list of things accessable for crafting by user
|
||||
get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
|
||||
@@ -60,6 +62,9 @@
|
||||
del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/component/personal_crafting/proc/check_contents(datum/crafting_recipe/R, list/contents)
|
||||
contents = contents["other"]
|
||||
main_loop:
|
||||
@@ -77,11 +82,11 @@
|
||||
continue main_loop
|
||||
else
|
||||
continue
|
||||
return 0
|
||||
return FALSE
|
||||
for(var/A in R.chem_catalysts)
|
||||
if(contents[A] < R.chem_catalysts[A])
|
||||
return 0
|
||||
return 1
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/get_environment(mob/user)
|
||||
. = list()
|
||||
@@ -307,43 +312,65 @@
|
||||
/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
cur_category = categories[1]
|
||||
if(islist(categories[cur_category]))
|
||||
var/list/subcats = categories[cur_category]
|
||||
cur_subcategory = subcats[1]
|
||||
else
|
||||
cur_subcategory = CAT_NONE
|
||||
ui = new(user, src, ui_key, "personal_crafting", "Crafting Menu", 700, 800, master_ui, state)
|
||||
ui.open()
|
||||
|
||||
|
||||
/datum/component/personal_crafting/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
var/list/subs = list()
|
||||
var/cur_subcategory = CAT_NONE
|
||||
var/cur_category = categories[viewing_category]
|
||||
if (islist(subcategories[viewing_category]))
|
||||
subs = subcategories[viewing_category]
|
||||
cur_subcategory = subs[viewing_subcategory]
|
||||
data["busy"] = busy
|
||||
data["prev_cat"] = categories[prev_cat()]
|
||||
data["prev_subcat"] = subs[prev_subcat()]
|
||||
data["category"] = cur_category
|
||||
data["subcategory"] = cur_subcategory
|
||||
data["next_cat"] = categories[next_cat()]
|
||||
data["next_subcat"] = subs[next_subcat()]
|
||||
data["display_craftable_only"] = display_craftable_only
|
||||
data["display_compact"] = display_compact
|
||||
|
||||
var/list/surroundings = get_surroundings(user)
|
||||
var/list/can_craft = list()
|
||||
var/list/cant_craft = list()
|
||||
var/list/craftability = list()
|
||||
for(var/rec in GLOB.crafting_recipes)
|
||||
var/datum/crafting_recipe/R = rec
|
||||
|
||||
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
|
||||
continue
|
||||
|
||||
if((R.category != cur_category) || (R.subcategory != cur_subcategory))
|
||||
continue
|
||||
if(check_contents(R, surroundings))
|
||||
can_craft += list(build_recipe_data(R))
|
||||
|
||||
craftability["[REF(R)]"] = check_contents(R, surroundings)
|
||||
|
||||
data["craftability"] = craftability
|
||||
return data
|
||||
|
||||
/datum/component/personal_crafting/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
var/list/crafting_recipes = list()
|
||||
for(var/rec in GLOB.crafting_recipes)
|
||||
var/datum/crafting_recipe/R = rec
|
||||
|
||||
if(R.name == "") //This is one of the invalid parents that sneaks in
|
||||
continue
|
||||
|
||||
if(!R.always_availible && !(R.type in user?.mind?.learned_recipes)) //User doesn't actually know how to make this.
|
||||
continue
|
||||
|
||||
if(isnull(crafting_recipes[R.category]))
|
||||
crafting_recipes[R.category] = list()
|
||||
|
||||
if(R.subcategory == CAT_NONE)
|
||||
crafting_recipes[R.category] += list(build_recipe_data(R))
|
||||
else
|
||||
cant_craft += list(build_recipe_data(R))
|
||||
data["can_craft"] = can_craft
|
||||
data["cant_craft"] = cant_craft
|
||||
if(isnull(crafting_recipes[R.category][R.subcategory]))
|
||||
crafting_recipes[R.category][R.subcategory] = list()
|
||||
crafting_recipes[R.category]["has_subcats"] = TRUE
|
||||
crafting_recipes[R.category][R.subcategory] += list(build_recipe_data(R))
|
||||
|
||||
data["crafting_recipes"] = crafting_recipes
|
||||
return data
|
||||
|
||||
|
||||
@@ -361,60 +388,21 @@
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>Construction failed[fail_msg]</span>")
|
||||
busy = FALSE
|
||||
if("forwardCat") //Meow
|
||||
viewing_category = next_cat(FALSE)
|
||||
. = TRUE
|
||||
if("backwardCat")
|
||||
viewing_category = prev_cat(FALSE)
|
||||
. = TRUE
|
||||
if("forwardSubCat")
|
||||
viewing_subcategory = next_subcat()
|
||||
. = TRUE
|
||||
if("backwardSubCat")
|
||||
viewing_subcategory = prev_subcat()
|
||||
. = TRUE
|
||||
if("toggle_recipes")
|
||||
display_craftable_only = !display_craftable_only
|
||||
. = TRUE
|
||||
if("toggle_compact")
|
||||
display_compact = !display_compact
|
||||
. = TRUE
|
||||
|
||||
//Next works nicely with modular arithmetic
|
||||
/datum/component/personal_crafting/proc/next_cat(readonly = TRUE)
|
||||
if (!readonly)
|
||||
viewing_subcategory = 1
|
||||
. = viewing_category % categories.len + 1
|
||||
|
||||
/datum/component/personal_crafting/proc/next_subcat()
|
||||
if(islist(subcategories[viewing_category]))
|
||||
var/list/subs = subcategories[viewing_category]
|
||||
. = viewing_subcategory % subs.len + 1
|
||||
|
||||
|
||||
//Previous can go fuck itself
|
||||
/datum/component/personal_crafting/proc/prev_cat(readonly = TRUE)
|
||||
if (!readonly)
|
||||
viewing_subcategory = 1
|
||||
if(viewing_category == categories.len)
|
||||
. = viewing_category-1
|
||||
else
|
||||
. = viewing_category % categories.len - 1
|
||||
if(. <= 0)
|
||||
. = categories.len
|
||||
|
||||
/datum/component/personal_crafting/proc/prev_subcat()
|
||||
if(islist(subcategories[viewing_category]))
|
||||
var/list/subs = subcategories[viewing_category]
|
||||
if(viewing_subcategory == subs.len)
|
||||
. = viewing_subcategory-1
|
||||
else
|
||||
. = viewing_subcategory % subs.len - 1
|
||||
if(. <= 0)
|
||||
. = subs.len
|
||||
else
|
||||
. = null
|
||||
|
||||
if("set_category")
|
||||
if(!isnull(params["category"]))
|
||||
cur_category = params["category"]
|
||||
if(!isnull(params["subcategory"]))
|
||||
if(params["subcategory"] == "0")
|
||||
cur_subcategory = ""
|
||||
else
|
||||
cur_subcategory = params["subcategory"]
|
||||
. = TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
|
||||
var/list/data = list()
|
||||
@@ -455,4 +443,3 @@
|
||||
if(!learned_recipes)
|
||||
learned_recipes = list()
|
||||
learned_recipes |= R
|
||||
|
||||
@@ -67,7 +67,7 @@ Bonus
|
||||
eyes.applyOrganDamage(eyes.maxHealth)
|
||||
else
|
||||
M.visible_message("<span class='warning'>[M]'s eyes fall off their sockets!</span>", "<span class='userdanger'>Your eyes fall off their sockets!</span>")
|
||||
eyes.Remove(M)
|
||||
eyes.Remove()
|
||||
eyes.forceMove(get_turf(M))
|
||||
else
|
||||
to_chat(M, "<span class='userdanger'>Your eyes burn horrifically!</span>")
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
addtimer(CALLBACK(src, .proc/pet_the_dog, source, user), 1)
|
||||
|
||||
/datum/element/wuv/proc/pet_the_dog(mob/target, mob/user)
|
||||
if(!QDELETED(target) || !QDELETED(user) || target.stat != CONSCIOUS)
|
||||
if(QDELETED(target) || QDELETED(user) || target.stat != CONSCIOUS)
|
||||
return
|
||||
new /obj/effect/temp_visual/heart(target.loc)
|
||||
if(pet_emote)
|
||||
@@ -52,7 +52,7 @@
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, target, pet_moodlet, target)
|
||||
|
||||
/datum/element/wuv/proc/kick_the_dog(mob/target, mob/user)
|
||||
if(!QDELETED(target) || !QDELETED(user) || target.stat != CONSCIOUS)
|
||||
if(QDELETED(target) || QDELETED(user) || target.stat != CONSCIOUS)
|
||||
return
|
||||
if(punt_emote)
|
||||
target.emote("me", punt_type, punt_emote)
|
||||
|
||||
@@ -201,51 +201,52 @@
|
||||
|
||||
/datum/mood_event/vampcandle
|
||||
description = "<span class='umbra'>Something is making your mind feel... loose...</span>\n"
|
||||
mood_change = -10
|
||||
mood_change = -15
|
||||
timeout = 1 MINUTES
|
||||
|
||||
/datum/mood_event/drankblood_bad
|
||||
description = "<span class='boldwarning'>I drank the blood of a lesser creature. Disgusting.</span>\n"
|
||||
mood_change = -4
|
||||
timeout = 900
|
||||
timeout = 8 MINUTES
|
||||
|
||||
/datum/mood_event/drankblood_dead
|
||||
description = "<span class='boldwarning'>I drank dead blood. I am better than this.</span>\n"
|
||||
mood_change = -7
|
||||
timeout = 900
|
||||
timeout = 10 MINUTES
|
||||
|
||||
/datum/mood_event/drankblood_synth
|
||||
description = "<span class='boldwarning'>I drank synthetic blood. What is wrong with me?</span>\n"
|
||||
mood_change = -7
|
||||
timeout = 900
|
||||
timeout = 15 MINUTES
|
||||
|
||||
/datum/mood_event/drankkilled
|
||||
description = "<span class='boldwarning'>I drank from my victim until they died. I feel...less human.</span>\n"
|
||||
mood_change = -12
|
||||
timeout = 6000
|
||||
timeout = 25 MINUTES
|
||||
|
||||
/datum/mood_event/madevamp
|
||||
description = "<span class='boldwarning'>A soul has been cursed to undeath by my own hand.</span>\n"
|
||||
mood_change = -10
|
||||
timeout = 10000
|
||||
timeout = 30 MINUTES
|
||||
|
||||
/datum/mood_event/vampatefood
|
||||
description = "<span class='boldwarning'>Mortal nourishment no longer sustains me. I feel unwell.</span>\n"
|
||||
mood_change = -6
|
||||
timeout = 1000
|
||||
timeout = 10 MINUTES
|
||||
|
||||
/datum/mood_event/daylight_1
|
||||
description = "<span class='boldwarning'>I slept poorly in a makeshift coffin during the day.</span>\n"
|
||||
mood_change = -3
|
||||
timeout = 1000
|
||||
timeout = 10 MINUTES
|
||||
|
||||
/datum/mood_event/nanite_sadness
|
||||
description = "<span class='warning robot'>+++++++HAPPINESS SUPPRESSION+++++++</span>\n"
|
||||
mood_change = -7
|
||||
/datum/mood_event/daylight_2
|
||||
description = "<span class='boldwarning'>I have been scorched by the unforgiving rays of the sun.</span>\n"
|
||||
mood_change = -6
|
||||
timeout = 1200
|
||||
timeout = 15 MINUTES
|
||||
|
||||
/datum/mood_event/nanite_sadness
|
||||
description = "<span class='warning robot'>+++++++HAPPINESS SUPPRESSION+++++++</span>\n"
|
||||
mood_change = -7
|
||||
|
||||
/datum/mood_event/nanite_sadness/add_effects(message)
|
||||
description = "<span class='warning robot'>+++++++[message]+++++++</span>\n"
|
||||
|
||||
+3
-1
@@ -767,6 +767,8 @@
|
||||
log_whisper(log_text)
|
||||
if(LOG_EMOTE)
|
||||
log_emote(log_text)
|
||||
if(LOG_SUBTLER)
|
||||
log_subtler(log_text)
|
||||
if(LOG_DSAY)
|
||||
log_dsay(log_text)
|
||||
if(LOG_PDA)
|
||||
@@ -869,4 +871,4 @@ Proc for attack log creation, because really why not
|
||||
return TRUE
|
||||
|
||||
/atom/proc/intercept_zImpact(atom/movable/AM, levels = 1)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
|
||||
. |= SEND_SIGNAL(src, COMSIG_ATOM_INTERCEPT_Z_FALL, AM, levels)
|
||||
|
||||
@@ -203,13 +203,18 @@
|
||||
clumsy_check = GRENADE_NONCLUMSY_FUMBLE
|
||||
|
||||
/obj/item/grenade/chem_grenade/teargas/moustache/prime()
|
||||
var/myloc = get_turf(src)
|
||||
var/list/check_later = list()
|
||||
for(var/mob/living/carbon/C in get_turf(src))
|
||||
check_later += C
|
||||
. = ..()
|
||||
for(var/mob/living/carbon/M in view(6, myloc))
|
||||
if(!istype(M.wear_mask, /obj/item/clothing/mask/gas/clown_hat) && !istype(M.wear_mask, /obj/item/clothing/mask/gas/mime) )
|
||||
if(!M.wear_mask || M.dropItemToGround(M.wear_mask))
|
||||
if(!.) //grenade did not properly prime.
|
||||
return
|
||||
for(var/M in check_later)
|
||||
var/mob/living/carbon/C = M
|
||||
if(!istype(C.wear_mask, /obj/item/clothing/mask/gas/clown_hat) && !istype(C.wear_mask, /obj/item/clothing/mask/gas/mime))
|
||||
if(!C.wear_mask || C.dropItemToGround(C.wear_mask))
|
||||
var/obj/item/clothing/mask/fakemoustache/sticky/the_stash = new /obj/item/clothing/mask/fakemoustache/sticky()
|
||||
M.equip_to_slot_or_del(the_stash, SLOT_WEAR_MASK, TRUE, TRUE, TRUE, TRUE)
|
||||
C.equip_to_slot_or_del(the_stash, SLOT_WEAR_MASK, TRUE, TRUE, TRUE, TRUE)
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/sticky
|
||||
var/unstick_time = 2 MINUTES
|
||||
@@ -217,10 +222,16 @@
|
||||
/obj/item/clothing/mask/fakemoustache/sticky/Initialize()
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, STICKY_MOUSTACHE_TRAIT)
|
||||
addtimer(CALLBACK(src, .proc/unstick), unstick_time)
|
||||
addtimer(TRAIT_CALLBACK_REMOVE(src, TRAIT_NODROP, STICKY_MOUSTACHE_TRAIT), unstick_time)
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/sticky/proc/unstick()
|
||||
ADD_TRAIT(src, TRAIT_NODROP, STICKY_MOUSTACHE_TRAIT)
|
||||
/obj/item/clothing/mask/fakemoustache/sticky/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
if(slot == SLOT_WEAR_MASK)
|
||||
ADD_TRAIT(user, TRAIT_NO_INTERNALS, STICKY_MOUSTACHE_TRAIT)
|
||||
|
||||
/obj/item/clothing/mask/fakemoustache/sticky/dropped(mob/user)
|
||||
. = ..()
|
||||
REMOVE_TRAIT(user, TRAIT_NO_INTERNALS, STICKY_MOUSTACHE_TRAIT)
|
||||
|
||||
//DARK H.O.N.K. AND CLOWN MECH WEAPONS
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
if(bag)
|
||||
. += "<span class='notice'>It has \a [bag.name] hooked to its <b>input</b> slot. The counter reads: \"Current Capacity: [bag.reagents.total_volume] of [bag.reagents.maximum_volume]\"</span>"
|
||||
if(outbag)
|
||||
. += "<span class='notice'>It has \a [bag.name] hooked to its <b>output</b> slot. The counter reads: \"Current Capacity: [outbag.reagents.total_volume] of [outbag.reagents.maximum_volume]\"</span>"
|
||||
. += "<span class='notice'>It has \a [outbag.name] hooked to its <b>output</b> slot. The counter reads: \"Current Capacity: [outbag.reagents.total_volume] of [outbag.reagents.maximum_volume]\"</span>"
|
||||
|
||||
|
||||
/obj/machinery/bloodbankgen/handle_atom_del(atom/A)
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
QDEL_LIST(unattached_flesh)
|
||||
. = ..()
|
||||
|
||||
/obj/machinery/clonepod/RefreshParts()
|
||||
/obj/machinery/clonepod/RefreshParts()
|
||||
speed_coeff = 0
|
||||
efficiency = 0
|
||||
for(var/obj/item/stock_parts/scanning_module/S in component_parts)
|
||||
@@ -471,7 +471,7 @@
|
||||
if(!istype(organ) || (organ.organ_flags & ORGAN_VITAL))
|
||||
continue
|
||||
organ.organ_flags |= ORGAN_FROZEN
|
||||
organ.Remove(H, special=TRUE)
|
||||
organ.Remove(TRUE)
|
||||
organ.forceMove(src)
|
||||
unattached_flesh += organ
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
/obj/item/melee/baton,
|
||||
/obj/item/ammo_box/magazine/recharge,
|
||||
/obj/item/modular_computer,
|
||||
/obj/item/gun/ballistic/automatic/magrifle_e,
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag_e))
|
||||
/obj/item/gun/ballistic/automatic/magrifle))
|
||||
|
||||
/obj/machinery/recharger/RefreshParts()
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/critfail()
|
||||
if(chassis)
|
||||
log_message("Critical failure", color="red")
|
||||
mecha_log_message("Critical failure", color="red")
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/get_equip_info()
|
||||
if(!chassis)
|
||||
@@ -116,7 +116,7 @@
|
||||
M.equipment += src
|
||||
chassis = M
|
||||
forceMove(M)
|
||||
M.log_message("[src] initialized.")
|
||||
M.mecha_log_message("[src] initialized.")
|
||||
if(!M.selected && selectable)
|
||||
M.selected = src
|
||||
src.update_chassis_page()
|
||||
@@ -129,7 +129,7 @@
|
||||
if(chassis.selected == src)
|
||||
chassis.selected = null
|
||||
update_chassis_page()
|
||||
chassis.log_message("[src] removed from equipment.")
|
||||
chassis.mecha_log_message("[src] removed from equipment.")
|
||||
chassis = null
|
||||
set_ready_state(1)
|
||||
return
|
||||
@@ -150,18 +150,14 @@
|
||||
chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]")
|
||||
return
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/log_message(message, message_type=LOG_GAME, color=null, log_globally)
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color)
|
||||
log_message(message, LOG_GAME, color) //pass to default admin logging too
|
||||
if(chassis)
|
||||
chassis.log_message("([src]) [message]", message_type, color)
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
chassis.mecha_log_message(message, color) //and pass to our chassis
|
||||
|
||||
//Used for reloading weapons/tools etc. that use some form of resource
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/rearm()
|
||||
return 0
|
||||
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/proc/needs_rearm()
|
||||
return 0
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
update_equip_info()
|
||||
occupant_message("<span class='notice'>[target] successfully loaded into [src]. Life support functions engaged.</span>")
|
||||
chassis.visible_message("<span class='warning'>[chassis] loads [target] into [src].</span>")
|
||||
log_message("[target] loaded. Life support functions engaged.")
|
||||
mecha_log_message("[target] loaded. Life support functions engaged.")
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical/sleeper/proc/patient_insertion_check(mob/living/carbon/target)
|
||||
if(target.buckled)
|
||||
@@ -85,7 +85,7 @@
|
||||
return
|
||||
patient.forceMove(get_turf(src))
|
||||
occupant_message("[patient] ejected. Life support functions disabled.")
|
||||
log_message("[patient] ejected. Life support functions disabled.")
|
||||
mecha_log_message("[patient] ejected. Life support functions disabled.")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
patient = null
|
||||
update_equip_info()
|
||||
@@ -193,7 +193,7 @@
|
||||
var/to_inject = min(R.volume, inject_amount)
|
||||
if(to_inject && patient.reagents.get_reagent_amount(R.type) + to_inject <= inject_amount*2)
|
||||
occupant_message("Injecting [patient] with [to_inject] units of [R.name].")
|
||||
log_message("Injecting [patient] with [to_inject] units of [R.name].")
|
||||
mecha_log_message("Injecting [patient] with [to_inject] units of [R.name].")
|
||||
log_combat(chassis.occupant, patient, "injected", "[name] ([R] - [to_inject] units)")
|
||||
SG.reagents.trans_id_to(patient,R.type,to_inject)
|
||||
update_equip_info()
|
||||
@@ -216,7 +216,7 @@
|
||||
return
|
||||
if(!chassis.has_charge(energy_drain))
|
||||
set_ready_state(1)
|
||||
log_message("Deactivated.")
|
||||
mecha_log_message("Deactivated.")
|
||||
occupant_message("[src] deactivated - no power.")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return
|
||||
@@ -312,7 +312,7 @@
|
||||
mechsyringe.icon = 'icons/obj/chemical.dmi'
|
||||
mechsyringe.icon_state = "syringeproj"
|
||||
playsound(chassis, 'sound/items/syringeproj.ogg', 50, 1)
|
||||
log_message("Launched [mechsyringe] from [src], targeting [target].")
|
||||
mecha_log_message("Launched [mechsyringe] from [src], targeting [target].")
|
||||
var/mob/originaloccupant = chassis.occupant
|
||||
spawn(0)
|
||||
src = null //if src is deleted, still process the syringe
|
||||
@@ -376,7 +376,7 @@
|
||||
START_PROCESSING(SSobj, src)
|
||||
occupant_message(message)
|
||||
occupant_message("Reagent processing started.")
|
||||
log_message("Reagent processing started.")
|
||||
mecha_log_message("Reagent processing started.")
|
||||
return
|
||||
if(afilter.get("show_reagents"))
|
||||
chassis.occupant << browse(get_reagents_page(),"window=msyringegun")
|
||||
@@ -511,7 +511,7 @@
|
||||
return
|
||||
if(!processed_reagents.len || reagents.total_volume >= reagents.maximum_volume || !chassis.has_charge(energy_drain))
|
||||
occupant_message("<span class=\"alert\">Reagent processing stopped.</a>")
|
||||
log_message("Reagent processing stopped.")
|
||||
mecha_log_message("Reagent processing stopped.")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return
|
||||
var/amount = synth_speed / processed_reagents.len
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
if(do_after_cooldown(target))
|
||||
set_ready_state(FALSE)
|
||||
log_message("Started drilling [target]")
|
||||
mecha_log_message("Started drilling [target]")
|
||||
if(isturf(target))
|
||||
var/turf/T = target
|
||||
T.drill_act(src)
|
||||
@@ -61,13 +61,13 @@
|
||||
|
||||
/turf/closed/wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
|
||||
if(drill.do_after_mecha(src, 60 / drill.drill_level))
|
||||
drill.log_message("Drilled through [src]")
|
||||
drill.mecha_log_message("Drilled through [src]")
|
||||
dismantle_wall(TRUE, FALSE)
|
||||
|
||||
/turf/closed/wall/r_wall/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
|
||||
if(drill.drill_level >= DRILL_HARDENED)
|
||||
if(drill.do_after_mecha(src, 120 / drill.drill_level))
|
||||
drill.log_message("Drilled through [src]")
|
||||
drill.mecha_log_message("Drilled through [src]")
|
||||
dismantle_wall(TRUE, FALSE)
|
||||
else
|
||||
drill.occupant_message("<span class='danger'>[src] is too durable to drill through.</span>")
|
||||
@@ -76,14 +76,14 @@
|
||||
for(var/turf/closed/mineral/M in range(drill.chassis,1))
|
||||
if(get_dir(drill.chassis,M)&drill.chassis.dir)
|
||||
M.gets_drilled()
|
||||
drill.log_message("Drilled through [src]")
|
||||
drill.mecha_log_message("Drilled through [src]")
|
||||
drill.move_ores()
|
||||
|
||||
/turf/open/floor/plating/asteroid/drill_act(obj/item/mecha_parts/mecha_equipment/drill/drill)
|
||||
for(var/turf/open/floor/plating/asteroid/M in range(1, drill.chassis))
|
||||
if((get_dir(drill.chassis,M)&drill.chassis.dir) && !M.dug)
|
||||
M.getDug()
|
||||
drill.log_message("Drilled through [src]")
|
||||
drill.mecha_log_message("Drilled through [src]")
|
||||
drill.move_ores()
|
||||
|
||||
|
||||
|
||||
@@ -216,12 +216,12 @@
|
||||
if(equip_ready)
|
||||
START_PROCESSING(SSobj, src)
|
||||
droid_overlay = new(src.icon, icon_state = "repair_droid_a")
|
||||
log_message("Activated.")
|
||||
mecha_log_message("Activated.")
|
||||
set_ready_state(0)
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
droid_overlay = new(src.icon, icon_state = "repair_droid")
|
||||
log_message("Deactivated.")
|
||||
mecha_log_message("Deactivated.")
|
||||
set_ready_state(1)
|
||||
chassis.add_overlay(droid_overlay)
|
||||
send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
|
||||
@@ -304,11 +304,11 @@
|
||||
if(equip_ready) //inactive
|
||||
START_PROCESSING(SSobj, src)
|
||||
set_ready_state(0)
|
||||
log_message("Activated.")
|
||||
mecha_log_message("Activated.")
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
set_ready_state(1)
|
||||
log_message("Deactivated.")
|
||||
mecha_log_message("Deactivated.")
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/tesla_energy_relay/get_equip_info()
|
||||
if(!chassis)
|
||||
@@ -379,11 +379,11 @@
|
||||
if(equip_ready) //inactive
|
||||
set_ready_state(0)
|
||||
START_PROCESSING(SSobj, src)
|
||||
log_message("Activated.")
|
||||
mecha_log_message("Activated.")
|
||||
else
|
||||
set_ready_state(1)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
log_message("Deactivated.")
|
||||
mecha_log_message("Deactivated.")
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/generator/get_equip_info()
|
||||
var/output = ..()
|
||||
@@ -440,14 +440,14 @@
|
||||
return
|
||||
if(fuel.amount<=0)
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
log_message("Deactivated - no fuel.")
|
||||
mecha_log_message("Deactivated - no fuel.")
|
||||
set_ready_state(1)
|
||||
return
|
||||
var/cur_charge = chassis.get_charge()
|
||||
if(isnull(cur_charge))
|
||||
set_ready_state(1)
|
||||
occupant_message("No powercell detected.")
|
||||
log_message("Deactivated.")
|
||||
mecha_log_message("Deactivated.")
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return
|
||||
var/use_fuel = fuel_per_cycle_idle
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
O.forceMove(chassis)
|
||||
O.anchored = FALSE
|
||||
occupant_message("<span class='notice'>[target] successfully loaded.</span>")
|
||||
log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
|
||||
mecha_log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
|
||||
else
|
||||
O.anchored = initial(O.anchored)
|
||||
else
|
||||
@@ -105,7 +105,7 @@
|
||||
O.forceMove(chassis)
|
||||
O.anchored = FALSE
|
||||
occupant_message("<span class='notice'>[target] successfully loaded.</span>")
|
||||
log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
|
||||
mecha_log_message("Loaded [O]. Cargo compartment capacity: [cargo_holder.cargo_capacity - cargo_holder.cargo.len]")
|
||||
else
|
||||
O.anchored = initial(O.anchored)
|
||||
else
|
||||
@@ -388,7 +388,7 @@
|
||||
if(href_list["toggle"])
|
||||
set_ready_state(!equip_ready)
|
||||
occupant_message("[src] [equip_ready?"dea":"a"]ctivated.")
|
||||
log_message("[equip_ready?"Dea":"A"]ctivated.")
|
||||
mecha_log_message("[equip_ready?"Dea":"A"]ctivated.")
|
||||
return
|
||||
if(href_list["cut"])
|
||||
if(cable && cable.amount)
|
||||
@@ -411,7 +411,7 @@
|
||||
if(!cable || cable.amount<1)
|
||||
set_ready_state(1)
|
||||
occupant_message("Cable depleted, [src] deactivated.")
|
||||
log_message("Cable depleted, [src] deactivated.")
|
||||
mecha_log_message("Cable depleted, [src] deactivated.")
|
||||
return
|
||||
if(cable.amount < amount)
|
||||
occupant_message("No enough cable to finish the task.")
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
if(kickback)
|
||||
chassis.newtonian_move(turn(chassis.dir,180))
|
||||
chassis.log_message("Fired from [src.name], targeting [target].")
|
||||
chassis.mecha_log_message("Fired from [src.name], targeting [target].")
|
||||
return 1
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
else
|
||||
M.Jitter(500)
|
||||
|
||||
log_message("Honked from [src.name]. HONK!")
|
||||
mecha_log_message("Honked from [src.name]. HONK!")
|
||||
var/turf/T = get_turf(src)
|
||||
message_admins("[ADMIN_LOOKUPFLW(chassis.occupant)] used a Mecha Honker in [ADMIN_VERBOSEJMP(T)]")
|
||||
log_game("[key_name(chassis.occupant)] used a Mecha Honker in [AREACOORD(T)]")
|
||||
@@ -220,7 +220,7 @@
|
||||
projectiles_to_add--
|
||||
chassis.use_power(projectile_energy_cost)
|
||||
send_byjax(chassis.occupant,"exosuit.browser","[REF(src)]",src.get_equip_info())
|
||||
log_message("Rearmed [src.name].")
|
||||
mecha_log_message("Rearmed [src.name].")
|
||||
return 1
|
||||
|
||||
|
||||
@@ -323,7 +323,7 @@
|
||||
return
|
||||
var/obj/O = new projectile(chassis.loc)
|
||||
playsound(chassis, fire_sound, 50, 1)
|
||||
log_message("Launched a [O.name] from [name], targeting [target].")
|
||||
mecha_log_message("Launched a [O.name] from [name], targeting [target].")
|
||||
projectiles--
|
||||
proj_init(O)
|
||||
O.throw_at(target, missile_range, missile_speed, chassis.occupant, FALSE, diagonals_first = diags_first)
|
||||
|
||||
@@ -139,7 +139,7 @@
|
||||
add_cell()
|
||||
START_PROCESSING(SSobj, src)
|
||||
GLOB.poi_list |= src
|
||||
log_message("[src.name] created.")
|
||||
mecha_log_message("[src.name] created.")
|
||||
GLOB.mechas_list += src //global mech list
|
||||
prepare_huds()
|
||||
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
|
||||
@@ -493,7 +493,7 @@
|
||||
events.fireEvent("onMove",get_turf(src))
|
||||
if (internal_tank.disconnect()) // Something moved us and broke connection
|
||||
occupant_message("<span class='warning'>Air port connection teared off!</span>")
|
||||
log_message("Lost connection to gas port.")
|
||||
mecha_log_message("Lost connection to gas port.")
|
||||
|
||||
/obj/mecha/Process_Spacemove(var/movement_dir = 0)
|
||||
. = ..()
|
||||
@@ -822,7 +822,7 @@
|
||||
return
|
||||
if(!ishuman(user)) // no silicons or drones in mechas.
|
||||
return
|
||||
log_message("[user] tries to move in.")
|
||||
mecha_log_message("[user] tries to move in.")
|
||||
if (occupant)
|
||||
to_chat(usr, "<span class='warning'>The [name] is already occupied!</span>")
|
||||
log_append_to_last("Permission denied.")
|
||||
@@ -932,7 +932,7 @@
|
||||
icon_state = initial(icon_state)
|
||||
update_icon()
|
||||
setDir(dir_in)
|
||||
log_message("[mmi_as_oc] moved in as pilot.")
|
||||
mecha_log_message("[mmi_as_oc] moved in as pilot.")
|
||||
if(!internal_damage)
|
||||
SEND_SOUND(occupant, sound('sound/mecha/nominal.ogg',volume=50))
|
||||
GrantActions(brainmob)
|
||||
@@ -983,7 +983,7 @@
|
||||
var/mob/living/L = occupant
|
||||
occupant = null //we need it null when forceMove calls Exited().
|
||||
if(mob_container.forceMove(newloc))//ejecting mob container
|
||||
log_message("[mob_container] moved out.")
|
||||
mecha_log_message("[mob_container] moved out.")
|
||||
L << browse(null, "window=exosuit")
|
||||
|
||||
if(istype(mob_container, /obj/item/mmi))
|
||||
@@ -1028,10 +1028,10 @@
|
||||
to_chat(occupant, "[icon2html(src, occupant)] [message]")
|
||||
return
|
||||
|
||||
/obj/mecha/log_message(message as text, message_type=LOG_GAME, color=null, log_globally)
|
||||
/obj/mecha/proc/mecha_log_message(message, color)
|
||||
log.len++
|
||||
log[log.len] = list("time"="[STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]","date","year"="[GLOB.year_integer]","message"="[color?"<font color='[color]'>":null][message][color?"</font>":null]")
|
||||
..()
|
||||
log_message(message, LOG_GAME, color) //also do the normal admin logs I guess.
|
||||
return log.len
|
||||
|
||||
/obj/mecha/proc/log_append_to_last(message as text,red=null)
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
chassis.use_internal_tank = !chassis.use_internal_tank
|
||||
button_icon_state = "mech_internals_[chassis.use_internal_tank ? "on" : "off"]"
|
||||
chassis.occupant_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].")
|
||||
chassis.log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].")
|
||||
chassis.mecha_log_message("Now taking air from [chassis.use_internal_tank?"internal airtank":"environment"].")
|
||||
UpdateButtonIcon()
|
||||
|
||||
/datum/action/innate/mecha/mech_cycle_equip
|
||||
@@ -114,7 +114,7 @@
|
||||
chassis.set_light(-chassis.lights_power)
|
||||
button_icon_state = "mech_lights_off"
|
||||
chassis.occupant_message("Toggled lights [chassis.lights?"on":"off"].")
|
||||
chassis.log_message("Toggled lights [chassis.lights?"on":"off"].")
|
||||
chassis.mecha_log_message("Toggled lights [chassis.lights?"on":"off"].")
|
||||
UpdateButtonIcon()
|
||||
|
||||
/datum/action/innate/mecha/mech_view_stats
|
||||
@@ -147,7 +147,7 @@
|
||||
strafe = !strafe
|
||||
|
||||
occupant_message("Toggled strafing mode [strafe?"on":"off"].")
|
||||
log_message("Toggled strafing mode [strafe?"on":"off"].")
|
||||
mecha_log_message("Toggled strafing mode [strafe?"on":"off"].")
|
||||
strafing_action.UpdateButtonIcon()
|
||||
|
||||
//////////////////////////////////////// Specific Ability Actions ///////////////////////////////////////////////
|
||||
@@ -163,7 +163,7 @@
|
||||
if(chassis.get_charge() > 0)
|
||||
chassis.thrusters_active = !chassis.thrusters_active
|
||||
button_icon_state = "mech_thrusters_[chassis.thrusters_active ? "on" : "off"]"
|
||||
chassis.log_message("Toggled thrusters.")
|
||||
chassis.mecha_log_message("Toggled thrusters.")
|
||||
chassis.occupant_message("<font color='[chassis.thrusters_active ?"blue":"red"]'>Thrusters [chassis.thrusters_active ?"en":"dis"]abled.")
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
else
|
||||
chassis.deflect_chance = initial(chassis.deflect_chance)
|
||||
chassis.occupant_message("<span class='danger'>You disable [chassis] defence mode.</span>")
|
||||
chassis.log_message("Toggled defence mode.")
|
||||
chassis.mecha_log_message("Toggled defence mode.")
|
||||
UpdateButtonIcon()
|
||||
|
||||
/datum/action/innate/mecha/mech_overload_mode
|
||||
@@ -200,7 +200,7 @@
|
||||
else
|
||||
chassis.leg_overload_mode = !chassis.leg_overload_mode
|
||||
button_icon_state = "mech_overload_[chassis.leg_overload_mode ? "on" : "off"]"
|
||||
chassis.log_message("Toggled leg actuators overload.")
|
||||
chassis.mecha_log_message("Toggled leg actuators overload.")
|
||||
if(chassis.leg_overload_mode)
|
||||
chassis.leg_overload_mode = 1
|
||||
chassis.bumpsmash = 1
|
||||
@@ -240,7 +240,7 @@
|
||||
if(owner.client)
|
||||
chassis.zoom_mode = !chassis.zoom_mode
|
||||
button_icon_state = "mech_zoom_[chassis.zoom_mode ? "on" : "off"]"
|
||||
chassis.log_message("Toggled zoom mode.")
|
||||
chassis.mecha_log_message("Toggled zoom mode.")
|
||||
chassis.occupant_message("<font color='[chassis.zoom_mode?"blue":"red"]'>Zoom mode [chassis.zoom_mode?"en":"dis"]abled.</font>")
|
||||
if(chassis.zoom_mode)
|
||||
owner.client.change_view(12)
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
playsound(loc, 'sound/weapons/tap.ogg', 40, 1, -1)
|
||||
user.visible_message("<span class='danger'>[user] hits [name]. Nothing happens</span>", null, null, COMBAT_MESSAGE_RANGE)
|
||||
log_message("Attack by hand/paw. Attacker - [user].", color="red")
|
||||
mecha_log_message("Attack by hand/paw. Attacker - [user].", color="red")
|
||||
log_append_to_last("Armor saved.")
|
||||
|
||||
/obj/mecha/attack_paw(mob/user as mob)
|
||||
@@ -70,12 +70,12 @@
|
||||
|
||||
|
||||
/obj/mecha/attack_alien(mob/living/user)
|
||||
log_message("Attack by alien. Attacker - [user].", color="red")
|
||||
mecha_log_message("Attack by alien. Attacker - [user].", color="red")
|
||||
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
|
||||
attack_generic(user, 15, BRUTE, "melee", 0)
|
||||
|
||||
/obj/mecha/attack_animal(mob/living/simple_animal/user)
|
||||
log_message("Attack by simple animal. Attacker - [user].", color="red")
|
||||
mecha_log_message("Attack by simple animal. Attacker - [user].", color="red")
|
||||
if(!user.melee_damage_upper && !user.obj_damage)
|
||||
user.emote("custom", message = "[user.friendly] [src].")
|
||||
return 0
|
||||
@@ -99,7 +99,7 @@
|
||||
/obj/mecha/attack_hulk(mob/living/carbon/human/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
log_message("Attack by hulk. Attacker - [user].", color="red")
|
||||
mecha_log_message("Attack by hulk. Attacker - [user].", color="red")
|
||||
log_combat(user, src, "punched", "hulk powers")
|
||||
|
||||
/obj/mecha/blob_act(obj/structure/blob/B)
|
||||
@@ -109,16 +109,16 @@
|
||||
return
|
||||
|
||||
/obj/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper
|
||||
log_message("Hit by [AM].", color="red")
|
||||
mecha_log_message("Hit by [AM].", color="red")
|
||||
. = ..()
|
||||
|
||||
|
||||
/obj/mecha/bullet_act(obj/item/projectile/Proj) //wrapper
|
||||
log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).", color="red")
|
||||
mecha_log_message("Hit by projectile. Type: [Proj.name]([Proj.flag]).", color="red")
|
||||
. = ..()
|
||||
|
||||
/obj/mecha/ex_act(severity, target)
|
||||
log_message("Affected by explosion of severity: [severity].", color="red")
|
||||
mecha_log_message("Affected by explosion of severity: [severity].", color="red")
|
||||
if(prob(deflect_chance))
|
||||
severity++
|
||||
log_append_to_last("Armor saved, changing severity to [severity].")
|
||||
@@ -148,7 +148,7 @@
|
||||
if(get_charge())
|
||||
use_power((cell.charge/3)/(severity*2))
|
||||
take_damage(30 / severity, BURN, "energy", 1)
|
||||
log_message("EMP detected", color="red")
|
||||
mecha_log_message("EMP detected", color="red")
|
||||
|
||||
if(istype(src, /obj/mecha/combat))
|
||||
mouse_pointer = 'icons/mecha/mecha_mouse-disable.dmi'
|
||||
@@ -160,7 +160,7 @@
|
||||
|
||||
/obj/mecha/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature>max_temperature)
|
||||
log_message("Exposed to dangerous temperature.", color="red")
|
||||
mecha_log_message("Exposed to dangerous temperature.", color="red")
|
||||
take_damage(5, BURN, 0, 1)
|
||||
|
||||
/obj/mecha/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
@@ -232,7 +232,7 @@
|
||||
cell = null
|
||||
state = 4
|
||||
to_chat(user, "<span class='notice'>You unscrew and pry out the powercell.</span>")
|
||||
log_message("Powercell removed")
|
||||
mecha_log_message("Powercell removed")
|
||||
else if(state==4 && cell)
|
||||
state=3
|
||||
to_chat(user, "<span class='notice'>You screw the cell in place.</span>")
|
||||
@@ -246,7 +246,7 @@
|
||||
var/obj/item/stock_parts/cell/C = W
|
||||
to_chat(user, "<span class='notice'>You install the powercell.</span>")
|
||||
cell = C
|
||||
log_message("Powercell installed")
|
||||
mecha_log_message("Powercell installed")
|
||||
else
|
||||
to_chat(user, "<span class='notice'>There's already a powercell installed.</span>")
|
||||
return
|
||||
@@ -280,7 +280,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/mecha/attacked_by(obj/item/I, mob/living/user)
|
||||
log_message("Attacked by [I]. Attacker - [user]")
|
||||
mecha_log_message("Attacked by [I]. Attacker - [user]")
|
||||
..()
|
||||
|
||||
/obj/mecha/proc/mech_toxin_damage(mob/living/target)
|
||||
|
||||
@@ -315,7 +315,7 @@
|
||||
if(internal_tank.connected_port)
|
||||
if(internal_tank.disconnect())
|
||||
occupant_message("Disconnected from the air system port.")
|
||||
log_message("Disconnected from gas port.")
|
||||
mecha_log_message("Disconnected from gas port.")
|
||||
else
|
||||
occupant_message("<span class='warning'>Unable to disconnect from the air system port!</span>")
|
||||
return
|
||||
@@ -323,7 +323,7 @@
|
||||
var/obj/machinery/atmospherics/components/unary/portables_connector/possible_port = locate() in loc
|
||||
if(internal_tank.connect(possible_port))
|
||||
occupant_message("Connected to the air system port.")
|
||||
log_message("Connected to gas port.")
|
||||
mecha_log_message("Connected to gas port.")
|
||||
else
|
||||
occupant_message("<span class='warning'>Unable to connect with air system port!</span>")
|
||||
return
|
||||
@@ -341,14 +341,14 @@
|
||||
|
||||
if(href_list["repair_int_control_lost"])
|
||||
occupant_message("Recalibrating coordination system...")
|
||||
log_message("Recalibration of coordination system started.")
|
||||
mecha_log_message("Recalibration of coordination system started.")
|
||||
var/T = loc
|
||||
spawn(100)
|
||||
if(T == loc)
|
||||
clearInternalDamage(MECHA_INT_CONTROL_LOST)
|
||||
occupant_message("<span class='notice'>Recalibration successful.</span>")
|
||||
log_message("Recalibration of coordination system finished with 0 errors.")
|
||||
mecha_log_message("Recalibration of coordination system finished with 0 errors.")
|
||||
else
|
||||
occupant_message("<span class='warning'>Recalibration failed!</span>")
|
||||
log_message("Recalibration of coordination system failed with 1 error.", color="red")
|
||||
mecha_log_message("Recalibration of coordination system failed with 1 error.", color="red")
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@
|
||||
occupant_message("<span class='notice'>You unload [O].</span>")
|
||||
O.forceMove(drop_location())
|
||||
cargo -= O
|
||||
log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - src.cargo.len]")
|
||||
mecha_log_message("Unloaded [O]. Cargo compartment capacity: [cargo_capacity - src.cargo.len]")
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -400,12 +400,14 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
||||
return usr.client.Click(src, src_location, src_control, params)
|
||||
var/list/directaccess = usr.DirectAccess() //This, specifically, is what requires the copypaste. If this were after the adjacency check, then it'd be impossible to use items in your inventory, among other things.
|
||||
//If this were before the above checks, then trying to click on items would act a little funky and signal overrides wouldn't work.
|
||||
if((usr.CanReach(src) || (src in directaccess)) && (usr.CanReach(over) || (over in directaccess)))
|
||||
if(!usr.get_active_held_item())
|
||||
usr.UnarmedAttack(src, TRUE)
|
||||
if(usr.get_active_held_item() == src)
|
||||
melee_attack_chain(usr, over)
|
||||
return TRUE //returning TRUE as a "is this overridden?" flag
|
||||
if(iscarbon(usr))
|
||||
var/mob/living/carbon/C = usr
|
||||
if(C.combatmode && ((C.CanReach(src) || (src in directaccess)) && (C.CanReach(over) || (over in directaccess))))
|
||||
if(!C.get_active_held_item())
|
||||
C.UnarmedAttack(src, TRUE)
|
||||
if(C.get_active_held_item() == src)
|
||||
melee_attack_chain(C, over)
|
||||
return TRUE //returning TRUE as a "is this overridden?" flag
|
||||
if(!Adjacent(usr) || !over.Adjacent(usr))
|
||||
return // should stop you from dragging through windows
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
if(!L)
|
||||
return OXYLOSS
|
||||
|
||||
L.Remove(user)
|
||||
L.Remove()
|
||||
|
||||
// make some colorful reagent, and apply it to the lungs
|
||||
L.create_reagents(10)
|
||||
|
||||
@@ -20,12 +20,12 @@
|
||||
owner.med_hud_set_status()
|
||||
INVOKE_ASYNC(src, .proc/AddInfectionImages, owner)
|
||||
|
||||
/obj/item/organ/body_egg/Remove(var/mob/living/carbon/M, special = 0)
|
||||
if(owner)
|
||||
/obj/item/organ/body_egg/Remove(special = FALSE)
|
||||
if(!QDELETED(owner))
|
||||
REMOVE_TRAIT(owner, TRAIT_XENO_HOST, TRAIT_GENERIC)
|
||||
owner.med_hud_set_status()
|
||||
INVOKE_ASYNC(src, .proc/RemoveInfectionImages, owner)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/body_egg/on_death()
|
||||
. = ..()
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
var/list/organs = M.getorganszone("head") + M.getorganszone("eyes") + M.getorganszone("mouth")
|
||||
for(var/internal_organ in organs)
|
||||
var/obj/item/organ/I = internal_organ
|
||||
I.Remove(M)
|
||||
I.Remove()
|
||||
I.forceMove(T)
|
||||
head.drop_limb()
|
||||
qdel(head)
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
|
||||
/obj/item/grenade/chem_grenade/prime()
|
||||
if(stage != READY)
|
||||
return
|
||||
return FALSE
|
||||
|
||||
var/list/datum/reagents/reactants = list()
|
||||
for(var/obj/item/reagent_containers/glass/G in beakers)
|
||||
@@ -192,7 +192,7 @@
|
||||
O.forceMove(drop_location())
|
||||
beakers = list()
|
||||
stage_change(EMPTY)
|
||||
return
|
||||
return FALSE
|
||||
|
||||
if(nadeassembly)
|
||||
var/mob/M = get_mob_by_ckey(assemblyattacher)
|
||||
@@ -205,6 +205,7 @@
|
||||
update_mob()
|
||||
|
||||
qdel(src)
|
||||
return TRUE
|
||||
|
||||
//Large chem grenades accept slime cores and use the appropriately.
|
||||
/obj/item/grenade/chem_grenade/large
|
||||
@@ -219,7 +220,7 @@
|
||||
|
||||
/obj/item/grenade/chem_grenade/large/prime()
|
||||
if(stage != READY)
|
||||
return
|
||||
return FALSE
|
||||
|
||||
for(var/obj/item/slime_extract/S in beakers)
|
||||
if(S.Uses)
|
||||
@@ -237,7 +238,7 @@
|
||||
else
|
||||
S.forceMove(get_turf(src))
|
||||
no_splash = TRUE
|
||||
..()
|
||||
return ..()
|
||||
|
||||
//I tried to just put it in the allowed_containers list but
|
||||
//if you do that it must have reagents. If you're going to
|
||||
@@ -288,7 +289,7 @@
|
||||
|
||||
/obj/item/grenade/chem_grenade/adv_release/prime()
|
||||
if(stage != READY)
|
||||
return
|
||||
return FALSE
|
||||
|
||||
var/total_volume = 0
|
||||
for(var/obj/item/reagent_containers/RC in beakers)
|
||||
@@ -296,7 +297,7 @@
|
||||
if(!total_volume)
|
||||
qdel(src)
|
||||
qdel(nadeassembly)
|
||||
return
|
||||
return FALSE
|
||||
var/fraction = unit_spread/total_volume
|
||||
var/datum/reagents/reactants = new(unit_spread)
|
||||
reactants.my_atom = src
|
||||
@@ -313,6 +314,7 @@
|
||||
else
|
||||
addtimer(CALLBACK(src, .proc/prime), det_time)
|
||||
log_game("A grenade detonated at [AREACOORD(DT)]")
|
||||
return TRUE
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
/obj/item/shield
|
||||
name = "shield"
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
block_chance = 50
|
||||
armor = list("melee" = 50, "bullet" = 50, "laser" = 50, "energy" = 0, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 70)
|
||||
var/transparent = FALSE // makes beam projectiles pass through the shield
|
||||
|
||||
/obj/item/shield/proc/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK)
|
||||
return TRUE
|
||||
|
||||
/obj/item/shield/riot
|
||||
name = "riot shield"
|
||||
desc = "A shield adept at blocking blunt objects from connecting with the torso of the shield wielder."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "riot"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
@@ -19,6 +23,19 @@
|
||||
materials = list(MAT_GLASS=7500, MAT_METAL=1000)
|
||||
attack_verb = list("shoved", "bashed")
|
||||
var/cooldown = 0 //shield bash cooldown. based on world.time
|
||||
transparent = TRUE
|
||||
max_integrity = 75
|
||||
|
||||
/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(transparent && (hitby.pass_flags & PASSGLASS))
|
||||
return FALSE
|
||||
if(attack_type == THROWN_PROJECTILE_ATTACK)
|
||||
final_block_chance += 30
|
||||
if(attack_type == LEAP_ATTACK)
|
||||
final_block_chance = 100
|
||||
. = ..()
|
||||
if(.)
|
||||
on_shield_block(owner, hitby, attack_text, damage, attack_type)
|
||||
|
||||
/obj/item/shield/riot/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/melee/baton))
|
||||
@@ -26,14 +43,40 @@
|
||||
user.visible_message("<span class='warning'>[user] bashes [src] with [W]!</span>")
|
||||
playsound(user.loc, 'sound/effects/shieldbash.ogg', 50, 1)
|
||||
cooldown = world.time
|
||||
else if(istype(W, /obj/item/stack/sheet/mineral/titanium))
|
||||
if(obj_integrity >= max_integrity)
|
||||
to_chat(user, "<span class='warning'>[src] is already in perfect condition.</span>")
|
||||
else
|
||||
var/obj/item/stack/sheet/mineral/titanium/T = W
|
||||
T.use(1)
|
||||
obj_integrity = max_integrity
|
||||
to_chat(user, "<span class='notice'>You repair [src] with [T].</span>")
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == THROWN_PROJECTILE_ATTACK)
|
||||
final_block_chance += 30
|
||||
if(attack_type == LEAP_ATTACK)
|
||||
final_block_chance = 100
|
||||
/obj/item/shield/riot/examine(mob/user)
|
||||
. = ..()
|
||||
var/healthpercent = round((obj_integrity/max_integrity) * 100, 1)
|
||||
switch(healthpercent)
|
||||
if(50 to 99)
|
||||
. += "<span class='info'>It looks slightly damaged.</span>"
|
||||
if(25 to 50)
|
||||
. += "<span class='info'>It appears heavily damaged.</span>"
|
||||
if(0 to 25)
|
||||
. += "<span class='warning'>It's falling apart!</span>"
|
||||
|
||||
/obj/item/shield/riot/proc/shatter(mob/living/carbon/human/owner)
|
||||
playsound(owner, 'sound/effects/glassbr3.ogg', 100)
|
||||
new /obj/item/shard((get_turf(src)))
|
||||
|
||||
/obj/item/shield/riot/on_shield_block(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(obj_integrity <= damage)
|
||||
var/turf/T = get_turf(owner)
|
||||
T.visible_message("<span class='warning'>[hitby] destroys [src]!</span>")
|
||||
shatter(owner)
|
||||
qdel(src)
|
||||
return FALSE
|
||||
take_damage(damage)
|
||||
return ..()
|
||||
|
||||
/obj/item/shield/riot/roman
|
||||
@@ -43,11 +86,18 @@
|
||||
item_state = "roman_shield"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
transparent = FALSE
|
||||
max_integrity = 65
|
||||
|
||||
/obj/item/shield/riot/roman/fake
|
||||
desc = "Bears an inscription on the inside: <i>\"Romanes venio domus\"</i>. It appears to be a bit flimsy."
|
||||
block_chance = 0
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
max_integrity = 30
|
||||
|
||||
/obj/item/shield/riot/roman/shatter(mob/living/carbon/human/owner)
|
||||
playsound(owner, 'sound/effects/grillehit.ogg', 100)
|
||||
new /obj/item/stack/sheet/metal(get_turf(src))
|
||||
|
||||
/obj/item/shield/riot/buckler
|
||||
name = "wooden buckler"
|
||||
@@ -59,11 +109,17 @@
|
||||
materials = list()
|
||||
resistance_flags = FLAMMABLE
|
||||
block_chance = 30
|
||||
transparent = FALSE
|
||||
max_integrity = 55
|
||||
|
||||
/obj/item/shield/riot/buckler/shatter(mob/living/carbon/human/owner)
|
||||
playsound(owner, 'sound/effects/bang.ogg', 50)
|
||||
new /obj/item/stack/sheet/mineral/wood(get_turf(src))
|
||||
|
||||
|
||||
/obj/item/shield/energy
|
||||
name = "energy combat shield"
|
||||
desc = "A shield that reflects almost all energy projectiles, but is useless against physical attacks. It can be retracted, expanded, and stored anywhere."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
@@ -91,7 +147,7 @@
|
||||
|
||||
/obj/item/shield/energy/attack_self(mob/living/carbon/human/user)
|
||||
if(clumsy_check && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50))
|
||||
to_chat(user, "<span class='warning'>You beat yourself in the head with [src].</span>")
|
||||
to_chat(user, "<span class='userdanger'>You beat yourself in the head with [src]!</span>")
|
||||
user.take_bodypart_damage(5)
|
||||
active = !active
|
||||
icon_state = "[base_icon_state][active]"
|
||||
@@ -101,21 +157,20 @@
|
||||
throwforce = on_throwforce
|
||||
throw_speed = on_throw_speed
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
playsound(user, 'sound/weapons/saberon.ogg', 35, 1)
|
||||
playsound(user, 'sound/weapons/saberon.ogg', 35, TRUE)
|
||||
to_chat(user, "<span class='notice'>[src] is now active.</span>")
|
||||
else
|
||||
force = initial(force)
|
||||
throwforce = initial(throwforce)
|
||||
throw_speed = initial(throw_speed)
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
playsound(user, 'sound/weapons/saberoff.ogg', 35, 1)
|
||||
playsound(user, 'sound/weapons/saberoff.ogg', 35, TRUE)
|
||||
to_chat(user, "<span class='notice'>[src] can now be concealed.</span>")
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/shield/riot/tele
|
||||
name = "telescopic shield"
|
||||
desc = "An advanced riot shield made of lightweight materials that collapses for easy storage."
|
||||
icon = 'icons/obj/items_and_weapons.dmi'
|
||||
icon_state = "teleriot0"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi'
|
||||
@@ -135,7 +190,7 @@
|
||||
/obj/item/shield/riot/tele/attack_self(mob/living/user)
|
||||
active = !active
|
||||
icon_state = "teleriot[active]"
|
||||
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, 1)
|
||||
playsound(src.loc, 'sound/weapons/batonextend.ogg', 50, TRUE)
|
||||
|
||||
if(active)
|
||||
force = 8
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
attack_verb = list("beaten")
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80)
|
||||
|
||||
var/stunforce = 140
|
||||
var/stunforce = 70
|
||||
var/status = FALSE
|
||||
var/obj/item/stock_parts/cell/cell
|
||||
var/hitcost = 1000
|
||||
@@ -188,8 +188,8 @@
|
||||
stunpwr *= round(stuncharge/hitcost, 0.1)
|
||||
|
||||
|
||||
L.Knockdown(stunpwr)
|
||||
L.adjustStaminaLoss(stunpwr*0.1)//CIT CHANGE - makes stunbatons deal extra staminaloss. Todo: make this also deal pain when pain gets implemented.
|
||||
L.Knockdown(stunpwr, override_stamdmg = 0)
|
||||
L.apply_damage(stunpwr*0.55, STAMINA, user.zone_selected)
|
||||
L.apply_effect(EFFECT_STUTTER, stunforce)
|
||||
SEND_SIGNAL(L, COMSIG_LIVING_MINOR_SHOCK)
|
||||
if(user)
|
||||
@@ -274,7 +274,7 @@
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 3
|
||||
throwforce = 5
|
||||
stunforce = 100
|
||||
stunforce = 60
|
||||
hitcost = 2000
|
||||
throw_hit_chance = 10
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
|
||||
@@ -33,6 +33,9 @@
|
||||
H.update_internals_hud_icon(0)
|
||||
else
|
||||
if(!H.getorganslot(ORGAN_SLOT_BREATHING_TUBE))
|
||||
if(HAS_TRAIT(H, TRAIT_NO_INTERNALS))
|
||||
to_chat(H, "<span class='warning'>Due to cumbersome equipment or anatomy, you are currently unable to use internals!</span>")
|
||||
return
|
||||
var/obj/item/clothing/check
|
||||
var/internals = FALSE
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
|
||||
/obj/structure/closet/crate/coffin/examine(mob/user)
|
||||
. = ..()
|
||||
if(user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
if(user.mind?.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
. += {"<span class='cult'>This is a coffin which you can use to regenerate your burns and other wounds faster.</span>"}
|
||||
. += {"<span class='cult'>You can also thicken your blood if you survive the day, and hide from the sun safely while inside.</span>"}
|
||||
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
|
||||
@@ -343,12 +343,12 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
set category = "Admin"
|
||||
set name = "Aghost"
|
||||
if(!holder)
|
||||
return
|
||||
return FALSE
|
||||
if(isobserver(mob))
|
||||
//re-enter
|
||||
var/mob/dead/observer/ghost = mob
|
||||
if(!ghost.mind || !ghost.mind.current) //won't do anything if there is no body
|
||||
return
|
||||
return FALSE
|
||||
if(!ghost.can_reenter_corpse)
|
||||
log_admin("[key_name(usr)] re-entered corpse")
|
||||
message_admins("[key_name_admin(usr)] re-entered corpse")
|
||||
@@ -357,6 +357,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin Reenter") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
else if(isnewplayer(mob))
|
||||
to_chat(src, "<font color='red'>Error: Aghost: Can't admin-ghost whilst in the lobby. Join or Observe first.</font>")
|
||||
return FALSE
|
||||
else
|
||||
//ghostize
|
||||
log_admin("[key_name(usr)] admin ghosted.")
|
||||
@@ -366,7 +367,7 @@ GLOBAL_PROTECT(admin_verbs_hideable)
|
||||
if(body && !body.key)
|
||||
body.key = "@[key]" //Haaaaaaaack. But the people have spoken. If it breaks; blame adminbus
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Admin Ghost") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
return TRUE
|
||||
|
||||
/client/proc/invisimin()
|
||||
set name = "Invisimin"
|
||||
|
||||
@@ -137,7 +137,8 @@ GLOBAL_LIST(round_end_notifiees)
|
||||
return "The Database is not enabled!"
|
||||
|
||||
GLOB.bunker_passthrough |= ckey(params)
|
||||
|
||||
GLOB.bunker_passthrough[ckey(params)] = world.realtime
|
||||
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
|
||||
log_admin("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
|
||||
message_admins("[sender.friendly_name] has added [params] to the current round's bunker bypass list.")
|
||||
return "[params] has been added to the current round's bunker bypass list."
|
||||
|
||||
@@ -1983,8 +1983,8 @@
|
||||
var/atom/movable/AM = locate(href_list["adminplayerobservefollow"])
|
||||
|
||||
var/client/C = usr.client
|
||||
if(!isobserver(usr))
|
||||
C.admin_ghost()
|
||||
if(!isobserver(usr) && !C.admin_ghost())
|
||||
return
|
||||
var/mob/dead/observer/A = C.mob
|
||||
A.ManualFollow(AM)
|
||||
|
||||
@@ -2006,8 +2006,8 @@
|
||||
var/z = text2num(href_list["Z"])
|
||||
|
||||
var/client/C = usr.client
|
||||
if(!isobserver(usr))
|
||||
C.admin_ghost()
|
||||
if(!isobserver(usr) && !C.admin_ghost())
|
||||
return
|
||||
sleep(2)
|
||||
C.jumptocoord(x,y,z)
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
|
||||
if(isorgan(organ))
|
||||
O = organ
|
||||
O.Remove(C)
|
||||
O.Remove()
|
||||
else
|
||||
I = organ
|
||||
I.removed(C)
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
return
|
||||
|
||||
GLOB.bunker_passthrough |= ckey(ckeytobypass)
|
||||
GLOB.bunker_passthrough[ckey(ckeytobypass)] = world.realtime
|
||||
SSpersistence.SavePanicBunker() //we can do this every time, it's okay
|
||||
log_admin("[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
message_admins("[key_name_admin(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has added [ckeytobypass] to the current round's bunker bypass list.")
|
||||
@@ -37,6 +39,7 @@
|
||||
return
|
||||
|
||||
GLOB.bunker_passthrough -= ckey(ckeytobypass)
|
||||
SSpersistence.SavePanicBunker()
|
||||
log_admin("[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
message_admins("[key_name_admin(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
send2irc("Panic Bunker", "[key_name(usr)] has removed [ckeytobypass] from the current round's bunker bypass list.")
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
if(IC)
|
||||
user.visible_message("[user] pulls [IC] out of [target]'s [target_zone]!", "<span class='notice'>You pull [IC] out of [target]'s [target_zone].</span>")
|
||||
user.put_in_hands(IC)
|
||||
IC.Remove(target)
|
||||
IC.Remove()
|
||||
return 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You don't find anything in [target]'s [target_zone]!</span>")
|
||||
|
||||
@@ -73,13 +73,14 @@
|
||||
active_mind_control = FALSE
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/heart/gland/Remove(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/heart/gland/Remove(special = FALSE)
|
||||
active = 0
|
||||
if(initial(uses) == 1)
|
||||
uses = initial(uses)
|
||||
var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR]
|
||||
hud.remove_from_hud(owner)
|
||||
clear_mind_control()
|
||||
if(!QDELETED(owner))
|
||||
var/datum/atom_hud/abductor/hud = GLOB.huds[DATA_HUD_ABDUCTOR]
|
||||
hud.remove_from_hud(owner)
|
||||
clear_mind_control()
|
||||
..()
|
||||
|
||||
/obj/item/organ/heart/gland/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
/obj/item/organ/heart/gland/access/proc/free_access(datum/source, obj/O)
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/heart/gland/access/Remove(mob/living/carbon/M, special = 0)
|
||||
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
|
||||
..()
|
||||
/obj/item/organ/heart/gland/access/Remove(special = FALSE)
|
||||
if(!QDELETED(owner))
|
||||
UnregisterSignal(owner, COMSIG_MOB_ALLOWED)
|
||||
return ..()
|
||||
@@ -11,9 +11,10 @@
|
||||
..()
|
||||
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
|
||||
|
||||
/obj/item/organ/heart/gland/electric/Remove(mob/living/carbon/M, special = 0)
|
||||
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
|
||||
..()
|
||||
/obj/item/organ/heart/gland/electric/Remove(special = FALSE)
|
||||
if(!QDELETED(owner))
|
||||
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, "abductor_gland")
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/heart/gland/electric/activate()
|
||||
owner.visible_message("<span class='danger'>[owner]'s skin starts emitting electric arcs!</span>",\
|
||||
|
||||
@@ -65,14 +65,14 @@
|
||||
/obj/item/organ/heart/gland/heal/proc/reject_implant(obj/item/organ/cyberimp/implant)
|
||||
owner.visible_message("<span class='warning'>[owner] vomits up his [implant.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [implant.name]!</span>")
|
||||
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
|
||||
implant.Remove(owner)
|
||||
implant.Remove()
|
||||
implant.forceMove(owner.drop_location())
|
||||
|
||||
/obj/item/organ/heart/gland/heal/proc/replace_liver(obj/item/organ/liver/liver)
|
||||
if(liver)
|
||||
owner.visible_message("<span class='warning'>[owner] vomits up his [liver.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [liver.name]!</span>")
|
||||
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
|
||||
liver.Remove(owner)
|
||||
liver.Remove()
|
||||
liver.forceMove(owner.drop_location())
|
||||
else
|
||||
to_chat(owner, "<span class='warning'>You feel a weird rumble in your bowels...</span>")
|
||||
@@ -87,7 +87,7 @@
|
||||
if(lungs)
|
||||
owner.visible_message("<span class='warning'>[owner] vomits up his [lungs.name]!</span>", "<span class='userdanger'>You suddenly vomit up your [lungs.name]!</span>")
|
||||
owner.vomit(0, TRUE, TRUE, 1, FALSE, FALSE, FALSE, TRUE)
|
||||
lungs.Remove(owner)
|
||||
lungs.Remove()
|
||||
lungs.forceMove(owner.drop_location())
|
||||
else
|
||||
to_chat(owner, "<span class='warning'>You feel a weird rumble inside your chest...</span>")
|
||||
@@ -102,7 +102,7 @@
|
||||
if(eyes)
|
||||
owner.visible_message("<span class='warning'>[owner]'s [eyes.name] fall out of their sockets!</span>", "<span class='userdanger'>Your [eyes.name] fall out of their sockets!</span>")
|
||||
playsound(owner, 'sound/effects/splat.ogg', 50, TRUE)
|
||||
eyes.Remove(owner)
|
||||
eyes.Remove()
|
||||
eyes.forceMove(owner.drop_location())
|
||||
else
|
||||
to_chat(owner, "<span class='warning'>You feel a weird rumble behind your eye sockets...</span>")
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
//It is called from your coffin on close (by you only)
|
||||
if(poweron_masquerade == TRUE || owner.current.AmStaked())
|
||||
return FALSE
|
||||
owner.current.adjustStaminaLoss(-2 + (regenRate * -8) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more.
|
||||
owner.current.adjustStaminaLoss(-1.5 + (regenRate * -7) * mult, 0) // Humans lose stamina damage really quickly. Vamps should heal more.
|
||||
owner.current.adjustCloneLoss(-0.1 * (regenRate * 2) * mult, 0)
|
||||
owner.current.adjustOrganLoss(ORGAN_SLOT_BRAIN, -1 * (regenRate * 4) * mult) //adjustBrainLoss(-1 * (regenRate * 4) * mult, 0)
|
||||
// No Bleeding
|
||||
@@ -125,7 +125,7 @@
|
||||
C.adjustFireLoss(-fireheal * mult, forced = TRUE)
|
||||
C.adjustToxLoss(-toxinheal * mult * 2, forced = TRUE) //Toxin healing because vamps arent immune
|
||||
//C.heal_overall_damage(bruteheal * mult, fireheal * mult) // REMOVED: We need to FORCE this, because otherwise, vamps won't heal EVER. Swapped to above.
|
||||
AddBloodVolume((bruteheal * -0.5 + fireheal * -1) / mult * costMult) // Costs blood to heal
|
||||
AddBloodVolume((bruteheal * -0.5 + fireheal * -1 + toxinheal * -0.2) / mult * costMult) // Costs blood to heal
|
||||
return TRUE // Healed! Done for this tick.
|
||||
if(amInCoffinWhileTorpor) // Limbs? (And I have no other healing)
|
||||
var/list/missing = owner.current.get_missing_limbs() // Heal Missing
|
||||
@@ -189,7 +189,7 @@
|
||||
/datum/antagonist/bloodsucker/proc/HandleDeath()
|
||||
// FINAL DEATH
|
||||
// Fire Damage? (above double health)
|
||||
if(owner.current.getFireLoss_nonProsthetic() >= owner.current.getMaxHealth() * 1.5)
|
||||
if(owner.current.getFireLoss_nonProsthetic() >= owner.current.maxHealth * 2.5)
|
||||
FinalDeath()
|
||||
return
|
||||
// Staked while "Temp Death" or Asleep
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
//var/not_bloodsucker = FALSE // This goes to Vassals or Hunters, but NOT bloodsuckers.
|
||||
|
||||
/datum/action/bloodsucker/New()
|
||||
if (bloodcost > 0)
|
||||
if(bloodcost > 0)
|
||||
desc += "<br><br><b>COST:</b> [bloodcost] Blood" // Modify description to add cost.
|
||||
if (warn_constant_cost)
|
||||
if(warn_constant_cost)
|
||||
desc += "<br><br><i>Your over-time blood consumption increases while [name] is active.</i>"
|
||||
if (amSingleUse)
|
||||
if(amSingleUse)
|
||||
desc += "<br><br><i>Useable once per night.</i>"
|
||||
..()
|
||||
|
||||
@@ -47,35 +47,35 @@
|
||||
|
||||
/datum/action/bloodsucker/Trigger()
|
||||
// Active? DEACTIVATE AND END!
|
||||
if (active && CheckCanDeactivate(TRUE))
|
||||
if(active && CheckCanDeactivate(TRUE))
|
||||
DeactivatePower()
|
||||
return
|
||||
if (!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
|
||||
if(!CheckCanPayCost(TRUE) || !CheckCanUse(TRUE))
|
||||
return
|
||||
PayCost()
|
||||
if (amToggle)
|
||||
if(amToggle)
|
||||
active = !active
|
||||
UpdateButtonIcon()
|
||||
if (!amToggle || !active)
|
||||
if(!amToggle || !active)
|
||||
StartCooldown() // Must come AFTER UpdateButton(), otherwise icon will revert.
|
||||
ActivatePower() // NOTE: ActivatePower() freezes this power in place until it ends.
|
||||
if (active) // Did we not manually disable? Handle it here.
|
||||
if(active) // Did we not manually disable? Handle it here.
|
||||
DeactivatePower()
|
||||
if (amSingleUse)
|
||||
if(amSingleUse)
|
||||
RemoveAfterUse()
|
||||
|
||||
/datum/action/bloodsucker/proc/CheckCanPayCost(display_error)
|
||||
if(!owner || !owner.mind)
|
||||
return FALSE
|
||||
// Cooldown?
|
||||
if (cooldownUntil > world.time)
|
||||
if (display_error)
|
||||
if(cooldownUntil > world.time)
|
||||
if(display_error)
|
||||
to_chat(owner, "[src] is unavailable. Wait [(cooldownUntil - world.time) / 10] seconds.")
|
||||
return FALSE
|
||||
// Have enough blood?
|
||||
var/mob/living/L = owner
|
||||
if (L.blood_volume < bloodcost)
|
||||
if (display_error)
|
||||
if(L.blood_volume < bloodcost)
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>You need at least [bloodcost] blood to activate [name]</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#define TIME_BLOODSUCKER_NIGHT 900 // 15 minutes
|
||||
#define TIME_BLOODSUCKER_DAY_WARN 90 // 1.5 minutes
|
||||
#define TIME_BLOODSUCKER_DAY_FINAL_WARN 25 // 25 sec
|
||||
#define TIME_BLOODSUCKER_DAY 60 // 1.5 minutes // 10 is a second, 600 is a minute.
|
||||
@@ -11,6 +10,7 @@
|
||||
var/cancel_me = FALSE
|
||||
var/amDay = FALSE
|
||||
var/time_til_cycle = 0
|
||||
var/nightime_duration = 900 //15 Minutes
|
||||
|
||||
/obj/effect/sunlight/Initialize()
|
||||
countdown()
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
while(!cancel_me)
|
||||
|
||||
time_til_cycle = TIME_BLOODSUCKER_NIGHT
|
||||
time_til_cycle = nightime_duration
|
||||
|
||||
// Part 1: Night (all is well)
|
||||
while(time_til_cycle > TIME_BLOODSUCKER_DAY_WARN)
|
||||
@@ -81,7 +81,9 @@
|
||||
"<span class = 'announce'>The solar flare has ended, and the daylight danger has passed...for now.</span>")
|
||||
amDay = FALSE
|
||||
day_end() // Remove VANISHING ACT power from all vamps who have it! Clear Warnings (sunlight, locker protection)
|
||||
message_admins("BLOODSUCKER NOTICE: Daylight Ended. Resetting to Night (Lasts for [TIME_BLOODSUCKER_NIGHT / 60] minutes.)")
|
||||
nightime_duration += 100 //Each day makes the night a minute longer.
|
||||
message_admins("BLOODSUCKER NOTICE: Daylight Ended. Resetting to Night (Lasts for [nightime_duration / 60] minutes.)")
|
||||
|
||||
|
||||
|
||||
/obj/effect/sunlight/proc/hud_tick()
|
||||
@@ -97,7 +99,7 @@
|
||||
sleep(10)
|
||||
time_til_cycle --
|
||||
|
||||
/obj/effect/sunlight/proc/warn_daylight(danger_level=0, vampwarn = "", vassalwarn = "")
|
||||
/obj/effect/sunlight/proc/warn_daylight(danger_level =0, vampwarn = "", vassalwarn = "")
|
||||
for(var/datum/mind/M in SSticker.mode.bloodsuckers)
|
||||
if(!istype(M))
|
||||
continue
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
// STATS
|
||||
var/vamplevel = 0
|
||||
var/vamplevel_unspent = 1
|
||||
var/regenRate = 0.3 // How many points of Brute do I heal per tick?
|
||||
var/regenRate = 0.4 // How many points of Brute do I heal per tick?
|
||||
var/feedAmount = 15 // Amount of blood drawn from a target per tick.
|
||||
var/maxBloodVolume = 600 // Maximum blood a Vamp can hold via feeding. // BLOOD_VOLUME_NORMAL 550 // BLOOD_VOLUME_SAFE 475 //BLOOD_VOLUME_OKAY 336 //BLOOD_VOLUME_BAD 224 // BLOOD_VOLUME_SURVIVE 122
|
||||
// OBJECTIVES
|
||||
@@ -34,6 +34,7 @@
|
||||
var/warn_sun_locker = FALSE // So we only get the locker burn message once per day.
|
||||
var/warn_sun_burn = FALSE // So we only get the sun burn message once per day.
|
||||
var/had_toxlover = FALSE
|
||||
var/level_bloodcost
|
||||
// LISTS
|
||||
var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_NIGHT_VISION, \
|
||||
TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE)
|
||||
@@ -98,7 +99,7 @@
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/SelectFirstName()
|
||||
// Names (EVERYONE gets one))
|
||||
if (owner.current.gender == MALE)
|
||||
if(owner.current.gender == MALE)
|
||||
vampname = pick("Desmond","Rudolph","Dracul","Vlad","Pyotr","Gregor","Cristian","Christoff","Marcu","Andrei","Constantin","Gheorghe","Grigore","Ilie","Iacob","Luca","Mihail","Pavel","Vasile","Octavian","Sorin", \
|
||||
"Sveyn","Aurel","Alexe","Iustin","Theodor","Dimitrie","Octav","Damien","Magnus","Caine","Abel", // Romanian/Ancient
|
||||
"Lucius","Gaius","Otho","Balbinus","Arcadius","Romanos","Alexios","Vitellius", // Latin
|
||||
@@ -119,7 +120,7 @@
|
||||
return
|
||||
// Titles [Master]
|
||||
if (!am_fledgling)
|
||||
if (owner.current.gender == MALE)
|
||||
if(owner.current.gender == MALE)
|
||||
vamptitle = pick ("Count","Baron","Viscount","Prince","Duke","Tzar","Dreadlord","Lord","Master")
|
||||
else
|
||||
vamptitle = pick ("Countess","Baroness","Viscountess","Princess","Duchess","Tzarina","Dreadlady","Lady","Mistress")
|
||||
@@ -130,18 +131,18 @@
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/SelectReputation(am_fledgling = 0, forced=FALSE)
|
||||
// Already have Reputation
|
||||
if (!forced && vampreputation != null)
|
||||
if(!forced && vampreputation != null)
|
||||
return
|
||||
// Reputations [Master]
|
||||
if (!am_fledgling)
|
||||
if(!am_fledgling)
|
||||
vampreputation = pick("Butcher","Blood Fiend","Crimson","Red","Black","Terror","Nightman","Feared","Ravenous","Fiend","Malevolent","Wicked","Ancient","Plaguebringer","Sinister","Forgotten","Wretched","Baleful", \
|
||||
"Inqisitor","Harvester","Reviled","Robust","Betrayer","Destructor","Damned","Accursed","Terrible","Vicious","Profane","Vile","Depraved","Foul","Slayer","Manslayer","Sovereign","Slaughterer", \
|
||||
"Forsaken","Mad","Dragon","Savage","Villainous","Nefarious","Inquisitor","Marauder","Horrible","Immortal","Undying","Overlord","Corrupt","Hellspawn","Tyrant","Sanguineous")
|
||||
if (owner.current.gender == MALE)
|
||||
if (prob(10)) // Gender override
|
||||
if(owner.current.gender == MALE)
|
||||
if(prob(10)) // Gender override
|
||||
vampreputation = pick("King of the Damned", "Blood King", "Emperor of Blades", "Sinlord", "God-King")
|
||||
else
|
||||
if (prob(10)) // Gender override
|
||||
if(prob(10)) // Gender override
|
||||
vampreputation = pick("Queen of the Damned", "Blood Queen", "Empress of Blades", "Sinlady", "God-Queen")
|
||||
|
||||
to_chat(owner, "<span class='announce'>You have earned a reputation! You are now known as <i>[ReturnFullName(TRUE)]</i>!</span>")
|
||||
@@ -202,7 +203,7 @@
|
||||
// Make Changes
|
||||
H.physiology.brute_mod *= 0.8 // <-------------------- Start small, but burn mod increases based on rank!
|
||||
H.physiology.cold_mod = 0
|
||||
H.physiology.stun_mod *= 0.35
|
||||
H.physiology.stun_mod *= 0.5
|
||||
H.physiology.siemens_coeff *= 0.75 //base electrocution coefficient 1
|
||||
//S.heatmod += 0.5 // Heat shouldn't affect. Only Fire.
|
||||
//S.punchstunthreshold = 8 //damage at which punches from this race will stun 9
|
||||
@@ -261,7 +262,7 @@
|
||||
owner.hasSoul = TRUE
|
||||
//owner.current.hellbound = FALSE
|
||||
|
||||
datum/antagonist/bloodsucker/proc/RankUp()
|
||||
/datum/antagonist/bloodsucker/proc/RankUp()
|
||||
set waitfor = FALSE
|
||||
if(!owner || !owner.current)
|
||||
return
|
||||
@@ -272,21 +273,23 @@ datum/antagonist/bloodsucker/proc/RankUp()
|
||||
else
|
||||
to_chat(owner, "<EM><span class='notice'>You have grown more ancient! Sleep in a coffin that you have claimed to thicken your blood and become more powerful.</span></EM>")
|
||||
if(vamplevel_unspent >= 2)
|
||||
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, they can be built from wooden planks.</span><br>")
|
||||
to_chat(owner, "<span class='announce'>Bloodsucker Tip: If you cannot find or steal a coffin to use, you can build one from wooden planks.</span><br>")
|
||||
|
||||
datum/antagonist/bloodsucker/proc/LevelUpPowers()
|
||||
/datum/antagonist/bloodsucker/proc/LevelUpPowers()
|
||||
for(var/datum/action/bloodsucker/power in powers)
|
||||
power.level_current ++
|
||||
|
||||
datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
/datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
set waitfor = FALSE
|
||||
if (vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client)
|
||||
if(vamplevel_unspent <= 0 || !owner || !owner.current || !owner.current.client || !isliving(owner.current))
|
||||
return
|
||||
/////////
|
||||
// Powers
|
||||
//TODO: Make this into a radial
|
||||
var/mob/living/L = owner.current
|
||||
level_bloodcost = maxBloodVolume * 0.2
|
||||
//If the blood volume of the bloodsucker is lower than the cost to level up, return and inform the bloodsucker
|
||||
|
||||
//TODO: Make this into a radial, or perhaps a tgui next UI
|
||||
// Purchase Power Prompt
|
||||
var/list/options = list() // Taken from gasmask.dm, for Clown Masks.
|
||||
var/list/options = list()
|
||||
for(var/pickedpower in typesof(/datum/action/bloodsucker))
|
||||
var/datum/action/bloodsucker/power = pickedpower
|
||||
// If I don't own it, and I'm allowed to buy it.
|
||||
@@ -295,7 +298,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
options["\[ Not Now \]"] = null
|
||||
// Abort?
|
||||
if(options.len > 1)
|
||||
var/choice = input(owner.current, "You have the opportunity to grow more ancient. Select a power to advance your Rank.", "Your Blood Thickens...") in options
|
||||
var/choice = input(owner.current, "You have the opportunity to grow more ancient at the cost of [level_bloodcost] units of blood. Select a power to advance your Rank.", "Your Blood Thickens...") in options
|
||||
// Cheat-Safety: Can't keep opening/closing coffin to spam levels
|
||||
if(vamplevel_unspent <= 0) // Already spent all your points, and tried opening/closing your coffin, pal.
|
||||
return
|
||||
@@ -305,10 +308,14 @@ datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
if(!choice || !options[choice] || (locate(options[choice]) in powers)) // ADDED: Check to see if you already have this power, due to window stacking.
|
||||
to_chat(owner.current, "<span class='notice'>You prevent your blood from thickening just yet, but you may try again later.</span>")
|
||||
return
|
||||
if(L.blood_volume < level_bloodcost)
|
||||
to_chat(owner.current, "<span class='warning'>You dont have enough blood to thicken your blood, you need [level_bloodcost - L.blood_volume] units more!</span>")
|
||||
return
|
||||
// Buy New Powers
|
||||
var/datum/action/bloodsucker/P = options[choice]
|
||||
AddBloodVolume(-level_bloodcost)
|
||||
BuyPower(new P)
|
||||
to_chat(owner.current, "<span class='notice'>You have learned [initial(P.name)]!</span>")
|
||||
to_chat(owner.current, "<span class='notice'>You have used [level_bloodcost] units of blood and learned [initial(P.name)]!</span>")
|
||||
else
|
||||
to_chat(owner.current, "<span class='notice'>You grow more ancient by the night!</span>")
|
||||
/////////
|
||||
@@ -326,7 +333,7 @@ datum/antagonist/bloodsucker/proc/SpendRank()
|
||||
// Vamp Stats
|
||||
regenRate += 0.05 // Points of brute healed (starts at 0.3)
|
||||
feedAmount += 2 // Increase how quickly I munch down vics (15)
|
||||
maxBloodVolume += 50 // Increase my max blood (600)
|
||||
maxBloodVolume += 100 // Increase my max blood (600)
|
||||
/////////
|
||||
vamplevel ++
|
||||
vamplevel_unspent --
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
return SSticker.mode.make_vassal(C,owner)
|
||||
|
||||
/datum/antagonist/bloodsucker/proc/FreeAllVassals()
|
||||
for (var/datum/antagonist/vassal/V in vassals)
|
||||
for(var/datum/antagonist/vassal/V in vassals)
|
||||
SSticker.mode.remove_vassal(V.owner)
|
||||
|
||||
/datum/antagonist/vassal
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
/datum/antagonist/vassal/can_be_owned(datum/mind/new_owner)
|
||||
// If we weren't created by a bloodsucker, then we cannot be a vassal (assigned from antag panel)
|
||||
if (!master)
|
||||
if(!master)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
@@ -63,9 +63,9 @@
|
||||
/datum/antagonist/vassal/on_removal()
|
||||
SSticker.mode.vassals -= owner // Add if not already in here (and you might be, if you were picked at round start)
|
||||
// Mindslave Remove
|
||||
if (master && master.owner)
|
||||
if(master && master.owner)
|
||||
master.vassals -= src
|
||||
if (owner.enslaved_to == master.owner.current)
|
||||
if(owner.enslaved_to == master.owner.current)
|
||||
owner.enslaved_to = null
|
||||
// Master Pinpointer
|
||||
owner.current.remove_status_effect(/datum/status_effect/agent_pinpointer/vassal_edition)
|
||||
|
||||
@@ -60,6 +60,8 @@
|
||||
breakout_time = 600
|
||||
pryLidTimer = 400
|
||||
resistance_flags = NONE
|
||||
integrity_failure = 70
|
||||
armor = list("melee" = 50, "bullet" = 20, "laser" = 30, "energy" = 0, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
|
||||
|
||||
/obj/structure/closet/crate/coffin/meatcoffin
|
||||
name = "meat coffin"
|
||||
@@ -75,7 +77,9 @@
|
||||
resistance_flags = NONE
|
||||
material_drop = /obj/item/reagent_containers/food/snacks/meat/slab
|
||||
material_drop_amount = 3
|
||||
|
||||
integrity_failure = 40
|
||||
armor = list("melee" = 70, "bullet" = 10, "laser" = 10, "energy" = 0, "bomb" = 70, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 100)
|
||||
|
||||
/obj/structure/closet/crate/coffin/metalcoffin
|
||||
name = "metal coffin"
|
||||
desc = "A big metal sardine can inside of another big metal sardine can, in space."
|
||||
@@ -90,6 +94,8 @@
|
||||
resistance_flags = NONE
|
||||
material_drop = /obj/item/stack/sheet/metal
|
||||
material_drop_amount = 5
|
||||
integrity_failure = 60
|
||||
armor = list("melee" = 40, "bullet" = 15, "laser" = 50, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 60)
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
var/convert_progress = 3 // Resets on each new character to be added to the chair. Some effects should lower it...
|
||||
var/disloyalty_confirm = FALSE // Command & Antags need to CONFIRM they are willing to lose their role (and will only do it if the Vassal'ing succeeds)
|
||||
var/disloyalty_offered = FALSE // Has the popup been issued? Don't spam them.
|
||||
var/convert_cost = 100
|
||||
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/deconstruct(disassembled = TRUE)
|
||||
new /obj/item/stack/sheet/metal(src.loc, 4)
|
||||
@@ -116,10 +116,10 @@
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/examine(mob/user)
|
||||
. = ..()
|
||||
if((user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)) || isobserver(user))
|
||||
if(isvamp(user) || isobserver(user))
|
||||
. += {"<span class='cult'>This is the vassal rack, which allows you to thrall crewmembers into loyal minions in your service.</span>"}
|
||||
. += {"<span class='cult'>You need to first secure the vassal rack by clicking on it while it is in your lair.</span>"}
|
||||
. += {"<span class='cult'>Simply click and hold on a victim, and then drag their sprite on the vassal rack.</span>"}
|
||||
. += {"<span class='cult'>Simply click and hold on a victim, and then drag their sprite on the vassal rack. Alt click on the vassal rack to unbuckle them.</span>"}
|
||||
. += {"<span class='cult'>Make sure that the victim is handcuffed, or else they can simply run away or resist, as the process is not instant.</span>"}
|
||||
. += {"<span class='cult'>To convert the victim, simply click on the vassal rack itself. Sharp weapons work faster than other tools.</span>"}
|
||||
/* if(user.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
@@ -177,7 +177,7 @@
|
||||
M.pixel_y = -2 //M.get_standard_pixel_y_offset(120)//180)
|
||||
update_icon()
|
||||
// Torture Stuff
|
||||
convert_progress = 2 // Goes down unless you start over.
|
||||
convert_progress = 4 // Goes down unless you start over.
|
||||
disloyalty_confirm = FALSE // New guy gets the chance to say NO if he's special.
|
||||
disloyalty_offered = FALSE // Prevents spamming torture window.
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
else
|
||||
M.visible_message("<span class='danger'>[user] tries to pull [M] rack!</span>",\
|
||||
"<span class='danger'>[user] attempts to release you from the rack!</span>") // For sound if not seen --> "<span class='italics'>You hear a squishy wet noise.</span>")
|
||||
if(!do_mob(user, M, 100))
|
||||
if(!do_mob(user, M, 200))
|
||||
return
|
||||
// Did the time. Now try to do it.
|
||||
..()
|
||||
@@ -248,7 +248,7 @@
|
||||
// Bloodsucker Owner! Let the boy go.
|
||||
if(C.mind)
|
||||
var/datum/antagonist/vassal/vassaldatum = C.mind.has_antag_datum(ANTAG_DATUM_VASSAL)
|
||||
if (istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD)
|
||||
if(istype(vassaldatum) && vassaldatum.master == bloodsuckerdatum || C.stat >= DEAD)
|
||||
unbuckle_mob(C)
|
||||
useLock = FALSE // Failsafe
|
||||
return
|
||||
@@ -256,7 +256,9 @@
|
||||
torture_victim(user, C)
|
||||
|
||||
/obj/structure/bloodsucker/vassalrack/proc/torture_victim(mob/living/user, mob/living/target)
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
// Check Bloodmob/living/M, force = FALSE, check_loc = TRUE
|
||||
var/convert_cost = 200 + 200 * bloodsuckerdatum.vassals
|
||||
if(user.blood_volume < convert_cost + 5)
|
||||
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target].</span>")
|
||||
return
|
||||
@@ -275,7 +277,7 @@
|
||||
// All done!
|
||||
if(convert_progress <= 0)
|
||||
// FAIL: Can't be Vassal
|
||||
if(!SSticker.mode.can_make_vassal(target, user, display_warning=FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
|
||||
if(!SSticker.mode.can_make_vassal(target, user, display_warning = FALSE) || HAS_TRAIT(target, TRAIT_MINDSHIELD)) // If I'm an unconvertable Antag ONLY
|
||||
to_chat(user, "<span class='danger'>[target] doesn't respond to your persuasion. It doesn't appear they can be converted to follow you, they either have a mindshield or their external loyalties are too difficult for you to break.<i>\[ALT+click to release\]</span>")
|
||||
convert_progress ++ // Pop it back up some. Avoids wasting Blood on a lost cause.
|
||||
// SUCCESS: All done!
|
||||
@@ -301,10 +303,9 @@
|
||||
return
|
||||
// Check: Blood
|
||||
if(user.blood_volume < convert_cost)
|
||||
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target].</span>")
|
||||
to_chat(user, "<span class='notice'>You don't have enough blood to initiate the Dark Communion with [target], you need [convert_cost - user.blood_volume] units more!</span>")
|
||||
useLock = FALSE
|
||||
return
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
bloodsuckerdatum.AddBloodVolume(-convert_cost)
|
||||
target.add_mob_blood(user)
|
||||
user.visible_message("<span class='notice'>[user] marks a bloody smear on [target]'s forehead and puts a wrist up to [target.p_their()] mouth!</span>", \
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
desc = "Snap restraints with ease, or deal terrible damage with your bare hands."
|
||||
button_icon_state = "power_strength"
|
||||
bloodcost = 10
|
||||
cooldown = 130
|
||||
cooldown = 90
|
||||
target_range = 1
|
||||
power_activates_immediately = TRUE
|
||||
message_Trigger = ""//"Whom will you subvert to your will?"
|
||||
@@ -66,16 +66,14 @@
|
||||
// Target Type: Mob
|
||||
if(isliving(target))
|
||||
var/mob/living/carbon/user_C = user
|
||||
var/hitStrength = user_C.dna.species.punchdamagehigh * 1.3 + 5
|
||||
var/hitStrength = user_C.dna.species.punchdamagehigh * 1.4 + 15
|
||||
// Knockdown!
|
||||
var/powerlevel = min(5, 1 + level_current)
|
||||
if(rand(5 + powerlevel) >= 5)
|
||||
target.visible_message("<span class='danger'>[user] lands a vicious punch, sending [target] away!</span>", \
|
||||
"<span class='userdanger'>[user] has landed a horrifying punch on you, sending you flying!!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
target.Knockdown(min(5, rand(10, 10 * powerlevel)) )
|
||||
// Chance of KO
|
||||
if(rand(6 + powerlevel) >= 6 && target.stat <= UNCONSCIOUS)
|
||||
target.Unconscious(40)
|
||||
|
||||
// Attack!
|
||||
playsound(get_turf(target), 'sound/weapons/punch4.ogg', 60, 1, -1)
|
||||
user.do_attack_animation(target, ATTACK_EFFECT_SMASH)
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
return
|
||||
// Wearing mask
|
||||
var/mob/living/L = owner
|
||||
if (L.is_mouth_covered())
|
||||
if (display_error)
|
||||
if(L.is_mouth_covered())
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>You cannot feed with your mouth covered! Remove your mask.</span>")
|
||||
return FALSE
|
||||
// Find my Target!
|
||||
if (!FindMyTarget(display_error)) // Sets feed_target within after Validating
|
||||
if(!FindMyTarget(display_error)) // Sets feed_target within after Validating
|
||||
return FALSE
|
||||
// Not in correct state
|
||||
// DONE!
|
||||
@@ -35,36 +35,36 @@
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/ValidateTarget(mob/living/target, display_error) // Called twice: validating a subtle victim, or validating your grapple victim.
|
||||
// Bloodsuckers + Animals MUST be grabbed aggressively!
|
||||
if (!owner.pulling || target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE)
|
||||
if(!owner.pulling || target == owner.pulling && owner.grab_state < GRAB_AGGRESSIVE)
|
||||
// NOTE: It's OKAY that we are checking if(!target) below, AFTER animals here. We want passive check vs animal to warn you first, THEN the standard warning.
|
||||
// Animals:
|
||||
if (isliving(target) && !iscarbon(target))
|
||||
if (display_error)
|
||||
if(isliving(target) && !iscarbon(target))
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>Lesser beings require a tighter grip.</span>")
|
||||
return FALSE
|
||||
// Bloodsuckers:
|
||||
else if (iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
if (display_error)
|
||||
else if(iscarbon(target) && target.mind && target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>Other Bloodsuckers will not fall for your subtle approach.</span>")
|
||||
return FALSE
|
||||
// Must have Target
|
||||
if (!target) // || !ismob(target)
|
||||
if (display_error)
|
||||
if(!target) // || !ismob(target)
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>You must be next to or grabbing a victim to feed from them.</span>")
|
||||
return FALSE
|
||||
// Not even living!
|
||||
if (!isliving(target) || issilicon(target))
|
||||
if (display_error)
|
||||
if(!isliving(target) || issilicon(target))
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>You may only feed from living beings.</span>")
|
||||
return FALSE
|
||||
if (target.blood_volume <= 0)
|
||||
if (display_error)
|
||||
if(target.blood_volume <= 0)
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>Your victim has no blood to take.</span>")
|
||||
return FALSE
|
||||
if (ishuman(target))
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
if(NOBLOOD in H.dna.species.species_traits)// || owner.get_blood_id() != target.get_blood_id())
|
||||
if (display_error)
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>Your victim's blood is not suitable for you to take.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
@@ -75,9 +75,9 @@
|
||||
feed_target = null
|
||||
target_grappled = FALSE
|
||||
// If you are pulling a mob, that's your target. If you don't like it, then release them.
|
||||
if (owner.pulling && ismob(owner.pulling))
|
||||
if(owner.pulling && ismob(owner.pulling))
|
||||
// Check grapple target Valid
|
||||
if (!ValidateTarget(owner.pulling, display_error)) // Grabbed targets display error.
|
||||
if(!ValidateTarget(owner.pulling, display_error)) // Grabbed targets display error.
|
||||
return FALSE
|
||||
target_grappled = TRUE
|
||||
feed_target = owner.pulling
|
||||
@@ -86,11 +86,11 @@
|
||||
var/list/mob/living/seen_targets = view(1, owner)
|
||||
var/list/mob/living/seen_mobs = list()
|
||||
for(var/mob/living/M in seen_targets)
|
||||
if (isliving(M) && M != owner)
|
||||
if(isliving(M) && M != owner)
|
||||
seen_mobs += M
|
||||
// None Seen!
|
||||
if (seen_mobs.len == 0)
|
||||
if (display_error)
|
||||
if(seen_mobs.len == 0)
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>You must be next to or grabbing a victim to feed from them.</span>")
|
||||
return FALSE
|
||||
// Check Valids...
|
||||
@@ -98,19 +98,19 @@
|
||||
var/list/targets_dead = list()
|
||||
for(var/mob/living/M in seen_mobs)
|
||||
// Check adjecent Valid target
|
||||
if (M != owner && ValidateTarget(M, display_error = FALSE)) // Do NOT display errors. We'll be doing this again in CheckCanUse(), which will rule out grabbed targets.
|
||||
if(M != owner && ValidateTarget(M, display_error = FALSE)) // Do NOT display errors. We'll be doing this again in CheckCanUse(), which will rule out grabbed targets.
|
||||
// Prioritize living, but remember dead as backup
|
||||
if (M.stat < DEAD)
|
||||
if(M.stat < DEAD)
|
||||
targets_valid += M
|
||||
else
|
||||
targets_dead += M
|
||||
// No Living? Try dead.
|
||||
if (targets_valid.len == 0 && targets_dead.len > 0)
|
||||
if(targets_valid.len == 0 && targets_dead.len > 0)
|
||||
targets_valid = targets_dead
|
||||
// No Targets
|
||||
if (targets_valid.len == 0)
|
||||
if(targets_valid.len == 0)
|
||||
// Did I see targets? Then display at least one error
|
||||
if (seen_mobs.len > 1)
|
||||
if(seen_mobs.len > 1)
|
||||
if (display_error)
|
||||
to_chat(owner, "<span class='warning'>None of these are valid targets to feed from subtly.</span>")
|
||||
else
|
||||
@@ -136,28 +136,28 @@
|
||||
// Initial Wait
|
||||
var/feed_time = (amSilent ? 45 : 25) - (2.5 * level_current)
|
||||
feed_time = max(15, feed_time)
|
||||
if (amSilent)
|
||||
if(amSilent)
|
||||
to_chat(user, "<span class='notice'>You lean quietly toward [target] and secretly draw out your fangs...</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You pull [target] close to you and draw out your fangs...</span>")
|
||||
if (!do_mob(user, target, feed_time,0,1,extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10)
|
||||
if(!do_mob(user, target, feed_time,0,1,extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))//sleep(10)
|
||||
to_chat(user, "<span class='warning'>Your feeding was interrupted.</span>")
|
||||
//DeactivatePower(user,target)
|
||||
return
|
||||
// Put target to Sleep (Bloodsuckers are immune to their own bite's sleep effect)
|
||||
if (!amSilent)
|
||||
if(!amSilent)
|
||||
ApplyVictimEffects(target) // Sleep, paralysis, immobile, unconscious, and mute
|
||||
if(target.stat <= UNCONSCIOUS)
|
||||
sleep(1)
|
||||
// Wait, then Cancel if Invalid
|
||||
if (!ContinueActive(user,target)) // Cancel. They're gone.
|
||||
if(!ContinueActive(user,target)) // Cancel. They're gone.
|
||||
//DeactivatePower(user,target)
|
||||
return
|
||||
// Pull Target Close
|
||||
if (!target.density) // Pull target to you if they don't take up space.
|
||||
if(!target.density) // Pull target to you if they don't take up space.
|
||||
target.Move(user.loc)
|
||||
// Broadcast Message
|
||||
if (amSilent)
|
||||
if(amSilent)
|
||||
//if (!iscarbon(target))
|
||||
// user.visible_message("<span class='notice'>[user] shifts [target] closer to [user.p_their()] mouth.</span>", \
|
||||
// "<span class='notice'>You secretly slip your fangs into [target]'s flesh.</span>", \
|
||||
@@ -173,7 +173,7 @@
|
||||
if(M != owner && M != target && iscarbon(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind && !M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
was_unnoticed = FALSE
|
||||
break
|
||||
if (was_unnoticed)
|
||||
if(was_unnoticed)
|
||||
to_chat(user, "<span class='notice'>You think no one saw you...</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Someone may have noticed...</span>")
|
||||
@@ -197,16 +197,16 @@
|
||||
|
||||
// FEEEEEEEEED!!! //
|
||||
bloodsuckerdatum.poweron_feed = TRUE
|
||||
while (bloodsuckerdatum && target && active)
|
||||
while(bloodsuckerdatum && target && active)
|
||||
//user.mobility_flags &= ~MOBILITY_MOVE // user.canmove = 0 // Prevents spilling blood accidentally.
|
||||
|
||||
// Abort? A bloody mistake.
|
||||
if (!do_mob(user, target, 20, 0, 0, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
|
||||
if(!do_mob(user, target, 20, 0, 0, extra_checks=CALLBACK(src, .proc/ContinueActive, user, target)))
|
||||
// May have disabled Feed during do_mob
|
||||
if (!active || !ContinueActive(user, target))
|
||||
if(!active || !ContinueActive(user, target))
|
||||
break
|
||||
|
||||
if (amSilent)
|
||||
if(amSilent)
|
||||
to_chat(user, "<span class='warning'>Your feeding has been interrupted...but [target.p_they()] didn't seem to notice you.<span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Your feeding has been interrupted!</span>")
|
||||
@@ -214,11 +214,11 @@
|
||||
"<span class='userdanger'>Your teeth are ripped from [target]'s throat. [target.p_their(TRUE)] blood sprays everywhere!</span>")
|
||||
|
||||
// Deal Damage to Target (should have been more careful!)
|
||||
if (iscarbon(target))
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
C.bleed(15)
|
||||
playsound(get_turf(target), 'sound/effects/splat.ogg', 40, 1)
|
||||
if (ishuman(target))
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.bleed_rate += 5
|
||||
target.add_splatter_floor(get_turf(target))
|
||||
@@ -228,7 +228,7 @@
|
||||
target.emote("scream")
|
||||
|
||||
// Killed Target?
|
||||
if (was_alive)
|
||||
if(was_alive)
|
||||
CheckKilledTarget(user,target)
|
||||
|
||||
return
|
||||
@@ -237,40 +237,40 @@
|
||||
// Handle Feeding! User & Victim Effects (per tick)
|
||||
bloodsuckerdatum.HandleFeeding(target, blood_take_mult)
|
||||
amount_taken += amSilent ? 0.3 : 1
|
||||
if (!amSilent)
|
||||
if(!amSilent)
|
||||
ApplyVictimEffects(target) // Sleep, paralysis, immobile, unconscious, and mute
|
||||
if (amount_taken > 5 && target.stat < DEAD && ishuman(target))
|
||||
if(amount_taken > 5 && target.stat < DEAD && ishuman(target))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood) // GOOD // in bloodsucker_life.dm
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// Not Human?
|
||||
if (!ishuman(target))
|
||||
if(!ishuman(target))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood_bad) // BAD // in bloodsucker_life.dm
|
||||
if (!warning_target_inhuman)
|
||||
if(!warning_target_inhuman)
|
||||
to_chat(user, "<span class='notice'>You recoil at the taste of a lesser lifeform.</span>")
|
||||
warning_target_inhuman = TRUE
|
||||
// Dead Blood?
|
||||
if (target.stat >= DEAD)
|
||||
if (ishuman(target))
|
||||
if(target.stat >= DEAD)
|
||||
if(ishuman(target))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankblood", /datum/mood_event/drankblood_dead) // BAD // in bloodsucker_life.dm
|
||||
if (!warning_target_dead)
|
||||
if(!warning_target_dead)
|
||||
to_chat(user, "<span class='notice'>Your victim is dead. [target.p_their(TRUE)] blood barely nourishes you.</span>")
|
||||
warning_target_dead = TRUE
|
||||
// Full?
|
||||
if (!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume)
|
||||
if(!warning_full && user.blood_volume >= bloodsuckerdatum.maxBloodVolume)
|
||||
to_chat(user, "<span class='notice'>You are full. Further blood will be wasted.</span>")
|
||||
warning_full = TRUE
|
||||
// Blood Remaining? (Carbons/Humans only)
|
||||
if (iscarbon(target) && !target.AmBloodsucker(1))
|
||||
if (target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD)
|
||||
if(iscarbon(target) && !target.AmBloodsucker(1))
|
||||
if(target.blood_volume <= BLOOD_VOLUME_BAD && warning_target_bloodvol > BLOOD_VOLUME_BAD)
|
||||
to_chat(user, "<span class='warning'>Your victim's blood volume is fatally low!</span>")
|
||||
else if (target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY)
|
||||
else if(target.blood_volume <= BLOOD_VOLUME_OKAY && warning_target_bloodvol > BLOOD_VOLUME_OKAY)
|
||||
to_chat(user, "<span class='warning'>Your victim's blood volume is dangerously low.</span>")
|
||||
else if (target.blood_volume <= BLOOD_VOLUME_SAFE && warning_target_bloodvol > BLOOD_VOLUME_SAFE)
|
||||
else if(target.blood_volume <= BLOOD_VOLUME_SAFE && warning_target_bloodvol > BLOOD_VOLUME_SAFE)
|
||||
to_chat(user, "<span class='notice'>Your victim's blood is at an unsafe level.</span>")
|
||||
warning_target_bloodvol = target.blood_volume // If we had a warning to give, it's been given by now.
|
||||
// Done?
|
||||
if (target.blood_volume <= 0)
|
||||
if(target.blood_volume <= 0)
|
||||
to_chat(user, "<span class='notice'>You have bled your victim dry.</span>")
|
||||
break
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
|
||||
// DONE!
|
||||
//DeactivatePower(user,target)
|
||||
if (amSilent)
|
||||
if(amSilent)
|
||||
to_chat(user, "<span class='notice'>You slowly release [target]'s wrist." + (target.stat == 0 ? " [target.p_their(TRUE)] face lacks expression, like you've already been forgotten.</span>" : ""))
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] unclenches their teeth from [target]'s neck.</span>", \
|
||||
@@ -289,13 +289,13 @@
|
||||
log_combat(owner, target, "fed on blood", addition="(and took [amount_taken] blood)")
|
||||
|
||||
// Killed Target?
|
||||
if (was_alive)
|
||||
if(was_alive)
|
||||
CheckKilledTarget(user,target)
|
||||
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/CheckKilledTarget(mob/living/user, mob/living/target)
|
||||
// Bad Vampire. You shouldn't do that.
|
||||
if (target && target.stat >= DEAD && ishuman(target))
|
||||
if(target && target.stat >= DEAD && ishuman(target))
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "drankkilled", /datum/mood_event/drankkilled) // BAD // in bloodsucker_life.dm
|
||||
|
||||
/datum/action/bloodsucker/feed/ContinueActive(mob/living/user, mob/living/target)
|
||||
@@ -304,18 +304,18 @@
|
||||
|
||||
/datum/action/bloodsucker/feed/proc/ApplyVictimEffects(mob/living/target)
|
||||
// Bloodsuckers not affected by "the Kiss" of another vampire
|
||||
if (!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
if(!target.mind || !target.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
target.Unconscious(50,0)
|
||||
target.Knockdown(40 + 5 * level_current,1)
|
||||
// NOTE: THis is based on level of power!
|
||||
if (ishuman(target))
|
||||
if(ishuman(target))
|
||||
target.adjustStaminaLoss(5, forced = TRUE)// Base Stamina Damage
|
||||
|
||||
/datum/action/bloodsucker/feed/DeactivatePower(mob/living/user = owner, mob/living/target)
|
||||
..() // activate = FALSE
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = user.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
// No longer Feeding
|
||||
if (bloodsuckerdatum)
|
||||
if(bloodsuckerdatum)
|
||||
bloodsuckerdatum.poweron_feed = FALSE
|
||||
feed_target = null
|
||||
// My mouth is no longer full
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
name = "Fortitude"//"Cellular Emporium"
|
||||
desc = "Withstand egregious physical wounds and walk away from attacks that would stun, pierce, and dismember lesser beings. You cannot run while active."
|
||||
button_icon_state = "power_fortitude"
|
||||
bloodcost = 5
|
||||
bloodcost = 30
|
||||
cooldown = 80
|
||||
bloodsucker_can_buy = TRUE
|
||||
amToggle = TRUE
|
||||
@@ -23,7 +23,7 @@
|
||||
ADD_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
|
||||
ADD_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
|
||||
ADD_TRAIT(user, TRAIT_NORUNNING, "fortitude")
|
||||
if (ishuman(owner))
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
this_resist = max(0.3, 0.7 - level_current * 0.1)
|
||||
H.physiology.brute_mod *= this_resist//0.5
|
||||
@@ -34,7 +34,7 @@
|
||||
user.toggle_move_intent()
|
||||
while(bloodsuckerdatum && ContinueActive(user) || user.m_intent == MOVE_INTENT_RUN)
|
||||
// Pay Blood Toll (if awake)
|
||||
if (user.stat == CONSCIOUS)
|
||||
if(user.stat == CONSCIOUS)
|
||||
bloodsuckerdatum.AddBloodVolume(-0.5) // Used to be 0.3 blood per 2 seconds, but we're making it more expensive to keep on.
|
||||
sleep(20) // Check every few ticks that we haven't disabled this power
|
||||
// Return to Running (if you were before)
|
||||
@@ -48,7 +48,7 @@
|
||||
REMOVE_TRAIT(user, TRAIT_NODISMEMBER, "fortitude")
|
||||
REMOVE_TRAIT(user, TRAIT_STUNIMMUNE, "fortitude")
|
||||
REMOVE_TRAIT(user, TRAIT_NORUNNING, "fortitude")
|
||||
if (ishuman(owner))
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.physiology.brute_mod /= this_resist//0.5
|
||||
H.physiology.burn_mod /= this_resist//0.5
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
background_icon_state_on = "vamp_power_off_oneshot" // Even though this never goes off.
|
||||
background_icon_state_off = "vamp_power_off_oneshot"
|
||||
|
||||
bloodcost = 25
|
||||
bloodcost = 100
|
||||
cooldown = 99999 // It'll never come back.
|
||||
amToggle = FALSE
|
||||
amSingleUse = TRUE
|
||||
@@ -23,11 +23,16 @@
|
||||
return
|
||||
// Have No Lair (NOTE: You only got this power if you had a lair, so this means it's destroyed)
|
||||
var/datum/antagonist/bloodsucker/bloodsuckerdatum = owner.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER)
|
||||
if (!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
|
||||
if (display_error)
|
||||
if(!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
|
||||
if(display_error)
|
||||
to_chat(owner, "<span class='warning'>Your coffin has been destroyed!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/gohome/proc/flicker_lights(var/flicker_range, var/beat_volume)
|
||||
for(var/obj/machinery/light/L in view(flicker_range, get_turf(owner)))
|
||||
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', beat_volume, 1)
|
||||
|
||||
|
||||
/datum/action/bloodsucker/gohome/ActivatePower()
|
||||
var/mob/living/carbon/user = owner
|
||||
@@ -35,34 +40,31 @@
|
||||
// IMPORTANT: Check for lair at every step! It might get destroyed.
|
||||
to_chat(user, "<span class='notice'>You focus on separating your consciousness from your physical form...</span>")
|
||||
// STEP ONE: Flicker Lights
|
||||
for(var/obj/machinery/light/L in view(3, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
|
||||
L.flicker(5)
|
||||
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 20, 1)
|
||||
flicker_lights(3, 20)
|
||||
sleep(50)
|
||||
for(var/obj/machinery/light/L in view(3, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
|
||||
L.flicker(5)
|
||||
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1)
|
||||
flicker_lights(4, 40)
|
||||
sleep(50)
|
||||
for(var/obj/machinery/light/L in view(6, get_turf(owner))) // /obj/machinery/light/proc/flicker(var/amount = rand(10, 20))
|
||||
flicker_lights(4, 60)
|
||||
for(var/obj/machinery/light/L in view(6, get_turf(owner)))
|
||||
L.flicker(5)
|
||||
playsound(get_turf(owner), 'sound/effects/singlebeat.ogg', 60, 1)
|
||||
// ( STEP TWO: Lights OFF? )
|
||||
// CHECK: Still have Coffin?
|
||||
if (!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
|
||||
if(!istype(bloodsuckerdatum) || !bloodsuckerdatum.coffin)
|
||||
to_chat(user, "<span class='warning'>Your coffin has been destroyed! You no longer have a destination.</span>")
|
||||
return FALSE
|
||||
if (!owner)
|
||||
if(!owner)
|
||||
return
|
||||
// SEEN?: (effects ONLY if there are witnesses! Otherwise you just POOF)
|
||||
// NOTE: Stolen directly from statue.dm, thanks guys!
|
||||
|
||||
var/am_seen = FALSE // Do Effects (seen by anyone)
|
||||
var/drop_item = FALSE // Drop Stuff (seen by non-vamp)
|
||||
if (isturf(owner.loc)) // Only check if I'm not in a Locker or something.
|
||||
if(isturf(owner.loc)) // Only check if I'm not in a Locker or something.
|
||||
// A) Check for Darkness (we can just leave)
|
||||
var/turf/T = get_turf(user)
|
||||
if(T && T.lighting_object && T.get_lumcount()>= 0.1)
|
||||
// B) Check for Viewers
|
||||
for(var/mob/living/M in viewers(owner))
|
||||
for(var/mob/living/M in viewers(get_turf(owner)))
|
||||
if(M != owner && isliving(M) && M.mind && !M.has_unlimited_silicon_privilege && !M.eye_blind) // M.client <--- add this in after testing!
|
||||
am_seen = TRUE
|
||||
if (!M.mind.has_antag_datum(ANTAG_DATUM_BLOODSUCKER))
|
||||
@@ -76,7 +78,7 @@
|
||||
var/obj/O = user.legcuffed
|
||||
user.dropItemToGround(O)
|
||||
// SEEN!
|
||||
if (drop_item)
|
||||
if(drop_item)
|
||||
// DROP: Clothes, held items, and cuffs etc
|
||||
// NOTE: Taken from unequip_everything() in inventory.dm. We need to
|
||||
// *force* all items to drop, so we had to just gut the code out of it.
|
||||
@@ -86,30 +88,28 @@
|
||||
user.dropItemToGround(I,TRUE)
|
||||
for(var/obj/item/I in owner.held_items) // drop_all_held_items()
|
||||
user.dropItemToGround(I, TRUE)
|
||||
if (am_seen)
|
||||
if(am_seen)
|
||||
// POOF EFFECTS
|
||||
playsound(get_turf(owner), 'sound/magic/summon_karp.ogg', 60, 1)
|
||||
var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/()
|
||||
puff.effect_type = /obj/effect/particle_effect/smoke/vampsmoke
|
||||
puff.set_up(3, 0, get_turf(owner))
|
||||
puff.start()
|
||||
|
||||
//STEP FIVE: Create animal at prev location
|
||||
var/mob/living/simple_animal/SA = pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
|
||||
new SA (owner.loc)
|
||||
// TELEPORT: Move to Coffin & Close it!
|
||||
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM) // in teleport.dm?
|
||||
// SLEEP
|
||||
do_teleport(owner, bloodsuckerdatum.coffin, no_effects = TRUE, forced = TRUE, channel = TELEPORT_CHANNEL_QUANTUM)
|
||||
user.resting = TRUE
|
||||
//user.Unconscious(30,0)
|
||||
user.Stun(30,1)
|
||||
// CLOSE LID: If fail, force me in.
|
||||
if (!bloodsuckerdatum.coffin.close(owner))
|
||||
if(!bloodsuckerdatum.coffin.close(owner))
|
||||
bloodsuckerdatum.coffin.insert(owner) // Puts me inside.
|
||||
// The following was taken from close() proc in closets.dm
|
||||
// (but we had to do it this way because there is no way to force entry)
|
||||
playsound(bloodsuckerdatum.coffin.loc, bloodsuckerdatum.coffin.close_sound, 15, 1, -3)
|
||||
bloodsuckerdatum.coffin.opened = FALSE
|
||||
bloodsuckerdatum.coffin.density = TRUE
|
||||
bloodsuckerdatum.coffin.update_icon()
|
||||
// Lock Coffin
|
||||
bloodsuckerdatum.coffin.LockMe(owner)
|
||||
// ( STEP FIVE: Create animal at prev location? )
|
||||
//var/mob/living/simple_animal/SA = /mob/living/simple_animal/hostile/retaliate/bat // pick(/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse,/mob/living/simple_animal/mouse, /mob/living/simple_animal/hostile/retaliate/bat) //prob(300) /mob/living/simple_animal/mouse,
|
||||
//new SA (owner.loc)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
desc = "Dash somewhere with supernatural speed. Those nearby may be knocked away, stunned, or left empty-handed."
|
||||
button_icon_state = "power_speed"
|
||||
bloodcost = 6
|
||||
cooldown = 30
|
||||
cooldown = 50
|
||||
target_range = 15
|
||||
power_activates_immediately = TRUE
|
||||
message_Trigger = ""//"Whom will you subvert to your will?"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
desc = "Spring at your target and aggressively grapple them without warning. Attacks from concealment or the rear may even knock them down."
|
||||
button_icon_state = "power_lunge"
|
||||
bloodcost = 10
|
||||
cooldown = 100
|
||||
cooldown = 120
|
||||
target_range = 3
|
||||
power_activates_immediately = TRUE
|
||||
message_Trigger = ""//"Whom will you subvert to your will?"
|
||||
@@ -28,7 +28,7 @@
|
||||
return TRUE
|
||||
|
||||
/datum/action/bloodsucker/targeted/lunge/CheckValidTarget(atom/A)
|
||||
return isliving(A)
|
||||
return iscarbon(A)
|
||||
|
||||
/datum/action/bloodsucker/targeted/lunge/CheckCanTarget(atom/A, display_error)
|
||||
// Check: Self
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
desc = "Dominate the mind of a mortal who can see your eyes."
|
||||
button_icon_state = "power_mez"
|
||||
bloodcost = 30
|
||||
cooldown = 200
|
||||
cooldown = 300
|
||||
target_range = 1
|
||||
power_activates_immediately = FALSE
|
||||
message_Trigger = "Whom will you subvert to your will?"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
button_icon_state = "power_tres"
|
||||
|
||||
bloodcost = 10
|
||||
cooldown = 60
|
||||
cooldown = 80
|
||||
amToggle = FALSE
|
||||
//target_range = 2
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
var/list/organs = user.getorganszone(BODY_ZONE_HEAD, 1)
|
||||
|
||||
for(var/obj/item/organ/I in organs)
|
||||
I.Remove(user, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
explosion(get_turf(user), 0, 0, 2, 0, TRUE)
|
||||
for(var/mob/living/carbon/human/H in range(2,user))
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
if(!istype(O))
|
||||
continue
|
||||
|
||||
O.Remove(user)
|
||||
O.Remove()
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.vomit(0, toxic = TRUE)
|
||||
|
||||
@@ -104,6 +104,6 @@
|
||||
transfer_personality(H)
|
||||
brainmob.fully_replace_character_name(null, "[braintype] [H.real_name]")
|
||||
name = "[initial(name)] ([brainmob.name])"
|
||||
B.Remove(H)
|
||||
B.Remove()
|
||||
qdel(B)
|
||||
H.update_hair()
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
if(2) //steal
|
||||
var/datum/objective/steal/special/O = new /datum/objective/steal/special()
|
||||
O.owner = owner
|
||||
O.find_target()
|
||||
objectives += O
|
||||
|
||||
if(3) //protect/kill
|
||||
|
||||
@@ -100,10 +100,9 @@
|
||||
if(M.mind)
|
||||
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
|
||||
|
||||
/obj/item/organ/heart/demon/Remove(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
if(M.mind)
|
||||
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
|
||||
/obj/item/organ/heart/demon/Remove(special = FALSE)
|
||||
owner?.mind?.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/heart/demon/Stop()
|
||||
return 0 // Always beating.
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
desc = "Hello brothers from the stars!!! Our fellow brethren have made contact at long last and gave us gifts man! They really did build the prymi- Connection Error- Bro we’ll send you a sheet of advanced alien alloy."
|
||||
cost = 15000
|
||||
DropPodOnly = TRUE
|
||||
contraband = TRUE
|
||||
contains = list(/obj/item/stack/sheet/mineral/abductor)
|
||||
crate_name = "alien bro alloy crate"
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
for(var/X in CM.internal_organs)
|
||||
var/destination = get_edge_target_turf(T, pick(GLOB.alldirs)) //Pick a random direction to toss them in
|
||||
var/obj/item/organ/O = X
|
||||
O.Remove(CM) //Note that this isn't the same proc as for lists
|
||||
O.Remove() //Note that this isn't the same proc as for lists
|
||||
O.forceMove(T) //Move the organ outta the body
|
||||
O.throw_at(destination, 2, 3) //Thow the organ at a random tile 3 spots away
|
||||
sleep(1)
|
||||
|
||||
@@ -514,7 +514,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
if (CONFIG_GET(flag/panic_bunker) && !holder && !GLOB.deadmins[ckey] && !(ckey in GLOB.bunker_passthrough))
|
||||
log_access("Failed Login: [key] - New account attempting to connect during panic bunker")
|
||||
message_admins("<span class='adminnotice'>Failed Login: [key] - New account attempting to connect during panic bunker</span>")
|
||||
to_chat(src, "<span class='notice'>You must first join the Discord to verify your account before joining this server.<br>To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: <a href='https://discord.gg/E6SQuhz'>https://discord.gg/E6SQuhz</a></span>") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
|
||||
to_chat(src, "<span class='notice'>You must first join the Discord to verify your account before joining this server.<br>To do so, read the rules and post a request in the #station-access-requests channel under the \"Main server\" category in the Discord server linked here: <a href='https://discord.gg/E6SQuhz'>https://discord.gg/E6SQuhz</a><br>If you have already done so, wait a few minutes then try again; sometimes the server needs to fully load before you can join.</span>") //CIT CHANGE - makes the panic bunker disconnect message point to the discord
|
||||
var/list/connectiontopic_a = params2list(connectiontopic)
|
||||
var/list/panic_addr = CONFIG_GET(string/panic_server_address)
|
||||
if(panic_addr && !connectiontopic_a["redirect"])
|
||||
@@ -538,6 +538,8 @@ GLOBAL_LIST_EMPTY(external_rsc_urls)
|
||||
if(!account_join_date)
|
||||
account_join_date = "Error"
|
||||
account_age = -1
|
||||
else if(ckey in GLOB.bunker_passthrough)
|
||||
GLOB.bunker_passthrough -= ckey
|
||||
qdel(query_client_in_db)
|
||||
var/datum/DBQuery/query_get_client_age = SSdbcore.NewQuery("SELECT firstseen, DATEDIFF(Now(),firstseen), accountjoindate, DATEDIFF(Now(),accountjoindate) FROM [format_table_name("player")] WHERE ckey = '[sql_ckey]'")
|
||||
if(!query_get_client_age.Execute())
|
||||
|
||||
@@ -57,3 +57,32 @@
|
||||
name = "blood-red magboots"
|
||||
icon_state = "syndiemag0"
|
||||
magboot_state = "syndiemag"
|
||||
|
||||
/obj/item/clothing/shoes/magboots/crushing
|
||||
desc = "Normal looking magboots that are altered to increase magnetic pull to crush anything underfoot."
|
||||
|
||||
/obj/item/clothing/shoes/magboots/crushing/proc/crush(mob/living/user)
|
||||
if (!isturf(user.loc) || !magpulse)
|
||||
return
|
||||
var/turf/T = user.loc
|
||||
for (var/mob/living/A in T)
|
||||
if (A != user && A.lying)
|
||||
A.adjustBruteLoss(rand(10,13))
|
||||
to_chat(A,"<span class='userdanger'>[user]'s magboots press down on you, crushing you!</span>")
|
||||
A.emote("scream")
|
||||
|
||||
/obj/item/clothing/shoes/magboots/crushing/attack_self(mob/user)
|
||||
. = ..()
|
||||
if (magpulse)
|
||||
RegisterSignal(user, COMSIG_MOVABLE_MOVED,.proc/crush)
|
||||
else
|
||||
UnregisterSignal(user,COMSIG_MOVABLE_MOVED)
|
||||
|
||||
/obj/item/clothing/shoes/magboots/crushing/equipped(mob/user,slot)
|
||||
. = ..()
|
||||
if (slot == SLOT_SHOES && magpulse)
|
||||
RegisterSignal(user, COMSIG_MOVABLE_MOVED,.proc/crush)
|
||||
|
||||
/obj/item/clothing/shoes/magboots/crushing/dropped(mob/user)
|
||||
. = ..()
|
||||
UnregisterSignal(user,COMSIG_MOVABLE_MOVED)
|
||||
|
||||
@@ -244,6 +244,7 @@
|
||||
/datum/reagent/consumable/spacemountainwind = 5
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/snowcones/spacemountainwind
|
||||
subcategory = CAT_ICE
|
||||
|
||||
/datum/crafting_recipe/food/pwrgame_sc
|
||||
name = "Pwrgame snowcone"
|
||||
@@ -273,4 +274,4 @@
|
||||
/datum/reagent/colorful_reagent = 1 //Harder to make
|
||||
)
|
||||
result = /obj/item/reagent_containers/food/snacks/snowcones/rainbow
|
||||
subcategory = CAT_ICE
|
||||
subcategory = CAT_ICE
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
/obj/machinery/seed_extractor/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
. += "<span class='notice'>The status display reads: Extracting <b>[seed_multiplier]</b> seed(s) per piece of produce.<br>Machine can store up to <b>[max_seeds]%</b> seeds.</span>"
|
||||
. += "<span class='notice'>The status display reads: Extracting <b>[seed_multiplier]</b> seed(s) per piece of produce.<br>Machine can store up to <b>[max_seeds]</b> seeds.</span>"
|
||||
|
||||
/obj/machinery/seed_extractor/attackby(obj/item/O, mob/user, params)
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -124,6 +124,10 @@
|
||||
/datum/language_holder/drone/syndicate
|
||||
only_speaks_language = null
|
||||
|
||||
/datum/language_holder/dwarf
|
||||
languages = list(/datum/language/common, /datum/language/dwarf)
|
||||
only_speaks_language = /datum/language/dwarf
|
||||
|
||||
/datum/language_holder/slime
|
||||
languages = list(/datum/language/common, /datum/language/slime)
|
||||
only_speaks_language = /datum/language/slime
|
||||
|
||||
@@ -111,8 +111,8 @@
|
||||
preserved(TRUE)
|
||||
owner.visible_message("<span class='notice'>[src] stabilizes as it's inserted.</span>")
|
||||
|
||||
/obj/item/organ/regenerative_core/Remove(mob/living/carbon/M, special = 0)
|
||||
if(!inert && !special)
|
||||
/obj/item/organ/regenerative_core/Remove(special = FALSE)
|
||||
if(!inert && !special && !QDELETED(owner))
|
||||
owner.visible_message("<span class='notice'>[src] rapidly decays as it's removed.</span>")
|
||||
go_inert()
|
||||
return ..()
|
||||
|
||||
@@ -159,6 +159,11 @@
|
||||
color_src = MATRIXED
|
||||
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
|
||||
|
||||
/datum/sprite_accessory/ears/bunny
|
||||
name = "Bunny"
|
||||
icon_state = "bunny"
|
||||
color_src = MATRIXED
|
||||
icon = 'modular_citadel/icons/mob/mam_ears.dmi'
|
||||
|
||||
/******************************************
|
||||
*************** Furry Ears ****************
|
||||
@@ -301,3 +306,7 @@
|
||||
/datum/sprite_accessory/mam_ears/wolf
|
||||
name = "Wolf"
|
||||
icon_state = "wolf"
|
||||
|
||||
/datum/sprite_accessory/mam_ears/bunny
|
||||
name = "Bunny"
|
||||
icon_state = "bunny"
|
||||
@@ -55,16 +55,18 @@
|
||||
//Update the body's icon so it doesnt appear debrained anymore
|
||||
C.update_hair()
|
||||
|
||||
/obj/item/organ/brain/Remove(mob/living/carbon/C, special = 0, no_id_transfer = FALSE)
|
||||
..()
|
||||
/obj/item/organ/brain/Remove(special = FALSE, no_id_transfer = FALSE)
|
||||
. = ..()
|
||||
var/mob/living/carbon/C = .
|
||||
for(var/X in traumas)
|
||||
var/datum/brain_trauma/BT = X
|
||||
BT.on_lose(TRUE)
|
||||
BT.owner = null
|
||||
|
||||
if((!gc_destroyed || (owner && !owner.gc_destroyed)) && !no_id_transfer)
|
||||
if((!QDELETED(src) || C) && !no_id_transfer)
|
||||
transfer_identity(C)
|
||||
C.update_hair()
|
||||
if(C)
|
||||
C.update_hair()
|
||||
|
||||
/obj/item/organ/brain/prepare_eat()
|
||||
return // Too important to eat.
|
||||
|
||||
@@ -20,9 +20,10 @@
|
||||
M.AddAbility(P)
|
||||
|
||||
|
||||
/obj/item/organ/alien/Remove(mob/living/carbon/M, special = 0)
|
||||
for(var/obj/effect/proc_holder/alien/P in alien_powers)
|
||||
M.RemoveAbility(P)
|
||||
/obj/item/organ/alien/Remove(special = FALSE)
|
||||
if(owner)
|
||||
for(var/obj/effect/proc_holder/alien/P in alien_powers)
|
||||
owner.RemoveAbility(P)
|
||||
..()
|
||||
|
||||
/obj/item/organ/alien/prepare_eat()
|
||||
@@ -100,11 +101,11 @@
|
||||
var/mob/living/carbon/alien/A = M
|
||||
A.updatePlasmaDisplay()
|
||||
|
||||
/obj/item/organ/alien/plasmavessel/Remove(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
if(isalien(M))
|
||||
var/mob/living/carbon/alien/A = M
|
||||
/obj/item/organ/alien/plasmavessel/Remove(special = FALSE)
|
||||
if(owner && isalien(owner))
|
||||
var/mob/living/carbon/alien/A = owner
|
||||
A.updatePlasmaDisplay()
|
||||
return ..()
|
||||
|
||||
#define QUEEN_DEATH_DEBUFF_DURATION 2400
|
||||
|
||||
@@ -121,9 +122,10 @@
|
||||
..()
|
||||
M.faction |= ROLE_ALIEN
|
||||
|
||||
/obj/item/organ/alien/hivenode/Remove(mob/living/carbon/M, special = 0)
|
||||
M.faction -= ROLE_ALIEN
|
||||
..()
|
||||
/obj/item/organ/alien/hivenode/Remove(special = FALSE)
|
||||
if(owner)
|
||||
owner.faction -= ROLE_ALIEN
|
||||
return ..()
|
||||
|
||||
//When the alien queen dies, all aliens suffer a penalty as punishment for failing to protect her.
|
||||
/obj/item/organ/alien/hivenode/proc/queen_death()
|
||||
|
||||
@@ -252,7 +252,9 @@
|
||||
return 0
|
||||
if(M.getorgan(/obj/item/organ/alien/hivenode))
|
||||
return 0
|
||||
|
||||
if(isvamp(M))
|
||||
return 0
|
||||
|
||||
if(ismonkey(M))
|
||||
return 1
|
||||
|
||||
|
||||
@@ -230,7 +230,7 @@
|
||||
|
||||
dat += "<BR><B>Back:</B> <A href='?src=[REF(src)];item=[SLOT_BACK]'>[back ? back : "Nothing"]</A>"
|
||||
|
||||
if(istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
|
||||
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS) && istype(wear_mask, /obj/item/clothing/mask) && istype(back, /obj/item/tank))
|
||||
dat += "<BR><A href='?src=[REF(src)];internal=1'>[internal ? "Disable Internals" : "Set Internals"]</A>"
|
||||
|
||||
if(handcuffed)
|
||||
@@ -249,7 +249,7 @@
|
||||
..()
|
||||
//strip panel
|
||||
if(usr.canUseTopic(src, BE_CLOSE, NO_DEXTERY))
|
||||
if(href_list["internal"])
|
||||
if(href_list["internal"] && !HAS_TRAIT(src, TRAIT_NO_INTERNALS))
|
||||
var/slot = text2num(href_list["internal"])
|
||||
var/obj/item/ITEM = get_item_by_slot(slot)
|
||||
if(ITEM && istype(ITEM, /obj/item/tank) && wear_mask && (wear_mask.clothing_flags & ALLOWINTERNALS))
|
||||
@@ -533,7 +533,7 @@
|
||||
break //Guess we're out of organs!
|
||||
var/obj/item/organ/guts = pick(internal_organs)
|
||||
var/turf/T = get_turf(src)
|
||||
guts.Remove(src)
|
||||
guts.Remove()
|
||||
guts.forceMove(T)
|
||||
var/atom/throw_target = get_edge_target_turf(guts, dir)
|
||||
guts.throw_at(throw_target, power, 4, src)
|
||||
@@ -872,7 +872,7 @@
|
||||
var/obj/item/organ/O = X
|
||||
if(prob(50))
|
||||
organs_amt++
|
||||
O.Remove(src)
|
||||
O.Remove()
|
||||
O.forceMove(drop_location())
|
||||
if(organs_amt)
|
||||
to_chat(user, "<span class='notice'>You retrieve some of [src]\'s internal organs!</span>")
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
continue
|
||||
var/org_zone = check_zone(O.zone) //both groin and chest organs.
|
||||
if(org_zone == BODY_ZONE_CHEST)
|
||||
O.Remove(src)
|
||||
O.Remove()
|
||||
O.forceMove(Tsec)
|
||||
O.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
|
||||
else
|
||||
@@ -55,7 +55,7 @@
|
||||
if(no_organs && !istype(I, /obj/item/organ/brain))
|
||||
qdel(I)
|
||||
continue
|
||||
I.Remove(src)
|
||||
I.Remove()
|
||||
I.forceMove(Tsec)
|
||||
I.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5)
|
||||
|
||||
|
||||
@@ -189,21 +189,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
if(brain && (replace_current || !should_have_brain))
|
||||
if(!brain.decoy_override)//Just keep it if it's fake
|
||||
brain.Remove(C,TRUE,TRUE)
|
||||
brain.Remove(TRUE,TRUE)
|
||||
QDEL_NULL(brain)
|
||||
if(should_have_brain && !brain)
|
||||
brain = new mutant_brain()
|
||||
brain.Insert(C, TRUE, TRUE)
|
||||
|
||||
if(heart && (!should_have_heart || replace_current))
|
||||
heart.Remove(C,1)
|
||||
heart.Remove(TRUE)
|
||||
QDEL_NULL(heart)
|
||||
if(should_have_heart && !heart)
|
||||
heart = new mutant_heart()
|
||||
heart.Insert(C)
|
||||
|
||||
if(lungs && (!should_have_lungs || replace_current))
|
||||
lungs.Remove(C,1)
|
||||
lungs.Remove(TRUE)
|
||||
QDEL_NULL(lungs)
|
||||
if(should_have_lungs && !lungs)
|
||||
if(mutantlungs)
|
||||
@@ -213,7 +213,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
lungs.Insert(C)
|
||||
|
||||
if(liver && (!should_have_liver || replace_current))
|
||||
liver.Remove(C,1)
|
||||
liver.Remove(TRUE)
|
||||
QDEL_NULL(liver)
|
||||
if(should_have_liver && !liver)
|
||||
if(mutantliver)
|
||||
@@ -223,7 +223,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
liver.Insert(C)
|
||||
|
||||
if(stomach && (!should_have_stomach || replace_current))
|
||||
stomach.Remove(C,1)
|
||||
stomach.Remove(TRUE)
|
||||
QDEL_NULL(stomach)
|
||||
if(should_have_stomach && !stomach)
|
||||
if(mutantstomach)
|
||||
@@ -233,14 +233,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
stomach.Insert(C)
|
||||
|
||||
if(appendix && (!should_have_appendix || replace_current))
|
||||
appendix.Remove(C,1)
|
||||
appendix.Remove(TRUE)
|
||||
QDEL_NULL(appendix)
|
||||
if(should_have_appendix && !appendix)
|
||||
appendix = new()
|
||||
appendix.Insert(C)
|
||||
|
||||
if(tail && (!should_have_tail || replace_current))
|
||||
tail.Remove(C,1)
|
||||
tail.Remove(TRUE)
|
||||
QDEL_NULL(tail)
|
||||
if(should_have_tail && !tail)
|
||||
tail = new mutanttail()
|
||||
@@ -248,21 +248,21 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
|
||||
if(C.get_bodypart(BODY_ZONE_HEAD))
|
||||
if(eyes && (replace_current || !should_have_eyes))
|
||||
eyes.Remove(C,1)
|
||||
eyes.Remove(TRUE)
|
||||
QDEL_NULL(eyes)
|
||||
if(should_have_eyes && !eyes)
|
||||
eyes = new mutanteyes
|
||||
eyes.Insert(C, TRUE)
|
||||
|
||||
if(ears && (replace_current || !should_have_ears))
|
||||
ears.Remove(C,1)
|
||||
ears.Remove(TRUE)
|
||||
QDEL_NULL(ears)
|
||||
if(should_have_ears && !ears)
|
||||
ears = new mutantears
|
||||
ears.Insert(C)
|
||||
|
||||
if(tongue && (replace_current || !should_have_tongue))
|
||||
tongue.Remove(C,1)
|
||||
tongue.Remove(TRUE)
|
||||
QDEL_NULL(tongue)
|
||||
if(should_have_tongue && !tongue)
|
||||
tongue = new mutanttongue
|
||||
@@ -272,7 +272,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
for(var/mutantorgan in old_species.mutant_organs)
|
||||
var/obj/item/organ/I = C.getorgan(mutantorgan)
|
||||
if(I)
|
||||
I.Remove(C)
|
||||
I.Remove()
|
||||
QDEL_NULL(I)
|
||||
|
||||
for(var/path in mutant_organs)
|
||||
@@ -1585,7 +1585,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if (!HAS_TRAIT(target, TRAIT_PERMABONER))
|
||||
stop_wagging_tail(target)
|
||||
return FALSE
|
||||
else if(aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
|
||||
else if(!(user.client?.prefs.cit_toggles & NO_ASS_SLAP) && aim_for_groin && (target == user || target.lying || same_dir) && (target_on_help || target_restrained || target_aiming_for_groin))
|
||||
if(target.client?.prefs.cit_toggles & NO_ASS_SLAP)
|
||||
to_chat(user,"A force stays your hand, preventing you from slapping \the [target]'s ass!")
|
||||
return FALSE
|
||||
@@ -1601,7 +1601,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
"<span class='danger'>\The [user] slaps \the [target]'s ass!</span>",\
|
||||
"<span class='notice'>You slap [user == target ? "your" : "\the [target]'s"] ass!</span>",\
|
||||
"You hear a slap."
|
||||
)
|
||||
)
|
||||
return FALSE
|
||||
else if(attacker_style && attacker_style.disarm_act(user,target))
|
||||
return 1
|
||||
@@ -1884,6 +1884,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
if(get_turf(target) == target_oldturf)
|
||||
shove_blocked = TRUE
|
||||
|
||||
var/append_message = ""
|
||||
if(shove_blocked && !target.buckled)
|
||||
var/directional_blocked = !target.Adjacent(target_shove_turf)
|
||||
var/targetatrest = target.resting
|
||||
@@ -1897,33 +1898,30 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
target_collateral_human.Knockdown(SHOVE_KNOCKDOWN_COLLATERAL)
|
||||
user.visible_message("<span class='danger'>[user.name] shoves [target.name] into [target_collateral_human.name]!</span>",
|
||||
"<span class='danger'>You shove [target.name] into [target_collateral_human.name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
log_combat(user, target, "shoved", "into [target_collateral_human.name]")
|
||||
append_message += ", into [target_collateral_human.name]"
|
||||
|
||||
else
|
||||
user.visible_message("<span class='danger'>[user.name] shoves [target.name]!</span>",
|
||||
"<span class='danger'>You shove [target.name]!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/target_held_item = target.get_active_held_item()
|
||||
var/knocked_item = FALSE
|
||||
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
|
||||
target_held_item = null
|
||||
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
|
||||
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
|
||||
if(target_held_item)
|
||||
var/obj/item/target_held_item = target.get_active_held_item()
|
||||
if(!is_type_in_typecache(target_held_item, GLOB.shove_disarming_types))
|
||||
target_held_item = null
|
||||
if(!target.has_movespeed_modifier(MOVESPEED_ID_SHOVE))
|
||||
target.add_movespeed_modifier(MOVESPEED_ID_SHOVE, multiplicative_slowdown = SHOVE_SLOWDOWN_STRENGTH)
|
||||
if(target_held_item)
|
||||
if(!HAS_TRAIT(target_held_item, TRAIT_NODROP))
|
||||
target.visible_message("<span class='danger'>[target.name]'s grip on \the [target_held_item] loosens!</span>",
|
||||
"<span class='danger'>Your grip on \the [target_held_item] loosens!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
|
||||
else if(target_held_item)
|
||||
target.dropItemToGround(target_held_item)
|
||||
knocked_item = TRUE
|
||||
append_message += ", loosening their grip on [target_held_item]"
|
||||
else
|
||||
append_message += ", but couldn't loose their grip on [target_held_item]"
|
||||
addtimer(CALLBACK(target, /mob/living/carbon/human/proc/clear_shove_slowdown), SHOVE_SLOWDOWN_LENGTH)
|
||||
else if(target_held_item)
|
||||
if(target.dropItemToGround(target_held_item))
|
||||
target.visible_message("<span class='danger'>[target.name] drops \the [target_held_item]!!</span>",
|
||||
"<span class='danger'>You drop \the [target_held_item]!!</span>", null, COMBAT_MESSAGE_RANGE)
|
||||
var/append_message = ""
|
||||
if(target_held_item)
|
||||
if(knocked_item)
|
||||
append_message = "causing them to drop [target_held_item]"
|
||||
else
|
||||
append_message = "loosening their grip on [target_held_item]"
|
||||
log_combat(user, target, "shoved", append_message)
|
||||
append_message += ", causing them to drop [target_held_item]"
|
||||
log_combat(user, target, "shoved", append_message)
|
||||
|
||||
/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE)
|
||||
var/hit_percent = (100-(blocked+armor))/100
|
||||
|
||||
@@ -31,6 +31,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
. = ..()
|
||||
var/dwarf_hair = pick("Beard (Dwarf)", "Beard (Very Long)", "Beard (Long)") //beard roullette
|
||||
var/mob/living/carbon/human/H = C
|
||||
H.grant_language(/datum/language/dwarf)
|
||||
H.facial_hair_style = dwarf_hair
|
||||
H.update_hair()
|
||||
H.transform = H.transform.Scale(1, 0.8) //We use scale, and yeah. Dwarves can become gnomes with DWARFISM.
|
||||
@@ -41,6 +42,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
|
||||
. = ..()
|
||||
H.transform = H.transform.Scale(1, 1.25) //And we undo it.
|
||||
UnregisterSignal(H, COMSIG_MOB_SAY) //We register handle_speech is not being used.
|
||||
H.remove_language(/datum/language/dwarf)
|
||||
|
||||
//Dwarf Name stuff
|
||||
/proc/dwarf_name() //hello caller: my name is urist mcuristurister
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
if(NT)
|
||||
NT.Insert(H, drop_if_replaced = FALSE)
|
||||
else
|
||||
tail.Remove(H)
|
||||
tail.Remove()
|
||||
|
||||
/proc/mass_purrbation()
|
||||
for(var/M in GLOB.mob_list)
|
||||
|
||||
@@ -31,14 +31,15 @@
|
||||
|
||||
/datum/species/mush/on_species_gain(mob/living/carbon/C, datum/species/old_species)
|
||||
. = ..()
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(!H.dna.features["caps"])
|
||||
H.dna.features["caps"] = "Round"
|
||||
handle_mutant_bodyparts(H)
|
||||
H.faction |= "mushroom"
|
||||
mush = new()
|
||||
mush.teach(H, TRUE)
|
||||
if(!ishuman(C))
|
||||
return
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(!H.dna.features["caps"])
|
||||
H.dna.features["caps"] = "Round"
|
||||
handle_mutant_bodyparts(H)
|
||||
H.faction |= "mushroom"
|
||||
mush = new()
|
||||
mush.teach(H, TRUE)
|
||||
RegisterSignal(C, COMSIG_MOB_ON_NEW_MIND, .proc/on_new_mind)
|
||||
|
||||
/datum/species/mush/proc/on_new_mind(mob/owner)
|
||||
|
||||
@@ -84,10 +84,10 @@
|
||||
shadowwalk = SW
|
||||
|
||||
|
||||
/obj/item/organ/brain/nightmare/Remove(mob/living/carbon/M, special = 0)
|
||||
if(shadowwalk)
|
||||
M.RemoveSpell(shadowwalk)
|
||||
..()
|
||||
/obj/item/organ/brain/nightmare/Remove(special = FALSE)
|
||||
if(shadowwalk && owner)
|
||||
owner.RemoveSpell(shadowwalk)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/item/organ/heart/nightmare
|
||||
@@ -120,12 +120,12 @@
|
||||
blade = new/obj/item/light_eater
|
||||
M.put_in_hands(blade)
|
||||
|
||||
/obj/item/organ/heart/nightmare/Remove(mob/living/carbon/M, special = 0)
|
||||
/obj/item/organ/heart/nightmare/Remove(special = FALSE)
|
||||
respawn_progress = 0
|
||||
if(blade && special != HEART_SPECIAL_SHADOWIFY)
|
||||
M.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
|
||||
if(!QDELETED(owner) && blade && special != HEART_SPECIAL_SHADOWIFY)
|
||||
owner.visible_message("<span class='warning'>\The [blade] disintegrates!</span>")
|
||||
QDEL_NULL(blade)
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/heart/nightmare/Stop()
|
||||
return 0
|
||||
@@ -146,7 +146,7 @@
|
||||
owner.revive(full_heal = TRUE)
|
||||
if(!(owner.dna.species.id == "shadow" || owner.dna.species.id == "nightmare"))
|
||||
var/mob/living/carbon/old_owner = owner
|
||||
Remove(owner, HEART_SPECIAL_SHADOWIFY)
|
||||
Remove(HEART_SPECIAL_SHADOWIFY)
|
||||
old_owner.set_species(/datum/species/shadow)
|
||||
Insert(old_owner, HEART_SPECIAL_SHADOWIFY)
|
||||
to_chat(owner, "<span class='userdanger'>You feel the shadows invade your skin, leaping into the center of your chest! You're alive!</span>")
|
||||
|
||||
@@ -334,9 +334,10 @@
|
||||
var/obj/item/clothing/check
|
||||
var/internals = FALSE
|
||||
|
||||
for(check in GET_INTERNAL_SLOTS(src))
|
||||
if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
|
||||
internals = TRUE
|
||||
if(!HAS_TRAIT(src, TRAIT_NO_INTERNALS))
|
||||
for(check in GET_INTERNAL_SLOTS(src))
|
||||
if(CHECK_BITFIELD(check.clothing_flags, ALLOWINTERNALS))
|
||||
internals = TRUE
|
||||
if(internal)
|
||||
if(internal.loc != src)
|
||||
internal = null
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
var/obj/item/organ/tail/cat/tail = L.getorgan(/obj/item/organ/tail/cat)
|
||||
if(!QDELETED(tail))
|
||||
visible_message("[src] severs [L]'s tail in one swift swipe!", "<span class='notice'>You sever [L]'s tail in one swift swipe.</span>")
|
||||
tail.Remove(L)
|
||||
tail.Remove()
|
||||
var/obj/item/organ/tail/cat/dropped_tail = new(target.drop_location())
|
||||
dropped_tail.color = L.hair_color
|
||||
return 1
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
time++
|
||||
if(time >= EGG_INCUBATION_TIME)
|
||||
Pop()
|
||||
Remove(owner)
|
||||
Remove()
|
||||
qdel(src)
|
||||
|
||||
/obj/item/organ/body_egg/changeling_egg/proc/Pop()
|
||||
|
||||
@@ -87,7 +87,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
to_chat(user, "You cannot send IC messages (muted).")
|
||||
return FALSE
|
||||
else if(!params)
|
||||
var/subtle_emote = stripped_multiline_input("Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN)
|
||||
var/subtle_emote = stripped_multiline_input(user, "Choose an emote to display.", "Subtle", null, MAX_MESSAGE_LEN)
|
||||
if(subtle_emote && !check_invalid(user, subtle_emote))
|
||||
var/type = input("Is this a visible or hearable emote?") as null|anything in list("Visible", "Hearable")
|
||||
switch(type)
|
||||
@@ -109,7 +109,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
if(!can_run_emote(user))
|
||||
return FALSE
|
||||
|
||||
user.log_message(message, INDIVIDUAL_EMOTE_LOG)
|
||||
user.log_message(message, LOG_EMOTE)
|
||||
message = "<b>[user]</b> " + "<i>[message]</i>"
|
||||
|
||||
for(var/mob/M in GLOB.dead_mob_list)
|
||||
@@ -123,10 +123,7 @@ proc/get_top_level_mob(var/mob/S)
|
||||
user.audible_message(message=message,hearing_distance=1)
|
||||
else
|
||||
user.visible_message(message=message,self_message=message,vision_distance=1)
|
||||
log_emote("[key_name(user)] : [message]")
|
||||
|
||||
message = null
|
||||
emote_type = EMOTE_VISIBLE
|
||||
|
||||
///////////////// SUBTLE 2: NO GHOST BOOGALOO
|
||||
|
||||
@@ -173,16 +170,13 @@ proc/get_top_level_mob(var/mob/S)
|
||||
if(!can_run_emote(user))
|
||||
return FALSE
|
||||
|
||||
user.log_message(message, INDIVIDUAL_EMOTE_LOG)
|
||||
user.log_message(message, LOG_SUBTLER)
|
||||
message = "<b>[user]</b> " + "<i>[message]</i>"
|
||||
|
||||
if(emote_type == EMOTE_AUDIBLE)
|
||||
user.audible_message(message=message,hearing_distance=1, ignored_mobs = GLOB.dead_mob_list)
|
||||
else
|
||||
user.visible_message(message=message,self_message=message,vision_distance=1, ignored_mobs = GLOB.dead_mob_list)
|
||||
log_emote("[key_name(user)] : (SUBTLER) [message]")
|
||||
|
||||
message = null
|
||||
|
||||
///////////////// VERB CODE
|
||||
/mob/living/verb/subtle()
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
if(tr_flags & TR_KEEPORGANS)
|
||||
for(var/X in O.internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
I.Remove(O, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
if(mind)
|
||||
mind.transfer_to(O)
|
||||
@@ -103,7 +103,7 @@
|
||||
for(var/X in internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
int_organs += I
|
||||
I.Remove(src, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
for(var/X in int_organs)
|
||||
var/obj/item/organ/I = X
|
||||
@@ -250,7 +250,7 @@
|
||||
if(tr_flags & TR_KEEPORGANS)
|
||||
for(var/X in O.internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
I.Remove(O, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
if(mind)
|
||||
mind.transfer_to(O)
|
||||
@@ -262,7 +262,7 @@
|
||||
for(var/X in internal_organs)
|
||||
var/obj/item/organ/I = X
|
||||
int_organs += I
|
||||
I.Remove(src, 1)
|
||||
I.Remove(TRUE)
|
||||
|
||||
for(var/X in int_organs)
|
||||
var/obj/item/organ/I = X
|
||||
|
||||
+40
-34
@@ -13,6 +13,7 @@
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/charge = 0 // note %age conveted to actual charge in New
|
||||
var/maxcharge = 1000
|
||||
var/start_charged = TRUE
|
||||
materials = list(MAT_METAL=700, MAT_GLASS=50)
|
||||
grind_results = list(/datum/reagent/lithium = 15, /datum/reagent/iron = 5, /datum/reagent/silicon = 5)
|
||||
var/rigged = FALSE // true if rigged to explode
|
||||
@@ -32,7 +33,8 @@
|
||||
create_reagents(5, INJECTABLE | DRAINABLE)
|
||||
if (override_maxcharge)
|
||||
maxcharge = override_maxcharge
|
||||
charge = maxcharge
|
||||
if(start_charged)
|
||||
charge = maxcharge
|
||||
if(ratingdesc)
|
||||
desc += " This one has a rating of [DisplayEnergy(maxcharge)], and you should not swallow it."
|
||||
update_icon()
|
||||
@@ -163,9 +165,8 @@
|
||||
return rating * maxcharge
|
||||
|
||||
/* Cell variants*/
|
||||
/obj/item/stock_parts/cell/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
/obj/item/stock_parts/cell/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/crap
|
||||
name = "\improper Nanotrasen brand rechargeable AA battery"
|
||||
@@ -173,10 +174,8 @@
|
||||
maxcharge = 500
|
||||
materials = list(MAT_GLASS=40)
|
||||
|
||||
/obj/item/stock_parts/cell/crap/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
update_icon()
|
||||
/obj/item/stock_parts/cell/crap/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/upgraded
|
||||
name = "upgraded power cell"
|
||||
@@ -195,10 +194,8 @@
|
||||
maxcharge = 1250 //25/12/6 disabler/laser/taser shots.
|
||||
materials = list(MAT_GLASS=40)
|
||||
|
||||
/obj/item/stock_parts/cell/secborg/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
update_icon()
|
||||
/obj/item/stock_parts/cell/secborg/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/lascarbine
|
||||
name = "laser carbine power supply"
|
||||
@@ -231,10 +228,8 @@
|
||||
maxcharge = 15000
|
||||
chargerate = 2250
|
||||
|
||||
/obj/item/stock_parts/cell/high/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
update_icon()
|
||||
/obj/item/stock_parts/cell/high/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/super
|
||||
name = "super-capacity power cell"
|
||||
@@ -243,10 +238,8 @@
|
||||
materials = list(MAT_GLASS=300)
|
||||
chargerate = 2000
|
||||
|
||||
/obj/item/stock_parts/cell/super/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
update_icon()
|
||||
/obj/item/stock_parts/cell/super/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/hyper
|
||||
name = "hyper-capacity power cell"
|
||||
@@ -255,10 +248,8 @@
|
||||
materials = list(MAT_GLASS=400)
|
||||
chargerate = 3000
|
||||
|
||||
/obj/item/stock_parts/cell/hyper/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
update_icon()
|
||||
/obj/item/stock_parts/cell/hyper/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/bluespace
|
||||
name = "bluespace power cell"
|
||||
@@ -268,10 +259,8 @@
|
||||
materials = list(MAT_GLASS=600)
|
||||
chargerate = 4000
|
||||
|
||||
/obj/item/stock_parts/cell/bluespace/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
update_icon()
|
||||
/obj/item/stock_parts/cell/bluespace/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/infinite
|
||||
name = "infinite-capacity power cell!"
|
||||
@@ -321,15 +310,13 @@
|
||||
maxcharge = 500
|
||||
rating = 3
|
||||
|
||||
/obj/item/stock_parts/cell/emproof/empty/Initialize()
|
||||
. = ..()
|
||||
charge = 0
|
||||
update_icon()
|
||||
|
||||
/obj/item/stock_parts/cell/emproof/empty/ComponentInitialize()
|
||||
/obj/item/stock_parts/cell/emproof/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF)
|
||||
|
||||
/obj/item/stock_parts/cell/emproof/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/emproof/corrupt()
|
||||
return
|
||||
|
||||
@@ -364,3 +351,22 @@
|
||||
//found inside the inducers ordered from cargo.
|
||||
/obj/item/stock_parts/cell/inducer_supply
|
||||
maxcharge = 5000
|
||||
|
||||
/obj/item/stock_parts/cell/magnetic
|
||||
name = "magrifle power supply"
|
||||
maxcharge = 12000
|
||||
chargerate = 600
|
||||
|
||||
/obj/item/stock_parts/cell/magnetic/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/magnetic/pistol
|
||||
name = "magpistol power supply"
|
||||
maxcharge = 6000
|
||||
|
||||
/obj/item/stock_parts/cell/magnetic/pistol/empty
|
||||
start_charged = FALSE
|
||||
|
||||
/obj/item/stock_parts/cell/toymagburst
|
||||
name = "toy mag burst rifle power supply"
|
||||
maxcharge = 4000
|
||||
|
||||
@@ -565,7 +565,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
||||
to_chat(C, "<span class='userdanger'>That was a really dense idea.</span>")
|
||||
C.visible_message("<span class='userdanger'>A bright flare of radiation is seen from [C]'s head, shortly before you hear a sickening sizzling!</span>")
|
||||
var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs
|
||||
rip_u.Remove(C)
|
||||
rip_u.Remove()
|
||||
qdel(rip_u)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
to_chat(C, "<span class='userdanger'>That was a shockingly dumb idea.</span>")
|
||||
C.visible_message("<span class='userdanger'>A bright flare of lightning is seen from [C]'s head, shortly before you hear a sickening sizzling!</span>")
|
||||
var/obj/item/organ/brain/rip_u = locate(/obj/item/organ/brain) in C.internal_organs
|
||||
rip_u.Remove(C)
|
||||
rip_u.Remove()
|
||||
qdel(rip_u)
|
||||
return
|
||||
return ..()
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/obj/item/ammo_casing/caseless/magnetic
|
||||
desc = "A large ferromagnetic slug intended to be launched out of a compatible weapon."
|
||||
caliber = "mag"
|
||||
icon_state = "mag-casing-live"
|
||||
click_cooldown_override = 2.5
|
||||
delay = 3
|
||||
var/energy_cost = 200
|
||||
|
||||
/obj/item/ammo_casing/caseless/magnetic
|
||||
projectile_type = /obj/item/projectile/bullet/magnetic
|
||||
|
||||
/obj/item/ammo_casing/caseless/magnetic/disabler
|
||||
desc = "A large, specialized ferromagnetic slug designed with a less-than-lethal payload."
|
||||
projectile_type = /obj/item/projectile/bullet/magnetic/disabler
|
||||
|
||||
/obj/item/ammo_casing/caseless/magnetic/weak
|
||||
desc = "A ferromagnetic slug intended to be launched out of a compatible weapon."
|
||||
projectile_type = /obj/item/projectile/bullet/magnetic/weak
|
||||
energy_cost = 125
|
||||
|
||||
/obj/item/ammo_casing/caseless/magnetic/weak/disabler
|
||||
desc = "A specialized ferromagnetic slug designed with a less-than-lethal payload."
|
||||
projectile_type = /obj/item/projectile/bullet/magnetic/weak/disabler
|
||||
energy_cost = 125
|
||||
|
||||
/obj/item/ammo_casing/caseless/magnetic/hyper
|
||||
desc = "A large block of speciallized ferromagnetic material designed to be fired out of the experimental Hyper-Burst Rifle."
|
||||
caliber = "hypermag"
|
||||
icon_state = "hyper-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/magnetic/hyper
|
||||
pellets = 8
|
||||
variance = 30
|
||||
energy_cost = 1500
|
||||
|
||||
/obj/item/ammo_casing/caseless/magnetic/hyper/inferno
|
||||
projectile_type = /obj/item/projectile/bullet/incendiary/mag_inferno
|
||||
pellets = 1
|
||||
variance = 0
|
||||
|
||||
@@ -63,3 +63,8 @@
|
||||
projectile_type = /obj/item/projectile/bullet/reusable/foam_dart/riot
|
||||
icon_state = "foamdart_riot"
|
||||
materials = list(MAT_METAL = 1125)
|
||||
|
||||
/obj/item/ammo_casing/caseless/foam_dart/mag
|
||||
name = "magfoam dart"
|
||||
desc = "A foam dart with fun light-up projectiles powered by magnets!"
|
||||
projectile_type = /obj/item/projectile/bullet/reusable/foam_dart/mag
|
||||
|
||||
@@ -62,6 +62,14 @@
|
||||
/obj/item/ammo_casing/energy/laser/redtag/hitscan/holy
|
||||
projectile_type = /obj/item/projectile/beam/lasertag/redtag/hitscan/holy
|
||||
|
||||
/obj/item/ammo_casing/energy/laser/magtag
|
||||
projectile_type = /obj/item/projectile/beam/lasertag/mag
|
||||
select_name = "magtag"
|
||||
pellets = 3
|
||||
variance = 30
|
||||
e_cost = 1000
|
||||
fire_sound = 'sound/weapons/magburst.ogg'
|
||||
|
||||
/obj/item/ammo_casing/energy/xray
|
||||
projectile_type = /obj/item/projectile/beam/xray
|
||||
e_cost = 50
|
||||
|
||||
@@ -87,7 +87,14 @@
|
||||
max_ammo = 40
|
||||
materials = list(MAT_METAL = 500)
|
||||
|
||||
/obj/item/ammo_box/foambox/mag
|
||||
name = "ammo box (Magnetic Foam Darts)"
|
||||
icon = 'icons/obj/guns/toy.dmi'
|
||||
icon_state = "foambox"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
|
||||
max_ammo = 42
|
||||
|
||||
/obj/item/ammo_box/foambox/riot
|
||||
icon_state = "foambox_riot"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
|
||||
materials = list(MAT_METAL = 50000)
|
||||
materials = list(MAT_METAL = 50000)
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/obj/item/ammo_box/magazine/mmag
|
||||
icon_state = "mediummagmag"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/magnetic/disabler
|
||||
caliber = "mag"
|
||||
max_ammo = 24
|
||||
multiple_sprites = 2
|
||||
|
||||
/obj/item/ammo_box/magazine/mmag/lethal
|
||||
name = "magrifle magazine (lethal)"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/magnetic
|
||||
|
||||
/obj/item/ammo_box/magazine/mmag/small
|
||||
name = "magpistol magazine (non-lethal disabler)"
|
||||
icon_state = "smallmagmag"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/magnetic/weak/disabler
|
||||
max_ammo = 15
|
||||
|
||||
/obj/item/ammo_box/magazine/mmag/small/lethal
|
||||
name = "magpistol magazine (lethal)"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/magnetic/weak
|
||||
|
||||
/obj/item/ammo_box/magazine/mhyper
|
||||
name = "hyper-burst rifle magazine"
|
||||
icon_state = "hypermag"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/magnetic/hyper
|
||||
caliber = "hypermag"
|
||||
desc = "A magazine for the Hyper-Burst Rifle. Loaded with a special slug that fragments into 6 smaller shards which can absolutely puncture anything, but has rather short effective range."
|
||||
max_ammo = 4
|
||||
multiple_sprites = 4
|
||||
|
||||
/obj/item/ammo_box/magazine/mhyper/inferno
|
||||
name = "hyper-burst rifle magazine (inferno)"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/magnetic/hyper/inferno
|
||||
desc = "A magazine for the Hyper-Burst Rifle. Loaded with a special slug that violently reacts with whatever surface it strikes, generating massive amount of heat and light."
|
||||
@@ -57,3 +57,11 @@
|
||||
/obj/item/ammo_box/magazine/toy/m762/riot
|
||||
icon_state = "a762-riot"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
|
||||
|
||||
/obj/item/ammo_box/magazine/toy/foamag
|
||||
name = "foam force magrifle magazine"
|
||||
icon_state = "foamagmag"
|
||||
max_ammo = 24
|
||||
multiple_sprites = 2
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/mag
|
||||
materials = list(MAT_METAL = 200)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user