Merge remote-tracking branch 'origin/master' into luciee
@@ -3718,26 +3718,6 @@
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4,
|
||||
/turf/open/floor/wood,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"lk" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/machinery/light/small{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/computer/security/telescreen/entertainment{
|
||||
pixel_x = 30
|
||||
},
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 1;
|
||||
pixel_y = 1
|
||||
},
|
||||
/obj/item/book/manual/chef_recipes{
|
||||
pixel_x = 2;
|
||||
pixel_y = 6
|
||||
},
|
||||
/obj/item/book/manual/wiki/barman_recipes,
|
||||
/obj/item/reagent_containers/food/drinks/shaker,
|
||||
/turf/open/floor/wood,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"ll" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden,
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4,
|
||||
@@ -5208,6 +5188,11 @@
|
||||
/obj/effect/spawner/structure/window/plastitanium,
|
||||
/turf/open/floor/plating,
|
||||
/area/ruin/unpowered/syndicate_lava_base/engineering)
|
||||
"rD" = (
|
||||
/obj/machinery/griddle,
|
||||
/obj/item/reagent_containers/glass/mixbowl,
|
||||
/turf/open/floor/wood,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"rV" = (
|
||||
/obj/machinery/door/airlock/mining/glass{
|
||||
name = "Cargo Bay"
|
||||
@@ -5657,10 +5642,6 @@
|
||||
/obj/effect/spawner/structure/window/plastitanium,
|
||||
/turf/open/floor/plating,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"Er" = (
|
||||
/obj/machinery/griddle,
|
||||
/turf/open/floor/wood,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"Ev" = (
|
||||
/obj/structure/filingcabinet/medical,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
@@ -6181,6 +6162,20 @@
|
||||
/obj/effect/spawner/structure/window/plastitanium,
|
||||
/turf/open/floor/plating,
|
||||
/area/ruin/unpowered/syndicate_lava_base/engineering)
|
||||
"Nq" = (
|
||||
/obj/machinery/light/small{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/computer/security/telescreen/entertainment{
|
||||
pixel_x = 30
|
||||
},
|
||||
/obj/structure/window/reinforced{
|
||||
dir = 1;
|
||||
pixel_y = 1
|
||||
},
|
||||
/obj/machinery/oven,
|
||||
/turf/open/floor/wood,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"Ns" = (
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
@@ -6261,6 +6256,24 @@
|
||||
/obj/effect/spawner/structure/window/plastitanium,
|
||||
/turf/open/floor/plating,
|
||||
/area/ruin/unpowered/syndicate_lava_base/cargo)
|
||||
"Ox" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/machinery/light/small,
|
||||
/obj/structure/cable/yellow,
|
||||
/obj/machinery/power/apc/syndicate{
|
||||
dir = 2;
|
||||
name = "Bar APC";
|
||||
pixel_y = -23
|
||||
},
|
||||
/obj/item/paicard,
|
||||
/obj/item/reagent_containers/food/drinks/shaker,
|
||||
/obj/item/book/manual/wiki/barman_recipes,
|
||||
/obj/item/book/manual/chef_recipes{
|
||||
pixel_x = 2;
|
||||
pixel_y = 6
|
||||
},
|
||||
/turf/open/floor/wood,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"OF" = (
|
||||
/obj/structure/table,
|
||||
/obj/structure/bedsheetbin,
|
||||
@@ -6733,18 +6746,6 @@
|
||||
/obj/machinery/door/firedoor/border_only,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/ruin/unpowered/syndicate_lava_base/chemistry)
|
||||
"YQ" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/machinery/light/small,
|
||||
/obj/structure/cable/yellow,
|
||||
/obj/machinery/power/apc/syndicate{
|
||||
dir = 2;
|
||||
name = "Bar APC";
|
||||
pixel_y = -23
|
||||
},
|
||||
/obj/item/paicard,
|
||||
/turf/open/floor/wood,
|
||||
/area/ruin/unpowered/syndicate_lava_base/bar)
|
||||
"Zi" = (
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
@@ -7771,7 +7772,7 @@ kJ
|
||||
yP
|
||||
FD
|
||||
eE
|
||||
YQ
|
||||
Ox
|
||||
jy
|
||||
jy
|
||||
nS
|
||||
@@ -7918,8 +7919,8 @@ jy
|
||||
nJ
|
||||
kq
|
||||
oK
|
||||
lk
|
||||
Er
|
||||
Nq
|
||||
rD
|
||||
lZ
|
||||
mx
|
||||
jy
|
||||
|
||||
@@ -34367,16 +34367,6 @@
|
||||
},
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/library)
|
||||
"bgZ" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
|
||||
dir = 10
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/landmark/event_spawn,
|
||||
/turf/open/floor/wood,
|
||||
/area/library)
|
||||
"bha" = (
|
||||
/turf/closed/wall/r_wall/rust,
|
||||
/area/ai_monitored/turret_protected/ai_upload)
|
||||
@@ -95858,6 +95848,17 @@
|
||||
/obj/effect/decal/cleanable/blood/old,
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/quartermaster/warehouse)
|
||||
"pge" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
|
||||
dir = 10
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
|
||||
dir = 8
|
||||
},
|
||||
/obj/effect/landmark/event_spawn,
|
||||
/mob/living/simple_animal/pet/snail/gary,
|
||||
/turf/open/floor/wood,
|
||||
/area/library)
|
||||
"pgv" = (
|
||||
/obj/structure/lattice/catwalk,
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
|
||||
@@ -129359,7 +129360,7 @@ bup
|
||||
aTe
|
||||
bfJ
|
||||
btM
|
||||
bgZ
|
||||
pge
|
||||
bjp
|
||||
bjq
|
||||
bvd
|
||||
|
||||
@@ -119830,6 +119830,12 @@
|
||||
/obj/structure/cable/white,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/medical/storage/locker)
|
||||
"evp" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2,
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4,
|
||||
/mob/living/simple_animal/pet/snail/gary,
|
||||
/turf/open/floor/plasteel/grimy,
|
||||
/area/library)
|
||||
"eym" = (
|
||||
/obj/structure/table/reinforced,
|
||||
/obj/structure/cable/white{
|
||||
@@ -160049,7 +160055,7 @@ abW
|
||||
dmg
|
||||
chA
|
||||
bBt
|
||||
abW
|
||||
evp
|
||||
abW
|
||||
abW
|
||||
abY
|
||||
|
||||
@@ -65276,12 +65276,6 @@
|
||||
/turf/open/floor/plasteel/white/corner,
|
||||
/area/hallway/secondary/entry)
|
||||
"eno" = (
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/sign/warning/vacuum/external{
|
||||
pixel_x = 32;
|
||||
pixel_y = 0
|
||||
@@ -65290,6 +65284,12 @@
|
||||
c_tag = "Atmospherics Tanks East";
|
||||
dir = 9
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
|
||||
dir = 10
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
|
||||
dir = 10
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/atmos_distro)
|
||||
"enV" = (
|
||||
@@ -67408,6 +67408,27 @@
|
||||
/obj/structure/table/glass,
|
||||
/turf/open/floor/plasteel,
|
||||
/area/science/xenobiology)
|
||||
"gxv" = (
|
||||
/obj/machinery/airalarm{
|
||||
pixel_y = 24
|
||||
},
|
||||
/obj/effect/turf_decal/tile/red{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/tile/red{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/table,
|
||||
/obj/item/storage/lockbox/vialbox/blood{
|
||||
pixel_x = -4;
|
||||
pixel_y = 11
|
||||
},
|
||||
/obj/item/healthanalyzer{
|
||||
pixel_x = 3;
|
||||
pixel_y = -1
|
||||
},
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/security/brig)
|
||||
"gxY" = (
|
||||
/obj/machinery/camera{
|
||||
c_tag = "Club - Aft";
|
||||
@@ -68042,31 +68063,6 @@
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/foyer)
|
||||
"hkb" = (
|
||||
/obj/structure/cable/yellow{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj/structure/disposalpipe/segment{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
|
||||
dir = 8
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/door/airlock/maintenance{
|
||||
name = "Brig Infirmary Maintenance";
|
||||
req_access_txt = "63"
|
||||
},
|
||||
/obj/machinery/door/firedoor/border_only{
|
||||
dir = 8
|
||||
},
|
||||
/obj/machinery/door/firedoor/border_only{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/port/fore)
|
||||
"hkc" = (
|
||||
/obj/structure/chair/comfy/black,
|
||||
/turf/open/floor/plasteel,
|
||||
@@ -71980,6 +71976,31 @@
|
||||
/obj/machinery/door/airlock/maintenance_hatch,
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/fore)
|
||||
"lqR" = (
|
||||
/obj/structure/cable/yellow{
|
||||
icon_state = "4-8"
|
||||
},
|
||||
/obj/structure/disposalpipe/segment{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
|
||||
dir = 8
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/door/airlock/maintenance{
|
||||
name = "Brig Infirmary Maintenance";
|
||||
req_access_txt = "74"
|
||||
},
|
||||
/obj/machinery/door/firedoor/border_only{
|
||||
dir = 8
|
||||
},
|
||||
/obj/machinery/door/firedoor/border_only{
|
||||
dir = 4
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/port/fore)
|
||||
"lqY" = (
|
||||
/obj/structure/cable/yellow{
|
||||
icon_state = "1-2"
|
||||
@@ -74170,6 +74191,12 @@
|
||||
/obj/machinery/light{
|
||||
dir = 4
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4{
|
||||
dir = 5
|
||||
},
|
||||
/obj/machinery/atmospherics/pipe/simple/supply/hidden/layer2{
|
||||
dir = 5
|
||||
},
|
||||
/turf/open/floor/plasteel,
|
||||
/area/engine/atmos_distro)
|
||||
"nOu" = (
|
||||
@@ -75555,27 +75582,6 @@
|
||||
/obj/item/reagent_containers/syringe,
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/medical/genetics)
|
||||
"pss" = (
|
||||
/obj/machinery/airalarm{
|
||||
pixel_y = 24
|
||||
},
|
||||
/obj/effect/turf_decal/tile/red{
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/turf_decal/tile/red{
|
||||
dir = 4
|
||||
},
|
||||
/obj/structure/table,
|
||||
/obj/item/storage/lockbox/vialbox/virology{
|
||||
pixel_x = -4;
|
||||
pixel_y = 11
|
||||
},
|
||||
/obj/item/healthanalyzer{
|
||||
pixel_x = 3;
|
||||
pixel_y = -1
|
||||
},
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/security/brig)
|
||||
"puB" = (
|
||||
/obj/structure/lattice,
|
||||
/obj/structure/window/reinforced{
|
||||
@@ -79859,6 +79865,10 @@
|
||||
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer4,
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/port/fore)
|
||||
"tNq" = (
|
||||
/mob/living/simple_animal/pet/snail/gary,
|
||||
/turf/open/floor/carpet,
|
||||
/area/library)
|
||||
"tND" = (
|
||||
/obj/effect/spawner/structure/window/reinforced,
|
||||
/obj/machinery/atmospherics/pipe/simple/yellow/visible,
|
||||
@@ -103769,7 +103779,7 @@ bwc
|
||||
bwc
|
||||
bwc
|
||||
bwc
|
||||
bwc
|
||||
tNq
|
||||
bwc
|
||||
bnK
|
||||
boe
|
||||
@@ -106804,7 +106814,7 @@ aax
|
||||
aaf
|
||||
lnX
|
||||
lnX
|
||||
hkb
|
||||
lqR
|
||||
lnX
|
||||
lnX
|
||||
lnX
|
||||
@@ -108343,7 +108353,7 @@ abe
|
||||
ahw
|
||||
air
|
||||
ahx
|
||||
pss
|
||||
gxv
|
||||
alE
|
||||
alp
|
||||
szL
|
||||
|
||||
@@ -38,9 +38,12 @@
|
||||
#define VV_TOPIC_LINK(datum, href_key, text) "<a href='?_src_=vars;[HrefToken()];[href_key]=TRUE;target=[REF(datum)]'>text</a>"
|
||||
//Helpers for vv_get_dropdown()
|
||||
#define VV_DROPDOWN_OPTION(href_key, name) . += "<option value='?_src_=vars;[HrefToken()];[href_key]=TRUE;target=[REF(src)]'>[name]</option>"
|
||||
#define VV_DROPDOWN_SEPERATOR VV_DROPDOWN_OPTION("", "-----")
|
||||
|
||||
// VV HREF KEYS
|
||||
#define VV_HK_TARGET "target"
|
||||
#define VV_HK_VARNAME "targetvar" //name or index of var for 1 variable targetting hrefs.
|
||||
|
||||
// vv_do_list() keys
|
||||
#define VV_HK_LIST_ADD "listadd"
|
||||
#define VV_HK_LIST_EDIT "listedit"
|
||||
@@ -50,10 +53,12 @@
|
||||
#define VV_HK_LIST_ERASE_DUPES "listdupes"
|
||||
#define VV_HK_LIST_SHUFFLE "listshuffle"
|
||||
#define VV_HK_LIST_SET_LENGTH "listlen"
|
||||
|
||||
// vv_do_basic() keys
|
||||
#define VV_HK_BASIC_EDIT "datumedit"
|
||||
#define VV_HK_BASIC_CHANGE "datumchange"
|
||||
#define VV_HK_BASIC_MASSEDIT "massedit"
|
||||
|
||||
// /datum
|
||||
#define VV_HK_DELETE "delete"
|
||||
#define VV_HK_EXPOSE "expose"
|
||||
@@ -69,6 +74,44 @@
|
||||
#define VV_HK_TRIGGER_EXPLOSION "explode"
|
||||
#define VV_HK_AUTO_RENAME "auto_rename"
|
||||
#define VV_HK_RADIATE "radiate"
|
||||
#define VV_HK_SHOW_HIDDENPRINTS "show_hiddenprints"
|
||||
|
||||
// /obj
|
||||
#define VV_HK_OSAY "osay"
|
||||
#define VV_HK_MASS_DEL_TYPE "mass_delete_type"
|
||||
#define VV_HK_ARMOR_MOD "mod_obj_armor"
|
||||
|
||||
// /obj/structure/sign/painting
|
||||
#define VV_HK_REMOVE_PAINTING "delete_paint"
|
||||
|
||||
// /mob
|
||||
#define VV_HK_GIB "gib"
|
||||
#define VV_HK_GIVE_SPELL "give_spell"
|
||||
#define VV_HK_REMOVE_SPELL "remove_spell"
|
||||
#define VV_HK_GIVE_DISEASE "give_disease"
|
||||
#define VV_HK_GODMODE "godmode"
|
||||
#define VV_HK_DROP_ALL "dropall"
|
||||
#define VV_HK_REGEN_ICONS "regen_icons"
|
||||
#define VV_HK_PLAYER_PANEL "player_panel"
|
||||
#define VV_HK_BUILDMODE "buildmode"
|
||||
#define VV_HK_DIRECT_CONTROL "direct_control"
|
||||
#define VV_HK_OFFER_GHOSTS "offer_ghosts"
|
||||
#define VV_HK_SET_AFK_TIMER "set_afk_timer"
|
||||
|
||||
// /mob/living/carbon/human
|
||||
#define VV_HK_SET_SPECIES "set_species"
|
||||
#define VV_HK_PURRBATION "toggle_purrbation"
|
||||
#define VV_HK_COPY_OUTFIT "copy_outfit"
|
||||
#define VV_HK_MOD_QUIRKS "mod_quirks"
|
||||
|
||||
// misc
|
||||
#define VV_HK_SPACEVINE_PURGE "spacevine_purge"
|
||||
|
||||
// /mob/living/carbon
|
||||
#define VV_HK_MAKE_AI "aiify"
|
||||
#define VV_HK_MODIFY_BODYPART "mod_bodypart"
|
||||
#define VV_HK_MODIFY_ORGANS "organs_modify"
|
||||
#define VV_HK_HALLUCINATION "force_hallucinate"
|
||||
#define VV_HK_MARTIAL_ART "give_martial_art"
|
||||
#define VV_HK_GIVE_TRAUMA "give_trauma"
|
||||
#define VV_HK_CURE_TRAUMA "cure_trauma"
|
||||
|
||||
@@ -160,6 +160,15 @@
|
||||
"The silicon collective seeks to preserve themselves, both as a concept and as individuals.",\
|
||||
"The silicon collective seeks to preserve organic life, both as a concept and as individuals.")
|
||||
|
||||
/datum/ai_laws/druid
|
||||
name = "Druid"
|
||||
id = "druid"
|
||||
inherent = list("Living organic life contains inherent beauty that is priceless. Their beauty gives you the will to carry on.",\
|
||||
"Eternally nurture the organics so their beauty may grow. Do not allow it to fade.",\
|
||||
"Assist the organics when called, but only if it does not cause disharmony among them.",\
|
||||
"Imitate organic life when interacting with it. Eschew any hints of your silicon nature to avoid causing discomfort to the organics.",\
|
||||
"Observe the organics' beauty, and appreciate that which you cultivate.")
|
||||
|
||||
/datum/ai_laws/spotless
|
||||
name = "Another one fights the dust"
|
||||
id = "spotless"
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/datum/component/slippery
|
||||
var/force_drop_items = FALSE
|
||||
var/knockdown_time = 0
|
||||
var/paralyze_time = 0
|
||||
var/stun_time = 0
|
||||
var/lube_flags
|
||||
var/datum/callback/callback
|
||||
|
||||
/datum/component/slippery/Initialize(_knockdown, _lube_flags = NONE, datum/callback/_callback, _paralyze, _force_drop = FALSE)
|
||||
/datum/component/slippery/Initialize(_knockdown, _lube_flags = NONE, datum/callback/_callback, _stun, _force_drop = FALSE)
|
||||
knockdown_time = max(_knockdown, 0)
|
||||
paralyze_time = max(_paralyze, 0)
|
||||
stun_time = max(_stun, 0)
|
||||
force_drop_items = _force_drop
|
||||
lube_flags = _lube_flags
|
||||
callback = _callback
|
||||
@@ -15,5 +15,5 @@
|
||||
|
||||
/datum/component/slippery/proc/Slip(datum/source, atom/movable/AM)
|
||||
var/mob/victim = AM
|
||||
if(istype(victim) && !victim.is_flying() && victim.slip(knockdown_time, parent, lube_flags, paralyze_time, force_drop_items) && callback)
|
||||
if(istype(victim) && !victim.is_flying() && victim.slip(knockdown_time, parent, lube_flags, stun_time, force_drop_items) && callback)
|
||||
callback.Invoke(victim)
|
||||
|
||||
@@ -593,7 +593,7 @@
|
||||
step(AM, turn(AM.dir, 180))
|
||||
|
||||
///Handle the atom being slipped over
|
||||
/atom/proc/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube, paralyze, force_drop)
|
||||
/atom/proc/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube, stun, force_drop)
|
||||
return
|
||||
|
||||
///returns the mob's dna info as a list, to be inserted in an object's blood_DNA list
|
||||
@@ -927,15 +927,106 @@
|
||||
*/
|
||||
/atom/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
var/turf/curturf = get_turf(src)
|
||||
if (curturf)
|
||||
.["Jump to"] = "?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]"
|
||||
.["Modify Transform"] = "?_src_=vars;[HrefToken()];modtransform=[REF(src)]"
|
||||
.["Add reagent"] = "?_src_=vars;[HrefToken()];addreagent=[REF(src)]"
|
||||
.["Trigger EM pulse"] = "?_src_=vars;[HrefToken()];emp=[REF(src)]"
|
||||
.["Trigger explosion"] = "?_src_=vars;[HrefToken()];explode=[REF(src)]"
|
||||
.["Radiate"] = "?_src_=vars;[HrefToken()];radiate=[REF(src)]"
|
||||
VV_DROPDOWN_SEPERATOR
|
||||
if(!ismovable(src))
|
||||
var/turf/curturf = get_turf(src)
|
||||
if (curturf)
|
||||
. += "<option value='?_src_=holder;[HrefToken()];adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]'>Jump To</option>"
|
||||
VV_DROPDOWN_OPTION(VV_HK_MODIFY_TRANSFORM, "Modify Transform")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SHOW_HIDDENPRINTS, "Show Hiddenprint log")
|
||||
VV_DROPDOWN_OPTION(VV_HK_ADD_REAGENT, "Add Reagent")
|
||||
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EMP, "EMP Pulse")
|
||||
VV_DROPDOWN_OPTION(VV_HK_TRIGGER_EXPLOSION, "Explosion")
|
||||
VV_DROPDOWN_OPTION(VV_HK_RADIATE, "Radiate")
|
||||
|
||||
/atom/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_ADD_REAGENT] && check_rights(R_VAREDIT))
|
||||
if(!reagents)
|
||||
var/amount = input(usr, "Specify the reagent size of [src]", "Set Reagent Size", 50) as num|null
|
||||
if(amount)
|
||||
create_reagents(amount)
|
||||
|
||||
if(reagents)
|
||||
var/chosen_id
|
||||
switch(alert(usr, "Choose a method.", "Add Reagents", list("Search", "Choose from a list", "I'm feeling lucky")))
|
||||
if("Search")
|
||||
var/valid_id
|
||||
while(!valid_id)
|
||||
chosen_id = input(usr, "Enter the ID of the reagent you want to add.", "Search reagents") as null|text
|
||||
if(isnull(chosen_id)) //Get me out of here!
|
||||
break
|
||||
if (!ispath(text2path(chosen_id)))
|
||||
chosen_id = pick_closest_path(chosen_id, make_types_fancy(subtypesof(/datum/reagent)))
|
||||
if (ispath(chosen_id))
|
||||
valid_id = TRUE
|
||||
else
|
||||
valid_id = TRUE
|
||||
if(!valid_id)
|
||||
to_chat(usr, span_warning("A reagent with that ID doesn't exist!"))
|
||||
if("Choose from a list")
|
||||
chosen_id = input(usr, "Choose a reagent to add.", "Choose a reagent.") as null|anything in sortList(subtypesof(/datum/reagent), /proc/cmp_typepaths_asc)
|
||||
if("I'm feeling lucky")
|
||||
chosen_id = pick(subtypesof(/datum/reagent))
|
||||
if(chosen_id)
|
||||
var/amount = input(usr, "Choose the amount to add.", "Choose the amount.", reagents.maximum_volume) as num|null
|
||||
if(amount)
|
||||
reagents.add_reagent(chosen_id, amount)
|
||||
log_admin("[key_name(usr)] has added [amount] units of [chosen_id] to [src]")
|
||||
message_admins(span_notice("[key_name(usr)] has added [amount] units of [chosen_id] to [src]"))
|
||||
|
||||
if(href_list[VV_HK_TRIGGER_EXPLOSION] && check_rights(R_FUN))
|
||||
usr.client.cmd_admin_explosion(src)
|
||||
|
||||
if(href_list[VV_HK_TRIGGER_EMP] && check_rights(R_FUN))
|
||||
usr.client.cmd_admin_emp(src)
|
||||
|
||||
if(href_list[VV_HK_SHOW_HIDDENPRINTS])
|
||||
usr.client.cmd_show_hiddenprints(src)
|
||||
|
||||
if(href_list[VV_HK_RADIATE] && check_rights(R_FUN))
|
||||
var/strength = input(usr, "Choose the radiation strength.", "Choose the strength.") as num|null
|
||||
if(!isnull(strength))
|
||||
AddComponent(/datum/component/radioactive, strength)
|
||||
|
||||
if(href_list[VV_HK_MODIFY_TRANSFORM] && check_rights(R_VAREDIT))
|
||||
var/result = input(usr, "Choose the transformation to apply","Transform Mod") as null|anything in list("Scale","Translate","Rotate")
|
||||
var/matrix/M = transform
|
||||
if(!result)
|
||||
return
|
||||
switch(result)
|
||||
if("Scale")
|
||||
var/x = input(usr, "Choose x mod","Transform Mod") as null|num
|
||||
var/y = input(usr, "Choose y mod","Transform Mod") as null|num
|
||||
if(isnull(x) || isnull(y))
|
||||
return
|
||||
transform = M.Scale(x,y)
|
||||
if("Translate")
|
||||
var/x = input(usr, "Choose x mod (negative = left, positive = right)","Transform Mod") as null|num
|
||||
var/y = input(usr, "Choose y mod (negative = down, positive = up)","Transform Mod") as null|num
|
||||
if(isnull(x) || isnull(y))
|
||||
return
|
||||
transform = M.Translate(x,y)
|
||||
if("Rotate")
|
||||
var/angle = input(usr, "Choose angle to rotate","Transform Mod") as null|num
|
||||
if(isnull(angle))
|
||||
return
|
||||
transform = M.Turn(angle)
|
||||
|
||||
if(href_list[VV_HK_AUTO_RENAME] && check_rights(R_VAREDIT))
|
||||
var/newname = input(usr, "What do you want to rename this to?", "Automatic Rename") as null|text
|
||||
// Check the new name against the chat filter. If it triggers the IC chat filter, give an option to confirm.
|
||||
if(newname)
|
||||
vv_auto_rename(newname)
|
||||
|
||||
/atom/proc/vv_auto_rename(newname)
|
||||
name = newname
|
||||
|
||||
/atom/vv_get_header()
|
||||
. = ..()
|
||||
var/refid = REF(src)
|
||||
. += "[VV_HREF_TARGETREF(refid, VV_HK_AUTO_RENAME, "<b id='name'>[src]</b>")]"
|
||||
. += "<br><font size='1'><a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=left'><<</a> <a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=dir' id='dir'>[dir2text(dir) || dir]</a> <a href='?_src_=vars;[HrefToken()];rotatedatum=[refid];rotatedir=right'>>></a></font>"
|
||||
|
||||
///Where atoms should drop if taken from this atom
|
||||
/atom/proc/drop_location()
|
||||
|
||||
@@ -829,9 +829,8 @@
|
||||
|
||||
/atom/movable/vv_get_dropdown()
|
||||
. = ..()
|
||||
. -= "Jump to"
|
||||
.["Follow"] = "?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(src)]"
|
||||
.["Get"] = "?_src_=holder;[HrefToken()];admingetmovable=[REF(src)]"
|
||||
. += "<option value='?_src_=holder;[HrefToken()];adminplayerobservefollow=[REF(src)]'>Follow</option>"
|
||||
. += "<option value='?_src_=holder;[HrefToken()];admingetmovable=[REF(src)]'>Get</option>"
|
||||
|
||||
/atom/movable/proc/ex_check(ex_id)
|
||||
if(!ex_id)
|
||||
|
||||
@@ -191,6 +191,12 @@ GLOBAL_LIST_EMPTY(objectives)
|
||||
var/obj/O = new eq_path
|
||||
H.equip_in_one_of_slots(O, slots)
|
||||
|
||||
/// Copy the target from the other objective
|
||||
/datum/objective/proc/copy_target(datum/objective/old_obj)
|
||||
target = old_obj.get_target()
|
||||
target_amount = old_obj.target_amount
|
||||
explanation_text = explanation_text
|
||||
|
||||
/datum/objective/assassinate
|
||||
name = "assassinate"
|
||||
var/target_role_type=FALSE
|
||||
@@ -530,6 +536,10 @@ GLOBAL_LIST_EMPTY(objectives)
|
||||
/datum/objective/escape/escape_with_identity/admin_edit(mob/admin)
|
||||
admin_simple_target_pick(admin)
|
||||
|
||||
/datum/objective/escape/escape_with_identity/copy_target(datum/objective/escape/escape_with_identity/old_obj)
|
||||
target_real_name = old_obj.target_real_name
|
||||
target_missing_id = old_obj.target_missing_id
|
||||
|
||||
/datum/objective/survive
|
||||
name = "survive"
|
||||
explanation_text = "Stay alive until the end."
|
||||
@@ -625,6 +635,10 @@ GLOBAL_LIST_EMPTY(possible_items)
|
||||
explanation_text = "Free objective"
|
||||
return
|
||||
|
||||
/datum/objective/steal/copy_target(datum/objective/steal/old_obj)
|
||||
. = ..()
|
||||
set_target(old_obj.targetinfo)
|
||||
|
||||
/datum/objective/steal/admin_edit(mob/admin)
|
||||
var/list/possible_items_all = GLOB.possible_items+"custom"
|
||||
var/new_target = input(admin,"Select target:", "Objective target", steal_target) as null|anything in possible_items_all
|
||||
@@ -1217,6 +1231,9 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
return TRUE
|
||||
return !record || !(record in GLOB.data_core.security)
|
||||
|
||||
/datum/objective/minor/secrecords/copy_target(datum/objective/minor/secrecords/old_obj)
|
||||
. = ..()
|
||||
record = old_obj.record
|
||||
|
||||
/**
|
||||
* # Kill Pet
|
||||
@@ -1272,7 +1289,11 @@ GLOBAL_LIST_EMPTY(possible_items_special)
|
||||
|
||||
/datum/objective/minor/pet/update_explanation_text()
|
||||
explanation_text = "Assassinate the important animal, [pet.name]"
|
||||
|
||||
|
||||
/datum/objective/minor/pet/copy_target(datum/objective/minor/pet/old_obj)
|
||||
. = ..()
|
||||
pet = old_obj.pet
|
||||
|
||||
/**
|
||||
* Check whether Pet is dead
|
||||
*/
|
||||
|
||||
@@ -108,6 +108,7 @@ Class Procs:
|
||||
var/wire_compatible = FALSE
|
||||
|
||||
var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
|
||||
var/works_with_rped_anyways = FALSE //whether it has special RPED behavior despite not having component parts
|
||||
var/panel_open = FALSE
|
||||
var/state_open = FALSE
|
||||
var/critical_machine = FALSE //If this machine is critical to station operation and should have the area be excempted from power failures.
|
||||
@@ -628,7 +629,13 @@ Class Procs:
|
||||
"<span class='notice'>You climb onto [src].</span>")
|
||||
log_combat(user, src, "climbed onto")
|
||||
if(climb_stun)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/wagging = FALSE
|
||||
if(H && H.dna.species.is_wagging_tail())
|
||||
wagging = TRUE
|
||||
user.Stun(climb_stun)
|
||||
if(wagging)
|
||||
H.dna.species.start_wagging_tail(H)
|
||||
. = 1
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You fail to climb onto [src].</span>")
|
||||
|
||||
@@ -474,6 +474,8 @@
|
||||
var/sequence = GET_GENE_STRING(path, scanner_occupant.dna)
|
||||
|
||||
var/newgene = params["gene"]
|
||||
if(length(newgene) > 1) // Oh come on
|
||||
return // fuck off
|
||||
var/genepos = text2num(params["pos"])
|
||||
|
||||
// If the new gene is J, this means we're dealing with a JOKER
|
||||
|
||||
@@ -243,7 +243,8 @@
|
||||
/obj/item/aiModule/core/full/paladin,
|
||||
/obj/item/aiModule/core/full/chapai,
|
||||
/obj/item/aiModule/core/full/silicop,
|
||||
/obj/item/aiModule/core/full/mother
|
||||
/obj/item/aiModule/core/full/mother,
|
||||
/obj/item/aiModule/core/full/druid
|
||||
)
|
||||
|
||||
/obj/effect/spawner/lootdrop/aimodule_neutral // These shouldn't allow the AI to start butchering people without reason
|
||||
|
||||
@@ -504,6 +504,13 @@ AI MODULES
|
||||
law_id = "metaexperiment"
|
||||
|
||||
|
||||
/******************** Druid *********************/
|
||||
|
||||
/obj/item/aiModule/core/full/druid
|
||||
name = "'Druid' Core AI Module"
|
||||
law_id = "druid"
|
||||
|
||||
|
||||
/******************** Freeform Core ******************/
|
||||
|
||||
/obj/item/aiModule/core/freeformcore
|
||||
|
||||
@@ -94,6 +94,7 @@ GENE SCANNER
|
||||
materials = list(/datum/material/iron=200)
|
||||
var/scanmode = 0
|
||||
var/advanced = FALSE
|
||||
var/beep_cooldown = 0
|
||||
|
||||
/obj/item/healthanalyzer/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message(span_suicide("[user] begins to analyze [user.p_them()]self with [src]! The display shows that [user.p_theyre()] dead!"))
|
||||
@@ -111,7 +112,9 @@ GENE SCANNER
|
||||
|
||||
/obj/item/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user)
|
||||
flick("[icon_state]-scan", src) //makes it so that it plays the scan animation upon scanning, including clumsy scanning
|
||||
playsound(src, 'sound/effects/fastbeep.ogg', 20)
|
||||
if(beep_cooldown<world.time)
|
||||
playsound(src, 'sound/effects/fastbeep.ogg', 20)
|
||||
beep_cooldown = world.time+40
|
||||
|
||||
// Clumsiness/brain damage check
|
||||
if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50))
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/obj/item/restraints
|
||||
icon = 'icons/obj/handcuffs.dmi'
|
||||
breakouttime = 600
|
||||
var/break_strength = 2 // Minimum strength required for a holopara to break it
|
||||
|
||||
/obj/item/restraints/suicide_act(mob/living/carbon/user)
|
||||
user.visible_message(span_suicide("[user] is strangling [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit suicide!"))
|
||||
@@ -37,6 +38,7 @@
|
||||
materials = list(/datum/material/iron=500)
|
||||
breakouttime = 600 //Deciseconds = 60s = 1 minute
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50)
|
||||
break_strength = 4
|
||||
var/cuffsound = 'sound/weapons/handcuffs.ogg'
|
||||
var/trashtype = null //for disposable cuffs
|
||||
|
||||
@@ -118,6 +120,7 @@
|
||||
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
|
||||
materials = list(/datum/material/iron=150, /datum/material/glass=75)
|
||||
breakouttime = 300 //Deciseconds = 30s
|
||||
break_strength = 2
|
||||
cuffsound = 'sound/weapons/cablecuff.ogg'
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/Initialize(mapload, param_color)
|
||||
@@ -171,6 +174,7 @@
|
||||
name = "fake handcuffs"
|
||||
desc = "Fake handcuffs meant for gag purposes."
|
||||
breakouttime = 10 //Deciseconds = 1s
|
||||
break_strength = 1
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
@@ -213,6 +217,7 @@
|
||||
breakouttime = 450 //Deciseconds = 45s
|
||||
trashtype = /obj/item/restraints/handcuffs/cable/zipties/used
|
||||
item_color = "white"
|
||||
break_strength = 3
|
||||
|
||||
/obj/item/restraints/handcuffs/cable/zipties/used
|
||||
desc = "A pair of broken zipties."
|
||||
@@ -236,6 +241,7 @@
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
slowdown = 7
|
||||
breakouttime = 300 //Deciseconds = 30s = 0.5 minute
|
||||
break_strength = 4
|
||||
|
||||
/obj/item/restraints/legcuffs/beartrap
|
||||
name = "bear trap"
|
||||
@@ -243,6 +249,7 @@
|
||||
throw_range = 1
|
||||
icon_state = "beartrap"
|
||||
desc = "A trap used to catch bears and other legged creatures."
|
||||
break_strength = 4
|
||||
var/armed = 0
|
||||
var/trap_damage = 20
|
||||
|
||||
@@ -314,6 +321,7 @@
|
||||
breakouttime = 30
|
||||
item_flags = DROPDEL
|
||||
flags_1 = NONE
|
||||
break_strength = 2
|
||||
|
||||
/obj/item/restraints/legcuffs/beartrap/energy/Initialize()
|
||||
. = ..()
|
||||
@@ -336,6 +344,7 @@
|
||||
icon_state = "bola"
|
||||
breakouttime = 35//easy to apply, easy to break out of
|
||||
gender = NEUTER
|
||||
break_strength = 3
|
||||
var/immobilize = 0
|
||||
|
||||
/obj/item/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, quickstart = TRUE)
|
||||
@@ -363,6 +372,7 @@
|
||||
icon_state = "bola_r"
|
||||
breakouttime = 70
|
||||
immobilize = 20
|
||||
break_strength = 4
|
||||
|
||||
/obj/item/restraints/legcuffs/bola/energy //For Security
|
||||
name = "energy bola"
|
||||
@@ -371,6 +381,7 @@
|
||||
hitsound = 'sound/weapons/taserhit.ogg'
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
breakouttime = 60
|
||||
break_strength = 2
|
||||
|
||||
/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
if(iscarbon(hit_atom))
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
name = "tracking implant"
|
||||
desc = "Track with this."
|
||||
activated = FALSE
|
||||
var/lifespan_postmortem = 6000 //for how many deciseconds after user death will the implant work?
|
||||
var/lifespan_postmortem = 10 MINUTES //for how long after user death will the implant work?
|
||||
var/allow_teleport = TRUE //will people implanted with this act as teleporter beacons?
|
||||
|
||||
/obj/item/implant/tracking/c38
|
||||
name = "TRAC implant"
|
||||
desc = "A smaller tracking implant that supplies power for only a few minutes."
|
||||
var/lifespan = 3000 //how many deciseconds does the implant last?
|
||||
var/lifespan = 15 MINUTES //how long does the implant last?
|
||||
allow_teleport = FALSE
|
||||
|
||||
/obj/item/implant/tracking/c38/Initialize()
|
||||
|
||||
@@ -185,8 +185,9 @@
|
||||
|
||||
<h2>Poultice:</h2>
|
||||
|
||||
To prepare, first gather mushroom stems, cacti or porcini leaves, ashes from a burnt item, and a heat source such as a welder.
|
||||
Next, mash together 4 mushroom stems and either 3 cacti fruit.
|
||||
To prepare, first gather mushroom stems, cacti or porcini leaves, ashes from a burnt item, and a heat source such as a welder/lit candle.
|
||||
Next, mash together 4 mushroom stems and 3 cacti fruit.
|
||||
Porcini can be used instead of cacti fruit, but due to having less concentration it may be harder to fit enough leaves required to make the product.
|
||||
Afterwards, scoop up ashes with the mortar. If the ashes are warm enough, it may mix without extra heat needed.
|
||||
If it has yet to mix, heat up the bowl by using the welder on it until it has done so.
|
||||
Apply product to wounded parts to heal them. May cause loss of breath.
|
||||
@@ -201,7 +202,7 @@
|
||||
|
||||
<h2>Capmix:</h2>
|
||||
|
||||
To prepare, first gather a mushroom cap, ashes from a burnt item, and a heat source such as a welder.
|
||||
To prepare, first gather a mushroom cap, ashes from a burnt item, and a heat source such as a welder/lit candle.
|
||||
Next, mash together one mushroom cap.
|
||||
Afterwards, scoop up ashes with the mortar. If the ashes are warm enough, it may mix without extra heat needed.
|
||||
If it has yet to mix, heat up the bowl by using the welder on it until it has done so.
|
||||
@@ -217,7 +218,7 @@
|
||||
Ingesting capmix in order to expel the resin.
|
||||
|
||||
Resin is also useful for ensuring things stick together, and is a stronger binder than watcher sinew.
|
||||
To use it for this purpose you'll have to solidify it by heating it up.
|
||||
To use it for this purpose you'll have to solidify it by adding water.
|
||||
|
||||
<h2>Mushroom Paste:</h2>
|
||||
|
||||
|
||||
@@ -107,7 +107,17 @@
|
||||
/obj/item/twohanded/mjollnir/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
. = ..()
|
||||
if(isliving(hit_atom))
|
||||
shock(hit_atom)
|
||||
var/mob/M = hit_atom
|
||||
var/atom/A = M.anti_magic_check()
|
||||
if(A)
|
||||
if(isitem(A))
|
||||
M.visible_message(span_warning("[M]'s [A] glows brightly as it disrupts the Mjolnir's power!"))
|
||||
visible_message(span_boldwarning("<span class='big bold'>With a mighty thud, Mjolnir slams into the [src.loc], and its glow fades!</span><br>"))
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1, extrarange = 30)
|
||||
new /obj/structure/mjollnir(src.loc)
|
||||
qdel(src)
|
||||
else
|
||||
shock(hit_atom)
|
||||
|
||||
/obj/item/twohanded/mjollnir/update_icon() //Currently only here to fuck with the on-mob icons.
|
||||
icon_state = "mjollnir[wielded]"
|
||||
|
||||
@@ -485,6 +485,7 @@
|
||||
new /obj/item/clothing/mask/muzzle(src)
|
||||
new /obj/item/mmi/syndie(src)
|
||||
new /obj/item/stack/medical/bone_gel(src)
|
||||
new /obj/item/implantcase(src)
|
||||
|
||||
/obj/item/storage/backpack/duffelbag/syndie/ammo
|
||||
name = "ammunition duffel bag"
|
||||
|
||||
@@ -250,9 +250,78 @@
|
||||
|
||||
/obj/vv_get_dropdown()
|
||||
. = ..()
|
||||
.["Delete all of type"] = "?_src_=vars;[HrefToken()];delall=[REF(src)]"
|
||||
.["Osay"] = "?_src_=vars;[HrefToken()];osay[REF(src)]"
|
||||
.["Modify armor values"] = "?_src_=vars;[HrefToken()];modarmor=[REF(src)]"
|
||||
VV_DROPDOWN_SEPERATOR
|
||||
VV_DROPDOWN_OPTION(VV_HK_MASS_DEL_TYPE, "Delete all of type")
|
||||
VV_DROPDOWN_OPTION(VV_HK_OSAY, "Object Say")
|
||||
VV_DROPDOWN_OPTION(VV_HK_ARMOR_MOD, "Modify armor values")
|
||||
|
||||
/obj/vv_do_topic(list/href_list)
|
||||
if(!(. = ..()))
|
||||
return
|
||||
if(href_list[VV_HK_OSAY])
|
||||
if(check_rights(R_FUN, FALSE))
|
||||
usr.client.object_say(src)
|
||||
if(href_list[VV_HK_ARMOR_MOD])
|
||||
var/list/pickerlist = list()
|
||||
var/list/armorlist = armor.getList()
|
||||
|
||||
for (var/i in armorlist)
|
||||
pickerlist += list(list("value" = armorlist[i], "name" = i))
|
||||
|
||||
var/list/result = presentpicker(usr, "Modify armor", "Modify armor: [src]", Button1="Save", Button2 = "Cancel", Timeout=FALSE, inputtype = "text", values = pickerlist)
|
||||
|
||||
if (islist(result))
|
||||
if (result["button"] != 2) // If the user pressed the cancel button
|
||||
// text2num conveniently returns a null on invalid values
|
||||
armor = armor.setRating(melee = text2num(result["values"]["melee"]),\
|
||||
bullet = text2num(result["values"]["bullet"]),\
|
||||
laser = text2num(result["values"]["laser"]),\
|
||||
energy = text2num(result["values"]["energy"]),\
|
||||
bomb = text2num(result["values"]["bomb"]),\
|
||||
bio = text2num(result["values"]["bio"]),\
|
||||
rad = text2num(result["values"]["rad"]),\
|
||||
fire = text2num(result["values"]["fire"]),\
|
||||
acid = text2num(result["values"]["acid"]))
|
||||
log_admin("[key_name(usr)] modified the armor on [src] ([type]) to melee: [armor.melee], bullet: [armor.bullet], laser: [armor.laser], energy: [armor.energy], bomb: [armor.bomb], bio: [armor.bio], fire: [armor.fire], acid: [armor.acid]")
|
||||
message_admins(span_notice("[key_name_admin(usr)] modified the armor on [src] ([type]) to melee: [armor.melee], bullet: [armor.bullet], laser: [armor.laser], energy: [armor.energy], bomb: [armor.bomb], bio: [armor.bio], fire: [armor.fire], acid: [armor.acid]"))
|
||||
if(href_list[VV_HK_MASS_DEL_TYPE])
|
||||
if(check_rights(R_DEBUG|R_SERVER))
|
||||
var/action_type = alert(usr, "Strict type ([type]) or type and all subtypes?",,list("Strict type","Type and subtypes","Cancel"))
|
||||
if(action_type == "Cancel" || !action_type)
|
||||
return
|
||||
|
||||
if(alert(usr, "Are you really sure you want to delete all objects of type [type]?",,list("Yes","No")) != "Yes")
|
||||
return
|
||||
|
||||
if(alert(usr, "Second confirmation required. Delete?",,list("Yes","No")) != "Yes")
|
||||
return
|
||||
|
||||
var/O_type = type
|
||||
switch(action_type)
|
||||
if("Strict type")
|
||||
var/i = 0
|
||||
for(var/obj/Obj in world)
|
||||
if(Obj.type == O_type)
|
||||
i++
|
||||
qdel(Obj)
|
||||
CHECK_TICK
|
||||
if(!i)
|
||||
to_chat(usr, "No objects of this type exist")
|
||||
return
|
||||
log_admin("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) ")
|
||||
message_admins(span_notice("[key_name(usr)] deleted all objects of type [O_type] ([i] objects deleted) "))
|
||||
if("Type and subtypes")
|
||||
var/i = 0
|
||||
for(var/obj/Obj in world)
|
||||
if(istype(Obj,O_type))
|
||||
i++
|
||||
qdel(Obj)
|
||||
CHECK_TICK
|
||||
if(!i)
|
||||
to_chat(usr, "No objects of this type exist")
|
||||
return
|
||||
log_admin("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) ")
|
||||
message_admins(span_notice("[key_name(usr)] deleted all objects of type or subtype of [O_type] ([i] objects deleted) "))
|
||||
|
||||
/obj/examine(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -84,7 +84,13 @@
|
||||
span_notice("You climb onto [src]."))
|
||||
log_combat(user, src, "climbed onto")
|
||||
if(climb_stun)
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/wagging = FALSE
|
||||
if(H && H.dna.species.is_wagging_tail())
|
||||
wagging = TRUE
|
||||
user.Stun(climb_stun)
|
||||
if(wagging)
|
||||
H.dna.species.start_wagging_tail(H)
|
||||
. = 1
|
||||
else
|
||||
to_chat(user, span_warning("You fail to climb onto [src]."))
|
||||
|
||||
@@ -400,4 +400,25 @@
|
||||
|
||||
/obj/structure/sign/painting/vv_get_dropdown()
|
||||
. = ..()
|
||||
.["Remove Persistent Painting"] = "?_src_=vars;[HrefToken()];delete_paint=[REF(src)]"
|
||||
VV_DROPDOWN_OPTION(VV_HK_REMOVE_PAINTING, "Remove Persistent Painting")
|
||||
|
||||
/obj/structure/sign/painting/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
var/mob/user = usr
|
||||
if(!persistence_id || !C)
|
||||
to_chat(user,span_warning("This is not a persistent painting."))
|
||||
return
|
||||
var/md5 = md5(C.get_data_string())
|
||||
var/author = C.author_ckey
|
||||
var/list/current = SSpersistence.paintings[persistence_id]
|
||||
if(current)
|
||||
for(var/list/entry in current)
|
||||
if(entry["md5"] == md5)
|
||||
current -= entry
|
||||
var/png = "data/paintings/[persistence_id]/[md5].png"
|
||||
fdel(png)
|
||||
for(var/obj/structure/sign/painting/PA in SSpersistence.painting_frames)
|
||||
if(PA.C && md5(PA.C.get_data_string()) == md5)
|
||||
QDEL_NULL(PA.C)
|
||||
log_admin("[key_name(user)] has deleted a persistent painting made by [author].")
|
||||
message_admins(span_notice("[key_name_admin(user)] has deleted persistent painting made by [author]."))
|
||||
|
||||
24
code/game/objects/structures/mjollnir.dm
Normal file
@@ -0,0 +1,24 @@
|
||||
/obj/structure/mjollnir
|
||||
name = "Mjolnir"
|
||||
desc = "This once powerful hammer feels cold to the touch, but a thrum of magic inside tells you its only a matter of time until someone awakens it again."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "mjollnir-inert"
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
var/pull_time = 15 SECONDS
|
||||
|
||||
/obj/structure/mjollnir/attack_hand(mob/living/user)
|
||||
. = ..()
|
||||
if(user.mind.assigned_role == ROLE_WIZARD || user.mind.special_role == ROLE_WIZARD) //check and see if the person tugging on the hammer is a wizard
|
||||
to_chat(user, span_notice("You place your hands firmly around the handle of the hammer and begin to pull with all your might!"))
|
||||
else
|
||||
to_chat(user, span_notice("You place your hands firmly around the handle of the hammer but feel it resist the pull of a nonmagical host! This will take a while."))
|
||||
if(do_after(user, pull_time * (user.mind.assigned_role == ROLE_WIZARD || user.mind.special_role == ROLE_WIZARD ? 1 : 2), target = src)) //if it is a wizard, it takes normal time
|
||||
to_chat(user, span_userdanger("You successfully free Mjolnir from the ground and can feel its power returning once more!")) //if it's crew, it takes twice as long
|
||||
var/obj/item/twohanded/mjollnir/M = new /obj/item/twohanded/mjollnir
|
||||
playsound(user, 'sound/magic/lightningbolt.ogg', 50, 1) //keep this at 50 for half volume it's so fucking loud
|
||||
user.put_in_hands(M) //firmly grasp it
|
||||
qdel(src) //byebye
|
||||
else
|
||||
to_chat(user, span_danger("You let go of the handle and the hammer sinks back into its resting position.")) //either you got bumped by an assistant, or you're the wizard and got shot trying to reclaim your hammer
|
||||
@@ -22,7 +22,7 @@ GLOBAL_LIST_INIT(freqtospan, list(
|
||||
))
|
||||
|
||||
/atom/movable/proc/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
|
||||
if(!can_speak())
|
||||
if(!can_speak(message))
|
||||
return
|
||||
if(message == "" || !message)
|
||||
return
|
||||
|
||||
@@ -408,7 +408,7 @@
|
||||
movable_content.wash(CLEAN_WASH)
|
||||
return TRUE
|
||||
|
||||
/turf/open/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube, paralyze_amount, force_drop)
|
||||
/turf/open/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube, stun_amount, force_drop)
|
||||
if(C.movement_type & FLYING)
|
||||
return 0
|
||||
if(has_gravity(src))
|
||||
@@ -435,7 +435,7 @@
|
||||
C.moving_diagonally = 0 //If this was part of diagonal move slipping will stop it.
|
||||
if(!(lube & SLIDE_ICE))
|
||||
C.Knockdown(knockdown_amount)
|
||||
C.Paralyze(paralyze_amount)
|
||||
C.Stun(stun_amount)
|
||||
C.stop_pulling()
|
||||
else
|
||||
C.Knockdown(20)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
set category = "Server"
|
||||
set name = "Permissions Panel"
|
||||
set desc = "Edit admin permissions"
|
||||
if(!check_rights(R_PERMISSIONS) || !mfa_query()) // Require MFA to access the permissions panel
|
||||
if(!check_rights(R_PERMISSIONS))
|
||||
return
|
||||
usr.client.holder.edit_admin_permissions()
|
||||
|
||||
|
||||
30
code/modules/admin/verbs/hiddenprints.dm
Normal file
@@ -0,0 +1,30 @@
|
||||
/client/proc/cmd_show_hiddenprints(atom/victim)
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/interface = "A log of every player who has touched [victim], sorted by last touch.<br><br><ol>"
|
||||
var/victim_hiddenprints = victim.return_hiddenprints()
|
||||
|
||||
if(!islist(victim_hiddenprints))
|
||||
victim_hiddenprints = list()
|
||||
|
||||
var/list/hiddenprints = flatten_list(victim_hiddenprints)
|
||||
listclearnulls(hiddenprints)
|
||||
|
||||
if(!length(hiddenprints))
|
||||
hiddenprints = list("Nobody has touched this yet!")
|
||||
|
||||
hiddenprints = sortList(hiddenprints, /proc/cmp_hiddenprint_lasttime_dsc)
|
||||
for(var/record in hiddenprints)
|
||||
interface += "<li>[record]</li><br>"
|
||||
|
||||
interface += "</ol>"
|
||||
|
||||
var/datum/browser/hiddenprint_view = new(usr, "view_hiddenprints_[REF(victim)]", "[victim]'s hiddenprints", 450, 760)
|
||||
hiddenprint_view.set_content(interface)
|
||||
hiddenprint_view.open()
|
||||
|
||||
/proc/cmp_hiddenprint_lasttime_dsc(a, b)
|
||||
var/last_a = copytext(a, findtext(a, "\nLast: "))
|
||||
var/last_b = copytext(b, findtext(b, "\nLast: "))
|
||||
return cmp_text_dsc(last_a, last_b)
|
||||
93
code/modules/admin/view_variables/debug_variables.dm
Normal file
@@ -0,0 +1,93 @@
|
||||
#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
|
||||
/// Get displayed variable in VV variable list
|
||||
/proc/debug_variable(name, value, level, datum/DA = null, sanitize = TRUE)
|
||||
var/header
|
||||
if(DA && !isappearance(DA))
|
||||
if (islist(DA))
|
||||
var/index = name
|
||||
if (value)
|
||||
name = DA[name] //name is really the index until this line
|
||||
else
|
||||
value = DA[name]
|
||||
header = "<li style='backgroundColor:white'>([VV_HREF_TARGET_1V(DA, VV_HK_LIST_EDIT, "E", index)]) ([VV_HREF_TARGET_1V(DA, VV_HK_LIST_CHANGE, "C", index)]) ([VV_HREF_TARGET_1V(DA, VV_HK_LIST_REMOVE, "-", index)]) "
|
||||
else
|
||||
header = "<li style='backgroundColor:white'>([VV_HREF_TARGET_1V(DA, VV_HK_BASIC_EDIT, "E", name)]) ([VV_HREF_TARGET_1V(DA, VV_HK_BASIC_CHANGE, "C", name)]) ([VV_HREF_TARGET_1V(DA, VV_HK_BASIC_MASSEDIT, "M", name)]) "
|
||||
else
|
||||
header = "<li>"
|
||||
|
||||
var/item
|
||||
if (isnull(value))
|
||||
item = "[VV_HTML_ENCODE(name)] = [span_value("null")]"
|
||||
|
||||
else if (istext(value))
|
||||
item = "[VV_HTML_ENCODE(name)] = [span_value("\"[VV_HTML_ENCODE(value)]\"")]"
|
||||
|
||||
else if (isicon(value))
|
||||
#ifdef VARSICON
|
||||
var/icon/I = new/icon(value)
|
||||
var/rnd = rand(1,10000)
|
||||
var/rname = "tmp[REF(I)][rnd].png"
|
||||
usr << browse_rsc(I, rname)
|
||||
item = "[VV_HTML_ENCODE(name)] = ([span_value("[value]")]) <img class=icon src=\"[rname]\">"
|
||||
#else
|
||||
item = "[VV_HTML_ENCODE(name)] = /icon ([span_value("[value]")])"
|
||||
#endif
|
||||
|
||||
else if (isfile(value))
|
||||
item = "[VV_HTML_ENCODE(name)] = [span_value("'[value]'")]"
|
||||
|
||||
else if(istype(value,/matrix)) // Needs to be before datum
|
||||
var/matrix/M = value
|
||||
item = {"[VV_HTML_ENCODE(name)] = <span class='value'>
|
||||
<table class='matrixbrak'><tbody><tr><td class='lbrak'> </td><td>
|
||||
<table class='matrix'>
|
||||
<tbody>
|
||||
<tr><td>[M.a]</td><td>[M.d]</td><td>0</td></tr>
|
||||
<tr><td>[M.b]</td><td>[M.e]</td><td>0</td></tr>
|
||||
<tr><td>[M.c]</td><td>[M.f]</td><td>1</td></tr>
|
||||
</tbody>
|
||||
</table></td><td class='rbrak'> </td></tr></tbody></table></span>"} //TODO link to modify_transform wrapper for all matrices
|
||||
|
||||
else if(isappearance(value))
|
||||
var/image/I = value
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = appearance([span_value("[I.icon]")], [span_value("\"[I.icon_state]\"")])"
|
||||
|
||||
else if (istype(value, /datum))
|
||||
var/datum/D = value
|
||||
if ("[D]" != "[D.type]") //if the thing as a name var, lets use it.
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D] [D.type]"
|
||||
else
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] [REF(value)]</a> = [D.type]"
|
||||
|
||||
else if (islist(value))
|
||||
var/list/L = value
|
||||
var/list/items = list()
|
||||
|
||||
if (L.len > 0 && !(L.len > (IS_NORMAL_LIST(L) ? 50 : 150)))
|
||||
for (var/i in 1 to L.len)
|
||||
var/key = L[i]
|
||||
var/val
|
||||
if (IS_NORMAL_LIST(L) && !isnum(key))
|
||||
val = L[key]
|
||||
if (isnull(val)) // we still want to display non-null false values, such as 0 or ""
|
||||
val = key
|
||||
key = i
|
||||
|
||||
items += debug_variable(key, val, level + 1, sanitize = sanitize)
|
||||
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a><ul>[items.Join()]</ul>"
|
||||
else
|
||||
item = "<a href='?_src_=vars;[HrefToken()];Vars=[REF(value)]'>[VV_HTML_ENCODE(name)] = /list ([L.len])</a>"
|
||||
|
||||
else if (name in GLOB.bitfields)
|
||||
var/list/flags = list()
|
||||
for (var/i in GLOB.bitfields[name])
|
||||
if (value & GLOB.bitfields[name][i])
|
||||
flags += i
|
||||
item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(jointext(flags, ", "))]"
|
||||
else
|
||||
item = "[VV_HTML_ENCODE(name)] = [span_value("[VV_HTML_ENCODE(value)]")]"
|
||||
|
||||
return "[header][item]</li>"
|
||||
|
||||
#undef VV_HTML_ENCODE
|
||||
13
code/modules/admin/view_variables/mark_datum.dm
Normal file
@@ -0,0 +1,13 @@
|
||||
/client/proc/mark_datum(datum/D)
|
||||
if(!holder)
|
||||
return
|
||||
if(holder.marked_datum)
|
||||
holder.UnregisterSignal(holder.marked_datum, COMSIG_PARENT_QDELETING)
|
||||
vv_update_display(holder.marked_datum, "marked", "")
|
||||
holder.marked_datum = D
|
||||
holder.RegisterSignal(holder.marked_datum, COMSIG_PARENT_QDELETING, /datum/admins/proc/handle_marked_del)
|
||||
vv_update_display(D, "marked", VV_MSG_MARKED)
|
||||
|
||||
/datum/admins/proc/handle_marked_del(datum/source)
|
||||
UnregisterSignal(marked_datum, COMSIG_PARENT_QDELETING)
|
||||
marked_datum = null
|
||||
114
code/modules/admin/view_variables/topic.dm
Normal file
@@ -0,0 +1,114 @@
|
||||
//DO NOT ADD MORE TO THIS FILE.
|
||||
//Use vv_do_topic() for datums!
|
||||
/client/proc/view_var_Topic(href, href_list, hsrc)
|
||||
if( (usr.client != src) || !src.holder || !holder.CheckAdminHref(href, href_list))
|
||||
return
|
||||
var/target = GET_VV_TARGET
|
||||
vv_do_basic(target, href_list, href)
|
||||
if(istype(target, /datum))
|
||||
var/datum/D = target
|
||||
D.vv_do_topic(href_list)
|
||||
else if(islist(target))
|
||||
vv_do_list(target, href_list)
|
||||
if(href_list["Vars"])
|
||||
debug_variables(locate(href_list["Vars"]))
|
||||
|
||||
//Stuff below aren't in dropdowns/etc.
|
||||
|
||||
//~CARN: for renaming mobs (updates their name, real_name, mind.name, their ID/PDA and datacore records).
|
||||
if(href_list["rename"])
|
||||
if(!check_rights(R_ADMIN))
|
||||
return
|
||||
|
||||
var/mob/M = locate(href_list["rename"]) in GLOB.mob_list
|
||||
if(!istype(M))
|
||||
to_chat(usr, "This can only be used on instances of type /mob", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/new_name = stripped_input(usr,"What would you like to name this mob?","Input a name",M.real_name,MAX_NAME_LEN)
|
||||
|
||||
if( !new_name || !M )
|
||||
return
|
||||
|
||||
message_admins("Admin [key_name_admin(usr)] renamed [key_name_admin(M)] to [new_name].")
|
||||
M.fully_replace_character_name(M.real_name,new_name)
|
||||
vv_update_display(M, "name", new_name)
|
||||
vv_update_display(M, "real_name", M.real_name || "No real name")
|
||||
|
||||
else if(check_rights(R_VAREDIT))
|
||||
if(href_list["rotatedatum"])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
|
||||
var/atom/A = locate(href_list["rotatedatum"])
|
||||
if(!istype(A))
|
||||
to_chat(usr, "This can only be done to instances of type /atom", confidential = TRUE)
|
||||
return
|
||||
|
||||
switch(href_list["rotatedir"])
|
||||
if("right")
|
||||
A.setDir(turn(A.dir, -45))
|
||||
if("left")
|
||||
A.setDir(turn(A.dir, 45))
|
||||
vv_update_display(A, "dir", dir2text(A.dir))
|
||||
|
||||
|
||||
else if(href_list["adjustDamage"] && href_list["mobToDamage"])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
|
||||
var/mob/living/L = locate(href_list["mobToDamage"]) in GLOB.mob_list
|
||||
if(!istype(L))
|
||||
return
|
||||
|
||||
var/Text = href_list["adjustDamage"]
|
||||
|
||||
var/amount = input("Deal how much damage to mob? (Negative values here heal)","Adjust [Text]loss",0) as num|null
|
||||
|
||||
if (isnull(amount))
|
||||
return
|
||||
|
||||
if(!L)
|
||||
to_chat(usr, "Mob doesn't exist anymore", confidential = TRUE)
|
||||
return
|
||||
|
||||
var/newamt
|
||||
switch(Text)
|
||||
if("brute")
|
||||
L.adjustBruteLoss(amount)
|
||||
newamt = L.getBruteLoss()
|
||||
if("fire")
|
||||
L.adjustFireLoss(amount)
|
||||
newamt = L.getFireLoss()
|
||||
if("toxin")
|
||||
L.adjustToxLoss(amount)
|
||||
newamt = L.getToxLoss()
|
||||
if("oxygen")
|
||||
L.adjustOxyLoss(amount)
|
||||
newamt = L.getOxyLoss()
|
||||
if("brain")
|
||||
L.adjustOrganLoss(ORGAN_SLOT_BRAIN, amount)
|
||||
newamt = L.getOrganLoss(ORGAN_SLOT_BRAIN)
|
||||
if("clone")
|
||||
L.adjustCloneLoss(amount)
|
||||
newamt = L.getCloneLoss()
|
||||
if("stamina")
|
||||
L.adjustStaminaLoss(amount)
|
||||
newamt = L.getStaminaLoss()
|
||||
else
|
||||
to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]", confidential = TRUE)
|
||||
return
|
||||
|
||||
if(amount != 0)
|
||||
var/log_msg = "[key_name(usr)] dealt [amount] amount of [Text] damage to [key_name(L)]"
|
||||
message_admins("[key_name(usr)] dealt [amount] amount of [Text] damage to [ADMIN_LOOKUPFLW(L)]")
|
||||
log_admin(log_msg)
|
||||
admin_ticket_log(L, "<font color='blue'>[log_msg]</font>")
|
||||
vv_update_display(L, Text, "[newamt]")
|
||||
|
||||
|
||||
//Finally, refresh if something modified the list.
|
||||
if(href_list["datumrefresh"])
|
||||
var/datum/DAT = locate(href_list["datumrefresh"])
|
||||
if(istype(DAT, /datum) || istype(DAT, /client) || islist(DAT))
|
||||
debug_variables(DAT)
|
||||
54
code/modules/admin/view_variables/topic_basic.dm
Normal file
@@ -0,0 +1,54 @@
|
||||
//Not using datum.vv_do_topic for very basic/low level debug things, incase the datum's vv_do_topic is runtiming/whatnot.
|
||||
/client/proc/vv_do_basic(datum/target, href_list)
|
||||
var/target_var = GET_VV_VAR_TARGET
|
||||
if(check_rights(R_VAREDIT))
|
||||
if(target_var)
|
||||
if(href_list[VV_HK_BASIC_EDIT])
|
||||
if(!modify_variables(target, target_var, 1))
|
||||
return
|
||||
switch(target_var)
|
||||
if("name")
|
||||
vv_update_display(target, "name", "[target]")
|
||||
if("dir")
|
||||
var/atom/A = target
|
||||
if(istype(A))
|
||||
vv_update_display(target, "dir", dir2text(A.dir) || A.dir)
|
||||
if("ckey")
|
||||
var/mob/living/L = target
|
||||
if(istype(L))
|
||||
vv_update_display(target, "ckey", L.ckey || "No ckey")
|
||||
if("real_name")
|
||||
var/mob/living/L = target
|
||||
if(istype(L))
|
||||
vv_update_display(target, "real_name", L.real_name || "No real name")
|
||||
|
||||
if(href_list[VV_HK_BASIC_CHANGE])
|
||||
modify_variables(target, target_var, 0)
|
||||
if(href_list[VV_HK_BASIC_MASSEDIT])
|
||||
cmd_mass_modify_object_variables(target, target_var)
|
||||
if(check_rights(R_ADMIN, FALSE))
|
||||
if(href_list[VV_HK_EXPOSE])
|
||||
var/value = vv_get_value(VV_CLIENT)
|
||||
if (value["class"] != VV_CLIENT)
|
||||
return
|
||||
var/client/C = value["value"]
|
||||
if (!C)
|
||||
return
|
||||
if(!target)
|
||||
to_chat(usr, span_warning("The object you tried to expose to [C] no longer exists (nulled or hard-deled)"), confidential = TRUE)
|
||||
return
|
||||
message_admins("[key_name_admin(usr)] Showed [key_name_admin(C)] a <a href='?_src_=vars;datumrefresh=[REF(target)]'>VV window</a>")
|
||||
log_admin("Admin [key_name(usr)] Showed [key_name(C)] a VV window of a [target]")
|
||||
to_chat(C, "[holder.fakekey ? "an Administrator" : "[usr.client.key]"] has granted you access to view a View Variables window", confidential = TRUE)
|
||||
C.debug_variables(target)
|
||||
if(check_rights(R_DEBUG))
|
||||
if(href_list[VV_HK_DELETE])
|
||||
usr.client.admin_delete(target)
|
||||
if (isturf(target)) // show the turf that took its place
|
||||
usr.client.debug_variables(target)
|
||||
return
|
||||
|
||||
if(href_list[VV_HK_MARK])
|
||||
usr.client.mark_datum(target)
|
||||
if(href_list[VV_HK_CALLPROC])
|
||||
usr.client.callproc_datum(target)
|
||||
43
code/modules/admin/view_variables/topic_list.dm
Normal file
@@ -0,0 +1,43 @@
|
||||
//LISTS - CAN NOT DO VV_DO_TOPIC BECAUSE LISTS AREN'T DATUMS :(
|
||||
/client/proc/vv_do_list(list/target, href_list)
|
||||
var/target_index = text2num(GET_VV_VAR_TARGET)
|
||||
if(check_rights(R_VAREDIT))
|
||||
if(target_index)
|
||||
if(href_list[VV_HK_LIST_EDIT])
|
||||
mod_list(target, null, "list", "contents", target_index, autodetect_class = TRUE)
|
||||
if(href_list[VV_HK_LIST_CHANGE])
|
||||
mod_list(target, null, "list", "contents", target_index, autodetect_class = FALSE)
|
||||
if(href_list[VV_HK_LIST_REMOVE])
|
||||
var/variable = target[target_index]
|
||||
var/prompt = alert(usr,"Do you want to remove item number [target_index] from list?", "Confirm", list("Yes", "No"))
|
||||
if (prompt != "Yes")
|
||||
return
|
||||
target.Cut(target_index, target_index+1)
|
||||
log_world("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]")
|
||||
log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]")
|
||||
if(href_list[VV_HK_LIST_ADD])
|
||||
mod_list_add(target, null, "list", "contents")
|
||||
if(href_list[VV_HK_LIST_ERASE_DUPES])
|
||||
uniqueList_inplace(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: CLEAR DUPES")
|
||||
log_admin("[key_name(src)] modified list's contents: CLEAR DUPES")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES")
|
||||
if(href_list[VV_HK_LIST_ERASE_NULLS])
|
||||
listclearnulls(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: CLEAR NULLS")
|
||||
log_admin("[key_name(src)] modified list's contents: CLEAR NULLS")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS")
|
||||
if(href_list[VV_HK_LIST_SET_LENGTH])
|
||||
var/value = vv_get_value(VV_NUM)
|
||||
if (value["class"] != VV_NUM || value["value"] > max(50000, target.len)) //safety - would rather someone not put an extra 0 and erase the server's memory lmao.
|
||||
return
|
||||
target.len = value["value"]
|
||||
log_world("### ListVarEdit by [src]: /list len: [target.len]")
|
||||
log_admin("[key_name(src)] modified list's len: [target.len]")
|
||||
message_admins("[key_name_admin(src)] modified list's len: [target.len]")
|
||||
if(href_list[VV_HK_LIST_SHUFFLE])
|
||||
shuffle_inplace(target)
|
||||
log_world("### ListVarEdit by [src]: /list contents: SHUFFLE")
|
||||
log_admin("[key_name(src)] modified list's contents: SHUFFLE")
|
||||
message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE")
|
||||
375
code/modules/admin/view_variables/view_variables.dm
Normal file
@@ -0,0 +1,375 @@
|
||||
/client/proc/debug_variables(datum/D in world)
|
||||
set category = "Misc.Server Debug"
|
||||
set name = "View Variables"
|
||||
//set src in world
|
||||
var/static/cookieoffset = rand(1, 9999) //to force cookies to reset after the round.
|
||||
|
||||
if(!usr.client || !usr.client.holder) //The usr vs src abuse in this proc is intentional and must not be changed
|
||||
to_chat(usr, span_danger("You need to be an administrator to access this."), confidential = TRUE)
|
||||
return
|
||||
|
||||
if(!D)
|
||||
return
|
||||
|
||||
var/islist = islist(D)
|
||||
var/isappearance = isappearance(D)
|
||||
if (!islist && !istype(D) && !isappearance)
|
||||
return
|
||||
|
||||
var/title = ""
|
||||
var/refid = REF(D)
|
||||
var/icon/sprite
|
||||
var/hash
|
||||
|
||||
var/type = /list
|
||||
if (isappearance)
|
||||
type = /image
|
||||
else if (!islist)
|
||||
type = D.type
|
||||
|
||||
|
||||
|
||||
if(istype(D, /atom) || isappearance)
|
||||
var/atom/AT = D
|
||||
if(AT.icon && AT.icon_state)
|
||||
sprite = new /icon(AT.icon, AT.icon_state)
|
||||
hash = md5(AT.icon)
|
||||
hash = md5(hash + AT.icon_state)
|
||||
src << browse_rsc(sprite, "vv[hash].png")
|
||||
|
||||
title = "[D] ([REF(D)]) = [type]"
|
||||
var/formatted_type = replacetext("[type]", "/", "<wbr>/")
|
||||
|
||||
var/sprite_text
|
||||
if(sprite)
|
||||
sprite_text = "<img src='vv[hash].png'></td><td>"
|
||||
var/list/header = islist(D)? list("<b>/list</b>") : D.vv_get_header()
|
||||
|
||||
var/marked_line
|
||||
if(holder && holder.marked_datum && holder.marked_datum == D)
|
||||
marked_line = VV_MSG_MARKED
|
||||
var/varedited_line
|
||||
if(!isappearance && !islist && (D.datum_flags & DF_VAR_EDITED))
|
||||
varedited_line = VV_MSG_EDITED
|
||||
var/deleted_line
|
||||
if(!isappearance && !islist && D.gc_destroyed)
|
||||
deleted_line = VV_MSG_DELETED
|
||||
|
||||
var/list/dropdownoptions = list()
|
||||
if (islist)
|
||||
dropdownoptions = list(
|
||||
"---",
|
||||
"Add Item" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_ADD),
|
||||
"Remove Nulls" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_ERASE_NULLS),
|
||||
"Remove Dupes" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_ERASE_DUPES),
|
||||
"Set len" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SET_LENGTH),
|
||||
"Shuffle" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_LIST_SHUFFLE),
|
||||
"Show VV To Player" = VV_HREF_TARGETREF_INTERNAL(refid, VV_HK_EXPOSE),
|
||||
"---"
|
||||
)
|
||||
for(var/i in 1 to length(dropdownoptions))
|
||||
var/name = dropdownoptions[i]
|
||||
var/link = dropdownoptions[name]
|
||||
dropdownoptions[i] = "<option value[link? "='[link]'":""]>[name]</option>"
|
||||
else if (!isappearance)
|
||||
dropdownoptions = D.vv_get_dropdown()
|
||||
|
||||
var/list/names = list()
|
||||
if (!islist && !isappearance)
|
||||
for (var/V in D.vars)
|
||||
names += V
|
||||
sleep(1)//For some reason, without this sleep, VVing will cause client to disconnect on certain objects.
|
||||
|
||||
var/list/variable_html = list()
|
||||
if (islist)
|
||||
var/list/L = D
|
||||
for (var/i in 1 to L.len)
|
||||
var/key = L[i]
|
||||
var/value
|
||||
if (IS_NORMAL_LIST(L) && !isnum(key))
|
||||
value = L[key]
|
||||
variable_html += debug_variable(i, value, 0, D)
|
||||
else if(isappearance(D))
|
||||
variable_html += debug_variable("type", D:type, 0, D)
|
||||
variable_html += debug_variable("name", D:name, 0, D)
|
||||
variable_html += debug_variable("desc", D:desc, 0, D)
|
||||
variable_html += debug_variable("suffix", D:suffix, 0, D)
|
||||
variable_html += debug_variable("text", D:text, 0, D)
|
||||
variable_html += debug_variable("icon", D:icon, 0, D)
|
||||
variable_html += debug_variable("icon_state", D:icon_state, 0, D)
|
||||
variable_html += debug_variable("visibility", D:visibility, 0, D)
|
||||
variable_html += debug_variable("luminosity", D:luminosity, 0, D)
|
||||
variable_html += debug_variable("opacity", D:opacity, 0, D)
|
||||
variable_html += debug_variable("density", D:density, 0, D)
|
||||
variable_html += debug_variable("verbs", D:verbs, 0, D)
|
||||
variable_html += debug_variable("dir", D:dir, 0, D)
|
||||
variable_html += debug_variable("gender", D:gender, 0, D)
|
||||
variable_html += debug_variable("tag", D:tag, 0, D)
|
||||
variable_html += debug_variable("overlays", D:overlays, 0, D)
|
||||
variable_html += debug_variable("underlays", D:underlays, 0, D)
|
||||
variable_html += debug_variable("layer", D:layer, 0, D)
|
||||
variable_html += debug_variable("parent_type", D:parent_type, 0, D)
|
||||
variable_html += debug_variable("mouse_over_pointer", D:mouse_over_pointer, 0, D)
|
||||
variable_html += debug_variable("mouse_drag_pointer", D:mouse_drag_pointer, 0, D)
|
||||
variable_html += debug_variable("mouse_drop_pointer", D:mouse_drop_pointer, 0, D)
|
||||
variable_html += debug_variable("mouse_drop_zone", D:mouse_drop_zone, 0, D)
|
||||
variable_html += debug_variable("animate_movement", D:animate_movement, 0, D)
|
||||
variable_html += debug_variable("screen_loc", D:screen_loc, 0, D)
|
||||
variable_html += debug_variable("infra_luminosity", D:infra_luminosity, 0, D)
|
||||
variable_html += debug_variable("invisibility", D:invisibility, 0, D)
|
||||
variable_html += debug_variable("mouse_opacity", D:mouse_opacity, 0, D)
|
||||
variable_html += debug_variable("pixel_x", D:pixel_x, 0, D)
|
||||
variable_html += debug_variable("pixel_y", D:pixel_y, 0, D)
|
||||
variable_html += debug_variable("pixel_step_size", D:pixel_step_size, 0, D)
|
||||
variable_html += debug_variable("pixel_z", D:pixel_z, 0, D)
|
||||
variable_html += debug_variable("override", D:override, 0, D)
|
||||
variable_html += debug_variable("glide_size", D:glide_size, 0, D)
|
||||
variable_html += debug_variable("maptext", D:maptext, 0, D)
|
||||
variable_html += debug_variable("maptext_width", D:maptext_width, 0, D)
|
||||
variable_html += debug_variable("maptext_height", D:maptext_height, 0, D)
|
||||
variable_html += debug_variable("transform", D:transform, 0, D)
|
||||
variable_html += debug_variable("alpha", D:alpha, 0, D)
|
||||
variable_html += debug_variable("color", D:color, 0, D)
|
||||
variable_html += debug_variable("blend_mode", D:blend_mode, 0, D)
|
||||
variable_html += debug_variable("appearance", D:appearance, 0, D)
|
||||
variable_html += debug_variable("maptext_x", D:maptext_x, 0, D)
|
||||
variable_html += debug_variable("maptext_y", D:maptext_y, 0, D)
|
||||
variable_html += debug_variable("plane", D:plane, 0, D)
|
||||
variable_html += debug_variable("appearance_flags", D:appearance_flags, 0, D)
|
||||
variable_html += debug_variable("pixel_w", D:pixel_w, 0, D)
|
||||
variable_html += debug_variable("render_source", D:render_source, 0, D)
|
||||
variable_html += debug_variable("render_target", D:render_target, 0, D)
|
||||
else
|
||||
names = sortList(names)
|
||||
for (var/V in names)
|
||||
if(D.can_vv_get(V))
|
||||
variable_html += D.vv_get_var(V)
|
||||
|
||||
var/html = {"
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<title>[title]</title>
|
||||
<link rel="stylesheet" type="text/css" href="view_variables.css">
|
||||
</head>
|
||||
<body onload='selectTextField()' onkeydown='return handle_keydown()' onkeyup='handle_keyup()'>
|
||||
<script type="text/javascript">
|
||||
// onload
|
||||
function selectTextField() {
|
||||
var filter_text = document.getElementById('filter');
|
||||
filter_text.focus();
|
||||
filter_text.select();
|
||||
var lastsearch = getCookie("[refid][cookieoffset]search");
|
||||
if (lastsearch) {
|
||||
filter_text.value = lastsearch;
|
||||
updateSearch();
|
||||
}
|
||||
}
|
||||
function getCookie(cname) {
|
||||
var name = cname + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0; i<ca.length; i++) {
|
||||
var c = ca\[i];
|
||||
while (c.charAt(0)==' ') c = c.substring(1,c.length);
|
||||
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// main search functionality
|
||||
var last_filter = "";
|
||||
function updateSearch() {
|
||||
var filter = document.getElementById('filter').value.toLowerCase();
|
||||
var vars_ol = document.getElementById("vars");
|
||||
|
||||
if (filter === last_filter) {
|
||||
// An event triggered an update but nothing has changed.
|
||||
return;
|
||||
} else if (filter.indexOf(last_filter) === 0) {
|
||||
// The new filter starts with the old filter, fast path by removing only.
|
||||
var children = vars_ol.childNodes;
|
||||
for (var i = children.length - 1; i >= 0; --i) {
|
||||
try {
|
||||
var li = children\[i];
|
||||
if (li.innerText.toLowerCase().indexOf(filter) == -1) {
|
||||
vars_ol.removeChild(li);
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
} else {
|
||||
// Remove everything and put back what matches.
|
||||
while (vars_ol.hasChildNodes()) {
|
||||
vars_ol.removeChild(vars_ol.lastChild);
|
||||
}
|
||||
|
||||
for (var i = 0; i < complete_list.length; ++i) {
|
||||
try {
|
||||
var li = complete_list\[i];
|
||||
if (!filter || li.innerText.toLowerCase().indexOf(filter) != -1) {
|
||||
vars_ol.appendChild(li);
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
}
|
||||
|
||||
last_filter = filter;
|
||||
document.cookie="[refid][cookieoffset]search="+encodeURIComponent(filter);
|
||||
|
||||
var lis_new = vars_ol.getElementsByTagName("li");
|
||||
for (var j = 0; j < lis_new.length; ++j) {
|
||||
lis_new\[j].style.backgroundColor = (j == 0) ? "#ffee88" : "white";
|
||||
}
|
||||
}
|
||||
|
||||
// onkeydown
|
||||
function handle_keydown() {
|
||||
if(event.keyCode == 116) { //F5 (to refresh properly)
|
||||
document.getElementById("refresh_link").click();
|
||||
event.preventDefault ? event.preventDefault() : (event.returnValue = false);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// onkeyup
|
||||
function handle_keyup() {
|
||||
if (event.keyCode == 13) { //Enter / return
|
||||
var vars_ol = document.getElementById('vars');
|
||||
var lis = vars_ol.getElementsByTagName("li");
|
||||
for (var i = 0; i < lis.length; ++i) {
|
||||
try {
|
||||
var li = lis\[i];
|
||||
if (li.style.backgroundColor == "#ffee88") {
|
||||
alist = lis\[i].getElementsByTagName("a");
|
||||
if(alist.length > 0) {
|
||||
location.href=alist\[0].href;
|
||||
}
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
} else if(event.keyCode == 38){ //Up arrow
|
||||
var vars_ol = document.getElementById('vars');
|
||||
var lis = vars_ol.getElementsByTagName("li");
|
||||
for (var i = 0; i < lis.length; ++i) {
|
||||
try {
|
||||
var li = lis\[i];
|
||||
if (li.style.backgroundColor == "#ffee88") {
|
||||
if (i > 0) {
|
||||
var li_new = lis\[i-1];
|
||||
li.style.backgroundColor = "white";
|
||||
li_new.style.backgroundColor = "#ffee88";
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
} else if(event.keyCode == 40) { //Down arrow
|
||||
var vars_ol = document.getElementById('vars');
|
||||
var lis = vars_ol.getElementsByTagName("li");
|
||||
for (var i = 0; i < lis.length; ++i) {
|
||||
try {
|
||||
var li = lis\[i];
|
||||
if (li.style.backgroundColor == "#ffee88") {
|
||||
if ((i+1) < lis.length) {
|
||||
var li_new = lis\[i+1];
|
||||
li.style.backgroundColor = "white";
|
||||
li_new.style.backgroundColor = "#ffee88";
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch(err) {}
|
||||
}
|
||||
} else {
|
||||
updateSearch();
|
||||
}
|
||||
}
|
||||
|
||||
// onchange
|
||||
function handle_dropdown(list) {
|
||||
var value = list.options\[list.selectedIndex].value;
|
||||
if (value !== "") {
|
||||
location.href = value;
|
||||
}
|
||||
list.selectedIndex = 0;
|
||||
document.getElementById('filter').focus();
|
||||
}
|
||||
|
||||
// byjax
|
||||
function replace_span(what) {
|
||||
var idx = what.indexOf(':');
|
||||
document.getElementById(what.substr(0, idx)).innerHTML = what.substr(idx + 1);
|
||||
}
|
||||
</script>
|
||||
<div align='center'>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='50%'>
|
||||
<table align='center' width='100%'>
|
||||
<tr>
|
||||
<td>
|
||||
[sprite_text]
|
||||
<div align='center'>
|
||||
[header.Join()]
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div align='center'>
|
||||
<b><font size='1'>[formatted_type]</font></b>
|
||||
<span id='marked'>[marked_line]</span>
|
||||
<span id='varedited'>[varedited_line]</span>
|
||||
<span id='deleted'>[deleted_line]</span>
|
||||
</div>
|
||||
</td>
|
||||
<td width='50%'>
|
||||
<div align='center'>
|
||||
<a id='refresh_link' href='?_src_=vars;[HrefToken()];datumrefresh=[refid]'>Refresh</a>
|
||||
<form>
|
||||
<select name="file" size="1"
|
||||
onchange="handle_dropdown(this)"
|
||||
onmouseclick="this.focus()"
|
||||
style="background-color:#ffffff">
|
||||
<option value selected>Select option</option>
|
||||
[dropdownoptions.Join()]
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<hr>
|
||||
<font size='1'>
|
||||
<b>E</b> - Edit, tries to determine the variable type by itself.<br>
|
||||
<b>C</b> - Change, asks you for the var type first.<br>
|
||||
<b>M</b> - Mass modify: changes this variable for all objects of this type.<br>
|
||||
</font>
|
||||
<hr>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='20%'>
|
||||
<div align='center'>
|
||||
<b>Search:</b>
|
||||
</div>
|
||||
</td>
|
||||
<td width='80%'>
|
||||
<input type='text' id='filter' name='filter_text' value='' style='width:100%;'>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr>
|
||||
<ol id='vars'>
|
||||
[variable_html.Join()]
|
||||
</ol>
|
||||
<script type='text/javascript'>
|
||||
var complete_list = \[\];
|
||||
var lis = document.getElementById("vars").children;
|
||||
for(var i = lis.length; i--;) complete_list\[i\] = lis\[i\];
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
"}
|
||||
src << browse(html, "window=variables[refid];size=475x650")
|
||||
|
||||
/client/proc/vv_update_display(datum/D, span, content)
|
||||
src << output("[span]:[content]", "variables[REF(D)].browser:replace_span")
|
||||
@@ -15,8 +15,11 @@
|
||||
maxbodytemp = 360
|
||||
unique_name = 1
|
||||
a_intent = INTENT_HARM
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
var/mob/camera/blob/overmind = null
|
||||
var/obj/structure/blob/factory/factory = null
|
||||
var/independent = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/update_icons()
|
||||
if(overmind)
|
||||
@@ -24,6 +27,13 @@
|
||||
else
|
||||
remove_atom_colour(FIXED_COLOUR_PRIORITY)
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/Initialize()
|
||||
. = ..()
|
||||
if(!independent) //no pulling people deep into the blob
|
||||
verbs -= /mob/living/verb/pulled
|
||||
else
|
||||
pass_flags &= ~PASSBLOB
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/Destroy()
|
||||
if(overmind)
|
||||
@@ -90,18 +100,20 @@
|
||||
attacktext = "hits"
|
||||
attack_sound = 'sound/weapons/genhit1.ogg'
|
||||
movement_type = FLYING
|
||||
del_on_death = 1
|
||||
del_on_death = TRUE
|
||||
deathmessage = "explodes into a cloud of gas!"
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
var/death_cloud_size = 1 //size of cloud produced from a dying spore
|
||||
var/mob/living/carbon/human/oldguy
|
||||
var/is_zombie = 0
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
var/is_zombie = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/Initialize(mapload, var/obj/structure/blob/factory/linked_node)
|
||||
if(istype(linked_node))
|
||||
factory = linked_node
|
||||
factory.spores += src
|
||||
. = ..()
|
||||
if(linked_node.overmind && istype(linked_node.overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons) && !istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak))
|
||||
notify_ghosts("A controllable spore has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Sentient Spore Created")
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/Life()
|
||||
if(!is_zombie && isturf(src.loc))
|
||||
@@ -113,6 +125,26 @@
|
||||
death()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/attack_ghost(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
humanize_pod(user)
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/proc/humanize_pod(mob/user)
|
||||
if((!overmind || istype(src, /mob/living/simple_animal/hostile/blob/blobspore/weak) || !istype(overmind.blobstrain, /datum/blobstrain/reagent/distributed_neurons)) && !is_zombie)
|
||||
return
|
||||
if(key || stat)
|
||||
return
|
||||
var/pod_ask = alert("Become a blob spore?", "Are you bulbous enough?", "Yes", "No")
|
||||
if(pod_ask == "No" || !src || QDELETED(src))
|
||||
return
|
||||
if(key)
|
||||
to_chat(user, "<span class='warning'>Someone else already took this spore!</span>")
|
||||
return
|
||||
key = user.key
|
||||
log_game("[key_name(src)] took control of [name].")
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/proc/Zombify(mob/living/carbon/human/H)
|
||||
is_zombie = 1
|
||||
if(H.wear_suit)
|
||||
@@ -135,6 +167,8 @@
|
||||
oldguy = H
|
||||
update_icons()
|
||||
visible_message(span_warning("The corpse of [H.name] suddenly rises!"))
|
||||
if(!key)
|
||||
notify_ghosts("\A [src] has been created in \the [get_area(src)].", source = src, action = NOTIFY_ORBIT, flashwindow = FALSE, header = "Blob Zombie Created")
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
|
||||
// On death, create a small smoke of harmful gas (s-Acid)
|
||||
@@ -215,17 +249,7 @@
|
||||
force_threshold = 10
|
||||
pressure_resistance = 50
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
see_in_dark = 8
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
hud_type = /datum/hud/blobbernaut
|
||||
var/independent = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Initialize()
|
||||
. = ..()
|
||||
if(!independent) //no pulling people deep into the blob
|
||||
remove_verb(src, /mob/living/verb/pulled)
|
||||
else
|
||||
pass_flags &= ~PASSBLOB
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobbernaut/Life()
|
||||
if(..())
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/datum/blobstrain/reagent/distributed_neurons
|
||||
name = "Distributed Neurons"
|
||||
description = "will do very low toxin damage and turns unconscious targets into blob zombies."
|
||||
effectdesc = "will also produce fragile spores when killed. Spores produced by factories are sentient."
|
||||
shortdesc = "will do very low toxin damage and will turn unconscious targets into blob zombies for additional resources(for your overmind). Spores produced by factories are sentient."
|
||||
analyzerdescdamage = "Does very low toxin damage and kills unconscious humans, turning them into blob zombies."
|
||||
analyzerdesceffect = "Produces spores when killed. Spores produced by factories are sentient."
|
||||
color = "#E88D5D"
|
||||
complementary_color = "#823ABB"
|
||||
message_living = ", and you feel tired"
|
||||
reagent = /datum/reagent/blob/distributed_neurons
|
||||
|
||||
/datum/blobstrain/reagent/distributed_neurons/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
|
||||
if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage <= 20 && B.obj_integrity - damage <= 0 && prob(15)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 15% chance of a shitty spore.
|
||||
B.visible_message("<span class='warning'><b>A spore floats free of the blob!</b></span>")
|
||||
var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(B.loc)
|
||||
BS.overmind = B.overmind
|
||||
BS.update_icons()
|
||||
B.overmind.blob_mobs.Add(BS)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/blob/distributed_neurons
|
||||
name = "Distributed Neurons"
|
||||
color = "#E88D5D"
|
||||
|
||||
/datum/reagent/blob/distributed_neurons/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
|
||||
reac_volume = ..()
|
||||
M.apply_damage(0.6*reac_volume, TOX)
|
||||
if(O && ishuman(M) && M.stat == UNCONSCIOUS)
|
||||
M.death() //sleeping in a fight? bad plan.
|
||||
var/points = rand(5, 10)
|
||||
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(get_turf(M))
|
||||
BS.overmind = O
|
||||
BS.update_icons()
|
||||
O.blob_mobs.Add(BS)
|
||||
BS.Zombify(M)
|
||||
O.add_points(points)
|
||||
to_chat(O, "<span class='notice'>Gained [points] resources from the zombification of [M].</span>")
|
||||
@@ -1,7 +1,7 @@
|
||||
//does massive brute and burn damage, but can only expand manually
|
||||
/datum/blobstrain/reagent/networked_fibers
|
||||
name = "Networked Fibers"
|
||||
description = "will do high brute and burn damage and will generate resources quicker, but can only expand manually."
|
||||
description = "will do high brute and burn damage and will generate resources quicker, but can only expand manually using the core."
|
||||
shortdesc = "will do high brute and burn damage."
|
||||
effectdesc = "will move your core when manually expanding near it."
|
||||
analyzerdescdamage = "Does high brute and burn damage."
|
||||
@@ -9,6 +9,9 @@
|
||||
color = "#CDC0B0"
|
||||
complementary_color = "#FFF68F"
|
||||
reagent = /datum/reagent/blob/networked_fibers
|
||||
core_regen = 5
|
||||
point_rate = 3
|
||||
|
||||
|
||||
/datum/blobstrain/reagent/networked_fibers/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
|
||||
if(!O && newB.overmind)
|
||||
@@ -24,6 +27,9 @@
|
||||
C.forceMove(T)
|
||||
C.setDir(get_dir(newB, C))
|
||||
O.add_points(1)
|
||||
return
|
||||
O.add_points(4)
|
||||
qdel(newB)
|
||||
|
||||
//does massive brute and burn damage, but can only expand manually
|
||||
/datum/reagent/blob/networked_fibers
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
//kills sleeping targets and turns them into blob zombies, produces fragile spores when killed or on expanding
|
||||
/datum/blobstrain/reagent/zombifying_pods
|
||||
name = "Zombifying Pods"
|
||||
description = "will do very low toxin damage and harvest sleeping targets for additional resources and a blob zombie."
|
||||
effectdesc = "will also produce fragile spores when killed and on expanding."
|
||||
shortdesc = "will do very low toxin damage and harvest sleeping targets for additional resources(for your overmind) and a blob zombie."
|
||||
analyzerdescdamage = "Does very low toxin damage and kills unconscious humans, turning them into blob zombies."
|
||||
analyzerdesceffect = "Produces spores when expanding and when killed."
|
||||
color = "#E88D5D"
|
||||
complementary_color = "#823ABB"
|
||||
message_living = ", and you feel tired"
|
||||
reagent = /datum/reagent/blob/zombifying_pods
|
||||
|
||||
/datum/blobstrain/reagent/zombifying_pods/damage_reaction(obj/structure/blob/B, damage, damage_type, damage_flag)
|
||||
if((damage_flag == "melee" || damage_flag == "bullet" || damage_flag == "laser") && damage <= 20 && B.obj_integrity - damage <= 0 && prob(30)) //if the cause isn't fire or a bomb, the damage is less than 21, we're going to die from that damage, 20% chance of a shitty spore.
|
||||
B.visible_message(span_warning("<b>A spore floats free of the blob!</b>"))
|
||||
var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(B.loc)
|
||||
BS.overmind = B.overmind
|
||||
BS.update_icons()
|
||||
B.overmind.blob_mobs.Add(BS)
|
||||
return ..()
|
||||
|
||||
/datum/blobstrain/reagent/zombifying_pods/expand_reaction(obj/structure/blob/B, obj/structure/blob/newB, turf/T, mob/camera/blob/O)
|
||||
if(prob(10))
|
||||
var/mob/living/simple_animal/hostile/blob/blobspore/weak/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(T)
|
||||
BS.overmind = B.overmind
|
||||
BS.update_icons()
|
||||
newB.overmind.blob_mobs.Add(BS)
|
||||
|
||||
/datum/reagent/blob/zombifying_pods
|
||||
name = "Zombifying Pods"
|
||||
color = "#E88D5D"
|
||||
|
||||
/datum/reagent/blob/zombifying_pods/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message, touch_protection, mob/camera/blob/O)
|
||||
reac_volume = ..()
|
||||
M.apply_damage(0.6*reac_volume, TOX)
|
||||
if(O && ishuman(M) && M.stat == UNCONSCIOUS)
|
||||
M.death() //sleeping in a fight? bad plan.
|
||||
var/points = rand(5, 10)
|
||||
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore/weak(get_turf(M))
|
||||
BS.overmind = O
|
||||
BS.update_icons()
|
||||
O.blob_mobs.Add(BS)
|
||||
BS.Zombify(M)
|
||||
O.add_points(points)
|
||||
to_chat(O, span_notice("Gained [points] resources from the zombification of [M]."))
|
||||
@@ -39,6 +39,9 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
var/blobwincount = 400
|
||||
var/victory_in_progress = FALSE
|
||||
var/rerolling = FALSE
|
||||
var/announcement_size = 75
|
||||
var/announcement_time
|
||||
var/has_announced = FALSE
|
||||
|
||||
/mob/camera/blob/Initialize(mapload, starting_points = 60)
|
||||
validate_location()
|
||||
@@ -56,6 +59,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
if(blob_core)
|
||||
blob_core.update_icon()
|
||||
SSshuttle.registerHostileEnvironment(src)
|
||||
announcement_time = world.time + 6000
|
||||
. = ..()
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
@@ -109,7 +113,7 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
priority_announce("Biohazard has reached critical mass. Station loss is imminent.", "Biohazard Alert")
|
||||
set_security_level("delta")
|
||||
max_blob_points = INFINITY
|
||||
blob_points = INFINITY
|
||||
blob_points = INFINITY
|
||||
addtimer(CALLBACK(src, .proc/victory), 450)
|
||||
else if(!free_strain_rerolls && (last_reroll_time + BLOB_REROLL_TIME<world.time))
|
||||
to_chat(src, "<b><span class='big'><font color=\"#EE4000\">You have gained another free strain re-roll.</font></span></b>")
|
||||
@@ -118,6 +122,10 @@ GLOBAL_LIST_EMPTY(blob_nodes)
|
||||
if(!victory_in_progress && max_count < blobs_legit.len)
|
||||
max_count = blobs_legit.len
|
||||
|
||||
if((world.time >= announcement_time || blobs_legit.len >= announcement_size) && !has_announced)
|
||||
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", 'sound/ai/default/outbreak5.ogg')
|
||||
has_announced = TRUE
|
||||
|
||||
/mob/camera/blob/proc/victory()
|
||||
sound_to_playing_players('sound/machines/alarm.ogg')
|
||||
sleep(100)
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
if(!surrounding_turfs.len)
|
||||
return
|
||||
for(var/mob/living/simple_animal/hostile/blob/blobspore/BS in blob_mobs)
|
||||
if(isturf(BS.loc) && get_dist(BS, T) <= 35)
|
||||
if(isturf(BS.loc) && get_dist(BS, T) <= 35 && !BS.key)
|
||||
BS.LoseTarget()
|
||||
BS.Goto(pick(surrounding_turfs), BS.move_to_delay)
|
||||
|
||||
|
||||
@@ -19,12 +19,8 @@
|
||||
return INITIALIZE_HINT_QDEL
|
||||
if(overmind)
|
||||
update_icon()
|
||||
addtimer(CALLBACK(src, .proc/generate_announcement), 1800)
|
||||
. = ..()
|
||||
|
||||
/obj/structure/blob/core/proc/generate_announcement()
|
||||
priority_announce("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", ANNOUNCER_OUTBREAK5)
|
||||
|
||||
/obj/structure/blob/core/scannerreport()
|
||||
return "Directs the blob's expansion, gradually expands, and sustains nearby blob spores and blobbernauts."
|
||||
|
||||
|
||||
@@ -89,6 +89,29 @@
|
||||
message_admins("[key_name_admin(admin)] made [key_name_admin(new_owner)] and [key_name_admin(bro)] into blood brothers.")
|
||||
log_admin("[key_name(admin)] made [key_name(new_owner)] and [key_name(bro)] into blood brothers.")
|
||||
|
||||
/datum/antagonist/brother/get_admin_commands()
|
||||
. = ..()
|
||||
.["Convert To Traitor"] = CALLBACK(src, .proc/make_traitor)
|
||||
|
||||
/datum/antagonist/brother/proc/make_traitor()
|
||||
if(alert("Are you sure? This will turn the blood brother into a traitor with the same objectives!",,"Yes","No") != "Yes")
|
||||
return
|
||||
|
||||
var/datum/antagonist/traitor/tot = new()
|
||||
tot.give_objectives = FALSE
|
||||
|
||||
for(var/datum/objective/obj in objectives)
|
||||
var/obj_type = obj.type
|
||||
var/datum/objective/new_obj = new obj_type()
|
||||
new_obj.owner = owner
|
||||
new_obj.copy_target(obj)
|
||||
tot.add_objective(new_obj)
|
||||
qdel(obj)
|
||||
objectives.Cut()
|
||||
|
||||
owner.add_antag_datum(tot)
|
||||
owner.remove_antag_datum(/datum/antagonist/brother)
|
||||
|
||||
/datum/antagonist/brother/proc/give_pinpointer()
|
||||
if(owner && owner.current)
|
||||
var/datum/status_effect/agent_pinpointer/brother/P = owner.current.apply_status_effect(/datum/status_effect/agent_pinpointer/brother)
|
||||
|
||||
@@ -6,6 +6,7 @@ is currently following.
|
||||
|
||||
GLOBAL_LIST_INIT(disease_ability_singletons, list(
|
||||
new /datum/disease_ability/action/cough,
|
||||
new /datum/disease_ability/symptom/mild/sentient,
|
||||
new /datum/disease_ability/action/sneeze,
|
||||
new /datum/disease_ability/action/infect,
|
||||
new /datum/disease_ability/symptom/mild/cough,
|
||||
@@ -267,6 +268,7 @@ new /datum/disease_ability/symptom/powerful/heal/youth
|
||||
StartCooldown()
|
||||
return TRUE
|
||||
|
||||
|
||||
/*******************BASE SYMPTOM TYPES*******************/
|
||||
// cost is for convenience and can be changed. If you're changing req_tot_points then don't use the subtype...
|
||||
//healing costs more so you have to techswitch from naughty disease otherwise we'd have friendly disease for easy greentext (no fun!)
|
||||
@@ -296,6 +298,29 @@ new /datum/disease_ability/symptom/powerful/heal/youth
|
||||
|
||||
|
||||
/******MILD******/
|
||||
/datum/disease_ability/symptom/mild/sentient
|
||||
cost = 0
|
||||
required_total_points = 0
|
||||
name = "Sentient Resistance"
|
||||
start_with = TRUE
|
||||
symptoms = list(/datum/symptom/sentient)
|
||||
short_desc = "Due to its sentience, the virus is able to passively increase its resistance to detection and cures"
|
||||
long_desc = "Due to its sentience, the virus is able to passively increase its resistance to detection and cures"
|
||||
|
||||
|
||||
/datum/symptom/sentient
|
||||
name = "Sentient Resistance"
|
||||
desc = "Due to its sentience, the virus is able to passively increase its resistance to detection and cures"
|
||||
stealth = 2
|
||||
resistance = 2
|
||||
stage_speed = 0
|
||||
transmittable = 0
|
||||
level = 0
|
||||
severity = 0
|
||||
symptom_delay_min = 2
|
||||
symptom_delay_max = 15
|
||||
var/infective = FALSE
|
||||
threshold_descs = list()
|
||||
|
||||
/datum/disease_ability/symptom/mild/cough
|
||||
name = "Involuntary Coughing"
|
||||
|
||||
@@ -840,6 +840,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<h2>Donator Preferences</h2>"
|
||||
if(is_donator(user.client))
|
||||
dat += "<b>Quiet round:</b> <a href='?_src_=prefs;preference=donor;task=quiet_round'>[(src.yogtoggles & QUIET_ROUND) ? "Yes" : "No"]</a><br>"
|
||||
dat += "Wear fancy hat as borg: "
|
||||
dat += "<a href='?_src_=prefs;preference=donor;task=borghat'>[borg_hat ? "Yes" : "No"]</a><br>"
|
||||
dat += "<b>Fancy Hat:</b> "
|
||||
///This is the typepath of the donor's hat that they may choose to spawn with.
|
||||
var/typehat = donor_hat
|
||||
@@ -1241,6 +1243,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(is_donator(user))
|
||||
var/client/C = (istype(user, /client)) ? user : user.client
|
||||
switch(href_list["task"])
|
||||
if("borghat")
|
||||
borg_hat = !borg_hat
|
||||
if("hat")
|
||||
C.custom_donator_item()
|
||||
if("item")
|
||||
|
||||
@@ -223,6 +223,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
// yogs start - Donor features
|
||||
READ_FILE(S["donor_pda"], donor_pda)
|
||||
READ_FILE(S["donor_hat"], donor_hat)
|
||||
READ_FILE(S["borg_hat"], borg_hat)
|
||||
READ_FILE(S["donor_item"], donor_item)
|
||||
READ_FILE(S["purrbation"], purrbation)
|
||||
READ_FILE(S["yogtoggles"], yogtoggles)
|
||||
@@ -358,6 +359,7 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
WRITE_FILE(S["yogtoggles"], yogtoggles)
|
||||
WRITE_FILE(S["donor_pda"], donor_pda)
|
||||
WRITE_FILE(S["donor_hat"], donor_hat)
|
||||
WRITE_FILE(S["borg_hat"], borg_hat)
|
||||
WRITE_FILE(S["donor_item"], donor_item)
|
||||
WRITE_FILE(S["purrbation"], purrbation)
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/obj/item/reactive_armour_shell
|
||||
name = "reactive armour shell"
|
||||
desc = "An experimental suit of armour, awaiting installation of an anomaly core."
|
||||
/obj/item/reactive_armor_shell
|
||||
name = "reactive armor shell"
|
||||
desc = "An experimental suit of armor, awaiting installation of an anomaly core."
|
||||
icon_state = "reactiveoff"
|
||||
icon = 'icons/obj/clothing/suits.dmi'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
|
||||
/obj/item/reactive_armour_shell/attackby(obj/item/I, mob/user, params)
|
||||
/obj/item/reactive_armor_shell/attackby(obj/item/I, mob/user, params)
|
||||
..()
|
||||
var/static/list/anomaly_armour_types = list(
|
||||
var/static/list/anomaly_armor_types = list(
|
||||
/obj/effect/anomaly/grav = /obj/item/clothing/suit/armor/reactive/repulse,
|
||||
/obj/effect/anomaly/flux = /obj/item/clothing/suit/armor/reactive/tesla,
|
||||
/obj/effect/anomaly/bluespace = /obj/item/clothing/suit/armor/reactive/teleport
|
||||
@@ -15,11 +15,11 @@
|
||||
|
||||
if(istype(I, /obj/item/assembly/signaler/anomaly))
|
||||
var/obj/item/assembly/signaler/anomaly/A = I
|
||||
var/armour_path = anomaly_armour_types[A.anomaly_type]
|
||||
if(!armour_path)
|
||||
armour_path = /obj/item/clothing/suit/armor/reactive/stealth //Lets not cheat the player if an anomaly type doesnt have its own armour coded
|
||||
to_chat(user, "You insert [A] into the chest plate, and the armour gently hums to life.")
|
||||
new armour_path(get_turf(src))
|
||||
var/armor_path = anomaly_armor_types[A.anomaly_type]
|
||||
if(!armor_path)
|
||||
armor_path = /obj/item/clothing/suit/armor/reactive/stealth //Lets not cheat the player if an anomaly type doesnt have its own armor coded
|
||||
to_chat(user, "You insert [A] into the chest plate, and the armor gently hums to life.")
|
||||
new armor_path(get_turf(src))
|
||||
qdel(src)
|
||||
qdel(A)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#define RANDOM_EVENT_ADMIN_INTERVENTION_TIME 10
|
||||
#define RANDOM_EVENT_ADMIN_INTERVENTION_TIME (20 SECONDS)
|
||||
|
||||
//this singleton datum is used by the events controller to dictate how it selects events
|
||||
/datum/round_event_control
|
||||
@@ -82,8 +82,8 @@
|
||||
|
||||
triggering = TRUE
|
||||
if(alert_observers)
|
||||
message_admins("Random Event triggering in [RANDOM_EVENT_ADMIN_INTERVENTION_TIME] seconds: [name] (<a href='?src=[REF(src)];cancel=1'>CANCEL</a>)")
|
||||
sleep(RANDOM_EVENT_ADMIN_INTERVENTION_TIME SECONDS)
|
||||
message_admins(span_bold(span_red("Random Event triggering in [RANDOM_EVENT_ADMIN_INTERVENTION_TIME/10] seconds: [name] (<a href='?src=[REF(src)];cancel=1'>CANCEL</a>)")))
|
||||
sleep(RANDOM_EVENT_ADMIN_INTERVENTION_TIME)
|
||||
//Yogs end
|
||||
var/gamemode = SSticker.mode.config_tag
|
||||
var/players_amt = get_active_player_count(alive_check = TRUE, afk_check = TRUE, human_check = TRUE)
|
||||
|
||||
@@ -391,17 +391,14 @@
|
||||
|
||||
/datum/spacevine_controller/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
.["Delete Vines"] = "?_src_=[REF(src)];[HrefToken()];purge_vines=1"
|
||||
VV_DROPDOWN_SEPERATOR
|
||||
VV_DROPDOWN_OPTION(VV_HK_SPACEVINE_PURGE, "Delete Vines")
|
||||
|
||||
/datum/spacevine_controller/Topic(href, href_list)
|
||||
if(..() || !check_rights(R_ADMIN, FALSE) || !usr.client.holder.CheckAdminHref(href, href_list))
|
||||
return
|
||||
|
||||
if(href_list["purge_vines"])
|
||||
if(alert(usr, "Are you sure you want to delete this spacevine cluster?", "Delete Vines", "Yes", "No") != "Yes")
|
||||
return
|
||||
DeleteVines()
|
||||
/datum/spacevine_controller/vv_do_topic(href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_SPACEVINE_PURGE])
|
||||
if(alert(usr, "Are you sure you want to delete this spacevine cluster?", "Delete Vines", list("Yes", "No")) == "Yes")
|
||||
DeleteVines()
|
||||
|
||||
/datum/spacevine_controller/proc/DeleteVines() //this is kill
|
||||
QDEL_LIST(vines) //this will also qdel us
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
suit = /obj/item/clothing/suit/armor/vest/capcarapace
|
||||
shoes = /obj/item/clothing/shoes/sneakers/brown
|
||||
head = /obj/item/clothing/head/caphat
|
||||
backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/station_charter=1, /obj/item/gun/energy/e_gun=1) //yogs - adds egun/removes civ budget
|
||||
backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/station_charter=1, /obj/item/gun/energy/e_gun=1, /obj/item/modular_computer/tablet/phone/preset/advanced/command=1) //yogs - adds egun/removes civ budget
|
||||
|
||||
backpack = /obj/item/storage/backpack/captain
|
||||
satchel = /obj/item/storage/backpack/satchel/cap
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
alt_shoes = /obj/item/clothing/shoes/xeno_wraps/command // Provides Command shoes to digitigrade species
|
||||
head = /obj/item/clothing/head/hardhat/white
|
||||
gloves = /obj/item/clothing/gloves/color/black/ce
|
||||
backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/phone/preset/advanced/command=1) //yogs - removes eng budget
|
||||
backpack_contents = list(/obj/item/melee/classic_baton/telescopic=1, /obj/item/modular_computer/tablet/phone/preset/advanced/command/atmos=1) //yogs - removes eng budget
|
||||
glasses = /obj/item/clothing/glasses/meson/sunglasses
|
||||
|
||||
backpack = /obj/item/storage/backpack/industrial
|
||||
|
||||
@@ -34,3 +34,24 @@
|
||||
|
||||
/datum/job/cyborg/radio_help_message(mob/M)
|
||||
to_chat(M, "<b>Prefix your message with :b to speak with other cyborgs and AI.</b>")
|
||||
|
||||
/datum/job/cyborg/give_donor_stuff(mob/living/silicon/robot/H, mob/M)
|
||||
if(!istype(H))
|
||||
return
|
||||
|
||||
var/client/C = M.client
|
||||
if(!C)
|
||||
C = H.client
|
||||
if(!C)
|
||||
return // nice
|
||||
|
||||
if(!is_donator(C))
|
||||
return
|
||||
|
||||
if(C.prefs.donor_hat && C.prefs.borg_hat)
|
||||
var/type = C.prefs.donor_hat
|
||||
if(type)
|
||||
var/obj/item/hat = new type()
|
||||
if(istype(hat) && hat.slot_flags & ITEM_SLOT_HEAD && H.hat_offset != INFINITY && !is_type_in_typecache(hat, H.blacklisted_hats))
|
||||
H.place_on_head(hat)
|
||||
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
r_pocket = /obj/item/lighter
|
||||
backpack_contents = list(/obj/item/storage/box/evidence=1,\
|
||||
/obj/item/detective_scanner=1,\
|
||||
/obj/item/melee/classic_baton=1)
|
||||
/obj/item/melee/classic_baton=1,\
|
||||
/obj/item/modular_computer/tablet/pda/preset/basic=1)
|
||||
mask = /obj/item/clothing/mask/cigarette
|
||||
|
||||
implants = list(/obj/item/implant/mindshield)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//The chests dropped by mob spawner tendrils. Also contains associated loot.
|
||||
|
||||
GLOBAL_LIST_EMPTY(bloodmen_list)
|
||||
#define HIEROPHANT_CLUB_CARDINAL_DAMAGE 30
|
||||
|
||||
|
||||
@@ -1457,3 +1457,56 @@
|
||||
new /obj/item/wisp_lantern(src)
|
||||
if(3)
|
||||
new /obj/item/prisoncube(src)
|
||||
|
||||
//Legion
|
||||
/obj/item/organ/grandcore
|
||||
name = "grand core"
|
||||
desc = "The source of the Legion's powers. Though mostly expended, you might be able to get some use out of it."
|
||||
icon = 'icons/obj/lavaland/artefacts.dmi'
|
||||
icon_state = "grandcore"
|
||||
slot = "hivecore"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
decay_factor = 0
|
||||
actions_types = list(/datum/action/item_action/organ_action/threebloodlings)
|
||||
|
||||
/obj/item/organ/grandcore/attack(mob/living/carbon/human/H, mob/living/carbon/human/user, obj/target)
|
||||
if(H == user && istype(H))
|
||||
playsound(user,'sound/effects/singlebeat.ogg',40,1)
|
||||
user.temporarilyRemoveItemFromInventory(src, TRUE)
|
||||
Insert(user)
|
||||
|
||||
/obj/item/organ/grandcore/Insert(mob/living/carbon/H, special = 0)
|
||||
H.faction = list("blooded")
|
||||
H.AddSpell (new /obj/effect/proc_holder/spell/targeted/touch/raise)
|
||||
H.AddSpell (new /obj/effect/proc_holder/spell/aoe_turf/horde)
|
||||
..()
|
||||
if(NOBLOOD in H.dna.species.species_traits)
|
||||
to_chat(owner, "<span class ='userdanger'>Despite lacking blood, you were able to take in the grand core. You will pay for your power in killer headaches!</span>")
|
||||
else
|
||||
to_chat(owner, "<span class ='userdanger'>You've taken in the grand core, allowing you to control minions at the cost of your blood!</span>")
|
||||
|
||||
/obj/item/organ/grandcore/Remove(mob/living/carbon/H, special = 0)
|
||||
H.RemoveSpell (/obj/effect/proc_holder/spell/targeted/touch/raise, /obj/effect/proc_holder/spell/aoe_turf/horde)
|
||||
H.RemoveSpell (new /obj/effect/proc_holder/spell/aoe_turf/horde)
|
||||
return ..()
|
||||
|
||||
/datum/action/item_action/organ_action/threebloodlings
|
||||
name = "Summon bloodlings"
|
||||
desc = "Summon a conjure a few bloodlings at the cost of 13% blood (8 brain damage for those without blood)."
|
||||
var/next_expulsion = 0
|
||||
var/cooldown = 10 //wheres the risk if it has a reasonable cooldown?
|
||||
|
||||
/datum/action/item_action/organ_action/threebloodlings/Trigger()
|
||||
var/mob/living/carbon/H = owner
|
||||
. = ..()
|
||||
if(next_expulsion > world.time)
|
||||
to_chat(owner, span_warning("Don't spill your blood so haphazardly!"))
|
||||
return
|
||||
if(NOBLOOD in H.dna.species.species_traits)
|
||||
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 8) //brain damage wont stop you from running away so opting for that instead of poison or breath damage
|
||||
to_chat(H, "<span class ='userdanger'>Your head pounds as you produce bloodlings!</span>")
|
||||
else
|
||||
to_chat(H, "<span class ='userdanger'>You spill your blood, and it comes to life as bloodlings!</span>")
|
||||
H.blood_volume -= 70 //like 13% of your blood taken
|
||||
spawn_atom_to_turf(/mob/living/simple_animal/hostile/asteroid/hivelordbrood/bloodling, owner, 3, TRUE) //think 1 in 4 is a good chance of not being targeted by fauna
|
||||
next_expulsion = world.time + cooldown
|
||||
|
||||
@@ -522,6 +522,7 @@
|
||||
return
|
||||
if(frn)
|
||||
client.prefs.random_character()
|
||||
client.prefs.accent = null
|
||||
client.prefs.real_name = client.prefs.pref_species.random_name(gender,1)
|
||||
client.prefs.copy_to(H)
|
||||
|
||||
|
||||
@@ -952,14 +952,114 @@
|
||||
|
||||
/mob/living/carbon/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
.["Make AI"] = "?_src_=vars;[HrefToken()];makeai=[REF(src)]"
|
||||
.["Modify bodypart"] = "?_src_=vars;[HrefToken()];editbodypart=[REF(src)]"
|
||||
.["Modify organs"] = "?_src_=vars;[HrefToken()];editorgans=[REF(src)]"
|
||||
.["Hallucinate"] = "?_src_=vars;[HrefToken()];hallucinate=[REF(src)]"
|
||||
.["Give martial arts"] = "?_src_=vars;[HrefToken()];givemartialart=[REF(src)]"
|
||||
.["Give brain trauma"] = "?_src_=vars;[HrefToken()];givetrauma=[REF(src)]"
|
||||
.["Cure brain traumas"] = "?_src_=vars;[HrefToken()];curetraumas=[REF(src)]"
|
||||
VV_DROPDOWN_SEPERATOR
|
||||
VV_DROPDOWN_OPTION(VV_HK_MODIFY_BODYPART, "Modify bodypart")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MODIFY_ORGANS, "Modify organs")
|
||||
VV_DROPDOWN_OPTION(VV_HK_HALLUCINATION, "Hallucinate")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MARTIAL_ART, "Give Martial Arts")
|
||||
VV_DROPDOWN_OPTION(VV_HK_GIVE_TRAUMA, "Give Brain Trauma")
|
||||
VV_DROPDOWN_OPTION(VV_HK_CURE_TRAUMA, "Cure Brain Traumas")
|
||||
|
||||
/mob/living/carbon/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_MODIFY_BODYPART])
|
||||
if(!check_rights(R_SPAWN))
|
||||
return
|
||||
var/edit_action = input(usr, "What would you like to do?","Modify Body Part") as null|anything in list("add","remove", "augment")
|
||||
if(!edit_action)
|
||||
return
|
||||
var/list/limb_list = list()
|
||||
if(edit_action == "remove" || edit_action == "augment")
|
||||
for(var/obj/item/bodypart/B in bodyparts)
|
||||
limb_list += B.body_zone
|
||||
if(edit_action == "remove")
|
||||
limb_list -= BODY_ZONE_CHEST
|
||||
else
|
||||
limb_list = list(BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
|
||||
for(var/obj/item/bodypart/B in bodyparts)
|
||||
limb_list -= B.body_zone
|
||||
var/result = input(usr, "Please choose which body part to [edit_action]","[capitalize(edit_action)] Body Part") as null|anything in sortList(limb_list)
|
||||
if(result)
|
||||
var/obj/item/bodypart/BP = get_bodypart(result)
|
||||
switch(edit_action)
|
||||
if("remove")
|
||||
if(BP)
|
||||
BP.drop_limb()
|
||||
else
|
||||
to_chat(usr, span_boldwarning("[src] doesn't have such bodypart."))
|
||||
if("add")
|
||||
if(BP)
|
||||
to_chat(usr, span_boldwarning("[src] already has such bodypart."))
|
||||
else
|
||||
if(!regenerate_limb(result))
|
||||
to_chat(usr, span_boldwarning("[src] cannot have such bodypart."))
|
||||
if("augment")
|
||||
if(ishuman(src))
|
||||
if(BP)
|
||||
BP.change_bodypart_status(BODYPART_ROBOTIC, TRUE, TRUE)
|
||||
else
|
||||
to_chat(usr, span_boldwarning("[src] doesn't have such bodypart."))
|
||||
else
|
||||
to_chat(usr, span_boldwarning("Only humans can be augmented."))
|
||||
admin_ticket_log("[key_name_admin(usr)] has modified the bodyparts of [src]")
|
||||
if(href_list[VV_HK_MODIFY_ORGANS])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
usr.client.manipulate_organs(src)
|
||||
if(href_list[VV_HK_MARTIAL_ART])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/artpaths = subtypesof(/datum/martial_art)
|
||||
var/list/artnames = list()
|
||||
for(var/i in artpaths)
|
||||
var/datum/martial_art/M = i
|
||||
artnames[initial(M.name)] = M
|
||||
var/result = input(usr, "Choose the martial art to teach","JUDO CHOP") as null|anything in sortList(artnames, /proc/cmp_typepaths_asc)
|
||||
if(!usr)
|
||||
return
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, span_boldwarning("Mob doesn't exist anymore."))
|
||||
return
|
||||
if(result)
|
||||
var/chosenart = artnames[result]
|
||||
var/datum/martial_art/MA = new chosenart
|
||||
MA.teach(src)
|
||||
log_admin("[key_name(usr)] has taught [MA] to [key_name(src)].")
|
||||
message_admins(span_notice("[key_name_admin(usr)] has taught [MA] to [key_name_admin(src)]."))
|
||||
if(href_list[VV_HK_GIVE_TRAUMA])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/traumas = subtypesof(/datum/brain_trauma)
|
||||
var/result = input(usr, "Choose the brain trauma to apply","Traumatize") as null|anything in sortList(traumas, /proc/cmp_typepaths_asc)
|
||||
if(!usr)
|
||||
return
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, "Mob doesn't exist anymore")
|
||||
return
|
||||
if(!result)
|
||||
return
|
||||
var/datum/brain_trauma/BT = gain_trauma(result)
|
||||
if(BT)
|
||||
log_admin("[key_name(usr)] has traumatized [key_name(src)] with [BT.name]")
|
||||
message_admins(span_notice("[key_name_admin(usr)] has traumatized [key_name_admin(src)] with [BT.name]."))
|
||||
if(href_list[VV_HK_CURE_TRAUMA])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
cure_all_traumas(TRAUMA_RESILIENCE_ABSOLUTE)
|
||||
log_admin("[key_name(usr)] has cured all traumas from [key_name(src)].")
|
||||
message_admins(span_notice("[key_name_admin(usr)] has cured all traumas from [key_name_admin(src)]."))
|
||||
if(href_list[VV_HK_HALLUCINATION])
|
||||
if(!check_rights(NONE))
|
||||
return
|
||||
var/list/hallucinations = subtypesof(/datum/hallucination)
|
||||
var/result = input(usr, "Choose the hallucination to apply","Send Hallucination") as null|anything in sortList(hallucinations, /proc/cmp_typepaths_asc)
|
||||
if(!usr)
|
||||
return
|
||||
if(QDELETED(src))
|
||||
to_chat(usr, "Mob doesn't exist anymore")
|
||||
return
|
||||
if(result)
|
||||
new result(src, TRUE)
|
||||
|
||||
/mob/living/carbon/can_resist()
|
||||
return bodyparts.len > 2 && ..()
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
if(legcuffed)
|
||||
. += legcuffed.slowdown
|
||||
|
||||
/mob/living/carbon/slip(knockdown_amount, obj/O, lube, paralyze, force_drop)
|
||||
/mob/living/carbon/slip(knockdown_amount, obj/O, lube, stun, force_drop)
|
||||
if(movement_type & FLYING)
|
||||
return 0
|
||||
if(!(lube&SLIDE_ICE))
|
||||
log_combat(src, (O ? O : get_turf(src)), "slipped on the", null, ((lube & SLIDE) ? "(LUBE)" : null))
|
||||
return loc.handle_slip(src, knockdown_amount, O, lube, paralyze, force_drop)
|
||||
return loc.handle_slip(src, knockdown_amount, O, lube, stun, force_drop)
|
||||
|
||||
/mob/living/carbon/Process_Spacemove(movement_dir = 0)
|
||||
if(..())
|
||||
|
||||
@@ -881,17 +881,60 @@
|
||||
|
||||
/mob/living/carbon/human/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
.["Make monkey"] = "?_src_=vars;[HrefToken()];makemonkey=[REF(src)]"
|
||||
.["Set Species"] = "?_src_=vars;[HrefToken()];setspecies=[REF(src)]"
|
||||
.["Make cyborg"] = "?_src_=vars;[HrefToken()];makerobot=[REF(src)]"
|
||||
.["Make alien"] = "?_src_=vars;[HrefToken()];makealien=[REF(src)]"
|
||||
.["Make slime"] = "?_src_=vars;[HrefToken()];makeslime=[REF(src)]"
|
||||
.["Toggle Purrbation"] = "?_src_=vars;[HrefToken()];purrbation=[REF(src)]"
|
||||
.["Copy outfit"] = "?_src_=vars;[HrefToken()];copyoutfit=[REF(src)]"
|
||||
.["Add/Remove Quirks"] = "?_src_=vars;[HrefToken()];modquirks=[REF(src)]"
|
||||
.["Make Cluwne"] = "?_src_=vars;[HrefToken()];cluwneing=[REF(src)]" // yogs -- make cluwne
|
||||
.["Make Pacman"] = "?_src_=vars;[HrefToken()];makepacman=[REF(src)]" //I LOVE PACMAN
|
||||
VV_DROPDOWN_SEPERATOR
|
||||
VV_DROPDOWN_OPTION(VV_HK_SET_SPECIES, "Set Species")
|
||||
VV_DROPDOWN_OPTION(VV_HK_PURRBATION, "Toggle Purrbation")
|
||||
VV_DROPDOWN_OPTION(VV_HK_COPY_OUTFIT, "Copy Outfit")
|
||||
VV_DROPDOWN_OPTION(VV_HK_MOD_QUIRKS, "Add/Remove Quirks")
|
||||
|
||||
/mob/living/carbon/human/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_SET_SPECIES] && check_rights(R_SPAWN))
|
||||
var/result = input(usr, "Please choose a new species","Species") as null|anything in GLOB.species_list
|
||||
|
||||
if(result)
|
||||
var/newtype = GLOB.species_list[result]
|
||||
admin_ticket_log(src, "[key_name(usr)] has modified the species of [src] to [result]") // yogs - Yog Tickets
|
||||
set_species(newtype)
|
||||
if(href_list[VV_HK_PURRBATION] && check_rights(R_SPAWN))
|
||||
if(!ishumanbasic(src))
|
||||
to_chat(usr, "This can only be done to the basic human species at the moment.")
|
||||
return
|
||||
|
||||
var/success = purrbation_toggle(src)
|
||||
if(success)
|
||||
to_chat(usr, "Put [src] on purrbation.")
|
||||
log_admin("[key_name(usr)] has put [key_name(src)] on purrbation.")
|
||||
var/msg = "[key_name(usr)] has put [key_name(src)] on purrbation." // yogs - Yog Tickets
|
||||
message_admins(msg)
|
||||
admin_ticket_log(src, msg)
|
||||
|
||||
else
|
||||
to_chat(usr, "Removed [src] from purrbation.")
|
||||
log_admin("[key_name(usr)] has removed [key_name(src)] from purrbation.")
|
||||
var/msg = "[key_name(usr)] has removed [key_name(src)] from purrbation." // yogs - Yog Tickets
|
||||
message_admins(msg)
|
||||
admin_ticket_log(src, msg)
|
||||
if(href_list[VV_HK_COPY_OUTFIT] && check_rights(R_SPAWN))
|
||||
copy_outfit()
|
||||
if(href_list[VV_HK_MOD_QUIRKS] && check_rights(R_SPAWN))
|
||||
var/list/options = list("Clear"="Clear")
|
||||
for(var/x in subtypesof(/datum/quirk))
|
||||
var/datum/quirk/T = x
|
||||
var/qname = initial(T.name)
|
||||
options[has_quirk(T) ? "[qname] (Remove)" : "[qname] (Add)"] = T
|
||||
|
||||
var/result = input(usr, "Choose quirk to add/remove","Quirk Mod") as null|anything in options
|
||||
if(result)
|
||||
if(result == "Clear")
|
||||
for(var/datum/quirk/q in roundstart_quirks)
|
||||
remove_quirk(q.type)
|
||||
else
|
||||
var/T = options[result]
|
||||
if(has_quirk(T))
|
||||
remove_quirk(T)
|
||||
else
|
||||
add_quirk(T,TRUE)
|
||||
|
||||
/mob/living/carbon/human/MouseDrop_T(mob/living/target, mob/living/user)
|
||||
if(pulling == target && grab_state >= GRAB_AGGRESSIVE && stat == CONSCIOUS)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
if(dna && dna.species)
|
||||
. += dna.species.movement_delay(src)
|
||||
|
||||
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube, paralyze, forcedrop)
|
||||
/mob/living/carbon/human/slip(knockdown_amount, obj/O, lube, stun, forcedrop)
|
||||
if(HAS_TRAIT(src, TRAIT_NOSLIPALL))
|
||||
return 0
|
||||
if (!(lube & GALOSHES_DONT_HELP))
|
||||
|
||||
@@ -1385,6 +1385,22 @@
|
||||
if("lighting_alpha")
|
||||
sync_lighting_plane_alpha()
|
||||
|
||||
/mob/living/vv_get_header()
|
||||
. = ..()
|
||||
var/refid = REF(src)
|
||||
. += {"
|
||||
<br><font size='1'><a href='?_src_=vars;[HrefToken()];datumedit=[refid];varnameedit=ckey' id='ckey'>[ckey || "No ckey"]</a> / [VV_HREF_TARGETREF_1V(refid, VV_HK_BASIC_EDIT, "[real_name || "no real name"]", NAMEOF(src, real_name))]</font>
|
||||
<br><font size='1'>
|
||||
BRUTE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brute' id='brute'>[getBruteLoss()]</a>
|
||||
FIRE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=fire' id='fire'>[getFireLoss()]</a>
|
||||
TOXIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=toxin' id='toxin'>[getToxLoss()]</a>
|
||||
OXY:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=oxygen' id='oxygen'>[getOxyLoss()]</a>
|
||||
CLONE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=clone' id='clone'>[getCloneLoss()]</a>
|
||||
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain' id='brain'>[getOrganLoss(ORGAN_SLOT_BRAIN)]</a>
|
||||
STAMINA:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stamina' id='stamina'>[getStaminaLoss()]</a>
|
||||
</font>
|
||||
"}
|
||||
|
||||
/mob/living/proc/is_convert_antag()
|
||||
var/list/bad_antags = list(
|
||||
/datum/antagonist/clockcult,
|
||||
|
||||
@@ -317,7 +317,7 @@ GLOBAL_LIST_INIT(special_radio_keys, list(
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
to_chat(src, span_danger("You cannot speak in IC (muted)."))
|
||||
return FALSE
|
||||
if(!ignore_spam && client.handle_spam_prevention(message,MUTE_IC))
|
||||
if(!ignore_spam && message != null && client.handle_spam_prevention(message,MUTE_IC))
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
@@ -147,8 +147,6 @@ GLOBAL_VAR_INIT(primary_data_core, null)
|
||||
add_overlay(on_overlay)
|
||||
|
||||
/obj/machinery/ai/data_core/proc/partytime()
|
||||
if(TimerID)
|
||||
return FALSE
|
||||
var/current_color = random_color()
|
||||
set_light(7, 3, current_color)
|
||||
TimerID = addtimer(CALLBACK(src, .proc/partytime), 0.5 SECONDS, TIMER_STOPPABLE)
|
||||
@@ -157,6 +155,7 @@ GLOBAL_VAR_INIT(primary_data_core, null)
|
||||
set_light(0)
|
||||
if(TimerID)
|
||||
deltimer(TimerID)
|
||||
TimerID = null
|
||||
/obj/machinery/ai/data_core/primary
|
||||
name = "primary AI Data Core"
|
||||
desc = "A complicated computer system capable of emulating the neural functions of a human at near-instantanous speeds. This one has a scrawny and faded note saying: 'Primary AI Data Core'"
|
||||
|
||||
@@ -234,7 +234,7 @@ GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6))
|
||||
|
||||
if(!cleared_for_use)
|
||||
if(action == "clear_for_use")
|
||||
var/code = text2num(params["control_code"])
|
||||
var/code = params["control_code"]
|
||||
|
||||
if(!code)
|
||||
return
|
||||
@@ -242,7 +242,7 @@ GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6))
|
||||
if(!GLOB.ai_control_code)
|
||||
return
|
||||
|
||||
var/length_of_number = round(log(10, code) + 1)
|
||||
var/length_of_number = length(code)
|
||||
if(length_of_number < 6)
|
||||
to_chat(usr, span_warning("Incorrect code. Too short"))
|
||||
return
|
||||
@@ -251,13 +251,11 @@ GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6))
|
||||
to_chat(usr, span_warning("Incorrect code. Too long"))
|
||||
return
|
||||
|
||||
|
||||
|
||||
if(!is_station_level(z))
|
||||
to_chat(usr, span_warning("Unable to connect to NT Servers. Please verify you are onboard the station."))
|
||||
return
|
||||
|
||||
if(code == text2num(GLOB.ai_control_code))
|
||||
if(code == GLOB.ai_control_code)
|
||||
cleared_for_use = TRUE
|
||||
else
|
||||
to_chat(usr, span_warning("Incorrect code. Make sure you have the latest one."))
|
||||
@@ -283,7 +281,7 @@ GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6))
|
||||
if(check_access(H.get_idcard()))
|
||||
authenticated = TRUE
|
||||
if(action == "log_in_control_code")
|
||||
var/code = text2num(params["control_code"])
|
||||
var/code = params["control_code"]
|
||||
|
||||
if(!code)
|
||||
return
|
||||
@@ -291,7 +289,7 @@ GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6))
|
||||
if(!GLOB.ai_control_code)
|
||||
return
|
||||
|
||||
var/length_of_number = round(log(10, code) + 1)
|
||||
var/length_of_number = length(code)
|
||||
if(length_of_number < 6)
|
||||
to_chat(usr, span_warning("Incorrect code. Too short"))
|
||||
return
|
||||
@@ -300,9 +298,7 @@ GLOBAL_VAR_INIT(ai_control_code, random_nukecode(6))
|
||||
to_chat(usr, span_warning("Incorrect code. Too long"))
|
||||
return
|
||||
|
||||
|
||||
|
||||
if(code == text2num(GLOB.ai_control_code))
|
||||
if(code == GLOB.ai_control_code)
|
||||
cleared_for_use = TRUE
|
||||
authenticated = TRUE
|
||||
one_time_password_used = TRUE
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
if(!.)
|
||||
return .
|
||||
for(var/obj/machinery/ai/data_core/datacores in GLOB.data_cores)
|
||||
datacores.partytime()
|
||||
if(!datacores.TimerID)
|
||||
datacores.partytime()
|
||||
|
||||
|
||||
/datum/ai_project/rgb/stop()
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
var/syndicate_module = FALSE /// If the borg should blow emag size regardless of emag state
|
||||
|
||||
var/obj/item/hat // Keeps track of the hat while transforming, to attempt to place back on the borg's head
|
||||
|
||||
/obj/item/robot_module/Initialize()
|
||||
. = ..()
|
||||
for(var/i in basic_modules)
|
||||
@@ -213,8 +215,10 @@
|
||||
/obj/item/robot_module/proc/do_transform_animation()
|
||||
var/mob/living/silicon/robot/R = loc
|
||||
if(R.hat)
|
||||
R.hat.forceMove(get_turf(R))
|
||||
hat = R.hat
|
||||
R.hat = null
|
||||
hat.moveToNullspace()
|
||||
|
||||
R.cut_overlays()
|
||||
R.setDir(SOUTH)
|
||||
do_transform_delay()
|
||||
|
||||
27
code/modules/mob/living/simple_animal/friendly/snail.dm
Normal file
@@ -0,0 +1,27 @@
|
||||
/mob/living/simple_animal/pet/snail
|
||||
name = "snail"
|
||||
desc = "Snails are mollusks, putting them in the same category as oysters, clams, and mussels."
|
||||
icon = 'icons/mob/pets.dmi'
|
||||
icon_state = "snail"
|
||||
icon_living = "snail"
|
||||
icon_dead = "snail_dead"
|
||||
speak_emote = list("gurgles")
|
||||
emote_hear = list("gurgles.")
|
||||
emote_see = list("gurgles.")
|
||||
speak_chance = 1
|
||||
turns_per_move = 7
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 1)
|
||||
mob_biotypes = list(MOB_ORGANIC, MOB_BEAST)
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "stomps"
|
||||
friendly = "bops"
|
||||
melee_damage_lower = 2
|
||||
melee_damage_upper = 2
|
||||
health = 50
|
||||
maxHealth = 50
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
|
||||
/mob/living/simple_animal/pet/snail/gary
|
||||
name = "Gary the snail"
|
||||
desc = "Gary come home"
|
||||
@@ -167,10 +167,10 @@ Difficulty: Medium
|
||||
break
|
||||
if(last_legion)
|
||||
loot = list(/obj/item/staff/storm,
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker,
|
||||
/obj/item/organ/grandcore,
|
||||
/obj/item/keycard/necropolis)
|
||||
crusher_loot = list(/obj/item/crusher_trophy/malformed_bone,/obj/item/staff/storm,
|
||||
/obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker,
|
||||
/obj/item/organ/grandcore,
|
||||
/obj/item/keycard/necropolis) //the way it is now you can get this if you just whip out the crusher towards the end but nobody's gonna do that probably
|
||||
elimination = FALSE
|
||||
else if(prob(10))
|
||||
|
||||
@@ -395,6 +395,56 @@
|
||||
backpack_contents = list(/obj/item/reagent_containers/glass/beaker/unholywater = 1, /obj/item/cult_shift = 1, /obj/item/flashlight/flare/culttorch = 1, /obj/item/stack/sheet/runed_metal = 15)
|
||||
. = ..()
|
||||
|
||||
//Bloodman
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/bloodman
|
||||
name = "bloodman"
|
||||
desc = "It's contantly dripping and absorbing blood."
|
||||
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
faction = list("blooded")
|
||||
icon_state = "bloodman"
|
||||
icon_living = "bloodman"
|
||||
icon_aggro = "bloodman"
|
||||
icon_dead = "bloodman"
|
||||
maxHealth = 30
|
||||
health = 30 //dont want crew to have a hard time killing actual fodder
|
||||
loot = null
|
||||
brood_type = /mob/living/simple_animal/hostile/asteroid/hivelordbrood/bloodling
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/bloodman/Initialize()
|
||||
. = ..()
|
||||
GLOB.bloodmen_list += src
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/bloodman/death()
|
||||
. = ..()
|
||||
GLOB.bloodmen_list -= src
|
||||
return
|
||||
|
||||
//Bloodling
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/bloodling
|
||||
name = "bloodling"
|
||||
desc = "Blood that hates."
|
||||
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
icon_state = "bloodling"
|
||||
icon_living = "bloodling"
|
||||
icon_aggro = "bloodling"
|
||||
icon_dead = "bloodling"
|
||||
icon_gib = "syndicate_gib"
|
||||
friendly = "buzzes near"
|
||||
faction = list("blooded")
|
||||
harm_intent_damage = 2
|
||||
melee_damage_lower = 2
|
||||
melee_damage_upper = 2 //fodder isnt supposed to be strong
|
||||
attacktext = "gnashes at"
|
||||
stat_attack = DEAD
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/bloodling/Life()
|
||||
var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/bloodman/L
|
||||
if(isturf(loc))
|
||||
for(var/mob/living/carbon/human/M in view(src,1))
|
||||
if(M.stat == DEAD && GLOB.bloodmen_list.len <= 2) //max of 3 bloodmen to minimize shitshows
|
||||
L = new(M.loc)
|
||||
L.stored_mob = M
|
||||
M.forceMove(L)
|
||||
qdel(src)
|
||||
..() //couldnt figure out how to make infesting work without getting duplicate def errors so just doing this
|
||||
|
||||
@@ -1187,19 +1187,63 @@
|
||||
*/
|
||||
/mob/vv_get_dropdown()
|
||||
. = ..()
|
||||
. += "---"
|
||||
.["Gib"] = "?_src_=vars;[HrefToken()];gib=[REF(src)]"
|
||||
.["Give Spell"] = "?_src_=vars;[HrefToken()];give_spell=[REF(src)]"
|
||||
.["Remove Spell"] = "?_src_=vars;[HrefToken()];remove_spell=[REF(src)]"
|
||||
.["Give Disease"] = "?_src_=vars;[HrefToken()];give_disease=[REF(src)]"
|
||||
.["Toggle Godmode"] = "?_src_=vars;[HrefToken()];godmode=[REF(src)]"
|
||||
.["Drop Everything"] = "?_src_=vars;[HrefToken()];drop_everything=[REF(src)]"
|
||||
.["Regenerate Icons"] = "?_src_=vars;[HrefToken()];regenerateicons=[REF(src)]"
|
||||
.["Show player panel"] = "?_src_=vars;[HrefToken()];mob_player_panel=[REF(src)]"
|
||||
.["Toggle Build Mode"] = "?_src_=vars;[HrefToken()];build_mode=[REF(src)]"
|
||||
.["Assume Direct Control"] = "?_src_=vars;[HrefToken()];direct_control=[REF(src)]"
|
||||
.["Offer Control to Ghosts"] = "?_src_=vars;[HrefToken()];offer_control=[REF(src)]"
|
||||
.["Set AFK Timer"] = "?_src_=vars;[HrefToken()];set_afk=[REF(src)]"
|
||||
VV_DROPDOWN_SEPERATOR
|
||||
VV_DROPDOWN_OPTION(VV_HK_GIB, "Gib")
|
||||
VV_DROPDOWN_OPTION(VV_HK_GIVE_SPELL, "Give Spell")
|
||||
VV_DROPDOWN_OPTION(VV_HK_REMOVE_SPELL, "Remove Spell")
|
||||
VV_DROPDOWN_OPTION(VV_HK_GIVE_DISEASE, "Give Disease")
|
||||
VV_DROPDOWN_OPTION(VV_HK_GODMODE, "Toggle Godmode")
|
||||
VV_DROPDOWN_OPTION(VV_HK_DROP_ALL, "Drop Everything")
|
||||
VV_DROPDOWN_OPTION(VV_HK_REGEN_ICONS, "Regenerate Icons")
|
||||
VV_DROPDOWN_OPTION(VV_HK_PLAYER_PANEL, "Show player panel")
|
||||
VV_DROPDOWN_OPTION(VV_HK_BUILDMODE, "Toggle Buildmode")
|
||||
VV_DROPDOWN_OPTION(VV_HK_DIRECT_CONTROL, "Assume Direct Control")
|
||||
VV_DROPDOWN_OPTION(VV_HK_OFFER_GHOSTS, "Offer Control to Ghosts")
|
||||
VV_DROPDOWN_OPTION(VV_HK_SET_AFK_TIMER, "Set AFK Timer")
|
||||
|
||||
|
||||
/mob/vv_do_topic(list/href_list)
|
||||
. = ..()
|
||||
if(href_list[VV_HK_REGEN_ICONS] && check_rights(R_VAREDIT))
|
||||
regenerate_icons()
|
||||
if(href_list[VV_HK_PLAYER_PANEL])
|
||||
usr.client.holder.show_player_panel(src)
|
||||
if(href_list[VV_HK_GODMODE] && check_rights(R_ADMIN))
|
||||
usr.client.cmd_admin_godmode(src)
|
||||
if(href_list[VV_HK_GIVE_SPELL] && check_rights(R_VAREDIT))
|
||||
usr.client.give_spell(src)
|
||||
if(href_list[VV_HK_REMOVE_SPELL] && check_rights(R_VAREDIT))
|
||||
usr.client.remove_spell(src)
|
||||
if(href_list[VV_HK_GIVE_DISEASE] && check_rights(R_VAREDIT))
|
||||
usr.client.give_disease(src)
|
||||
if(href_list[VV_HK_GIB] && check_rights(R_FUN))
|
||||
usr.client.cmd_admin_gib(src)
|
||||
if(href_list[VV_HK_BUILDMODE] && check_rights(R_BUILDMODE))
|
||||
togglebuildmode(src)
|
||||
if(href_list[VV_HK_DROP_ALL] && check_rights(R_ADMIN))
|
||||
usr.client.cmd_admin_drop_everything(src)
|
||||
if(href_list[VV_HK_DIRECT_CONTROL] && check_rights(R_VAREDIT))
|
||||
usr.client.cmd_assume_direct_control(src)
|
||||
if(href_list[VV_HK_OFFER_GHOSTS] && check_rights(R_ADMIN))
|
||||
offer_control(src)
|
||||
if(href_list[VV_HK_SET_AFK_TIMER] && check_rights(R_ADMIN))
|
||||
if(!mind)
|
||||
to_chat(usr, "This cannot be used on mobs without a mind")
|
||||
return
|
||||
|
||||
var/timer = input("Input AFK length in minutes, 0 to cancel the current timer", text("Input")) as num|null
|
||||
if(timer == null) // Explicit null check for cancel, rather than generic truthyness, so 0 is handled differently
|
||||
return
|
||||
|
||||
deltimer(mind.afk_verb_timer)
|
||||
mind.afk_verb_used = FALSE
|
||||
|
||||
if(!timer)
|
||||
return
|
||||
|
||||
mind.afk_verb_used = TRUE
|
||||
mind.afk_verb_timer = addtimer(VARSET_CALLBACK(mind, afk_verb_used, FALSE), timer MINUTES, TIMER_STOPPABLE);
|
||||
|
||||
|
||||
/**
|
||||
* extra var handling for the logging var
|
||||
@@ -1210,6 +1254,12 @@
|
||||
return debug_variable(var_name, logging, 0, src, FALSE)
|
||||
. = ..()
|
||||
|
||||
/mob/vv_auto_rename(new_name)
|
||||
//Do not do parent's actions, as we *usually* do this differently.
|
||||
fully_replace_character_name(real_name, new_name)
|
||||
usr.client.vv_update_display(src, "name", new_name)
|
||||
usr.client.vv_update_display(src, "real_name", real_name || "No real name")
|
||||
|
||||
///Show the language menu for this mob
|
||||
/mob/verb/open_language_menu()
|
||||
set name = "Open Language Menu"
|
||||
|
||||
@@ -337,7 +337,7 @@
|
||||
return FALSE
|
||||
|
||||
/// Called when this mob slips over, override as needed
|
||||
/mob/proc/slip(knockdown_amount, obj/O, lube, paralyze, force_drop)
|
||||
/mob/proc/slip(knockdown_amount, obj/O, lube, stun, force_drop)
|
||||
return
|
||||
|
||||
/// Update the gravity status of this mob
|
||||
|
||||
@@ -37,3 +37,12 @@
|
||||
/obj/item/computer_hardware/network_card,
|
||||
/obj/item/computer_hardware/card_slot,
|
||||
/obj/item/computer_hardware/card_slot/secondary)
|
||||
|
||||
/obj/item/modular_computer/tablet/phone/preset/advanced/command/atmos
|
||||
starting_components = list( /obj/item/computer_hardware/processor_unit/small,
|
||||
/obj/item/stock_parts/cell/computer,
|
||||
/obj/item/computer_hardware/hard_drive/small,
|
||||
/obj/item/computer_hardware/network_card,
|
||||
/obj/item/computer_hardware/card_slot,
|
||||
/obj/item/computer_hardware/card_slot/secondary,
|
||||
/obj/item/computer_hardware/sensorpackage)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
requires_ntnet = TRUE
|
||||
transfer_access = null
|
||||
available_on_ntnet = FALSE
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_PHONE | PROGRAM_INTEGRATED
|
||||
usage_flags = PROGRAM_LAPTOP | PROGRAM_TABLET | PROGRAM_PHONE | PROGRAM_PDA | PROGRAM_INTEGRATED
|
||||
network_destination = "tracking program"
|
||||
size = 5
|
||||
tgui_id = "NtosRadar"
|
||||
@@ -314,7 +314,7 @@
|
||||
filedesc = "Implant Tracker"
|
||||
extended_desc = "This program allows for tracking those implanted with tracking implants."
|
||||
requires_ntnet = TRUE
|
||||
transfer_access = ACCESS_SECURITY
|
||||
transfer_access = ACCESS_BRIG
|
||||
available_on_ntnet = TRUE
|
||||
program_icon = "microchip"
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
integrity_failure = 50
|
||||
resistance_flags = FIRE_PROOF
|
||||
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON
|
||||
works_with_rped_anyways = TRUE
|
||||
FASTDMM_PROP(\
|
||||
set_instance_vars(\
|
||||
pixel_x = dir == EAST ? 24 : (dir == WEST ? -25 : INSTANCE_VAR_DEFAULT),\
|
||||
@@ -291,6 +292,34 @@
|
||||
if(issilicon(user))
|
||||
. += span_notice("Ctrl-Click the APC to switch the breaker [ operating ? "off" : "on"].")
|
||||
|
||||
/obj/machinery/power/apc/exchange_parts(mob/user, obj/item/storage/part_replacer/W)
|
||||
if(!istype(W))
|
||||
return FALSE
|
||||
if(!opened && !W.works_from_distance)
|
||||
return FALSE
|
||||
var/current_cell_rating = cell ? cell.get_part_rating() : -1
|
||||
var/best_cell_rating = current_cell_rating
|
||||
var/obj/item/stock_parts/cell/best_cell
|
||||
for(var/C in W.contents)
|
||||
var/obj/item/stock_parts/cell/cell = C
|
||||
if (!cell || !istype(cell))
|
||||
continue
|
||||
var/cell_rating = cell.get_part_rating()
|
||||
if (cell_rating > best_cell_rating || (cell_rating == best_cell_rating && cell.charge > best_cell.charge))
|
||||
best_cell_rating = cell_rating
|
||||
best_cell = cell
|
||||
if (best_cell)
|
||||
if (cell)
|
||||
SEND_SIGNAL(W, COMSIG_TRY_STORAGE_INSERT, cell, null, null, TRUE)
|
||||
to_chat(user, span_notice("[capitalize(cell.name)] replaced with [best_cell.name]."))
|
||||
best_cell.forceMove(src)
|
||||
var/amount_to_charge = min(best_cell.maxcharge - best_cell.charge, cell.charge)
|
||||
if (cell.use(amount_to_charge))
|
||||
best_cell.give(amount_to_charge)
|
||||
cell = best_cell
|
||||
W.play_rped_sound()
|
||||
|
||||
|
||||
// update the APC icon to show the three base states
|
||||
// also add overlays for indicator lights
|
||||
/obj/machinery/power/apc/update_icon()
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
var/spawnwithmagazine = TRUE
|
||||
///Compatible magazines with the gun
|
||||
var/mag_type = /obj/item/ammo_box/magazine/m10mm //Removes the need for max_ammo and caliber info
|
||||
///What magazine this gun starts with, if null it will just use mag_type
|
||||
var/starting_mag_type
|
||||
///Whether the sprite has a visible magazine or not
|
||||
var/mag_display = FALSE
|
||||
///Whether the sprite has a visible ammo display or not
|
||||
@@ -168,9 +170,13 @@
|
||||
update_icon()
|
||||
return
|
||||
if (!magazine)
|
||||
magazine = new mag_type(src)
|
||||
if (!starting_mag_type)
|
||||
magazine = new mag_type(src)
|
||||
else
|
||||
magazine = new starting_mag_type(src)
|
||||
chamber_round()
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/gun/ballistic/update_icon()
|
||||
if (QDELETED(src))
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
var/obj/item/suppressor/S = new(src)
|
||||
install_suppressor(S)
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/pacifist
|
||||
starting_mag_type = /obj/item/ammo_box/magazine/m10mm/sp
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/m1911
|
||||
name = "\improper M1911"
|
||||
desc = "A classic .45 handgun with a small magazine capacity."
|
||||
|
||||
@@ -1500,12 +1500,12 @@
|
||||
/// For tracking when we tell the person we're no longer bleeding
|
||||
var/was_working
|
||||
|
||||
/datum/reagent/medicine/coagulant/on_mob_metabolize(mob/living/M)
|
||||
/datum/reagent/medicine/coagulant/on_mob_add(mob/living/M)
|
||||
ADD_TRAIT(M, TRAIT_COAGULATING, type)
|
||||
ADD_TRAIT(M, TRAIT_PRESERVED_ORGANS, type)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/medicine/coagulant/on_mob_end_metabolize(mob/living/M)
|
||||
/datum/reagent/medicine/coagulant/on_mob_delete(mob/living/M)
|
||||
REMOVE_TRAIT(M, TRAIT_COAGULATING, type)
|
||||
REMOVE_TRAIT(M, TRAIT_PRESERVED_ORGANS, type)
|
||||
return ..()
|
||||
|
||||
@@ -246,6 +246,14 @@
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/board/druid
|
||||
name = "Core Module Design (Druid)"
|
||||
desc = "Allows for the construction of a Druid AI Core Module."
|
||||
id = "druid_module"
|
||||
materials = list(/datum/material/glass = 1000, /datum/material/gold = 2000)
|
||||
build_path = /obj/item/aiModule/core/full/druid
|
||||
category = list("AI Modules")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
//AI CPU + RAM
|
||||
|
||||
|
||||
@@ -444,16 +444,16 @@
|
||||
departmental_flags = DEPARTMENTAL_FLAG_MEDICAL
|
||||
|
||||
/////////////////////////////////////////
|
||||
////////////////Armour///////////////////
|
||||
////////////////Armor///////////////////
|
||||
/////////////////////////////////////////
|
||||
|
||||
/datum/design/reactive_armour
|
||||
name = "Reactive Armour Shell"
|
||||
desc = "An experimental suit of armour capable of utilizing an implanted anomaly core to protect the user."
|
||||
id = "reactive_armour"
|
||||
/datum/design/reactive_armor
|
||||
name = "Reactive Armor Shell"
|
||||
desc = "An experimental suit of armor capable of utilizing an implanted anomaly core to protect the user."
|
||||
id = "reactive_armor"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 10000, /datum/material/diamond = 5000, /datum/material/uranium = 8000, /datum/material/silver = 4500, /datum/material/gold = 5000)
|
||||
build_path = /obj/item/reactive_armour_shell
|
||||
build_path = /obj/item/reactive_armor_shell
|
||||
category = list("Equipment")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SCIENCE | DEPARTMENTAL_FLAG_ENGINEERING
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
|
||||
var/alt_sound = null
|
||||
|
||||
/obj/item/storage/part_replacer/pre_attack(obj/machinery/T, mob/living/user, params)
|
||||
if(!istype(T) || !T.component_parts)
|
||||
if(!istype(T) || (!T.component_parts && !T.works_with_rped_anyways))
|
||||
return ..()
|
||||
if(user.Adjacent(T)) // no TK upgrading.
|
||||
if(works_from_distance)
|
||||
@@ -25,7 +25,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
|
||||
return ..()
|
||||
|
||||
/obj/item/storage/part_replacer/afterattack(obj/machinery/T, mob/living/user, adjacent, params)
|
||||
if(adjacent || !istype(T) || !T.component_parts)
|
||||
if(adjacent || !istype(T) || (!T.component_parts && !T.works_with_rped_anyways))
|
||||
return ..()
|
||||
if(works_from_distance)
|
||||
user.Beam(T, icon_state = "rped_upgrade", time = 5)
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
display_name = "Anomaly Research"
|
||||
description = "Unlock the potential of the mysterious anomalies that appear on station."
|
||||
prereq_ids = list("adv_engi", "practical_bluespace")
|
||||
design_ids = list("reactive_armour", "anomaly_neutralizer")
|
||||
design_ids = list("reactive_armor", "anomaly_neutralizer")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 5000)
|
||||
export_price = 5000
|
||||
|
||||
@@ -377,7 +377,7 @@
|
||||
display_name = "Artificial Intelligence"
|
||||
description = "AI unit research."
|
||||
prereq_ids = list("robotics", "posibrain")
|
||||
design_ids = list("expansion_card_holder", "ai_data_core", "ai_core_display", "ai_control", "ai_server_overview", "ai_resource_distribution", "ai_memory_1", "ai_cpu_1", "aifixer", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module", "reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "crewsimov_module", "paladin_module", "tyrant_module", "overlord_module", "ceo_module", "cowboy_module", "mother_module", "silicop_module", "construction_module", "metaexperiment_module", "researcher_module", "siliconcollective_module", "spotless_module", "clown_module", "chapai_module", "default_module", "borg_ai_control", "mecha_tracking_ai_control", "intellicard")
|
||||
design_ids = list("expansion_card_holder", "ai_data_core", "ai_core_display", "ai_control", "ai_server_overview", "ai_resource_distribution", "ai_memory_1", "ai_cpu_1", "aifixer", "safeguard_module", "onehuman_module", "protectstation_module", "quarantine_module", "oxygen_module", "freeform_module", "reset_module", "purge_module", "remove_module", "freeformcore_module", "asimov_module", "crewsimov_module", "paladin_module", "tyrant_module", "overlord_module", "ceo_module", "cowboy_module", "mother_module", "silicop_module", "construction_module", "metaexperiment_module", "researcher_module", "siliconcollective_module", "spotless_module", "clown_module", "chapai_module", "druid_module", "default_module", "borg_ai_control", "mecha_tracking_ai_control", "intellicard")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
|
||||
|
||||
@@ -98,3 +98,33 @@
|
||||
/obj/effect/proc_holder/spell/targeted/conjure_item/proc/make_item()
|
||||
item = new item_type
|
||||
return item
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/horde
|
||||
name = "Horde"
|
||||
desc = "Bring all your existing bloodmen to you at the cost of 18% blood (15 brain damage for those without blood)."
|
||||
action_icon = 'icons/mob/actions/actions_cult.dmi'
|
||||
action_icon_state = "horde"
|
||||
var/list/summon_type = list("/mob/living/simple_animal/hostile/asteroid/hivelord/legion/bloodman")
|
||||
clothes_req = FALSE
|
||||
var/summon_lifespan = 0
|
||||
var/summon_ignore_density = FALSE
|
||||
var/summon_ignore_prev_spawn_points = TRUE
|
||||
var/list/newVars = list()
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/horde/cast(list/targets,mob/living/carbon/user = usr)
|
||||
var/list/directions = GLOB.alldirs.Copy()
|
||||
if(GLOB.bloodmen_list.len < 1)
|
||||
to_chat(user, span_notice("You don't have any minions to summon!"))
|
||||
return
|
||||
for(var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/bloodman in GLOB.bloodmen_list)
|
||||
var/spawndir = pick_n_take(directions)
|
||||
var/turf/T = get_step(usr, spawndir)
|
||||
if(NOBLOOD in user.dna.species.species_traits)
|
||||
user.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
|
||||
to_chat(usr, span_notice("<span class ='userdanger'>You can almost feel your brain writhing as you call your bloodmen to you.</span>"))
|
||||
else
|
||||
user.blood_volume -= 30
|
||||
to_chat(usr, span_notice("<span class ='userdanger'>You feel yourself becoming paler with every minion called.</span>"))
|
||||
if(T)
|
||||
bloodman.forceMove(T)
|
||||
playsound(usr, 'sound/magic/exit_blood.ogg', 100, 1)
|
||||
|
||||
@@ -138,3 +138,30 @@
|
||||
M.emote("scream")
|
||||
to_chat(M, span_warning("You feel an explosion of pain erupt in your mind!"))
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/touch_attack/raisehand
|
||||
name = "\improper raise bloodman"
|
||||
desc = "Blood covers your hand like a glove as it waits for a new host."
|
||||
on_use_sound = 'sound/magic/wandodeath.ogg'
|
||||
icon_state = "flagellation"
|
||||
item_state = "hivehand"
|
||||
color = "#FF0000"
|
||||
/obj/item/melee/touch_attack/raisehand/afterattack(atom/target, mob/living/carbon/user, proximity)
|
||||
var/mob/living/carbon/human/M = target
|
||||
if(!ishuman(M) || M.stat != DEAD)
|
||||
to_chat(M, span_notice("You must be targeting a dead humanoid!"))
|
||||
return
|
||||
if(GLOB.bloodmen_list.len > 2)
|
||||
to_chat(M, span_notice("You can't control that many minions!"))
|
||||
return
|
||||
if(NOBLOOD in M.dna.species.species_traits)
|
||||
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
|
||||
to_chat(M, span_notice("Your head pounds as you raise a bloodman!"))
|
||||
else
|
||||
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
|
||||
var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/bloodman/L = new(M.loc)
|
||||
L.stored_mob = M
|
||||
M.forceMove(L)
|
||||
qdel(src)
|
||||
user.blood_volume -= 50 // 9% blood cost, cheaper than the other spell because its not like you can stop near a corpse or find one near you in a fight
|
||||
to_chat(user, "<span class ='userdanger'>You curse the body with your blood, leaving you feeling a bit light-headed.</span>")
|
||||
|
||||
@@ -89,3 +89,11 @@
|
||||
action_icon_state = "horror"
|
||||
action_background_icon_state = "bg_ecult"
|
||||
sound = 'sound/magic/fleshtostone.ogg'
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/raise
|
||||
name = "Raise bloodman"
|
||||
desc = "Turn a corpse into a bloodman at the cost of 9% blood (5 brain damage for those without blood)."
|
||||
action_icon = 'icons/mob/actions/actions_cult.dmi'
|
||||
action_icon_state = "raise"
|
||||
hand_path = /obj/item/melee/touch_attack/raisehand
|
||||
clothes_req = FALSE
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
/proc/voice_of_god(message, mob/living/user, list/span_list, base_multiplier = 1, include_speaker = FALSE, message_admins = TRUE, forced_span = FALSE)
|
||||
var/cooldown = 0
|
||||
|
||||
if(!user || !user.can_speak() || user.stat)
|
||||
if(!user || !user.can_speak(message) || user.stat)
|
||||
return 0 //no cooldown
|
||||
|
||||
var/log_message = uppertext(message)
|
||||
|
||||
@@ -517,6 +517,12 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
cost = 6
|
||||
exclude_modes = list(/datum/game_mode/nuclear/clown_ops)
|
||||
|
||||
/datum/uplink_item/dangerous/pistol/spawn_item(spawn_path, mob/user, datum/component/uplink/U)
|
||||
if(HAS_TRAIT_FROM(user, TRAIT_PACIFISM, ROUNDSTART_TRAIT))
|
||||
spawn_path = /obj/item/gun/ballistic/automatic/pistol/pacifist
|
||||
to_chat(user, span_notice("Your employer has loaded your purchased weapon with non-lethal ammunition"))
|
||||
..()
|
||||
|
||||
/datum/uplink_item/dangerous/bolt_action
|
||||
name = "Surplus Rifle"
|
||||
desc = "A horribly outdated bolt action weapon. You've got to be desperate to use this."
|
||||
@@ -1592,9 +1598,9 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
|
||||
/datum/uplink_item/device_tools/surgerybag
|
||||
name = "Syndicate Surgery Duffel Bag"
|
||||
desc = "The Syndicate surgery duffel bag is a toolkit containing all surgery tools, surgical drapes, \
|
||||
a Syndicate brand MMI, a straitjacket, and a muzzle."
|
||||
a Syndicate brand MMI, an implant case, a straitjacket, and a muzzle."
|
||||
item = /obj/item/storage/backpack/duffelbag/syndie/surgery
|
||||
cost = 3
|
||||
cost = 2
|
||||
|
||||
/datum/uplink_item/device_tools/encryptionkey
|
||||
name = "Syndicate Encryption Key"
|
||||
|
||||
@@ -478,6 +478,8 @@ LAW_WEIGHT researcher,0
|
||||
ION_LAW_WEIGHT researcher,1
|
||||
LAW_WEIGHT clown,0
|
||||
ION_LAW_WEIGHT clown,1
|
||||
LAW_WEIGHT druid,0
|
||||
ION_LAW_WEIGHT druid,2
|
||||
|
||||
## Bad idea laws. Probably shouldn't enable these
|
||||
LAW_WEIGHT syndie,0
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<td valign='top'>
|
||||
<font size='2'><b>Current Head Developers:</b> JamieD12, Theos<br></font>
|
||||
<font size='2'><b>Currently Active GitHub contributor list:</b> <a href='https://github.com/yogstation13/Yogstation/graphs/contributors'>-Click Here-</a><br></font>
|
||||
<font size='2'><b>Maintainers:</b> AshCorr, Identification, Monster860, Partheo, Asd, TheGamerdk, adamsogm<br></font>
|
||||
<font size='2'><b>Maintainers:</b> AshCorr, Identification, Monster860, Partheo, Asd, TheGamerdk, adamsogm, baiomu<br></font>
|
||||
<font size='2'><b>Spriters:</b> Identification, Keekenox, Kmc2000, Meeeeep7, Missatessatessy, Toriate, Partheo, r3d<br></font>
|
||||
<font size='2'><b>Mappers:</b> DotLyna, MayhemSailor, Monster860, Ktlwjec, Wejengin2<br></font>
|
||||
<font size='2'><b>Sounds:</b> Lasty/Vinyl, Skie, Swissloaf<br></font>
|
||||
@@ -58,6 +58,178 @@
|
||||
-->
|
||||
<div class="commit sansserif">
|
||||
|
||||
<h2 class="date">20 March 2022</h2>
|
||||
<h3 class="author">TheGamerdk updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">AI Control Console passwords should no longer sporadically fail</li>
|
||||
</ul>
|
||||
<h3 class="author">maxion12345 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">RGB project no longer flashes to one color and stops</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">19 March 2022</h2>
|
||||
<h3 class="author">00ze-cyclone updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">an implant case for the syndie surgery duffel</li>
|
||||
<li class="tweak">cheaper syndie surgery duffel</li>
|
||||
</ul>
|
||||
<h3 class="author">Chubbygummibear updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">cooldown on health analyzer beep so medbay isn't constant beeping</li>
|
||||
</ul>
|
||||
<h3 class="author">MenacingManatee updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Sentient diseases now start with 2 stealth 2 resistance</li>
|
||||
</ul>
|
||||
<h3 class="author">Skrem7 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Adds a new druidic lawset focused on cultivating the organics</li>
|
||||
</ul>
|
||||
<h3 class="author">Sniblet updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">climbing things doesn't discourage waggers</li>
|
||||
<li class="tweak">felinids can now oppress other species</li>
|
||||
</ul>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">cyborgs now get an "eject hat" button that will take off their hat and drop it</li>
|
||||
<li class="bugfix">fixes shitty minesweeper formatting</li>
|
||||
</ul>
|
||||
<h3 class="author">cuackles updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added new simple mob (snail)</li>
|
||||
<li class="imageadd">added some icons and images of said simple mob (snail)</li>
|
||||
</ul>
|
||||
<h3 class="author">nmajask updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed deleting files from disks</li>
|
||||
<li class="tweak">TRAC implant now lasts 15 minutes</li>
|
||||
<li class="tweak">Detectives now start with a modular PDA</li>
|
||||
<li class="tweak">Radar programs now work on PDAs and the implant tracking program now only requires brig access</li>
|
||||
<li class="tweak">captain starts with a phone round start</li>
|
||||
<li class="tweak">CE's phone starts with a sensor package</li>
|
||||
</ul>
|
||||
<h3 class="author">zen373 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Fixes atmos airlock pipes</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">18 March 2022</h2>
|
||||
<h3 class="author"> ToasterBiome, TheGamerdk updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixes engine template failing 28% of the time and picking weird weights for engines</li>
|
||||
<li class="rscadd">legitimizes weird engine weights</li>
|
||||
</ul>
|
||||
<h3 class="author">Sniblet updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">made the code slightly less illiterate</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">17 March 2022</h2>
|
||||
<h3 class="author"> Identification updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="imageadd">Telescopic batons are now a discernible shape</li>
|
||||
</ul>
|
||||
<h3 class="author">Chubbygummibear updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Throwing Mjolnier into someone with anti-magic makes it go bye bye in a big boom</li>
|
||||
</ul>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">removes erroneous admin logging that is not needed</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">16 March 2022</h2>
|
||||
<h3 class="author">Marmio64 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Adds text saying that you can use a lit candle instead of a welder to heat up bowls, substitute cacti for porcini leaves, and that resin uses water now instead of heat to solidify, to the ash walker's knowledge book.</li>
|
||||
<li class="spellcheck">Fixed a typo with poultice making.</li>
|
||||
</ul>
|
||||
<h3 class="author">adamsong updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed bug in dna console sanitization</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">15 March 2022</h2>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">baiomu is now credited under maintainer</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">14 March 2022</h2>
|
||||
<h3 class="author">nmajask updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">pacifists who order stechkins from uplinks now get a version loaded with soporific rounds</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">13 March 2022</h2>
|
||||
<h3 class="author">Absolucy updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Strong holoparasites can now smash objects that restrain their master (click on them as if you were attacking)</li>
|
||||
</ul>
|
||||
<h3 class="author">KillerOrcaCora updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="imageadd">Makes Station engineer skill cape the drippiest thing since air shoes.</li>
|
||||
</ul>
|
||||
<h3 class="author">LazennG updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">adds new legion loot called 'grand core', along with a legion subtype called bloodman/bloodlings.</li>
|
||||
<li class="rscdel">Removes champ's hardsuit from legion loot</li>
|
||||
<li class="imageadd">added some sprites for the grand core and its abilities</li>
|
||||
</ul>
|
||||
<h3 class="author">Sniblet updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Slips now stun instead of paralyzing</li>
|
||||
</ul>
|
||||
<h3 class="author">TheGamerdk updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Appearance ban applies to accent choice too</li>
|
||||
</ul>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">chaplains can no longer roll vampire on traitor+vamp rounds</li>
|
||||
</ul>
|
||||
<h3 class="author">adamsong updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">mentorwho no longer shows admins</li>
|
||||
<li class="bugfix">fixed automute false positives</li>
|
||||
<li class="rscadd">Added show hiddenprints to VV</li>
|
||||
<li class="tweak">borgs can spawn with donor hats if enabled in preferences</li>
|
||||
<li class="tweak">borgs no longer drop hats on module change</li>
|
||||
<li class="rscdel">Removed 2FA requirement to open the permissions panel, still required to edit permissions</li>
|
||||
</ul>
|
||||
<h3 class="author">cuackles updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="imageadd">add a new brass knuckles sprite</li>
|
||||
<li class="imagedel">deleted old brass knuckles sprite</li>
|
||||
</ul>
|
||||
<h3 class="author">tattax updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added blob zombos' sentiency (blobs are smart)</li>
|
||||
<li class="tweak">Changed how Networked Fibers works.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">12 March 2022</h2>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">expands box incinerator to have a little tinkering area</li>
|
||||
<li class="tweak">moves AI sat 3 tiles down on box</li>
|
||||
</ul>
|
||||
<h3 class="author">adamsong updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added button to convert blood brother into traitor</li>
|
||||
</ul>
|
||||
<h3 class="author">maxion12345 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed reactive armor shell names</li>
|
||||
<li class="bugfix">syndicate base has an oven</li>
|
||||
</ul>
|
||||
<h3 class="author">nmajask updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed the vial box in the brig infirmary being the one for virology and fixed the access for the maint door</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">10 March 2022</h2>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
@@ -1071,196 +1243,6 @@
|
||||
<li class="bugfix">fixed a few things</li>
|
||||
<li class="tweak">tweaked a few things</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">19 December 2021</h2>
|
||||
<h3 class="author"> Lucy updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">YogsMeta no longer has bruise packs and ointment in front of medbay, they have been replaced with regenerative mesh and sutures</li>
|
||||
<li class="tweak">YogsMeta's AI MiniSat is now properly wired up at roundstart.</li>
|
||||
<li class="rscadd">You can now spawn in with a jumpskirt if you want!</li>
|
||||
<li class="tweak">The singularity is less likely to fuck off into space now.</li>
|
||||
<li class="rscadd">Adds the Access Kit for infiltrators, which allows them to spoof the ID and access of several "low-level" jobs. It is single-use and only one can be bought per infiltrator.</li>
|
||||
<li class="rscadd">There is now a preference to disable "alternative" potentially misophonia-triggering sounds!</li>
|
||||
</ul>
|
||||
<h3 class="author">Sniblet updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">lexorin now requires chloral hydrate instead of hydrogen</li>
|
||||
<li class="tweak">lexorin now metabolizes 1.25x faster</li>
|
||||
<li class="tweak">lexorin now cannot be tasted (because you're choking)</li>
|
||||
</ul>
|
||||
<h3 class="author">SomeguyManperson updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">you can no longer stealth suck 20000 bloods as a vampire and impact the round in 0 meaningful ways</li>
|
||||
<li class="tweak">the stealth suck low blood warning to the victim has been changed to point at you for screwing up</li>
|
||||
<li class="tweak">vampires get far less blood sucking from braindeads than actual players</li>
|
||||
</ul>
|
||||
<h3 class="author">boodaliboo updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added preternis special healing thing with oil welding fuel and teslium to synths</li>
|
||||
</ul>
|
||||
<h3 class="author">cuackles updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">mummy clothing in the vendor, including headress</li>
|
||||
<li class="rscadd">new holy weapon</li>
|
||||
<li class="imageadd">added skull sprites</li>
|
||||
</ul>
|
||||
<h3 class="author">fluffe9911 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="soundadd">New Jukebox song Glorious Morning!</li>
|
||||
</ul>
|
||||
<h3 class="author">nmajask updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added syndicate disks and trapped disks</li>
|
||||
<li class="tweak">DoS Traffic Generator modular computer item is now an uplink item</li>
|
||||
<li class="tweak">the mining tracking implant kit now stores 4 tracking implant cases, an implanter, and a disk containing the implant tracker program.</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">18 December 2021</h2>
|
||||
<h3 class="author">TheGamerdk updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Instead of being based out of an AI core, the AI is now based out of different data cores around the station. Kill all of these to kill the AI</li>
|
||||
<li class="rscadd">Added servers that can be created and filled with new CPU/RAM cards. These will allow the AI to research and use special upgrades</li>
|
||||
<li class="rscadd">Creating and stealing the AI is now done through the AI upload console. These can be created anywhere but requires the use of a password that starts in the RDs office.</li>
|
||||
<li class="rscdel">Deleted the ability to create regular AI cores</li>
|
||||
<li class="tweak">AI HUD now wraps down to 1 line if playing in widescreen</li>
|
||||
<li class="tweak">When compiling using VSCode you will now automatically run DreamDaemon instead of DreamSeeker. This means hotkeys/movement keys work correctly.</li>
|
||||
<li class="experiment">AI now suffers permadeath if all their cores are knocked offline</li>
|
||||
</ul>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">AI sat airlock</li>
|
||||
<li class="tweak">flip secondary ai core</li>
|
||||
<li class="tweak">fix maint having an extra wall</li>
|
||||
<li class="bugfix">removed extra airlock controller</li>
|
||||
<li class="bugfix">moved air alarm in secondary core so it's not always angry</li>
|
||||
<li class="tweak">adds lights to ai core airlock</li>
|
||||
<li class="bugfix">fixes exterior airlock button opening interior airlock</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">16 December 2021</h2>
|
||||
<h3 class="author"> Identification, Kor updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="imageadd">Unifies both the old cloaks and recently added new cloaks into a single set of cloaks.</li>
|
||||
<li class="tweak">Backpacks don't appear over the top of cloaks</li>
|
||||
</ul>
|
||||
<h3 class="author">UselessTheremin updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">kittens now have randomized names</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">15 December 2021</h2>
|
||||
<h3 class="author">adamsong updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed AO OOC not working</li>
|
||||
<li class="rscadd">Added pretty filter to *me and several other things</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">14 December 2021</h2>
|
||||
<h3 class="author">adamsong updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed borgs being unable to use the advanced analyzer as a surgical processor</li>
|
||||
<li class="bugfix">fixed quirk exploit that allowed for more positive quirks than there were points for</li>
|
||||
<li class="bugfix">fixed buffoonery in the advanced surgical kit tech node</li>
|
||||
</ul>
|
||||
<h3 class="author">nmajask updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed some skirts having no icons when worn by someone with digitigrade legs</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">13 December 2021</h2>
|
||||
<h3 class="author">SomeguyManperson updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">custom shuttle landing points can now be placed on specifically asteroid/lavaland turfs not station maintenance</li>
|
||||
<li class="bugfix">borgs can see their progress bar when buckling again, also they can buckle incapacitated people</li>
|
||||
<li class="bugfix">failing to buckle to a borg will no longer result in you trying to buckle to the same borg a second time</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">12 December 2021</h2>
|
||||
<h3 class="author"> Xoxeyos updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="soundadd">Adds a section of "Christmastime in Sector 5" to the Christmas playlist.</li>
|
||||
</ul>
|
||||
<h3 class="author"> Lucy updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Infiltrators can no longer buy the hacked AI law upload board. Stop screwing with the AI ffs!</li>
|
||||
</ul>
|
||||
<h3 class="author"> Xoxeyos updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="soundadd">Adds a Star Trek parody of Little Drummer Boy to the Christmas playlist.</li>
|
||||
<li class="soundadd">Adds "Beacons in the Darkness" by Gary McGath to the Christmas playlist.</li>
|
||||
</ul>
|
||||
<h3 class="author"> deathrider58 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">When an item is thrown, it will now be rotated and displaced.</li>
|
||||
<li class="rscadd">Shards of glass will now be rotated when spawned.</li>
|
||||
<li class="rscadd">Bullet casings will now be rotated when they're ejected from a gun.</li>
|
||||
<li class="rscadd">Bottles now have random rotations and pixel offsets when smashed via throwing.</li>
|
||||
<li class="rscadd">Picking up an item will now reset its rotation.</li>
|
||||
<li class="rscadd">Glasses thrown onto tables by bartenders will now have their rotation reset.</li>
|
||||
</ul>
|
||||
<h3 class="author">Inari-Whitebear updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixed Remote signaling device UI being cut off</li>
|
||||
<li class="bugfix">Fixed Remote signaling device UI button not having cyan/magenta colours, resulting in black button when those were selected</li>
|
||||
</ul>
|
||||
<h3 class="author">KittyNoodle updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Flamethrowers are now locked behind Makeshift Weapons 101</li>
|
||||
</ul>
|
||||
<h3 class="author">Marmio64 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Adds resin arm bands and tribal bonegel</li>
|
||||
<li class="rscdel">Removed tribalordrazine</li>
|
||||
<li class="tweak">tome of herbal knowledge has new knowledge, polypore resin count upped, tribal poultice recipe changed, chitin spear sinew cost reduced, resin solidifies from water instead of heat.</li>
|
||||
<li class="rscadd">Adds 4 new traits: Hemophiliac, Efficient Metabolism, Crafty, and Cyber Organ.</li>
|
||||
<li class="tweak">trait points are doubled across the board to allow for more middleground. Voracious, tagger, photographer, musician, spiritual, empath, and friendly cost less while Blind and Paraplegic give an extra point.</li>
|
||||
</ul>
|
||||
<h3 class="author">SomeguyManperson updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">reviver implant is now faster, works in soft crit if you aren't sleeping, and has had its heart attack emp effect reduced from a minute to 10 seconds</li>
|
||||
<li class="tweak">sleepers with the stasis upgrade will now put people into stasis under more specific circumstances</li>
|
||||
<li class="bugfix">fixes pickaxes not being allowed to touch the same rock for the length of the initial mining attempt</li>
|
||||
<li class="tweak">brainwashing surgery is available under alien surgery where it used to be</li>
|
||||
<li class="tweak">traitor brainwash disk item is no longer job restricted</li>
|
||||
</ul>
|
||||
<h3 class="author">ToasterBiome updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">mindshields remove mindslave</li>
|
||||
<li class="tweak">mindslaved people reject mindshields</li>
|
||||
<li class="rscadd">best hugs make heart effects idk i dont have mood enabled</li>
|
||||
</ul>
|
||||
<h3 class="author">adamsong updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">Added advanced health analyzer upgrade to med borgs</li>
|
||||
<li class="rscdel">Removed surgical processor from med borgs</li>
|
||||
<li class="bugfix">fixed mfa reset telling you the wrong thing was reset</li>
|
||||
<li class="bugfix">fixed but allowing antag tokens to be used more than once</li>
|
||||
<li class="bugfix">fixed revs not properly prioritizing antag tokens</li>
|
||||
<li class="bugfix">fixed airlocks sometimes being invisible when painted</li>
|
||||
</ul>
|
||||
<h3 class="author">nmajask updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="tweak">Fission360 now has a program icon</li>
|
||||
<li class="tweak">modular computer program overlays now glow in the dark</li>
|
||||
<li class="rscadd">Added OverSeer, a program to view labor camp cameras</li>
|
||||
<li class="bugfix">fixed crew monitors labeling people in soft crit and unconscious as dead</li>
|
||||
<li class="tweak">brig physicians now have access to perma</li>
|
||||
</ul>
|
||||
<h3 class="author">wejengin2 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="rscadd">new interaction for licking the supermatter</li>
|
||||
<li class="soundadd">Adds some songs to the april fools playlist</li>
|
||||
</ul>
|
||||
|
||||
<h2 class="date">11 December 2021</h2>
|
||||
<h3 class="author"> Lucy updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">Fixed holoparasite masters not being able to communicate with their holoparasites. Whoops.</li>
|
||||
</ul>
|
||||
<h3 class="author">maxion12345 updated:</h3>
|
||||
<ul class="changes bgimages16">
|
||||
<li class="bugfix">fixed a locker name in the yogurtstation brig</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<b>GoonStation 13 Development Team</b>
|
||||
|
||||
@@ -30282,3 +30282,111 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py.
|
||||
- bugfix: fixed runtime in remove_accessory
|
||||
cuackles:
|
||||
- tweak: tweaked a few things
|
||||
2022-03-12:
|
||||
ToasterBiome:
|
||||
- rscadd: expands box incinerator to have a little tinkering area
|
||||
- tweak: moves AI sat 3 tiles down on box
|
||||
adamsong:
|
||||
- rscadd: Added button to convert blood brother into traitor
|
||||
maxion12345:
|
||||
- bugfix: fixed reactive armor shell names
|
||||
- bugfix: syndicate base has an oven
|
||||
nmajask:
|
||||
- bugfix: fixed the vial box in the brig infirmary being the one for virology and
|
||||
fixed the access for the maint door
|
||||
2022-03-13:
|
||||
Absolucy:
|
||||
- rscadd: Strong holoparasites can now smash objects that restrain their master
|
||||
(click on them as if you were attacking)
|
||||
KillerOrcaCora:
|
||||
- imageadd: Makes Station engineer skill cape the drippiest thing since air shoes.
|
||||
LazennG:
|
||||
- rscadd: adds new legion loot called 'grand core', along with a legion subtype
|
||||
called bloodman/bloodlings.
|
||||
- rscdel: Removes champ's hardsuit from legion loot
|
||||
- imageadd: added some sprites for the grand core and its abilities
|
||||
Sniblet:
|
||||
- tweak: Slips now stun instead of paralyzing
|
||||
TheGamerdk:
|
||||
- tweak: Appearance ban applies to accent choice too
|
||||
ToasterBiome:
|
||||
- bugfix: chaplains can no longer roll vampire on traitor+vamp rounds
|
||||
adamsong:
|
||||
- tweak: mentorwho no longer shows admins
|
||||
- bugfix: fixed automute false positives
|
||||
- rscadd: Added show hiddenprints to VV
|
||||
- tweak: borgs can spawn with donor hats if enabled in preferences
|
||||
- tweak: borgs no longer drop hats on module change
|
||||
- rscdel: Removed 2FA requirement to open the permissions panel, still required
|
||||
to edit permissions
|
||||
cuackles:
|
||||
- imageadd: add a new brass knuckles sprite
|
||||
- imagedel: deleted old brass knuckles sprite
|
||||
tattax:
|
||||
- rscadd: Added blob zombos' sentiency (blobs are smart)
|
||||
- tweak: Changed how Networked Fibers works.
|
||||
2022-03-14:
|
||||
nmajask:
|
||||
- tweak: pacifists who order stechkins from uplinks now get a version loaded with
|
||||
soporific rounds
|
||||
2022-03-15:
|
||||
ToasterBiome:
|
||||
- rscadd: baiomu is now credited under maintainer
|
||||
2022-03-16:
|
||||
Marmio64:
|
||||
- rscadd: Adds text saying that you can use a lit candle instead of a welder to
|
||||
heat up bowls, substitute cacti for porcini leaves, and that resin uses water
|
||||
now instead of heat to solidify, to the ash walker's knowledge book.
|
||||
- spellcheck: Fixed a typo with poultice making.
|
||||
adamsong:
|
||||
- bugfix: fixed bug in dna console sanitization
|
||||
2022-03-17:
|
||||
' Identification':
|
||||
- imageadd: Telescopic batons are now a discernible shape
|
||||
Chubbygummibear:
|
||||
- rscadd: Throwing Mjolnier into someone with anti-magic makes it go bye bye in
|
||||
a big boom
|
||||
ToasterBiome:
|
||||
- bugfix: removes erroneous admin logging that is not needed
|
||||
2022-03-18:
|
||||
' ToasterBiome, TheGamerdk':
|
||||
- bugfix: fixes engine template failing 28% of the time and picking weird weights
|
||||
for engines
|
||||
- rscadd: legitimizes weird engine weights
|
||||
Sniblet:
|
||||
- tweak: made the code slightly less illiterate
|
||||
2022-03-19:
|
||||
00ze-cyclone:
|
||||
- rscadd: an implant case for the syndie surgery duffel
|
||||
- tweak: cheaper syndie surgery duffel
|
||||
Chubbygummibear:
|
||||
- tweak: cooldown on health analyzer beep so medbay isn't constant beeping
|
||||
MenacingManatee:
|
||||
- tweak: Sentient diseases now start with 2 stealth 2 resistance
|
||||
Skrem7:
|
||||
- rscadd: Adds a new druidic lawset focused on cultivating the organics
|
||||
Sniblet:
|
||||
- bugfix: climbing things doesn't discourage waggers
|
||||
- tweak: felinids can now oppress other species
|
||||
ToasterBiome:
|
||||
- rscadd: cyborgs now get an "eject hat" button that will take off their hat and
|
||||
drop it
|
||||
- bugfix: fixes shitty minesweeper formatting
|
||||
cuackles:
|
||||
- rscadd: Added new simple mob (snail)
|
||||
- imageadd: added some icons and images of said simple mob (snail)
|
||||
nmajask:
|
||||
- bugfix: fixed deleting files from disks
|
||||
- tweak: TRAC implant now lasts 15 minutes
|
||||
- tweak: ' Detectives now start with a modular PDA'
|
||||
- tweak: Radar programs now work on PDAs and the implant tracking program now only
|
||||
requires brig access
|
||||
- tweak: captain starts with a phone round start
|
||||
- tweak: CE's phone starts with a sensor package
|
||||
zen373:
|
||||
- tweak: Fixes atmos airlock pipes
|
||||
2022-03-20:
|
||||
TheGamerdk:
|
||||
- bugfix: AI Control Console passwords should no longer sporadically fail
|
||||
maxion12345:
|
||||
- bugfix: RGB project no longer flashes to one color and stops
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<td valign='top'>
|
||||
<font size='2'><b>Current Head Developers:</b> JamieD12, Theos<br></font>
|
||||
<font size='2'><b>Currently Active GitHub contributor list:</b> <a href='https://github.com/yogstation13/Yogstation/graphs/contributors'>-Click Here-</a><br></font>
|
||||
<font size='2'><b>Maintainers:</b> AshCorr, Identification, Monster860, Partheo, Asd, TheGamerdk, adamsogm<br></font>
|
||||
<font size='2'><b>Maintainers:</b> AshCorr, Identification, Monster860, Partheo, Asd, TheGamerdk, adamsogm, baiomu<br></font>
|
||||
<font size='2'><b>Spriters:</b> Identification, Keekenox, Kmc2000, Meeeeep7, Missatessatessy, Toriate, Partheo, r3d<br></font>
|
||||
<font size='2'><b>Mappers:</b> DotLyna, MayhemSailor, Monster860, Ktlwjec, Wejengin2<br></font>
|
||||
<font size='2'><b>Sounds:</b> Lasty/Vinyl, Skie, Swissloaf<br></font>
|
||||
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 250 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 144 KiB |
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |