Merge branch 'master' into upstream-merge-38661

This commit is contained in:
LetterJay
2018-06-24 18:13:53 -05:00
committed by GitHub
63 changed files with 510 additions and 384 deletions
-2
View File
@@ -27,7 +27,6 @@ matrix:
addons:
apt:
packages:
- libc6-i386
- libstdc++6:i386
cache:
directories:
@@ -39,7 +38,6 @@ matrix:
mariadb: '10.2'
apt:
packages:
- libc6-i386
- libstdc++6:i386
- libssl-dev:i386
- gcc-multilib
+9 -10
View File
@@ -203,21 +203,20 @@
//Print a list of antagonists to the server log
var/list/total_antagonists = list()
//Look into all mobs in world, dead or alive
for(var/datum/mind/Mind in minds)
var/temprole = Mind.special_role
if(temprole) //if they are an antagonist of some sort.
if(temprole in total_antagonists) //If the role exists already, add the name to it
total_antagonists[temprole] += ", [Mind.name]([Mind.key])"
else
total_antagonists.Add(temprole) //If the role doesnt exist in the list, create it and add the mob
total_antagonists[temprole] += ": [Mind.name]([Mind.key])"
for(var/datum/antagonist/A in GLOB.antagonists)
if(!A.owner)
continue
if(!(A.name in total_antagonists))
total_antagonists[A.name] = list()
total_antagonists[A.name] += "[key_name(A.owner)]"
CHECK_TICK
//Now print them all into the log!
log_game("Antagonists at round end were...")
for(var/i in total_antagonists)
log_game("[i]s[total_antagonists[i]].")
for(var/antag_name in total_antagonists)
var/list/L = total_antagonists[antag_name]
log_game("[antag_name]s :[L.Join(", ")].")
CHECK_TICK
SSdbcore.SetRoundEnd()
+19 -5
View File
@@ -375,6 +375,7 @@ Turf and target are separate in case you want to teleport some distance from a t
var/client/C
var/key
var/ckey
var/fallback_name
if(!whom)
return "*null*"
@@ -394,6 +395,16 @@ Turf and target are separate in case you want to teleport some distance from a t
C = GLOB.directory[ckey]
if(C)
M = C.mob
else if(istype(whom,/datum/mind))
var/datum/mind/mind = whom
key = mind.key
ckey = ckey(key)
if(mind.current)
M = mind.current
if(M.client)
C = M.client
else
fallback_name = mind.name
else
return "*invalid*"
@@ -419,11 +430,14 @@ Turf and target are separate in case you want to teleport some distance from a t
else
. += "*no key*"
if(include_name && M)
if(M.real_name)
. += "/([M.real_name])"
else if(M.name)
. += "/([M.name])"
if(include_name)
if(M)
if(M.real_name)
. += "/([M.real_name])"
else if(M.name)
. += "/([M.name])"
else if(fallback_name)
. += "/([fallback_name])"
return .
+18
View File
@@ -237,11 +237,29 @@ Delayed insert mode was removed in mysql 7 and only works with MyISAM type table
item = list()
_db_query = _dm_db_new_query()
/datum/DBQuery/Destroy()
Close()
SSdbcore.active_queries -= src
return ..()
/datum/DBQuery/CanProcCall(proc_name)
//fuck off kevinz
return FALSE
/datum/DBQuery/proc/Activity(activity)
last_activity = activity
last_activity_time = world.time
/datum/DBQuery/proc/warn_execute()
. = Execute()
if(!.)
to_chat(usr, "<span class='danger'>A SQL error occurred during this operation, check the server logs.</span>")
/datum/DBQuery/proc/SetQuery(new_sql)
Activity("SetQuery")
Close()
sql = new_sql
/datum/DBQuery/proc/Execute(sql_query = sql, cursor_handler = default_cursor, log_error = TRUE)
var/start_time
var/timeout = CONFIG_GET(number/query_debug_log_timeout)
@@ -78,5 +78,8 @@ PROCESSING_SUBSYSTEM_DEF(circuit)
/obj/item/integrated_electronics/wirer,
/obj/item/integrated_electronics/debugger,
/obj/item/integrated_electronics/analyzer,
/obj/item/integrated_electronics/detailer
/obj/item/integrated_electronics/detailer,
/obj/item/card/data,
/obj/item/card/data/full_color,
/obj/item/card/data/disk
)
@@ -45,8 +45,9 @@
/obj/machinery/computer/communications/process()
if(..())
if(state != STATE_STATUSDISPLAY && state != STATE_CALLSHUTTLE && state != STATE_PURCHASE && state != STATE_VIEWMESSAGE)
updateDialog()
var/ai_autoupdate = aistate != STATE_STATUSDISPLAY && aistate != STATE_CALLSHUTTLE && aistate != STATE_PURCHASE && aistate != STATE_VIEWMESSAGE
var/machine_user_autoupdate = state != STATE_STATUSDISPLAY && state != STATE_CALLSHUTTLE && state != STATE_PURCHASE && state != STATE_VIEWMESSAGE
updateDialog(machine_user_autoupdate,ai_autoupdate)
/obj/machinery/computer/communications/Topic(href, href_list)
if(..())
+2 -2
View File
@@ -11,8 +11,8 @@
var/static/list/AllTeleporters
/obj/effect/bump_teleporter/New()
..()
/obj/effect/bump_teleporter/Initialize()
. = ..()
LAZYADD(AllTeleporters, src)
/obj/effect/bump_teleporter/Destroy()
+2 -2
View File
@@ -14,9 +14,9 @@
anchored = TRUE
layer = GHOST_LAYER
/obj/effect/countdown/New(atom/A)
/obj/effect/countdown/Initialize()
. = ..()
attach(A)
attach(loc)
/obj/effect/countdown/examine(mob/user)
. = ..()
@@ -12,13 +12,13 @@ would spawn and follow the beaker, even if it is carried or thrown.
pass_flags = PASSTABLE | PASSGRILLE
anchored = TRUE
/obj/effect/particle_effect/New()
..()
/obj/effect/particle_effect/Initialize()
. = ..()
GLOB.cameranet.updateVisibility(src)
/obj/effect/particle_effect/Destroy()
GLOB.cameranet.updateVisibility(src)
. = ..()
return ..()
/datum/effect_system
var/number = 3
@@ -4,8 +4,8 @@
opacity = 1
anchored = TRUE
/obj/effect/particle_effect/expl_particles/New()
..()
/obj/effect/particle_effect/expl_particles/Initialize()
. = ..()
QDEL_IN(src, 15)
/datum/effect_system/expl_particles
@@ -29,8 +29,8 @@
pixel_x = -32
pixel_y = -32
/obj/effect/explosion/New()
..()
/obj/effect/explosion/Initialize()
. = ..()
QDEL_IN(src, 10)
/datum/effect_system/explosion
@@ -270,8 +270,8 @@
max_integrity = 20
CanAtmosPass = ATMOS_PASS_DENSITY
/obj/structure/foamedmetal/New()
..()
/obj/structure/foamedmetal/Initialize()
. = ..()
air_update_turf(1)
@@ -30,8 +30,8 @@
set_opacity(0) //if we were blocking view, we aren't now because we're fading out
stoplag()
/obj/effect/particle_effect/smoke/New()
..()
/obj/effect/particle_effect/smoke/Initialize()
. = ..()
create_reagents(500)
START_PROCESSING(SSobj, src)
@@ -22,8 +22,8 @@
anchored = TRUE
light_range = 1
/obj/effect/particle_effect/sparks/New()
..()
/obj/effect/particle_effect/sparks/Initialize()
. = ..()
flick("sparks", src) // replay the animation
playsound(src.loc, "sparks", 100, 1)
var/turf/T = loc
@@ -7,8 +7,8 @@
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/obj/effect/particle_effect/water/New()
..()
/obj/effect/particle_effect/water/Initialize()
. = ..()
QDEL_IN(src, 70)
/obj/effect/particle_effect/water/Move(turf/newloc)
@@ -45,8 +45,8 @@ steam.start() -- spawns the effect
icon_state = "extinguish"
density = FALSE
/obj/effect/particle_effect/steam/New()
..()
/obj/effect/particle_effect/steam/Initialize()
. = ..()
QDEL_IN(src, 20)
/datum/effect_system/steam_spread
+2 -2
View File
@@ -8,8 +8,8 @@
CanAtmosPass = ATMOS_PASS_DENSITY
var/timeleft = 300 //Set to 0 for permanent forcefields (ugh)
/obj/effect/forcefield/New()
..()
/obj/effect/forcefield/Initialize()
. = ..()
if(timeleft)
QDEL_IN(src, timeleft)
+3 -2
View File
@@ -3,8 +3,9 @@
icon = 'icons/mob/screen_gen.dmi'
icon_state = "x"
/obj/effect/manifest/New()
src.invisibility = INVISIBILITY_ABSTRACT
/obj/effect/manifest/Initialize()
. = ..()
invisibility = INVISIBILITY_ABSTRACT
/obj/effect/manifest/proc/manifest()
var/dat = "<B>Crew Manifest</B>:<BR>"
+2 -2
View File
@@ -98,8 +98,8 @@
density = FALSE
var/duration = 0
/obj/effect/mine/pickup/New()
..()
/obj/effect/mine/pickup/Initialize()
. = ..()
animate(src, pixel_y = 4, time = 20, loop = -1)
/obj/effect/mine/pickup/triggermine(mob/victim)
+2 -2
View File
@@ -13,8 +13,8 @@
icon_state="b_beam"
var/atom/BeamSource
/obj/effect/overlay/beam/New()
..()
/obj/effect/overlay/beam/Initialize()
. = ..()
QDEL_IN(src, 10)
/obj/effect/overlay/palmtree_r
+2 -2
View File
@@ -15,8 +15,8 @@
var/obj/item/toner/ink = null
/obj/item/airlock_painter/New()
..()
/obj/item/airlock_painter/Initialize()
. = ..()
ink = new /obj/item/toner(src)
//This proc doesn't just check if the painter can be used, but also uses it.
+2 -2
View File
@@ -14,8 +14,8 @@
var/start_lit = FALSE
heat = 1000
/obj/item/candle/New()
..()
/obj/item/candle/Initialize()
. = ..()
if(start_lit)
// No visible message
light(show_message = FALSE)
+34 -15
View File
@@ -9,7 +9,7 @@
/*
* DATA CARDS - Used for the teleporter
* DATA CARDS - Used for the IC data card reader
*/
/obj/item/card
name = "card"
@@ -24,30 +24,49 @@
return BRUTELOSS
/obj/item/card/data
name = "data disk"
desc = "A disk of data."
icon_state = "data"
name = "data card"
desc = "A plastic magstripe card for simple and speedy data storage and transfer. This one has a stripe running down the middle."
icon_state = "data_1"
obj_flags = UNIQUE_RENAME
var/function = "storage"
var/data = "null"
var/special = null
item_state = "card-id"
lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi'
var/detail_color = COLOR_ASSEMBLY_ORANGE
/obj/item/card/data/verb/label(t as text)
set name = "Label Disk"
set category = "Object"
set src in usr
/obj/item/card/data/Initialize()
.=..()
update_icon()
if(usr.stat || !usr.canmove || usr.restrained())
/obj/item/card/data/update_icon()
cut_overlays()
if(detail_color == COLOR_FLOORTILE_GRAY)
return
var/mutable_appearance/detail_overlay = mutable_appearance('icons/obj/card.dmi', "[icon_state]-color")
detail_overlay.color = detail_color
add_overlay(detail_overlay)
if (t)
src.name = "data disk- '[t]'"
else
src.name = "data disk"
src.add_fingerprint(usr)
return
/obj/item/card/data/attackby(obj/item/I, mob/living/user)
if(istype(I, /obj/item/integrated_electronics/detailer))
var/obj/item/integrated_electronics/detailer/D = I
detail_color = D.detail_color
update_icon()
return ..()
/obj/item/proc/GetCard()
/obj/item/card/data/GetCard()
return src
/obj/item/card/data/full_color
desc = "A plastic magstripe card for simple and speedy data storage and transfer. This one has the entire card colored."
icon_state = "data_2"
/obj/item/card/data/disk
desc = "A plastic magstripe card for simple and speedy data storage and transfer. This one inexplicibly looks like a floppy disk."
icon_state = "data_3"
/*
* ID CARDS
+15 -2
View File
@@ -92,8 +92,12 @@ GLOBAL_LIST_EMPTY(PDAs)
..()
if(!id && !inserted_item)
return
else
to_chat(user, "<span class='notice'>Alt-click to remove contents.</span>")
if(id)
to_chat(user, "<span class='notice'>Alt-click to remove the id.</span>")
if(inserted_item && (!isturf(loc)))
to_chat(user, "<span class='notice'>Ctrl-click to remove [inserted_item].</span>")
/obj/item/pda/Initialize()
. = ..()
@@ -712,6 +716,15 @@ GLOBAL_LIST_EMPTY(PDAs)
else
remove_pen()
/obj/item/pda/CtrlClick()
..()
if(issilicon(usr))
return
if(usr.canUseTopic(src) && !isturf(loc))
remove_pen()
/obj/item/pda/verb/verb_remove_id()
set category = "Object"
set name = "Eject ID"
@@ -160,11 +160,22 @@
if(sensor.on && sensor.visible)
add_overlay("proxy_beam")
/obj/item/transfer_valve/proc/merge_gases()
tank_two.air_contents.volume += tank_one.air_contents.volume
/obj/item/transfer_valve/proc/merge_gases(datum/gas_mixture/target, change_volume = TRUE)
var/target_self = FALSE
if(!target || (target == tank_one.air_contents))
target = tank_two.air_contents
if(target == tank_two.air_contents)
target_self = TRUE
if(change_volume)
if(!target_self)
target.volume += tank_two.volume
target.volume += tank_one.air_contents.volume
var/datum/gas_mixture/temp
temp = tank_one.air_contents.remove_ratio(1)
tank_two.air_contents.merge(temp)
target.merge(temp)
if(!target_self)
temp = tank_two.air_contents.remove_ratio(1)
target.merge(temp)
/obj/item/transfer_valve/proc/split_gases()
if (!valve_open || !tank_one || !tank_two)
@@ -67,6 +67,7 @@
attack_verb = list("bluespace polybashed", "bluespace polybattered", "bluespace polybludgeoned", "bluespace polythrashed", "bluespace polysmashed")
novariants = TRUE
grind_results = list("bluespace" = 20)
point_value = 30
var/crystal_type = /obj/item/stack/ore/bluespace_crystal/refined
/obj/item/stack/sheet/bluespace_crystal/attack_self(mob/user)// to prevent the construction menu from ever happening
@@ -24,6 +24,7 @@ GLOBAL_LIST_INIT(glass_recipes, list ( \
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/glass
grind_results = list("silicon" = 20)
point_value = 1
/obj/item/stack/sheet/glass/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins to slice [user.p_their()] neck with \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -138,6 +139,7 @@ GLOBAL_LIST_INIT(reinforced_glass_recipes, list ( \
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/rglass
grind_results = list("silicon" = 20, "iron" = 10)
point_value = 4
/obj/item/stack/sheet/rglass/attackby(obj/item/W, mob/user, params)
add_fingerprint(user)
@@ -180,6 +182,7 @@ GLOBAL_LIST_INIT(prglass_recipes, list ( \
resistance_flags = ACID_PROOF
merge_type = /obj/item/stack/sheet/plasmarglass
grind_results = list("silicon" = 20, "plasma" = 10, "iron" = 10)
point_value = 23
/obj/item/stack/sheet/plasmarglass/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.prglass_recipes
@@ -104,6 +104,7 @@ GLOBAL_LIST_INIT(sandbag_recipes, list ( \
materials = list(MAT_DIAMOND=MINERAL_MATERIAL_AMOUNT)
novariants = TRUE
grind_results = list("carbon" = 20)
point_value = 25
GLOBAL_LIST_INIT(diamond_recipes, list ( \
new/datum/stack_recipe("diamond door", /obj/structure/mineral_door/transparent/diamond, 10, one_per_turf = 1, on_floor = 1), \
@@ -129,6 +130,7 @@ GLOBAL_LIST_INIT(diamond_recipes, list ( \
materials = list(MAT_URANIUM=MINERAL_MATERIAL_AMOUNT)
novariants = TRUE
grind_results = list("uranium" = 20)
point_value = 20
GLOBAL_LIST_INIT(uranium_recipes, list ( \
new/datum/stack_recipe("uranium door", /obj/structure/mineral_door/uranium, 10, one_per_turf = 1, on_floor = 1), \
@@ -154,6 +156,7 @@ GLOBAL_LIST_INIT(uranium_recipes, list ( \
max_integrity = 100
materials = list(MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
grind_results = list("plasma" = 20)
point_value = 20
/obj/item/stack/sheet/mineral/plasma/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins licking \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
@@ -193,6 +196,7 @@ GLOBAL_LIST_INIT(plasma_recipes, list ( \
sheettype = "gold"
materials = list(MAT_GOLD=MINERAL_MATERIAL_AMOUNT)
grind_results = list("gold" = 20)
point_value = 20
GLOBAL_LIST_INIT(gold_recipes, list ( \
new/datum/stack_recipe("golden door", /obj/structure/mineral_door/gold, 10, one_per_turf = 1, on_floor = 1), \
@@ -220,6 +224,7 @@ GLOBAL_LIST_INIT(gold_recipes, list ( \
sheettype = "silver"
materials = list(MAT_SILVER=MINERAL_MATERIAL_AMOUNT)
grind_results = list("silver" = 20)
point_value = 20
GLOBAL_LIST_INIT(silver_recipes, list ( \
new/datum/stack_recipe("silver door", /obj/structure/mineral_door/silver, 10, one_per_turf = 1, on_floor = 1), \
@@ -247,6 +252,7 @@ GLOBAL_LIST_INIT(silver_recipes, list ( \
materials = list(MAT_BANANIUM=MINERAL_MATERIAL_AMOUNT)
novariants = TRUE
grind_results = list("banana" = 20)
point_value = 50
GLOBAL_LIST_INIT(bananium_recipes, list ( \
new/datum/stack_recipe("bananium tile", /obj/item/stack/tile/mineral/bananium, 1, 4, 20), \
@@ -272,6 +278,7 @@ GLOBAL_LIST_INIT(bananium_recipes, list ( \
throw_range = 3
sheettype = "titanium"
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT)
point_value = 20
GLOBAL_LIST_INIT(titanium_recipes, list ( \
new/datum/stack_recipe("titanium tile", /obj/item/stack/tile/mineral/titanium, 1, 4, 20), \
@@ -300,6 +307,7 @@ GLOBAL_LIST_INIT(titanium_recipes, list ( \
throw_range = 3
sheettype = "plastitanium"
materials = list(MAT_TITANIUM=MINERAL_MATERIAL_AMOUNT, MAT_PLASMA=MINERAL_MATERIAL_AMOUNT)
point_value = 45
GLOBAL_LIST_INIT(plastitanium_recipes, list ( \
new/datum/stack_recipe("plas-titanium tile", /obj/item/stack/tile/mineral/plastitanium, 1, 4, 20), \
@@ -106,6 +106,7 @@ GLOBAL_LIST_INIT(metal_recipes, list ( \
resistance_flags = FIRE_PROOF
merge_type = /obj/item/stack/sheet/metal
grind_results = list("iron" = 20)
point_value = 2
/obj/item/stack/sheet/metal/ratvar_act()
new /obj/item/stack/tile/brass(loc, amount)
@@ -166,6 +167,7 @@ GLOBAL_LIST_INIT(plasteel_recipes, list ( \
resistance_flags = FIRE_PROOF
merge_type = /obj/item/stack/sheet/plasteel
grind_results = list("iron" = 20, "plasma" = 20)
point_value = 23
/obj/item/stack/sheet/plasteel/Initialize(mapload, new_amount, merge = TRUE)
recipes = GLOB.plasteel_recipes
@@ -11,4 +11,5 @@
attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "smashed")
novariants = FALSE
var/perunit = MINERAL_MATERIAL_AMOUNT
var/sheettype = null //this is used for girders in the creation of walls/false walls
var/sheettype = null //this is used for girders in the creation of walls/false walls
var/point_value = 0 //turn-in value for the gulag stacker - loosely relative to its rarity.
@@ -231,3 +231,35 @@
new /obj/item/reagent_containers/pill/patch/silver_sulf(src)
for(var/i in 1 to 3)
new /obj/item/reagent_containers/pill/patch/styptic(src)
/obj/item/storage/pill_bottle/zoom
name = "suspicious pill bottle"
desc = "The label is pretty old and almost unreadable, you recognize some chemical compounds."
/obj/item/storage/pill_bottle/zoom/PopulateContents()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/pill/zoom(src)
/obj/item/storage/pill_bottle/happy
name = "suspicious pill bottle"
desc = "There is a smiley on the top."
/obj/item/storage/pill_bottle/happy/PopulateContents()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/pill/happy(src)
/obj/item/storage/pill_bottle/lsd
name = "suspicious pill bottle"
desc = "There is a badly drawn thing with the shape of a mushroom."
/obj/item/storage/pill_bottle/lsd/PopulateContents()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/pill/lsd(src)
/obj/item/storage/pill_bottle/aranesp
name = "suspicious pill bottle"
desc = "The label says 'gotta go fast'."
/obj/item/storage/pill_bottle/aranesp/PopulateContents()
for(var/i in 1 to 5)
new /obj/item/reagent_containers/pill/aranesp(src)
-1
View File
@@ -226,7 +226,6 @@
air_contents.react()
check_status()
/obj/item/tank/proc/check_status()
//Handle exploding, leaking, and rupturing of the tank
+13 -10
View File
@@ -138,19 +138,22 @@
else
obj_flags &= ~IN_USE
/obj/proc/updateDialog()
/obj/proc/updateDialog(update_viewers = TRUE,update_ais = TRUE)
// Check that people are actually using the machine. If not, don't update anymore.
if(obj_flags & IN_USE)
var/list/nearby = viewers(1, src)
var/is_in_use = 0
for(var/mob/M in nearby)
if ((M.client && M.machine == src))
is_in_use = 1
src.interact(M)
var/ai_in_use = AutoUpdateAI(src)
var/is_in_use = FALSE
if(update_viewers)
for(var/mob/M in viewers(1, src))
if ((M.client && M.machine == src))
is_in_use = TRUE
src.interact(M)
var/ai_in_use = FALSE
if(update_ais)
ai_in_use = AutoUpdateAI(src)
if(!ai_in_use && !is_in_use)
obj_flags &= ~IN_USE
if(update_viewers && update_ais) //State change is sure only if we check both
if(!ai_in_use && !is_in_use)
obj_flags &= ~IN_USE
/obj/attack_ghost(mob/user)
+1 -1
View File
@@ -6,7 +6,7 @@
anchored = TRUE
var/popped = FALSE
/obj/effect/fun_balloon/New()
/obj/effect/fun_balloon/Initialize()
. = ..()
SSobj.processing |= src
+1 -1
View File
@@ -57,7 +57,7 @@
var/mob/living/carbon/human/H = null
for(var/mob/living/carbon/human/applicant in GLOB.player_list)
if(isReadytoRumble(applicant, ROLE_TRAITOR, FALSE))
if(isReadytoRumble(applicant, ROLE_TRAITOR))
if(temp.age_check(applicant.client))
if(!(applicant.job in temp.restricted_jobs))
candidates += applicant
@@ -496,10 +496,4 @@
#undef STIMULUM_SECOND_RISE
#undef STIMULUM_ABSOLUTE_DROP
#undef REACTION_OPPRESSION_THRESHOLD
#undef PLASMA_BINDING_ENERGY
#undef MAX_CATALYST_EFFICENCY
#undef PLASMA_FUSED_COEFFICENT
#undef CATALYST_COEFFICENT
#undef FUSION_PURITY_THRESHOLD
#undef FUSION_HEAT_DROPOFF
#undef NOBLIUM_FORMATION_ENERGY
+16 -4
View File
@@ -1746,14 +1746,26 @@
/datum/supply_pack/costumes_toys/randomised/contraband
name = "Contraband Crate"
desc = "Psst.. bud... want some contraband? I can get you a poster, some nice cigs, bling, even some ambrosia deus...you know, the good stuff. Just keep it away from the cops, kay?"
desc = "Psst.. bud... want some contraband? I can get you a poster, some nice cigs, dank, even some sponsored items...you know, the good stuff. Just keep it away from the cops, kay?"
contraband = TRUE
cost = 3000
num_contained = 5
num_contained = 7
contains = list(/obj/item/poster/random_contraband,
/obj/item/poster/random_contraband,
/obj/item/reagent_containers/food/snacks/grown/cannabis,
/obj/item/reagent_containers/food/snacks/grown/cannabis/rainbow,
/obj/item/reagent_containers/food/snacks/grown/cannabis/white,
/obj/item/storage/pill_bottle/zoom,
/obj/item/storage/pill_bottle/happy,
/obj/item/storage/pill_bottle/lsd,
/obj/item/storage/pill_bottle/aranesp,
/obj/item/storage/pill_bottle/stimulant,
/obj/item/toy/cards/deck/syndicate,
/obj/item/reagent_containers/food/drinks/bottle/absinthe,
/obj/item/clothing/under/syndicate/tacticool,
/obj/item/storage/fancy/cigarettes/cigpack_syndicate,
/obj/item/storage/fancy/cigarettes/cigpack_shadyjims,
/obj/item/storage/fancy/cigarettes/cigpack_midori,
/obj/item/seeds/ambrosia/deus,
/obj/item/clothing/mask/gas/syndicate,
/obj/item/clothing/neck/necklace/dope)
crate_name = "crate"
+7 -2
View File
@@ -100,6 +100,11 @@
icon_state = "scarf"
color = "#4A4A4B" //Grey but it looks black
/obj/item/clothing/neck/scarf/pink
name = "pink scarf"
icon_state = "scarf"
color = "#F699CD" //Pink
/obj/item/clothing/neck/scarf/red
name = "red scarf"
icon_state = "scarf"
@@ -118,7 +123,7 @@
/obj/item/clothing/neck/scarf/purple
name = "purple scarf"
icon_state = "scarf"
color = "#9557C5" //purple
color = "#9557C5" //Purple
/obj/item/clothing/neck/scarf/yellow
name = "yellow scarf"
@@ -128,7 +133,7 @@
/obj/item/clothing/neck/scarf/orange
name = "orange scarf"
icon_state = "scarf"
color = "#C67A4B" //orange
color = "#C67A4B" //Orange
/obj/item/clothing/neck/scarf/cyan
name = "cyan scarf"
@@ -59,7 +59,7 @@
if(!proximity)
return
if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it.
if(target.is_refillable() && is_drainable()) //Something like a glass. Player probably wants to transfer TO it.
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty.</span>")
return
+3 -1
View File
@@ -427,7 +427,7 @@
/obj/item/disk/plantgene/proc/update_name()
if(gene)
name = "[gene.get_name()] (Plant Data Disk)"
name = "[gene.get_name()] (plant data disk)"
else
name = "plant data disk"
@@ -437,4 +437,6 @@
/obj/item/disk/plantgene/examine(mob/user)
..()
if(gene && (istype(gene, /datum/plant_gene/core/potency)))
to_chat(user,"<span class='notice'>Percent is relative to potency, not maximum volume of the plant.</span>")
to_chat(user, "The write-protect tab is set to [src.read_only ? "protected" : "unprotected"].")
@@ -1,5 +1,5 @@
/obj/item/integrated_circuit/input/card_reader
name = "card reader"
name = "ID card reader" //To differentiate it from the data card reader
desc = "A circuit that can read the registred name, assignment, and PassKey string from an ID card."
icon_state = "card_reader"
@@ -14,6 +14,10 @@
"on read" = IC_PINTYPE_PULSE_OUT
)
/obj/item/integrated_circuit/input/card_reader/old
name = "card reader"
spawn_flags = 0
/obj/item/integrated_circuit/input/card_reader/attackby_react(obj/item/I, mob/living/user, intent)
var/obj/item/card/id/card = I.GetID()
var/list/access = I.GetAccess()
@@ -1104,3 +1104,43 @@
else
activate_pin(3)
/obj/item/integrated_circuit/input/data_card_reader
name = "data card reader"
desc = "A circuit that can read from and write to data cards."
extended_desc = "Setting the \"write mode\" boolean to true will cause any data cards that are used on the assembly to replace\
their existing function and data strings with the given strings, if it is set to false then using a data card on the assembly will cause\
the function and data strings stored on the card to be written to the output pins."
icon_state = "card_reader"
complexity = 4
spawn_flags = IC_SPAWN_DEFAULT|IC_SPAWN_RESEARCH
inputs = list(
"function" = IC_PINTYPE_STRING,
"data to store" = IC_PINTYPE_STRING,
"write mode" = IC_PINTYPE_BOOLEAN
)
outputs = list(
"function" = IC_PINTYPE_STRING,
"stored data" = IC_PINTYPE_STRING
)
activators = list(
"on write" = IC_PINTYPE_PULSE_OUT,
"on read" = IC_PINTYPE_PULSE_OUT
)
/obj/item/integrated_circuit/input/data_card_reader/attackby_react(obj/item/I, mob/living/user, intent)
var/obj/item/card/data/card = I.GetCard()
var/write_mode = get_pin_data(IC_INPUT, 3)
if(card)
if(write_mode == TRUE)
card.function = get_pin_data(IC_INPUT, 1)
card.data = get_pin_data(IC_INPUT, 2)
push_data()
activate_pin(1)
else
set_pin_data(IC_OUTPUT, 1, card.function)
set_pin_data(IC_OUTPUT, 2, card.data)
push_data()
activate_pin(2)
else
return FALSE
return TRUE
+4 -5
View File
@@ -56,10 +56,10 @@
if (top_atom)
LAZYREMOVE(top_atom.light_sources, src)
if (needs_update)
GLOB.lighting_update_lights -= src
. = ..()
// Yes this doesn't align correctly on anything other than 4 width tabs.
@@ -116,7 +116,6 @@
. = LUM_FALLOFF(C, pixel_turf); \
. *= light_power; \
var/OLD = effect_str[C]; \
\
effect_str[C] = .; \
\
C.update_lumcount \
@@ -126,7 +125,6 @@
(. * lum_b) - (OLD * applied_lum_b) \
);
#define REMOVE_CORNER(C) \
. = -effect_str[C]; \
C.update_lumcount \
@@ -167,8 +165,9 @@
/datum/light_source/proc/update_corners()
var/update = FALSE
var/atom/source_atom = src.source_atom
if (!source_atom || QDELETED(source_atom))
if (QDELETED(source_atom))
qdel(src)
return
+17 -14
View File
@@ -1,3 +1,5 @@
GLOBAL_LIST(labor_sheet_values)
/**********************Prisoners' Console**************************/
/obj/machinery/mineral/labor_claim_console
@@ -20,6 +22,18 @@
Radio.listening = FALSE
locate_stacking_machine()
if(!GLOB.labor_sheet_values)
var/sheet_list = list()
for(var/sheet_type in subtypesof(/obj/item/stack/sheet))
var/obj/item/stack/sheet/sheet = sheet_type
if(!initial(sheet.point_value) || (initial(sheet.merge_type) && initial(sheet.merge_type) != sheet_type)) //ignore no-value sheets and x/fifty subtypes
continue
sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value)))
GLOB.labor_sheet_values = sortList(sheet_list, /proc/cmp_sheet_list)
/proc/cmp_sheet_list(list/a, list/b)
return a["value"] - b["value"]
/obj/machinery/mineral/labor_claim_console/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/card/id/prisoner))
if(!inserted_id)
@@ -52,16 +66,10 @@
if(check_auth())
can_go_home = TRUE
var/list/ores = list()
if(stacking_machine)
data["unclaimed_points"] = stacking_machine.points
for(var/ore in stacking_machine.ore_values)
var/list/O = list()
O["ore"] = ore
O["value"] = stacking_machine.ore_values[ore]
ores += list(O)
data["ores"] = ores
data["ores"] = GLOB.labor_sheet_values
data["can_go_home"] = can_go_home
return data
@@ -127,15 +135,10 @@
/obj/machinery/mineral/stacking_machine/laborstacker
var/points = 0 //The unclaimed value of ore stacked. Value for each ore loosely relative to its rarity.
var/list/ore_values = list("glass" = 1, "metal" = 2, "reinforced glass" = 4, "gold" = 20, "silver" = 20, "uranium" = 20, "titanium" = 20, "solid plasma" = 20, "plasteel" = 23, "plasma glass" = 23, "diamond" = 25, "bluespace polycrystal" = 30, "plastitanium" = 45, "bananium" = 50)
var/points = 0 //The unclaimed value of ore stacked.
/obj/machinery/mineral/stacking_machine/laborstacker/process_sheet(obj/item/stack/sheet/inp)
if(istype(inp))
var/n = inp.name
var/a = inp.amount
if(n in ore_values)
points += ore_values[n] * a
points += inp.point_value * inp.amount
..()
+1 -1
View File
@@ -105,8 +105,8 @@
stack_list[inp.type] = s
var/obj/item/stack/sheet/storage = stack_list[inp.type]
storage.amount += inp.amount //Stack the sheets
qdel(inp) //Let the old sheet garbage collect
while(storage.amount > stack_amt) //Get rid of excessive stackage
var/obj/item/stack/sheet/out = new inp.type(null, stack_amt)
unload_mineral(out)
storage.amount -= stack_amt
qdel(inp) //Let the old sheet garbage collect
-4
View File
@@ -171,8 +171,6 @@
if("Survival Capsule and Explorer's Webbing")
new /obj/item/storage/belt/mining/vendor(drop_location)
if("Resonator Kit")
new /obj/item/storage/belt/mining/alt(drop_location)
new /obj/item/t_scanner/adv_mining_scanner(drop_location)
new /obj/item/extinguisher/mini(drop_location)
new /obj/item/resonator(drop_location)
if("Minebot Kit")
@@ -185,8 +183,6 @@
new /obj/item/fulton_core(drop_location)
new /obj/item/stack/marker_beacon/thirty(drop_location)
if("Crusher Kit")
new /obj/item/storage/belt/mining/alt(drop_location)
new /obj/item/t_scanner/adv_mining_scanner(drop_location)
new /obj/item/extinguisher/mini(drop_location)
new /obj/item/twohanded/required/kinetic_crusher(drop_location)
if("Mining Conscription Kit")
@@ -164,8 +164,8 @@
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
/mob/living/silicon/robot/Destroy()
var/atom/T = drop_location()//To hopefully prevent run time errors.
if(mmi && mind)//Safety for when a cyborg gets dust()ed. Or there is no MMI inside.
var/turf/T = get_turf(loc)//To hopefully prevent run time errors.
if(T)
mmi.forceMove(T)
if(mmi.brainmob)
@@ -184,6 +184,10 @@
connected_ai.connected_robots -= src
if(shell)
GLOB.available_ai_shells -= src
else
if(T && istype(radio) && istype(radio.keyslot))
radio.keyslot.forceMove(T)
radio.keyslot = null
qdel(wires)
qdel(module)
qdel(eye_lights)
@@ -1,3 +1,5 @@
#define MEDAL_PREFIX "Bubblegum"
/*
BUBBLEGUM
@@ -7,22 +9,15 @@ Bubblegum's footsteps are heralded by shaking booms, proving its tremendous size
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
It tries to strike at its target through any bloodpools under them; if it fails to do that, it will spray blood and then attempt to warp to a bloodpool near the target.
If it fails to warp to a target, it may summon up to 6 slaughterlings from the blood around it.
If it does not summon all 6 slaughterlings, it will instead charge at its target, dealing massive damage to anything it hits and spraying a stream of blood.
At half health, it will either charge three times or warp, then charge, instead of doing a single charge.
It often charges, dealing massive damage to anything unfortunate enough to be standing where it's aiming.
Whenever it isn't chasing something down, it will sink into nearby blood pools (if possible) and springs out of the closest one to its target.
To make this possible, it sprays streams of blood at random.
From these blood pools Bubblegum may summon slaughterlings - weak, low-damage minions designed to impede the target's progress.
<<<<<<< HEAD
When Bubblegum dies, it leaves behind a H.E.C.K. mining suit as well as a chest that can contain three things:
1. A bottle that, when activated, drives everyone nearby into a frenzy
2. A contract that marks for death the chosen target
3. A spellblade that can slice off limbs at range
=======
When Bubblegum dies, it leaves behind a H.E.C.K. suit+helmet as well as a chest that can contain three things:
1. A spellblade that can slice off limbs at range
2. A bottle that, when activated, drives everyone nearby into a frenzy
3. A contract that marks for death the chosen target
>>>>>>> c6ca01f... Merge pull request #38661 from 81Denton/fug
Difficulty: Hard
@@ -51,8 +46,7 @@ Difficulty: Hard
del_on_death = 1
crusher_loot = list(/obj/structure/closet/crate/necropolis/bubblegum/crusher)
loot = list(/obj/structure/closet/crate/necropolis/bubblegum)
blood_volume = BLOOD_VOLUME_MAXIMUM //BLEED FOR ME
var/charging = FALSE
var/charging = 0
medal_type = BOSS_MEDAL_BUBBLEGUM
score_type = BUBBLEGUM_SCORE
deathmessage = "sinks into a pool of blood, fleeing the battle. You've won, for now... "
@@ -64,54 +58,33 @@ Difficulty: Hard
desc = "You're not quite sure how a signal can be bloody."
invisibility = 100
/mob/living/simple_animal/hostile/megafauna/bubblegum/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
. = ..()
if(. > 0 && prob(25))
var/obj/effect/decal/cleanable/blood/gibs/bubblegum/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegum(loc)
if(prob(40))
step(B, pick(GLOB.cardinals))
else
B.setDir(pick(GLOB.cardinals))
/obj/effect/decal/cleanable/blood/gibs/bubblegum
name = "thick blood"
desc = "Thick, splattered blood."
random_icon_states = list("gib3", "gib5", "gib6")
bloodiness = 20
/obj/effect/decal/cleanable/blood/gibs/bubblegum/can_bloodcrawl_in()
return TRUE
/mob/living/simple_animal/hostile/megafauna/bubblegum/Life()
..()
move_to_delay = CLAMP((health/maxHealth) * 10, 5, 10)
move_to_delay = CLAMP(round((health/maxHealth) * 10), 5, 10)
/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire()
anger_modifier = CLAMP(((maxHealth - health)/60),0,20)
anger_modifier = CLAMP(((maxHealth - health)/50),0,20)
if(charging)
return
ranged_cooldown = world.time + ranged_cooldown_time
var/warped = FALSE
if(!try_bloodattack())
INVOKE_ASYNC(src, .proc/blood_spray)
warped = blood_warp()
if(warped && prob(100 - anger_modifier))
return
blood_warp()
if(prob(90 - anger_modifier) || slaughterlings())
if(health > maxHealth * 0.5)
if(prob(25))
INVOKE_ASYNC(src, .proc/blood_spray)
else if(prob(5+anger_modifier/2))
slaughterlings()
else
if(health > maxHealth/2 && !client)
INVOKE_ASYNC(src, .proc/charge)
else
if(prob(70) || warped)
INVOKE_ASYNC(src, .proc/charge, 2)
else
INVOKE_ASYNC(src, .proc/warp_charge)
INVOKE_ASYNC(src, .proc/triple_charge)
/mob/living/simple_animal/hostile/megafauna/bubblegum/Initialize()
. = ..()
for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.mob_living_list)
for(var/mob/living/simple_animal/hostile/megafauna/bubblegum/B in GLOB.mob_list)
if(B != src)
return INITIALIZE_HINT_QDEL //There can be only one
var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
@@ -125,56 +98,53 @@ Difficulty: Hard
if(.)
SSshuttle.shuttle_purchase_requirements_met |= "bubblegum"
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A, visual_effect_icon)
if(!charging)
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/do_attack_animation(atom/A)
if(charging)
return
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/AttackingTarget()
if(!charging)
return ..()
if(charging)
return
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Goto(target, delay, minimum_distance)
if(!charging)
..()
if(charging)
return
..()
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
if(!stat)
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
new /obj/effect/temp_visual/decoy/fading(loc,src)
new/obj/effect/temp_visual/decoy/fading(loc,src)
DestroySurroundings()
. = ..()
if(!stat && .)
playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
if(charging)
DestroySurroundings()
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/warp_charge()
blood_warp()
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/triple_charge()
charge()
sleep(10)
charge()
sleep(10)
charge()
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge(bonus_charges)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge()
var/turf/T = get_turf(target)
if(!T || T == loc)
return
new /obj/effect/temp_visual/dragon_swoop/bubblegum(T)
charging = TRUE
new /obj/effect/temp_visual/dragon_swoop(T)
charging = 1
DestroySurroundings()
walk(src, 0)
setDir(get_dir(src, T))
var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 3)
sleep(3)
throw_at(T, get_dist(src, T), 1, src, 0, callback = CALLBACK(src, .charge_end, bonus_charges))
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/charge_end(bonus_charges, list/effects_to_destroy)
charging = FALSE
try_bloodattack()
if(target)
if(bonus_charges)
bonus_charges--
charge(bonus_charges)
else
Goto(target, move_to_delay, minimum_distance)
SetRecoveryTime(MEGAFAUNA_DEFAULT_RECOVERY_TIME)
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
sleep(5)
throw_at(T, get_dist(src, T), 1, src, 0)
charging = 0
Goto(target, move_to_delay, minimum_distance)
/mob/living/simple_animal/hostile/megafauna/bubblegum/Collide(atom/A)
@@ -198,142 +168,20 @@ Difficulty: Hard
var/throwtarget = get_edge_target_turf(src, get_dir(src, get_step_away(L, src)))
L.throw_at(throwtarget, 3)
charging = FALSE
charging = 0
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_mobs_on_blood()
var/list/targets = ListTargets()
. = list()
for(var/mob/living/L in targets)
var/list/bloodpool = get_pools(get_turf(L), 0)
if(bloodpool.len && (!faction_check_mob(L) || L.stat == DEAD))
. += L
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/try_bloodattack()
var/list/targets = get_mobs_on_blood()
if(targets.len)
INVOKE_ASYNC(src, .proc/bloodattack, targets, prob(50))
return TRUE
return FALSE
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodattack(list/targets, handedness)
var/mob/living/target_one = pick_n_take(targets)
var/turf/target_one_turf = get_turf(target_one)
var/mob/living/target_two
if(targets.len)
target_two = pick_n_take(targets)
var/turf/target_two_turf = get_turf(target_two)
if(target_two.stat != CONSCIOUS || prob(10))
bloodgrab(target_two_turf, handedness)
else
bloodsmack(target_two_turf, handedness)
if(target_one)
var/list/pools = get_pools(get_turf(target_one), 0)
if(pools.len)
target_one_turf = get_turf(target_one)
if(target_one_turf)
if(target_one.stat != CONSCIOUS || prob(10))
bloodgrab(target_one_turf, !handedness)
else
bloodsmack(target_one_turf, !handedness)
if(!target_two && target_one)
var/list/poolstwo = get_pools(get_turf(target_one), 0)
if(poolstwo.len)
target_one_turf = get_turf(target_one)
if(target_one_turf)
if(target_one.stat != CONSCIOUS || prob(10))
bloodgrab(target_one_turf, handedness)
else
bloodsmack(target_one_turf, handedness)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T, handedness)
if(handedness)
new /obj/effect/temp_visual/bubblegum_hands/rightsmack(T)
else
new /obj/effect/temp_visual/bubblegum_hands/leftsmack(T)
sleep(2.5)
for(var/mob/living/L in T)
if(!faction_check_mob(L))
to_chat(L, "<span class='userdanger'>[src] rends you!</span>")
playsound(T, attack_sound, 100, 1, -1)
var/limb_to_hit = L.get_bodypart(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
sleep(3)
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodgrab(turf/T, handedness)
if(handedness)
new /obj/effect/temp_visual/bubblegum_hands/rightpaw(T)
new /obj/effect/temp_visual/bubblegum_hands/rightthumb(T)
else
new /obj/effect/temp_visual/bubblegum_hands/leftpaw(T)
new /obj/effect/temp_visual/bubblegum_hands/leftthumb(T)
sleep(6)
for(var/mob/living/L in T)
if(!faction_check_mob(L))
to_chat(L, "<span class='userdanger'>[src] drags you through the blood!</span>")
playsound(T, 'sound/magic/enter_blood.ogg', 100, 1, -1)
var/turf/targetturf = get_step(src, dir)
L.forceMove(targetturf)
playsound(targetturf, 'sound/magic/exit_blood.ogg', 100, 1, -1)
if(L.stat != CONSCIOUS)
addtimer(CALLBACK(src, .proc/devour, L), 2)
sleep(1)
/obj/effect/temp_visual/dragon_swoop/bubblegum
duration = 10
/obj/effect/temp_visual/bubblegum_hands
icon = 'icons/effects/bubblegum.dmi'
duration = 9
/obj/effect/temp_visual/bubblegum_hands/rightthumb
icon_state = "rightthumbgrab"
/obj/effect/temp_visual/bubblegum_hands/leftthumb
icon_state = "leftthumbgrab"
/obj/effect/temp_visual/bubblegum_hands/rightpaw
icon_state = "rightpawgrab"
layer = BELOW_MOB_LAYER
/obj/effect/temp_visual/bubblegum_hands/leftpaw
icon_state = "leftpawgrab"
layer = BELOW_MOB_LAYER
/obj/effect/temp_visual/bubblegum_hands/rightsmack
icon_state = "rightsmack"
/obj/effect/temp_visual/bubblegum_hands/leftsmack
icon_state = "leftsmack"
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_warp()
if(Adjacent(target))
return FALSE
var/list/can_jaunt = get_pools(get_turf(src), 1)
if(!can_jaunt.len)
return FALSE
var/list/pools = get_pools(get_turf(target), 2)
var/list/pools_to_remove = get_pools(get_turf(target), 1)
pools -= pools_to_remove
if(!pools.len)
return FALSE
var/obj/effect/temp_visual/decoy/DA = new /obj/effect/temp_visual/decoy(loc,src)
DA.color = "#FF0000"
var/oldtransform = DA.transform
DA.transform = matrix()*2
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 3)
sleep(3)
qdel(DA)
var/obj/effect/decal/cleanable/blood/found_bloodpool
pools = get_pools(get_turf(target), 2)
pools_to_remove = get_pools(get_turf(target), 1)
pools -= pools_to_remove
var/list/pools = list()
var/can_jaunt = FALSE
for(var/obj/effect/decal/cleanable/blood/nearby in view(src,2))
can_jaunt = TRUE
break
if(!can_jaunt)
return
for(var/obj/effect/decal/cleanable/blood/nearby in view(get_turf(target),2))
pools += nearby
if(pools.len)
shuffle_inplace(pools)
found_bloodpool = pick(pools)
@@ -343,51 +191,30 @@ Difficulty: Hard
forceMove(get_turf(found_bloodpool))
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
visible_message("<span class='danger'>And springs back out!</span>")
return TRUE
return FALSE
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/get_pools(turf/T, range)
. = list()
for(var/obj/effect/decal/cleanable/nearby in view(T, range))
if(nearby.can_bloodcrawl_in())
. += nearby
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/blood_spray()
visible_message("<span class='danger'>[src] sprays a stream of gore!</span>")
var/range = 6 + round(anger_modifier * 0.4)
var/turf/E = get_edge_target_turf(src, src.dir)
var/range = 10
var/turf/previousturf = get_turf(src)
var/turf/J = previousturf
var/targetdir = get_dir(src, target)
if(target.loc == loc)
targetdir = dir
face_atom(target)
new /obj/effect/decal/cleanable/blood/bubblegum(J)
for(var/i in 1 to range)
J = get_step(previousturf, targetdir)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(previousturf, get_dir(previousturf, J))
playsound(previousturf,'sound/effects/splat.ogg', 100, 1, -1)
if(!J || !previousturf.atmos_adjacent_turfs || !previousturf.atmos_adjacent_turfs[J])
for(var/turf/J in getline(src,E))
if(!range)
break
new /obj/effect/decal/cleanable/blood/bubblegum(J)
new /obj/effect/temp_visual/dir_setting/bloodsplatter(previousturf, get_dir(previousturf, J))
if(!previousturf.CanAtmosPass(J))
break
playsound(J,'sound/effects/splat.ogg', 100, 1, -1)
new /obj/effect/decal/cleanable/blood(J)
range--
previousturf = J
sleep(1)
/obj/effect/decal/cleanable/blood/bubblegum
bloodiness = 0
/obj/effect/decal/cleanable/blood/bubblegum/can_bloodcrawl_in()
return TRUE
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/slaughterlings()
visible_message("<span class='danger'>[src] summons a shoal of slaughterlings!</span>")
var/max_amount = 6
for(var/H in get_pools(get_turf(src), 1))
if(!max_amount)
break
max_amount--
var/obj/effect/decal/cleanable/blood/B = H
new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/slaughter(B.loc)
return max_amount
for(var/obj/effect/decal/cleanable/blood/H in range(src, 10))
if(prob(25))
new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/slaughter(H.loc)
/mob/living/simple_animal/hostile/asteroid/hivelordbrood/slaughter
name = "slaughterling"
@@ -405,3 +232,5 @@ Difficulty: Hard
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum))
return 1
return 0
#undef MEDAL_PREFIX
@@ -11,8 +11,21 @@
clumsy_check = FALSE
randomspread = FALSE
var/hugbox = TRUE
var/max_power = INFINITY
var/reaction_volume_mod = 0
var/reaction_cycles = 3 //How many times gases react() before calculation. Very finnicky value, do not mess with without good reason.
var/prereaction = TRUE
var/bombcheck = TRUE
var/debug_power = 0
var/obj/item/transfer_valve/bomb
/obj/item/gun/blastcannon/debug
debug_power = 80
bombcheck = FALSE
/obj/item/gun/blastcannon/Initialize()
. = ..()
if(!pin)
@@ -56,27 +69,33 @@
return TRUE
return ..()
//returns the third value of a bomb blast
/obj/item/gun/blastcannon/proc/calculate_bomb()
if(!istype(bomb) || !istype(bomb.tank_one) || !istype(bomb.tank_two))
return 0
var/datum/gas_mixture/temp = new(60) //directional buff.
temp.merge(bomb.tank_one.air_contents.remove_ratio(1))
temp.merge(bomb.tank_two.air_contents.remove_ratio(2))
for(var/i in 1 to 6)
var/datum/gas_mixture/temp = new(max(reaction_volume_mod, 0))
bomb.merge_gases(temp)
if(prereaction)
temp.react(src)
var/prereaction_pressure = temp.return_pressure()
if(prereaction_pressure < TANK_FRAGMENT_PRESSURE)
return 0
for(var/i in 1 to reaction_cycles)
temp.react(src)
var/pressure = temp.return_pressure()
qdel(temp)
if(pressure < TANK_FRAGMENT_PRESSURE)
return 0
return (pressure / TANK_FRAGMENT_SCALE)
return ((pressure - TANK_FRAGMENT_PRESSURE) / TANK_FRAGMENT_SCALE)
/obj/item/gun/blastcannon/afterattack(atom/target, mob/user, flag, params)
if((!bomb) || (!target) || (get_dist(get_turf(target), get_turf(user)) <= 2))
if((!bomb && bombcheck) || (!target) || (get_dist(get_turf(target), get_turf(user)) <= 2))
return ..()
var/power = calculate_bomb()
var/power = bomb? calculate_bomb() : debug_power
power = min(power, max_power)
QDEL_NULL(bomb)
update_icon()
var/heavy = power * 0.2
var/heavy = power * 0.25
var/medium = power * 0.5
var/light = power
user.visible_message("<span class='danger'>[user] opens [bomb] on [user.p_their()] [name] and fires a blast wave at [target]!</span>","<span class='danger'>You open [bomb] on your [name] and fire a blast wave at [target]!</span>")
@@ -87,7 +106,8 @@
message_admins(log_str)
log_game(log_str)
var/obj/item/projectile/blastwave/BW = new(loc, heavy, medium, light)
BW.preparePixelProjectile(target, get_turf(target), user, params, 0)
BW.hugbox = hugbox
BW.preparePixelProjectile(target, get_turf(src), params, 0)
BW.fire()
/obj/item/projectile/blastwave
@@ -99,6 +119,7 @@
var/heavyr = 0
var/mediumr = 0
var/lightr = 0
var/hugbox = TRUE
range = 150
/obj/item/projectile/blastwave/Initialize(mapload, _h, _m, _l)
@@ -110,14 +131,25 @@
/obj/item/projectile/blastwave/Range()
..()
var/amount_destruction = EXPLODE_NONE
var/wallbreak_chance = 0
if(heavyr)
amount_destruction = EXPLODE_DEVASTATE
wallbreak_chance = 99
else if(mediumr)
amount_destruction = EXPLODE_HEAVY
wallbreak_chance = 66
else if(lightr)
amount_destruction = EXPLODE_LIGHT
wallbreak_chance = 33
if(amount_destruction)
loc.ex_act(amount_destruction)
if(hugbox)
loc.contents_explosion(EXPLODE_HEAVY, loc)
if(istype(loc, /turf/closed/wall))
var/turf/closed/wall/W = loc
if(prob(wallbreak_chance))
W.dismantle_wall(TRUE, TRUE)
else
loc.ex_act(amount_destruction)
else
qdel(src)
@@ -151,10 +151,32 @@
icon_state = "pill18"
list_reagents = list("insulin" = 50)
roundstart = 1
///////////////////////////////////////// this pill is used only in a legion mob drop
/obj/item/reagent_containers/pill/shadowtoxin
name = "black pill"
desc = "I wouldn't eat this if I were you."
icon_state = "pill9"
color = "#454545"
list_reagents = list("shadowmutationtoxin" = 1)
list_reagents = list("shadowmutationtoxin" = 1)
//////////////////////////////////////// drugs
/obj/item/reagent_containers/pill/zoom
name = "zoom pill"
list_reagents = list("synaptizine" = 10, "nicotine" = 10, "methamphetamine" = 1)
/obj/item/reagent_containers/pill/happy
name = "happy pill"
list_reagents = list("sugar" = 10, "space_drugs" = 10)
/obj/item/reagent_containers/pill/lsd
name = "hallucinogen pill"
list_reagents = list("mushroomhallucinogen" = 15, "mindbreaker" = 15)
/obj/item/reagent_containers/pill/aranesp
name = "speedy pill"
list_reagents = list("aranesp" = 10)
@@ -199,7 +199,7 @@
/obj/item/bodypart/r_leg/drop_limb(special)
if(owner && !special)
if(owner.legcuffed)
owner.legcuffed.forceMove(drop_location())
owner.legcuffed.forceMove(owner.drop_location()) //At this point bodypart is still in nullspace
owner.legcuffed.dropped(owner)
owner.legcuffed = null
owner.update_inv_legcuffed()
@@ -210,7 +210,7 @@
/obj/item/bodypart/l_leg/drop_limb(special) //copypasta
if(owner && !special)
if(owner.legcuffed)
owner.legcuffed.forceMove(drop_location())
owner.legcuffed.forceMove(owner.drop_location())
owner.legcuffed.dropped(owner)
owner.legcuffed = null
owner.update_inv_legcuffed()
+10
View File
@@ -1412,6 +1412,16 @@ GLOBAL_LIST_INIT(uplink_items, subtypesof(/datum/uplink_item))
limited_stock = 2 //you can't use more than two!
restricted_roles = list("Shaft Miner")
/datum/uplink_item/role_restricted/blastcannon
name = "Blast Cannon"
desc = "A highly specialized weapon, the Blast Cannon is actually relatively simple. It contains an attachment for a tank transfer valve mounted to an angled pipe specially constructed \
withstand extreme pressure and temperatures, and has a mechanical trigger for triggering the transfer valve. Essentially, it turns the explosive force of a bomb into a narrow-angle \
blast wave \"projectile\". Aspiring scientists may find this highly useful, as forcing the pressure shockwave into a narrow angle seems to be able to bypass whatever quirk of physics \
disallows explosive ranges above a certain distance, allowing for the device to use the theoretical yield of a transfer valve bomb, instead of the factual yield."
item = /obj/item/gun/blastcannon
cost = 14 //High cost because of the potential for extreme damage in the hands of a skilled scientist.
restricted_roles = list("Research Director", "Scientist")
/datum/uplink_item/device_tools/clown_bomb
name = "Clown Bomb"
desc = "The Clown bomb is a hilarious device capable of massive pranks. It has an adjustable timer, \
+3 -2
View File
@@ -35,6 +35,7 @@
/obj/item/clothing/neck/tie/red = 1,
/obj/item/clothing/neck/tie/black = 1,
/obj/item/clothing/neck/tie/horrible = 1,
/obj/item/clothing/neck/scarf/pink = 1,
/obj/item/clothing/neck/scarf/red = 1,
/obj/item/clothing/neck/scarf/green = 1,
/obj/item/clothing/neck/scarf/darkblue = 1,
@@ -118,5 +119,5 @@
/obj/item/vending_refill/clothing
machine_name = "ClothesMate"
icon_state = "refill_clothes"
charges = list(37, 4, 4)// of 111 standard, 12 contraband, 10 premium(?)
init_charges = list(37, 4, 4)
charges = list(38, 4, 4)// of 112 standard, 12 contraband, 10 premium(?)
init_charges = list(38, 4, 4)
@@ -0,0 +1,8 @@
author: "JStheguy"
delete-after: True
changes:
- rscadd: "Added the data card reader circuit, a circuit that is able to read data cards, as well as write to them."
- tweak: "Data cards are now longer inexplicably called data disks despite clearly being cards, and can be printed from the \"tools\" section of the integrated circuit printer."
- tweak: "Data cards no longer have a special \"label card\" verb and instead can have their names and descriptions changed with a pen."
- rscadd: "Also, some aesthetically different variants of the data cards, because why not."
- imageadd: "Data cards have new sprites, with support for coloring them via the assembly detailer."
@@ -0,0 +1,4 @@
author: "CitadelStationBot"
delete-after: True
changes:
- rscadd: "Added a pink scarf to vendomats"
@@ -0,0 +1,4 @@
author: "CitadelStationBot"
delete-after: True
changes:
- rscadd: "Players can now ctrl-click the PDA to remove the item in its pen slot"
@@ -0,0 +1,5 @@
author: "Cobby"
delete-after: True
changes:
- rscdel: "Removed Advanced Mining Scanner from roundstart voucher kits."
- rscdel: "Removed Explorer Webbing from all voucher kits besides the shelter capsule pack."
@@ -0,0 +1,4 @@
author: "CitadelStationBot"
delete-after: True
changes:
- spellcheck: "Plant disks with potency genes clarify the percent is for potency scaling and not relative to max volume on examine."
@@ -0,0 +1,4 @@
author: "Dax Dupont"
delete-after: True
changes:
- admin: "Create antags now checks for people being on station before applying."
@@ -0,0 +1,6 @@
author: "CitadelStationBot"
delete-after: True
changes:
- rscadd: "Blast cannons have been fixed and are now available for purchase by traitorous scientists for a low low price of 14TC."
- rscadd: "Blast cannons take the explosive power of a TTV bomb and ejects a linear projectile that will apply what the bomb would do to a certain tile at that distance to that tile. However, this will not cause breaches, or gib mobs, unless the gods (admins) so will it.
experimental: Blast cannons do not respect maxcap. (Unless the admins so will it.)"
@@ -0,0 +1,4 @@
author: "Kor"
delete-after: True
changes:
- rscadd: "Bubblegum has regained his original (deadlier) move set."
@@ -0,0 +1,4 @@
author: "CitadelStationBot"
delete-after: True
changes:
- rscadd: "Cyborgs now drop keys on deconstruction/detonation"
@@ -0,0 +1,4 @@
author: "Time-Green"
delete-after: True
changes:
- bugfix: "Soda is no longer intangible to the laws of physics"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.