Merge master and build TGUI

This commit is contained in:
Cadyn
2020-11-15 02:17:53 -08:00
208 changed files with 46799 additions and 24054 deletions
@@ -21,9 +21,61 @@
/obj/item/device/starcaster_news/attack_self(mob/user as mob)
user.set_machine(src)
ui_interact(user) //Activates nanoUI. Fuck nanoUI.
tgui_interact(user) //Activates tgui. Bless tgui.
return
/obj/item/device/starcaster_news/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "StarcasterCh", name)
ui.open()
/obj/item/device/starcaster_news/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) //Mostly ripped off from news_browser.dm
var/list/data = list()
var/list/all_articles = list()
data["showing_archived"] = show_archived
data["article"] = null
if(loaded_article) // Viewing an article.
data["article"] = list(
"title" = loaded_article.filename,
"cover" = loaded_article.cover,
"content" = loaded_article.stored_data,
)
else // Viewing list of articles
for(var/datum/computer_file/data/news_article/F in ntnet_global.available_news)
if(!show_archived && F.archived)
continue
all_articles.Add(list(list(
"name" = F.filename,
"uid" = F.uid,
"archived" = F.archived
)))
data["all_articles"] = all_articles
return data
/obj/item/device/starcaster_news/tgui_act(action, list/params, datum/tgui/ui) //Also ripped from news_browser.dm. Bless tgui
if(..())
return TRUE
switch(action)
if("PRG_openarticle")
. = TRUE
if(loaded_article)
return TRUE
for(var/datum/computer_file/data/news_article/N in ntnet_global.available_news)
if(N.uid == text2num(params["uid"]))
loaded_article = N.clone()
break
if("PRG_reset")
. = TRUE
loaded_article = null
if("PRG_toggle_archived")
. = TRUE
show_archived = !show_archived
/* Deprecated nanoUI code. Keeping mostly for reference.
/obj/item/device/starcaster_news/Topic(href, href_list) //Mostly ripped off from news_browser.dm
if(..())
return 1
@@ -73,3 +125,4 @@
ui.auto_update_layout = 1
ui.set_initial_data(data)
ui.open()
*/
@@ -1,70 +1,75 @@
/obj/item/stack/animalhide
name = "hide"
desc = "The hide of some creature."
icon_state = "sheet-hide"
drop_sound = 'sound/items/drop/cloth.ogg'
pickup_sound = 'sound/items/pickup/cloth.ogg'
amount = 1
stacktype = "hide"
no_variants = TRUE
var/process_type = /obj/item/stack/hairlesshide
/obj/item/stack/animalhide/human
name = "human skin"
desc = "The by-product of human farming."
singular_name = "human skin piece"
name = "skin"
desc = "The by-product of sapient farming."
singular_name = "skin piece"
icon_state = "sheet-hide"
no_variants = FALSE
drop_sound = 'sound/items/drop/leather.ogg'
pickup_sound = 'sound/items/pickup/leather.ogg'
/obj/item/stack/animalhide/human
amount = 50
amount = 1
stacktype = "hide-human"
/obj/item/stack/animalhide/corgi
name = "corgi hide"
desc = "The by-product of corgi farming."
singular_name = "corgi hide piece"
icon_state = "sheet-corgi"
/obj/item/stack/animalhide/corgi
amount = 50
amount = 1
stacktype = "hide-corgi"
/obj/item/stack/animalhide/cat
name = "cat hide"
desc = "The by-product of cat farming."
singular_name = "cat hide piece"
icon_state = "sheet-cat"
/obj/item/stack/animalhide/cat
amount = 50
amount = 1
stacktype = "hide-cat"
/obj/item/stack/animalhide/monkey
name = "monkey hide"
desc = "The by-product of monkey farming."
singular_name = "monkey hide piece"
icon_state = "sheet-monkey"
/obj/item/stack/animalhide/monkey
amount = 50
amount = 1
stacktype = "hide-monkey"
/obj/item/stack/animalhide/lizard
name = "lizard skin"
desc = "Sssssss..."
singular_name = "lizard skin piece"
icon_state = "sheet-lizard"
/obj/item/stack/animalhide/lizard
amount = 50
amount = 1
stacktype = "hide-lizard"
/obj/item/stack/animalhide/xeno
name = "alien hide"
desc = "The skin of a terrible creature."
singular_name = "alien hide piece"
icon_state = "sheet-xeno"
/obj/item/stack/animalhide/xeno
amount = 50
amount = 1
stacktype = "hide-xeno"
//don't see anywhere else to put these, maybe together they could be used to make the xenos suit?
/obj/item/stack/xenochitin
name = "alien chitin"
desc = "A piece of the hide of a terrible creature."
singular_name = "alien hide piece"
singular_name = "alien chitin piece"
icon = 'icons/mob/alien.dmi'
icon_state = "chitin"
/obj/item/stack/xenochitin
amount = 50
amount = 1
stacktype = "hide-chitin"
/obj/item/xenos_claw
name = "alien claw"
@@ -84,9 +89,22 @@
singular_name = "hairless hide piece"
icon_state = "sheet-hairlesshide"
no_variants = FALSE
amount = 1
stacktype = "hairlesshide"
var/cleaning = FALSE // Can we be water_acted, or are we busy? To prevent accidental hide duplication and the collapse of causality.
/obj/item/stack/hairlesshide
amount = 50
var/wet_type = /obj/item/stack/wetleather
/obj/item/stack/hairlesshide/water_act(var/wateramount)
..()
cleaning = TRUE
while(amount > 0 && wateramount > 0)
use(1)
wateramount--
new wet_type(get_turf(src))
cleaning = FALSE
return
/obj/item/stack/wetleather
name = "wet leather"
@@ -96,29 +114,28 @@
var/wetness = 30 //Reduced when exposed to high temperautres
var/drying_threshold_temperature = 500 //Kelvin to start drying
no_variants = FALSE
amount = 1
stacktype = "wetleather"
/obj/item/stack/wetleather
amount = 50
var/dry_type = /obj/item/stack/material/leather
//Step one - dehairing.
/obj/item/stack/animalhide/attackby(obj/item/weapon/W as obj, mob/user as mob)
if( istype(W, /obj/item/weapon/material/knife) || \
istype(W, /obj/item/weapon/material/twohanded/fireaxe) || \
istype(W, /obj/item/weapon/material/knife/machete/hatchet) )
if(has_edge(W) || is_sharp(W))
//visible message on mobs is defined as visible_message(var/message, var/self_message, var/blind_message)
usr.visible_message("<span class='notice'>\The [usr] starts cutting hair off \the [src]</span>", "<span class='notice'>You start cutting the hair off \the [src]</span>", "You hear the sound of a knife rubbing against flesh")
if(do_after(user,50))
to_chat(usr, "<span class='notice'>You cut the hair from this [src.singular_name]</span>")
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/hairlesshide/HS in usr.loc)
if(HS.amount < 50)
if(HS.amount < 50 && istype(HS, process_type))
HS.amount++
src.use(1)
break
return
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/hairlesshide/HS = new(usr.loc)
HS.amount = 1
var/obj/item/stack/HS = new process_type(usr.loc)
if(istype(HS))
HS.amount = 1
src.use(1)
else
..()
@@ -132,15 +149,20 @@
if(exposed_temperature >= drying_threshold_temperature)
wetness--
if(wetness == 0)
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/material/leather/HS in src.loc)
if(HS.amount < 50)
HS.amount++
src.use(1)
wetness = initial(wetness)
break
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/material/leather/HS = new(src.loc)
HS.amount = 1
dry()
/obj/item/stack/wetleather/proc/dry()
//Try locating an exisitng stack on the tile and add to there if possible
for(var/obj/item/stack/material/leather/HS in src.loc)
if(HS.amount < 50)
HS.amount++
wetness = initial(wetness)
src.use(1)
return
//If it gets to here it means it did not find a suitable stack on the tile.
var/obj/item/stack/HS = new dry_type(src.loc)
if(istype(HS))
HS.amount = 1
wetness = initial(wetness)
src.use(1)
+12 -12
View File
@@ -59,7 +59,7 @@
/obj/item/stack/examine(mob/user)
. = ..()
if(Adjacent(user))
if(!uses_charge)
. += "There are [src.amount] [src.singular_name]\s in the stack."
@@ -380,17 +380,17 @@
var/use_material
var/pass_color
New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, pass_stack_color)
src.title = title
src.result_type = result_type
src.req_amount = req_amount
src.res_amount = res_amount
src.max_res_amount = max_res_amount
src.time = time
src.one_per_turf = one_per_turf
src.on_floor = on_floor
src.use_material = supplied_material
src.pass_color = pass_stack_color
/datum/stack_recipe/New(title, result_type, req_amount = 1, res_amount = 1, max_res_amount = 1, time = 0, one_per_turf = 0, on_floor = 0, supplied_material = null, pass_stack_color)
src.title = title
src.result_type = result_type
src.req_amount = req_amount
src.res_amount = res_amount
src.max_res_amount = max_res_amount
src.time = time
src.one_per_turf = one_per_turf
src.on_floor = on_floor
src.use_material = supplied_material
src.pass_color = pass_stack_color
/*
* Recipe list datum
@@ -1,9 +1,9 @@
/obj/item/weapon/implant/reagent_generator/egg
name = "egg laying implant"
name = "regular egg laying implant"
desc = "This is an implant that allows the user to lay eggs."
generated_reagents = list("egg" = 2)
usable_volume = 500
transfer_amount = 50
usable_volume = 1500
transfer_amount = 300
var/verb_descriptor = list("squeezes", "pushes", "hugs")
var/self_verb_descriptor = list("squeeze", "push", "hug")
var/short_emote_descriptor = list("lays", "forces out", "pushes out")
@@ -11,11 +11,13 @@
random_emote = list("lets out an embarrassed moan", "yelps in embarrassment", "quietly groans in a mixture of discomfort and pleasure")
assigned_proc = /mob/living/carbon/human/proc/use_reagent_implant_egg
var/eggtype = /obj/item/weapon/reagent_containers/food/snacks/egg
var/cascade
/obj/item/weapon/implant/reagent_generator/egg/post_implant(mob/living/carbon/source)
START_PROCESSING(SSobj, src)
to_chat(source, "<span class='notice'>You implant [source] with \the [src].</span>")
source.verbs |= assigned_proc
source.verbs |= /mob/living/carbon/human/proc/toggle_cascade
return 1
/mob/living/carbon/human/proc/use_reagent_implant_egg()
@@ -51,59 +53,82 @@
to_chat(usr, "<span class='notice'>It seems that [src] is out of eggs!</span>")
to_chat(src, "<span class='notice'>[pick(rimplant.empty_message)]</span>")
return
visible_message("<span class='notice'>[usr] starts squeezing [src]'s lower body firmly...</span>")
if (rimplant && do_after(usr,60))
var/egg = rimplant.eggtype
new egg(get_turf(src))
src.SetStunned(3)
playsound(src,'sound/vore/insert.ogg',50,1)
var/index = rand(1,3)
visible_message("<span class='danger'>[usr] starts squeezing [src]'s lower body firmly...</span>")
if (rimplant && do_after(usr,120,src))
if(src.Adjacent(usr))
var/egg = rimplant.eggtype
new egg(get_turf(src))
src.SetStunned(3)
playsound(src,'sound/vore/insert.ogg',50,1)
var/index = rand(1,3)
if (usr != src)
var/emote = rimplant.emote_descriptor[index]
var/verb_desc = rimplant.verb_descriptor[index]
var/self_verb_desc = rimplant.self_verb_descriptor[index]
visible_message("<span class='notice'>[usr] [verb_desc] [emote]</span>",
"<span class='notice'>You [self_verb_desc] [emote]</span>")
if (usr != src)
var/emote = rimplant.emote_descriptor[index]
var/verb_desc = rimplant.verb_descriptor[index]
var/self_verb_desc = rimplant.self_verb_descriptor[index]
visible_message("<span class='notice'>[usr] [verb_desc] [emote]</span>",
"<span class='notice'>You [self_verb_desc] [emote]</span>")
else
visible_message("<span class='notice'>[src] [pick(rimplant.short_emote_descriptor)] an egg.</span>",
"<span class='notice'>You [pick(rimplant.self_emote_descriptor)] an egg.</span>")
if(prob(15))
visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>")
rimplant.reagents.remove_any(rimplant.transfer_amount)
if(rimplant.cascade)
to_chat(src, "<span class='notice'>You feel your legs quake as your muscles fail to stand strong!</span>")
while(rimplant.reagents.total_volume >= rimplant.transfer_amount)
if(do_after(src,30))
src.SetStunned(3)
playsound(src,'sound/vore/insert.ogg',50,1)
src.apply_effect(10,STUTTER,0)
new egg(get_turf(src))
rimplant.reagents.remove_any(rimplant.transfer_amount)
if(prob(25))
visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>")
else
visible_message("<span class='notice'>[src] [pick(rimplant.short_emote_descriptor)] an egg.</span>",
"<span class='notice'>You [pick(rimplant.self_emote_descriptor)] an egg.</span>")
return
/mob/living/carbon/human/proc/toggle_cascade()
if(prob(15))
visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>")
rimplant.reagents.remove_any(rimplant.transfer_amount)
set name = "Toggle cascading"
set desc = "Toggle whether or not being forced to lay an egg will cause you to lay all others as well, in rapid succession"
set category = "Local"
var/obj/item/weapon/implant/reagent_generator/egg/rimplant
for(var/obj/item/organ/external/E in organs)
for(var/obj/item/weapon/implant/I in E.implants)
if(istype(I, /obj/item/weapon/implant/reagent_generator))
rimplant = I
break
if(rimplant.cascade)
rimplant.cascade = 0
to_chat(src, "<span class='notice'>You toggle cascading off</span>")
else
rimplant.cascade = 1
to_chat(src, "<span class='notice'>You toggle cascading on</span>")
if(prob(70*rimplant.reagents.total_volume/rimplant.usable_volume))
to_chat(src, "<span class='notice'>You feel your legs quake as your muscles fail to stand strong!</span>")
while(rimplant.reagents.total_volume >= rimplant.transfer_amount)
if(do_after(src,30))
src.SetStunned(5)
playsound(src,'sound/vore/insert.ogg',50,1)
src.apply_effect(10,STUTTER,0)
new egg(get_turf(src))
rimplant.reagents.remove_any(rimplant.transfer_amount)
if(prob(25))
visible_message("<span class='notice'>[src] [pick(rimplant.random_emote)].</span>")
/obj/item/weapon/implant/reagent_generator/egg/slow
name = "slow egg laying implant"
usable_volume = 3000
transfer_amount = 300
transfer_amount = 600
/obj/item/weapon/implant/reagent_generator/egg/veryslow
name = "very slow egg laying implant"
usable_volume = 6000
transfer_amount = 600
transfer_amount = 1200
/obj/item/weapon/implant/reagent_generator/egg/hicap
name = "high capacity egg laying implant" // Note that the capacity does not affect the regeneration rate, rather, the transfer amount does
usable_volume = 1000 // Effectively, the transfer_amount is the cost/time of making an egg. Usable volume is simply the max number of eggs.
transfer_amount = 50
usable_volume = 3000 // Effectively, the transfer_amount is the cost/time of making an egg. Usable volume is simply the max number of eggs.
transfer_amount = 300
/obj/item/weapon/implant/reagent_generator/egg/doublehicap
name = "extreme capacity egg laying implant"
usable_volume = 2000
transfer_amount = 50
usable_volume = 6000
transfer_amount = 300
/obj/item/weapon/implant/reagent_generator/egg/slowlowcap
name = "slow, low capacity egg laying implant"
@@ -68,7 +68,7 @@
item_state = "candlebox5"
throwforce = 2
slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5
max_storage_space = ITEMSIZE_COST_TINY * 5 //CHOMPEdit
starts_with = list(/obj/item/weapon/flame/candle = 5)
/obj/item/weapon/storage/fancy/whitecandle_box
@@ -80,7 +80,7 @@
item_state = "whitecandlebox5"
throwforce = 2
slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5
max_storage_space = ITEMSIZE_COST_TINY * 5 //CHOMPEdit
starts_with = list(/obj/item/weapon/flame/candle/white = 5)
/obj/item/weapon/storage/fancy/blackcandle_box
@@ -92,7 +92,7 @@
item_state = "blackcandlebox5"
throwforce = 2
slot_flags = SLOT_BELT
max_storage_space = ITEMSIZE_COST_SMALL * 5
max_storage_space = ITEMSIZE_COST_TINY * 5 //CHOMPEdit
starts_with = list(/obj/item/weapon/flame/candle/black = 5)
@@ -0,0 +1,7 @@
/obj/item/weapon/storage/fancy/cigar/cohiba
name = "cohiban cigar case"
starts_with = list(/obj/item/clothing/mask/smokable/cigarette/cigar/cohiba = 7)
/obj/item/weapon/storage/fancy/cigar/havana
name = "havanian cigar case"
starts_with = list(/obj/item/clothing/mask/smokable/cigarette/cigar/havana = 7)
@@ -349,9 +349,11 @@
to_chat(user, "<span class='danger'>You go blind!</span>")
user.Blind(5)
user.eye_blurry = 5
user.disabilities |= NEARSIGHTED
spawn(100)
user.disabilities &= ~NEARSIGHTED
// Don't cure being nearsighted
if(!(H.disabilities & NEARSIGHTED))
user.disabilities |= NEARSIGHTED
spawn(100)
user.disabilities &= ~NEARSIGHTED
return
/obj/item/weapon/weldingtool/is_hot()
@@ -0,0 +1,96 @@
//Try not to question it too hard. These are the spicy tools.
/obj/item/weapon/tool/crowbar/heavysniper
name = "anti-materiel sniper crowbar"
desc = "This abomination or piece of art, depending on how you view it, seems to use a 14.5mm anti-materiel sniper rifle to the same effect of a crowbar."
icon = 'icons/obj/gun.dmi'
icon_state = "heavysniper"
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi')
item_state = "heavysniper"
toolspeed = 0.1
force = 30
usesound = 'sound/weapons/Gunshot_cannon.ogg'
/obj/item/weapon/weldingtool/lasercannon
name = "laser cannon welding tool"
desc = "This abomination or piece of art, depending on how you view it, seems to be a laser cannon converted into a welding tool."
icon = 'icons/obj/gun.dmi'
icon_state = "lasercannon"
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi')
item_state = "mhdhowitzer-wielded"
toolspeed = 0.1
usesound = 'sound/weapons/lasercannonfire.ogg'
acti_sound = 'sound/weapons/kenetic_reload.ogg'
always_process = TRUE
/obj/item/weapon/weldingtool/lasercannon/process()
if(get_fuel() <= get_max_fuel())
reagents.add_reagent("fuel", 1)
..()
/obj/item/weapon/weldingtool/lasercannon/update_icon()
// Lights
if(welding && flame_intensity)
set_light(flame_intensity, flame_intensity, flame_color)
else
set_light(0)
// icon_state = welding ? "[icon_state]1" : "[initial(icon_state)]"
var/mob/M = loc
if(istype(M))
M.update_inv_l_hand()
M.update_inv_r_hand()
/obj/item/weapon/tool/wrench/fuelrod
name = "fuel-rod cannon wrench"
desc = "This abomination or piece of art, depending on how you view it, seems to by some means use a fuel rod cannon as a wrench... how this is possible, one can only theorize."
icon = 'icons/obj/railgun.dmi'
icon_state = "fuelrodgun"
item_icons = list(slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi')
item_state = "coilgun"
usesound = 'sound/weapons/railgun.ogg'
toolspeed = 0.1
force = 30
/obj/item/weapon/tool/wirecutters/chainsaw
name = "chainsaw wirecutters"
desc = "This abomination or piece of art, depending on how you view it, seems to be a chainsaw that is by some means converted into wirecutters."
icon = 'icons/obj/weapons.dmi'
icon_state = "chainsaw0"
item_state = "chainsaw0"
usesound = 'sound/weapons/chainsaw_attack.ogg'
random_color = FALSE
toolspeed = 0.1
force = 30
/obj/item/weapon/tool/screwdriver/diamonddrill
name = "diamond drill power screwdriver"
desc = "This abomination or piece of art, depending on how you view it, seems to be a diamond drill that was converted into a power screwdriver."
icon = 'icons/obj/items.dmi'
icon_state = "diamonddrill"
item_state = "jackhammer"
hitsound = 'sound/items/drill_hit.ogg'
usesound = 'sound/items/drill_use.ogg'
random_color = FALSE
toolspeed = 0.1
force = 30
/obj/item/stack/cable_coil/alien/blood
name = "Blood cable coil"
desc = "This seems to be a blood red cable coil which magically replenishes itself, and if you look closely at the insulation you can read the words \"forged from the blood of our enemies\""
icon = 'icons/obj/power.dmi'
icon_state = "coil"
item_state = "coil"
color = "#8A0303"
catalogue_data = null
toolspeed = 0.1
/obj/item/weapon/storage/belt/utility/spicyfull
starts_with = list(
/obj/item/weapon/tool/crowbar/heavysniper,
/obj/item/weapon/weldingtool/lasercannon,
/obj/item/weapon/tool/wrench/fuelrod,
/obj/item/weapon/tool/wirecutters/chainsaw,
/obj/item/weapon/tool/screwdriver/diamonddrill,
/obj/item/stack/cable_coil/alien/blood
)
+230
View File
@@ -0,0 +1,230 @@
/obj/kbutton
name = "button"
icon = 'icons/obj/objects.dmi'
icon_state = "launcherbtt"
desc = "A remote control switch for something."
anchored = 1.0
var/nothing_sound_file //Sound to play when button fails to be pressed
var/nothing_sound_volume //Volume of sound when button fails to be pressed
var/pressed_sound_file = 'sound/machines/button.ogg'//Sound to play when button is successfully pressed
var/pressed_sound_volume = 100 //Volume of sound when button is successfully pressed
var/list/trig_target_paths = list() //What are the paths of whatever we want to call our proc on?
var/trig_target_trigger_uid //What is the trigger_uid of whatever we want to call our proc on?
var/trig_proc //What proc do we want to call?
var/list/trig_args = list() //What are the arguments for said proc?
var/trig_message = "You press the button" //Should we send a message to the person who pressed the button?
var/trig_message_span_class = "notice" //Span class used for pressed message, normal ones include notice, warning, and danger.
var/nothing_message = "Nothing happens." //Should we send a message if nothing happens when the button is pressed?
var/nothing_message_span_class = "warning" //Span class used for nothing message, normal ones include notice, warning, and danger.
var/list/trig_targets = list()
var/trig_target_is_trigerrer = FALSE //Should we use the button presser as the target?
/obj/kbutton/attackby(obj/item/weapon/W, mob/user as mob)
return attack_hand(user)
/obj/kbutton/attack_hand(mob/user as mob)
. = ..()
if(can_press(user))
if(trig_target_is_trigerrer)
trig_targets = list(user)
button_trigger()
if(pressed_sound_file)
playsound(src, pressed_sound_file, pressed_sound_volume, 1)
if(trig_message)
to_chat(user,"<span class='[trig_message_span_class]'>"+trig_message+"</span>")
else
if(nothing_sound_file)
playsound(src, nothing_sound_file, nothing_sound_volume, 1)
if(nothing_message)
to_chat(user,"<span class='[nothing_message_span_class]'>"+nothing_message+"</span>")
return
/obj/kbutton/proc/button_trigger()
if(trig_proc)
if(trig_targets.len)
var/testname = trig_proc
//Find one of the 3 possible ways they could have written /proc/PROCNAME
if(findtext(trig_proc, "/proc/"))
testname = replacetext(trig_proc, "/proc/", "")
else if(findtext(trig_proc, "/proc"))
testname = replacetext(trig_proc, "/proc", "")
else if(findtext(trig_proc, "proc/"))
testname = replacetext(trig_proc, "proc/", "")
//Clear out any parenthesis if they're a dummy
testname = replacetext(testname, "()", "")
for(var/trig_target in trig_targets)
if(trig_target && !hascall(trig_target,testname))
message_admins("TRIGGER ERROR: ONE OR MORE TRIGGER TARGETS LACKS THE MENTIONED PROC")
return
for(var/trig_target in trig_targets)
call(trig_target,testname)(arglist(trig_args))
else
var/procpath = text2path(trig_proc)
if(!procpath)
message_admins("TRIGGER ERROR: INVALID PROC")
return
call(procpath)(arglist(trig_args))
/obj/kbutton/proc/can_press(mob/user)
return TRUE
/obj/kbutton/proc/update_trig_targets()
trig_targets = list()
for(var/path in trig_target_paths)
var/trig_target_path = text2path(path)
if(trig_target_path && trig_target_trigger_uid)
var/list/candidates = get_all_of_type(trig_target_path)
for(var/candidate in candidates)
var/datum/cand_datum = candidate
if(istype(cand_datum))
if(cand_datum.trigger_uid == trig_target_trigger_uid)
trig_targets += candidate
continue
continue
if(!trig_targets.len)
message_admins("TRIGGER ERROR: trig_targets STILL EMPTY AFTER CALLED update_trig_targets()")
/obj/kbutton/Initialize(mapload)
. = ..()
update_trig_targets()
return
/obj/kbutton/single_use
name = "single use button"
var/has_been_pressed = FALSE
/obj/kbutton/single_use/button_trigger()
has_been_pressed = TRUE
..()
/obj/kbutton/single_use/can_press(mob/user)
return !has_been_pressed
/obj/kbutton/single_use_per_mob
name = "button"
var/list/been_triggered_by = list()
/obj/kbutton/single_use_per_mob/can_press(mob/user)
if(user in been_triggered_by)
return FALSE
else
been_triggered_by |= user
return TRUE
/obj/kbutton/toggle
name = "toggle button"
var/toggled = FALSE
//For each of the following, each of the following variables will be used when switching to that state,
//and if it's set to null, it will use def(short for default)
var/trig_message_types = list(\
"def" = "You toggle the button.", \
"on" = null, \
"off" = null)
var/nothing_message_types = list(\
"def" = "Nothing happens.", \
"on" = null, \
"off" = null)
var/pressed_sound_file_types = list(\
"def" = 'sound/machines/button.ogg', \
"on" = null, \
"off" = null)
var/pressed_sound_volume_types = list(\
"def" = 100, \
"on" = null, \
"off" = null)
var/nothing_sound_file_types = list(\
"def" = null, \
"on" = null, \
"off" = null)
var/nothing_sound_volume_types = list(\
"def" = null, \
"on" = null, \
"off" = null)
var/icon_types = list(\
"def" = 'icons/obj/objects.dmi', \
"on" = null, \
"off" = null)
var/icon_state_types = list(\
"def" = "launcherbtt", \
"on" = null, \
"off" = null)
var/trig_proc_types = list(\
"def" = null, \
"on" = null, \
"off" = null)
var/trig_args_types = list(\
"def" = list(), \
"on" = list(), \
"off" = list())
/obj/kbutton/toggle/Initialize(mapload)
. = ..()
update_variables()
/obj/kbutton/toggle/proc/update_variables()
var/index = toggled ? "on" : "off"
trig_message = trig_message_types[index] ? trig_message_types[index] : trig_message_types["def"]
nothing_message = nothing_message_types[index] ? nothing_message_types[index] : nothing_message_types["def"]
pressed_sound_file = pressed_sound_file_types[index] ? pressed_sound_file_types[index] : pressed_sound_file_types["def"]
pressed_sound_volume = pressed_sound_volume_types[index] ? pressed_sound_volume_types[index] : pressed_sound_volume_types["def"]
nothing_sound_file = nothing_sound_file_types[index] ? nothing_sound_file_types[index] : nothing_sound_file_types["def"]
nothing_sound_volume = nothing_sound_volume_types[index] ? nothing_sound_volume_types[index] : nothing_sound_volume_types["def"]
icon = icon_types[index] ? icon_types[index] : icon_types["def"]
icon_state = icon_state_types[index] ? icon_state_types[index] : icon_state_types["def"]
trig_proc = trig_proc_types[index] ? trig_proc_types[index] : trig_proc_types["def"]
trig_args = trig_args_types[index].len ? trig_args_types[index] : trig_args_types["def"]
/obj/kbutton/toggle/button_trigger()
toggled = !toggled
update_variables()
..()
//An example button which opens and closes a closet.
/obj/kbutton/toggle/example
var/press_wait_time = 25
var/last_pressed = 0
trig_target_paths = list("/obj/structure/closet")
trig_target_trigger_uid = 97482
trig_message_types = list(\
"def" = "You toggle the button.", \
"on" = "You switch the button on.", \
"off" = "You switch the button off.")
nothing_message_types = list(\
"def" = "Nothing happens.", \
"on" = "You fail to switch the button off.", \
"off" = "You fail to switch the button on.")
pressed_sound_file_types = list(\
"def" = 'sound/machines/button.ogg', \
"on" = 'sound/machines/chime.ogg', \
"off" = 'sound/machines/buttonbeep.ogg')
pressed_sound_volume_types = list(\
"def" = 80, \
"on" = 80, \
"off" = 80)
nothing_sound_file_types = list(\
"def" = 'sound/machines/buzz-sigh.ogg', \
"on" = 'sound/machines/buzz-sigh.ogg', \
"off" = 'sound/machines/buzz-two.ogg')
nothing_sound_volume_types = list(\
"def" = 100, \
"on" = 100, \
"off" = 100)
icon_state_types = list(\
"def" = "launcherbtt", \
"on" = "launcheract", \
"off" = "launcherbtt")
trig_proc_types = list(\
"def" = "close", \
"on" = "open", \
"off" = "close")
/obj/kbutton/toggle/example/can_press(mob/user)
if(world.time > last_pressed + press_wait_time)
last_pressed = world.time
return TRUE
else
return FALSE
//Corresponding closet for example button
/obj/structure/closet/button_example
trigger_uid = 97482
+10
View File
@@ -250,6 +250,16 @@
removed.add_thermal_energy(heat_transfer)
for(var/mob/living/L in view(3, src))
L.add_modifier(/datum/modifier/endothermic, 10 SECONDS, null, TRUE)
for(var/obj/item/stack/wetleather/WL in view(2, src))
if(WL.wetness >= 0)
WL.dry()
continue
WL.wetness = max(0, WL.wetness - rand(1, 4))
env.merge(removed)
/obj/structure/bonfire/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+45 -1
View File
@@ -235,7 +235,7 @@
/obj/structure/flora/pottedplant/attackby(obj/item/I, mob/user)
if(issilicon(user))
return // Don't try to put modules in here, you're a borg. TODO: Inventory refactor to not be ass.
if(stored_item)
to_chat(user, "<span class='notice'>[I] won't fit in. There already appears to be something in here...</span>")
return
@@ -494,3 +494,47 @@
/obj/structure/flora/sif/tendrils/get_harvestable_desc()
return "<span class='notice'>\The [src] seems to be growing over something.</span>"
/datum/category_item/catalogue/flora/frostbelle
name = "Sivian Flora - Frostbelle"
desc = "A rare plant native to Sif, with very peculiar growing requirements. Rarely seen outside of their original habitat,\
or the homes of the wealthy, the plant's unique vein structure is actually used to carry the plant's reproductive material \
to forming buds, the petals of which secrete the luminescent sap containing the pollen at the time of blooming. Certain \
horticulturists have found ways of halting this process prior to the secretion of the sap, leaving the flower's petals \
bright, at the cost of making that bud sterile."
value = CATALOGUER_REWARD_HARD
/obj/structure/flora/sif/frostbelle
name = "gnarly shrub"
desc = "A stocky plant with fins bearing luminescent veins along its branches."
icon_state = "grass"
randomize_size = TRUE
catalogue_data = list(/datum/category_item/catalogue/flora/frostbelle)
harvest_tool = /obj/item/weapon/material/knife
max_harvests = 2
min_harvests = -4
harvest_loot = list(
/obj/item/weapon/reagent_containers/food/snacks/frostbelle = 1
)
var/variantnum = null
/obj/structure/flora/sif/frostbelle/Initialize()
. = ..()
variantnum = rand(1,3)
update_icon()
/obj/structure/flora/sif/frostbelle/update_icon()
..()
if(max_harvests > 0 && harvest_count < max_harvests)
icon_state = "[initial(icon_state)][variantnum]"
else
icon_state = initial(icon_state)
/obj/structure/flora/sif/frostbelle/get_harvestable_desc()
return "<span class='notice'>\The [src] seems to be budding.</span>"
+2 -2
View File
@@ -11,12 +11,12 @@
/obj/structure/lattice/Initialize()
. = ..()
if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/mineral)))
if(!(istype(src.loc, /turf/space) || istype(src.loc, /turf/simulated/open) || istype(src.loc, /turf/simulated/mineral) || istype(src.loc, /turf/simulated/shuttle/plating/airless/carry)))
return INITIALIZE_HINT_QDEL
for(var/obj/structure/lattice/LAT in src.loc)
if(LAT != src)
crash_with("Found multiple lattices at '[log_info_line(loc)]'")
log_debug("Found multiple lattices at '[log_info_line(loc)]'") //VOREStation Edit, why was this a runtime, it's harmless
return INITIALIZE_HINT_QDEL
icon = 'icons/obj/smoothlattice.dmi'
icon_state = "latticeblank"
@@ -0,0 +1,313 @@
/obj/structure/reflector
name = "reflector base"
icon = 'icons/obj/tgs_structures_ch.dmi'
icon_state = "reflector_map"
desc = "A base for reflector assemblies."
anchored = FALSE
density = FALSE
var/deflector_icon_state
var/image/deflector_overlay
var/finished = FALSE
var/admin = FALSE //Can't be rotated or deconstructed
var/can_rotate = TRUE
var/framebuildstacktype = /obj/item/stack/material//metal
var/framebuildstackamount = 5
var/buildstacktype = /obj/item/stack/material//metal
var/buildstackamount = 0
var/fires_projectile = /obj/item/projectile/beam/emitter
var/fires_accuracy = 10000
var/fires_dispersion = 0
var/list/allowed_projectile_typecache = list(/obj/item/projectile/beam)
var/rotation_angle = -1
var/can_decon = TRUE
var/list/has_projectiles = list()
var/bullet_act_in_progress = FALSE
/obj/structure/reflector/Initialize()
. = ..()
icon_state = "reflector_base"
allowed_projectile_typecache = typecacheof(allowed_projectile_typecache)
if(deflector_icon_state)
deflector_overlay = image(icon, deflector_icon_state)
add_overlay(deflector_overlay)
if(rotation_angle == -1)
setAngle(dir2angle(dir))
else
setAngle(rotation_angle)
if(admin)
can_rotate = FALSE
SSreflector.processing += src
/obj/structure/reflector/examine(mob/user)
. = ..()
if(finished)
. += "It is set to [rotation_angle] degrees, and the rotation is [can_rotate ? "unlocked" : "locked"]."
if(!admin)
if(can_rotate)
. += "<span class='notice'>Alt-click to adjust its direction.</span>"
else
. += "<span class='notice'>Use screwdriver to unlock the rotation.</span>"
/obj/structure/reflector/proc/Fire()
UNTIL(!bullet_act_in_progress)
var/list/angles = list()
for(var/obj/item/projectile/P in has_projectiles)
angles[num2text(has_projectiles[P])] += P.damage
for(var/angle in angles)
var/obj/item/projectile/P = new fires_projectile(src)
P.firer = src
P.damage = angles[angle]
P.accuracy = 350
P.dispersion = 0
P.fire(text2num(angle))
has_projectiles = list()
/obj/structure/reflector/proc/setAngle(new_angle)
if(can_rotate)
rotation_angle = new_angle
if(deflector_overlay)
cut_overlay(deflector_overlay)
deflector_overlay.transform = turn(matrix(), new_angle)
add_overlay(deflector_overlay)
/obj/structure/reflector/proc/redirect_projectile(obj/item/projectile/P,pangle)
has_projectiles[P] = pangle
qdel(P)
/obj/structure/reflector/set_dir(new_dir)
return ..(NORTH)
/obj/structure/reflector/Crossed(atom/movable/AM) //Ok so this is my solution to garbage projectile code. Please god let this work.
if(istype(AM,/obj/item/projectile))
AM.Bump(src)
/obj/structure/reflector/bullet_act(obj/item/projectile/P)
bullet_act_in_progress = TRUE
var/pdir = P.dir
var/pangle = P.Angle
var/ploc = get_turf(P)
if(!finished || !allowed_projectile_typecache[P.type] || !(P.dir in cardinal))
return ..()
if(auto_reflect(P, pdir, ploc, pangle) != 2)
return ..()
bullet_act_in_progress = FALSE
/obj/structure/reflector/proc/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
P.ignore_source_check = TRUE
return 2
/obj/structure/reflector/attackby(obj/item/W, mob/user, params)
if(admin)
return
if(W.is_screwdriver())
can_rotate = !can_rotate
to_chat(user, "<span class='notice'>You [can_rotate ? "unlock" : "lock"] [src]'s rotation.</span>")
playsound(W, W.usesound, 50, 1)
return
if(W.is_wrench() && can_decon)
if(anchored)
to_chat(user, "<span class='warning'>Unweld [src] from the floor first!</span>")
return
user.visible_message("<span class='notice'>[user] starts to dismantle [src].</span>", "<span class='notice'>You start to dismantle [src]...</span>")
to_chat(user, "<span class='notice'>You dismantle [src].</span>")
new framebuildstacktype(drop_location(), framebuildstackamount)
if(buildstackamount)
new buildstacktype(drop_location(), buildstackamount)
qdel(src)
else if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/I = W
if(!anchored)
if(!I.remove_fuel(1,user))
return
user.visible_message("<span class='notice'>[user] starts to weld [src] to the floor.</span>",
"<span class='notice'>You start to weld [src] to the floor...</span>",
"<span class='hear'>You hear welding.</span>")
anchored = TRUE
to_chat(user, "<span class='notice'>You weld [src] to the floor.</span>")
else
if(!I.remove_fuel(1,user))
return
user.visible_message("<span class='notice'>[user] starts to cut [src] free from the floor.</span>",
"<span class='notice'>You start to cut [src] free from the floor...</span>",
"<span class='hear'>You hear welding.</span>")
anchored = FALSE
to_chat(user, "<span class='notice'>You cut [src] free from the floor.</span>")
//Finishing the frame
else if(istype(W, /obj/item/stack/material))
if(finished)
return
var/obj/item/stack/material/S = W
if(istype(S, /obj/item/stack/material/glass))
if(S.use(5))
new /obj/structure/reflector/single(drop_location())
qdel(src)
else
to_chat(user, "<span class='warning'>You need five sheets of glass to create a reflector!</span>")
return
if(istype(S, /obj/item/stack/material/glass/reinforced))
if(S.use(10))
new /obj/structure/reflector/double(drop_location())
qdel(src)
else
to_chat(user, "<span class='warning'>You need ten sheets of reinforced glass to create a double reflector!</span>")
return
if(istype(S, /obj/item/stack/material/diamond))
if(S.use(1))
new /obj/structure/reflector/box(drop_location())
qdel(src)
else
return ..()
/obj/structure/reflector/proc/rotate(mob/user)
if (!can_rotate || admin)
to_chat(user, "<span class='warning'>The rotation is locked!</span>")
return FALSE
var/new_angle = input(user, "Input a new angle for primary reflection face.", "Reflector Angle", rotation_angle) as null|num
if(!CanUseTopic(user))
return
if(!isnull(new_angle))
setAngle(SIMPLIFY_DEGREES(new_angle))
return TRUE
/obj/structure/reflector/AltClick(mob/user)
if(!CanUseTopic(user))
return
else if(finished)
rotate(user)
//TYPES OF REFLECTORS, SINGLE, DOUBLE, BOX
//SINGLE
/obj/structure/reflector/single
name = "reflector"
deflector_icon_state = "reflector"
desc = "An angled mirror for reflecting laser beams."
density = TRUE
finished = TRUE
buildstacktype = /obj/item/stack/material//glass
buildstackamount = 5
/obj/structure/reflector/single/anchored
anchored = TRUE
/obj/structure/reflector/single/mapping
admin = TRUE
anchored = TRUE
/obj/structure/reflector/single/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
var/incidence = GET_ANGLE_OF_INCIDENCE(rotation_angle, (P.Angle + 180))
if(abs(incidence) > 90 && abs(incidence) < 270)
return FALSE
var/new_angle = SIMPLIFY_DEGREES(rotation_angle + incidence)
redirect_projectile(P,new_angle)
return ..()
//DOUBLE
/obj/structure/reflector/double
name = "double sided reflector"
deflector_icon_state = "reflector_double"
desc = "A double sided angled mirror for reflecting laser beams."
density = TRUE
finished = TRUE
buildstacktype = /obj/item/stack/material/glass/reinforced
buildstackamount = 10
/obj/structure/reflector/double/anchored
anchored = TRUE
/obj/structure/reflector/double/mapping
admin = TRUE
anchored = TRUE
/obj/structure/reflector/double/auto_reflect(obj/item/projectile/P, pdir, turf/ploc, pangle)
var/incidence = GET_ANGLE_OF_INCIDENCE(rotation_angle, (P.Angle + 180))
var/new_angle = SIMPLIFY_DEGREES(rotation_angle + incidence)
redirect_projectile(P,new_angle)
return ..()
//BOX
/obj/structure/reflector/box
name = "reflector box"
deflector_icon_state = "reflector_box"
desc = "A box with an internal set of mirrors that reflects all laser beams in a single direction."
density = TRUE
finished = TRUE
buildstacktype = /obj/item/stack/material/diamond
buildstackamount = 1
/obj/structure/reflector/box/Fire() //Since they all end up at the same angle, this should save a tad bit of processing power and memory <3
UNTIL(!bullet_act_in_progress)
var/total_damage = 0
for(var/obj/item/projectile/P in has_projectiles)
total_damage += P.damage
if(total_damage)
var/obj/item/projectile/P = new fires_projectile(src)
P.firer = src
P.damage = total_damage
P.accuracy = 350
P.dispersion = 0
P.fire(rotation_angle)
has_projectiles = list()
/obj/structure/reflector/box/anchored
anchored = TRUE
/obj/structure/reflector/box/mapping
admin = TRUE
anchored = TRUE
/obj/structure/reflector/box/auto_reflect(obj/item/projectile/P)
redirect_projectile(P,rotation_angle)
return ..()
/obj/structure/reflector/ex_act()
if(admin)
return
else
return ..()
/obj/structure/reflector/singularity_act()
if(admin)
return
else
return ..()
/obj/structure/reflector/box/orderable
name = "NanoTrasen reflector box"
desc = "A box with an internal set of mirrors that reflects all laser beams in a single direction. This one is marked with NanoTrasen's logo."
can_decon = FALSE
/datum/material/steel/generate_recipes()
..()
recipes += new/datum/stack_recipe("reflector frame", /obj/structure/reflector, 5, time = 25, one_per_turf = TRUE, on_floor = TRUE)
/datum/supply_pack/eng/reflector
name = "Reflector crate"
cost = 35
containername = "Reflector crate"
containertype = /obj/structure/closet/crate/secure/einstein
contains = list(/obj/structure/reflector/box/orderable = 3)
//Below is mostly mapping stuff for the spicy storage I added to house these new reflectors ;p
/area/engineering/secret_storage
name = "Engineering Secret Storage"
/obj/machinery/portable_atmospherics/canister
var/dont_burst = FALSE
/obj/machinery/portable_atmospherics/canister/phoron/cold/New()
src.air_contents.temperature = 2.72
..()