Merge remote-tracking branch 'upstream/master' into advanced-camera-fixup

This commit is contained in:
Fox-McCloud
2017-02-12 09:44:07 -05:00
259 changed files with 5467 additions and 3366 deletions
+3 -3
View File
@@ -447,7 +447,7 @@
new/obj/machinery/door/airlock(get_turf(object))
else if(istype(object,/turf) && ctrl_click && left_click)
var/obj/structure/window/reinforced/WIN = new/obj/structure/window/reinforced(get_turf(object))
WIN.set_dir(build_dir)
WIN.setDir(build_dir)
log_admin("Build Mode: [key_name(user)] built a window at ([object.x],[object.y],[object.z])")
if(ADV_BUILDMODE)
@@ -458,7 +458,7 @@
T.ChangeTurf(objholder)
else
var/obj/A = new objholder (get_turf(object))
A.set_dir(build_dir)
A.setDir(build_dir)
log_admin("Build Mode: [key_name(user)] modified [A]'s ([A.x],[A.y],[A.z]) dir to [build_dir]")
else if(right_click)
if(isobj(object))
@@ -547,7 +547,7 @@
T.ChangeTurf(objholder)
else
var/obj/A = new objholder(T)
A.set_dir(build_dir)
A.setDir(build_dir)
deselect_region()
return
@@ -4,10 +4,10 @@
name = "\improper Clown Planet"
icon_state = "honk"
luminosity = 1
lighting_use_dynamic = 0
dynamic_lighting = 0
requires_power = 0
report_alerts = 0
/area/awaymission/clownplanet/miningtown
name = "\improper Clown Planet - Bananium-o-Rama"
icon_state = "away1"
-7
View File
@@ -13,13 +13,6 @@ var/global/list/potentialRandomZlevels = generateMapList(filename = "config/away
air_master.setup_allturfs(turfs)
log_debug("\tTook [stop_watch(subtimer)]s")
subtimer = start_watch()
log_debug("Initializing lighting")
for(var/turf/T in turfs)
if(T.dynamic_lighting)
T.lighting_build_overlays()
log_debug("\tTook [stop_watch(subtimer)]s")
subtimer = start_watch()
log_debug("Smoothing tiles")
for(var/turf/T in smoothTurfs)
+1 -1
View File
@@ -1,7 +1,7 @@
/area/awaymission/upperlevel
name = "Open Space"
color = "#888"
lighting_use_dynamic = 0
dynamic_lighting = 0
requires_power = 0
// Used by /turf/unsimulated/floor/upperlevel as a reference for where the other floor is
+3 -1
View File
@@ -92,4 +92,6 @@
var/datum/chatOutput/chatOutput
// Donator stuff.
var/donator_level = DONATOR_LEVEL_NONE
var/donator_level = DONATOR_LEVEL_NONE
var/var_edited = FALSE
+10
View File
@@ -233,6 +233,10 @@
return 0
return 1
//Like for /atoms, but clients are their own snowflake FUCK
/client/proc/setDir(newdir)
dir = newdir
/client/proc/handle_spam_prevention(var/message, var/mute_type, var/throttle = 0)
if(throttle)
if((last_message_time + throttle > world.time) && !check_rights(R_ADMIN, 0))
@@ -621,3 +625,9 @@
if(lang.flags & RESTRICTED)
message += " (RESTRICTED)"
to_chat(world, "[message]")
/client/proc/colour_transition(var/list/colour_to = null, var/time = 10) //Call this with no parameters to reset to default.
animate(src, color=colour_to, time=time, easing=SINE_EASING)
/client/proc/on_varedit()
var_edited = TRUE
@@ -817,6 +817,7 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
HTML += ShowDisabilityState(user,DISABILITY_FLAG_EPILEPTIC,"Seizures")
HTML += ShowDisabilityState(user,DISABILITY_FLAG_DEAF,"Deaf")
HTML += ShowDisabilityState(user,DISABILITY_FLAG_BLIND,"Blind")
HTML += ShowDisabilityState(user,DISABILITY_FLAG_COLOURBLIND,"Colourblind")
HTML += ShowDisabilityState(user,DISABILITY_FLAG_MUTE,"Mute")
@@ -1339,9 +1340,8 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
//Reset prosthetics.
organ_data = list()
rlimb_data = list()
if("speciesprefs")//oldvox code
speciesprefs = !speciesprefs
if("speciesprefs")
speciesprefs = !speciesprefs //Starts 0, so if someone clicks the button up top there, this won't be 0 anymore. If they click it again, it'll go back to 0.
if("language")
// var/languages_available
var/list/new_languages = list("None")
@@ -2168,6 +2168,9 @@ var/global/list/special_role_times = list( //minimum age (in days) for accounts
if(disabilities & DISABILITY_FLAG_BLIND)
character.dna.SetSEState(BLINDBLOCK,1,1)
if(disabilities & DISABILITY_FLAG_COLOURBLIND)
character.dna.SetSEState(COLOURBLINDBLOCK,1,1)
if(disabilities & DISABILITY_FLAG_MUTE)
character.dna.SetSEState(MUTEBLOCK,1,1)
+27 -32
View File
@@ -232,8 +232,6 @@
name = "noir sunglasses"
desc = "Somehow these seem even more out-of-date than normal sunglasses."
actions_types = list(/datum/action/item_action/noir)
var/noir_mode = 0
color_view = MATRIX_GREYSCALE
/obj/item/clothing/glasses/sunglasses/noir/attack_self()
toggle_noir()
@@ -243,36 +241,8 @@
return 1
/obj/item/clothing/glasses/sunglasses/noir/proc/toggle_noir()
var/list/difference = difflist(usr.client.color, color_view)
if(!noir_mode)
if(color_view && usr.client && (!usr.client.color || difference))
animate(usr.client, color = color_view, time = 10)
noir_mode = 1
else
if(usr.client && usr.client.color && !difference)
animate(usr.client, color = initial(usr.client.color), time = 10)
noir_mode = 0
/obj/item/clothing/glasses/sunglasses/noir/equipped(mob/user, slot)
var/list/difference = difflist(user.client.color, color_view)
if(slot == slot_glasses)
if(noir_mode)
if(color_view && user.client && (!user.client.color || difference.len))
animate(user.client, color = color_view, time = 10)
else
if(user.client && user.client.color && !difference.len)
animate(user.client, color = initial(user.client.color), time = 10)
..(user, slot)
/obj/item/clothing/glasses/sunglasses/noir/dropped(mob/living/carbon/human/user)
var/list/difference = difflist(user.client.color, color_view)
if(istype(user) && user.glasses == src)
if(user.client && user.client.color && !difference.len)
animate(user.client, color = initial(user.client.color), time = 10)
..(user)
color_view = color_view ? null : MATRIX_GREYSCALE //Toggles between null and grayscale, with null being the default option.
usr.update_client_colour()
/obj/item/clothing/glasses/sunglasses/yeah
name = "agreeable glasses"
@@ -498,3 +468,28 @@
name = "gar glasses"
icon_state = "gar"
item_state = "gar"
/obj/item/clothing/glasses/godeye
name = "eye of god"
desc = "A strange eye, said to have been torn from an omniscient creature that used to roam the wastes."
icon_state = "godeye"
item_state = "godeye"
vision_flags = SEE_TURFS|SEE_MOBS|SEE_OBJS
darkness_view = 8
scan_reagents = 1
flags = NODROP
invis_view = SEE_INVISIBLE_MINIMUM
/obj/item/clothing/glasses/godeye/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W, src) && W != src && W.loc == user)
if(W.icon_state == "godeye")
W.icon_state = "doublegodeye"
W.item_state = "doublegodeye"
W.desc = "A pair of strange eyes, said to have been torn from an omniscient creature that used to roam the wastes. There's no real reason to have two, but that isn't stopping you."
if(iscarbon(user))
var/mob/living/carbon/C = user
C.update_inv_wear_mask()
else
to_chat(user, "<span class='notice'>The eye winks at you and vanishes into the abyss, you feel really unlucky.</span>")
qdel(src)
..()
+31 -6
View File
@@ -7,20 +7,21 @@
armor = list(melee = 45, bullet = 25, laser = 30, energy = 10, bomb = 25, bio = 100, rad = 50)
rig_restrict_helmet = 0 // ERT helmets can be taken on and off at will.
var/obj/machinery/camera/camera
var/has_camera = TRUE
strip_delay = 130
/obj/item/clothing/head/helmet/space/rig/ert/attack_self(mob/user)
if(camera)
if(camera || !has_camera)
..(user)
else
camera = new /obj/machinery/camera(src)
camera.network = list("ERT")
cameranet.removeCamera(camera)
camera.c_tag = user.name
to_chat(user, "\blue User scanned as [camera.c_tag]. Camera activated.")
to_chat(user, "<span class='notice'>User scanned as [camera.c_tag]. Camera activated.</span>")
/obj/item/clothing/head/helmet/space/rig/ert/examine(mob/user)
if(..(user, 1))
if(..(user, 1) && has_camera)
to_chat(user, "This helmet has a built-in camera. It's [camera ? "" : "in"]active.")
/obj/item/clothing/suit/space/rig/ert
@@ -101,6 +102,7 @@
desc = "A suit worn by the janitorial of a Nanotrasen Emergency Response Team. Has purple highlights. Armoured, space ready, and fire resistant."
icon_state = "ert_janitor"
//Paranormal
/obj/item/clothing/head/helmet/space/rig/ert/paranormal
name = "paranormal response unit helmet"
desc = "A helmet worn by those who deal with paranormal threats for a living."
@@ -108,16 +110,39 @@
item_color = "ert_paranormal"
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
sprite_sheets = null
icon_override = 'icons/mob/clothing/paranormal_hardsuit.dmi'
actions_types = list()
has_camera = 0
/obj/item/clothing/suit/space/rig/ert/paranormal
name = "paranormal response team suit"
desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats."
icon_state = "knight_grey"
item_state = "knight_grey"
icon_state = "rig-paranormal"
max_heat_protection_temperature = FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT
sprite_sheets = null
icon_override = 'icons/mob/clothing/paranormal_hardsuit.dmi'
actions_types = list()
/obj/item/clothing/suit/space/rig/ert/paranormal/New()
..()
new /obj/item/weapon/nullrod(src)
/obj/item/clothing/head/helmet/space/rig/ert/paranormal/inquisitor
name = "inquisitor's helmet"
icon_state = "rig0-inquisitor"
item_color = "inquisitor"
/obj/item/clothing/suit/space/rig/ert/paranormal/inquisitor
name = "inquisitor's hardsuit"
icon_state = "rig-inquisitor"
/obj/item/clothing/head/helmet/space/rig/ert/paranormal/berserker
name = "champion's helmet"
desc = "Peering into the eyes of the helmet is enough to seal damnation."
icon_state = "rig0-berserker"
item_color = "berserker"
/obj/item/clothing/suit/space/rig/ert/paranormal/berserker
name = "champion's hardsuit"
desc = "Voices echo from the hardsuit, driving the user insane."
icon_state = "rig-berserker"
+9 -2
View File
@@ -101,8 +101,13 @@ var/list/event_last_fired = list()
playercount_modifier = 1
if(26 to 35)
playercount_modifier = 0.9
if(36 to 100000)
if(36 to 50)
playercount_modifier = 0.8
if(50 to 80)
playercount_modifier = 0.7
if(80 to 10000)
playercount_modifier = 0.6
playercount_modifier = playercount_modifier * delay_modifier
var/event_delay = rand(config.event_delay_lower[severity], config.event_delay_upper[severity]) * playercount_modifier
@@ -155,6 +160,7 @@ var/list/event_last_fired = list()
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Spider Infestation", /datum/event/spider_infestation, 100, list(ASSIGNMENT_SECURITY = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Ion Storm", /datum/event/ion_storm, 0, list(ASSIGNMENT_AI = 50, ASSIGNMENT_CYBORG = 50, ASSIGNMENT_ENGINEER = 15, ASSIGNMENT_SCIENTIST = 5)),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Borer Infestation", /datum/event/borer_infestation, 40, list(ASSIGNMENT_SECURITY = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Immovable Rod", /datum/event/immovable_rod, 0, list(ASSIGNMENT_ENGINEER = 30), 1),
//new /datum/event_meta/ninja(EVENT_LEVEL_MODERATE, "Space Ninja", /datum/event/space_ninja, 0, list(ASSIGNMENT_SECURITY = 15), 1),
// NON-BAY EVENTS
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Mass Hallucination", /datum/event/mass_hallucination, 300),
@@ -170,7 +176,7 @@ var/list/event_last_fired = list()
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Gravitational Anomaly", /datum/event/anomaly/anomaly_grav, 200),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Revenant", /datum/event/revenant, 150),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Swarmer Spawn", /datum/event/spawn_swarmer, 150, is_one_shot = 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/spawn_morph, 0, is_one_shot = 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Morph Spawn", /datum/event/spawn_morph, 40, is_one_shot = 1),
new /datum/event_meta(EVENT_LEVEL_MODERATE, "Disease Outbreak", /datum/event/disease_outbreak, 0, list(ASSIGNMENT_MEDICAL = 150), 1)
)
@@ -185,6 +191,7 @@ var/list/event_last_fired = list()
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Abductor Visit", /datum/event/abductor, 80, is_one_shot = 1),
new /datum/event_meta/alien(EVENT_LEVEL_MAJOR, "Alien Infestation", /datum/event/alien_infestation, 0, list(ASSIGNMENT_SECURITY = 30), 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Traders", /datum/event/traders, 0, is_one_shot = 1),
new /datum/event_meta(EVENT_LEVEL_MAJOR, "Slaughter Demon", /datum/event/spawn_slaughter, 15, is_one_shot = 1),
)
+11 -2
View File
@@ -34,10 +34,19 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
loc = start
z_original = z
destination = end
notify_ghosts("\A [src] is inbound!",
enter_link="<a href=?src=[UID()];follow=1>(Click to follow)</a>",
source=src, action=NOTIFY_FOLLOW)
poi_list |= src
if(end && end.z==z_original)
walk_towards(src, destination, 1)
/obj/effect/immovablerod/Topic(href, href_list)
if(href_list["follow"])
var/mob/dead/observer/ghost = usr
if(istype(ghost))
ghost.ManualFollow(src)
/obj/effect/immovablerod/Destroy()
poi_list.Remove(src)
return ..()
@@ -70,4 +79,4 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
H.adjustBruteLoss(160)
if(clong.density || prob(10))
clong.ex_act(2)
return
return
+2 -2
View File
@@ -37,8 +37,8 @@
player_mind.transfer_to(S)
player_mind.assigned_role = "Slaughter Demon"
player_mind.special_role = SPECIAL_ROLE_SLAUGHTER_DEMON
message_admins("[key_of_slaughter] has been made into a Slaughter Demon by an event.")
log_game("[key_of_slaughter] was spawned as a Slaughter Demon by an event.")
message_admins("[key_name_admin(S)] has been made into a Slaughter Demon by an event.")
log_game("[key_name_admin(S)] was spawned as a Slaughter Demon by an event.")
return 1
/datum/event/spawn_slaughter/start()
@@ -61,7 +61,7 @@
to_chat(user, "<span class='warning'> [src] is full.</span>")
return
var/trans = target.reagents.trans_to(src, target:amount_per_transfer_from_this)
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'> You fill [src] with [trans] units of the contents of [target].</span>")
else if(target.is_open_container()) //Something like a glass. Player probably wants to transfer TO it.
@@ -332,7 +332,7 @@
desc = "A cup with the british flag emblazoned on it."
icon_state = "britcup"
volume = 30
/obj/item/weapon/reagent_containers/food/drinks/mushroom_bowl
name = "mushroom bowl"
desc = "A bowl made out of mushrooms. Not food, though it might have contained some at some point."
+1 -35
View File
@@ -1213,25 +1213,18 @@
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/afterattack(obj/O, mob/user, proximity)
if(!proximity)
return
if(istype(O,/obj/structure/sink) && !wrapped)
if(istype(O, /obj/structure/sink))
to_chat(user, "<span class='notice'>You place [src] under a stream of water...</span>")
user.drop_item()
forceMove(get_turf(O))
return Expand()
..()
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/attack_self(mob/user)
if(wrapped)
Unwrap(user)
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/water_act(volume, temperature)
if(volume >= 5)
return Expand()
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wash(mob/user, atom/source)
if(wrapped)
..()
return
if(do_after(user, 40, target = source))
return 1
@@ -1241,49 +1234,22 @@
new/mob/living/carbon/human(get_turf(src),monkey_type)
qdel(src)
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/proc/Unwrap(mob/user)
icon_state = "monkeycube"
desc = "Just add water!"
to_chat(user, "<span class='notice'>You unwrap the cube.</span>")
wrapped = 0
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped
desc = "Still wrapped in some paper."
icon_state = "monkeycubewrap"
wrapped = 1
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/farwacube
name = "farwa cube"
monkey_type = "Farwa"
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/farwacube
name = "farwa cube"
monkey_type = "Farwa"
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wolpincube
name = "wolpin cube"
monkey_type = "Wolpin"
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/wolpincube
name = "wolpin cube"
monkey_type = "Wolpin"
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/stokcube
name = "stok cube"
monkey_type = "Stok"
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/stokcube
name = "stok cube"
monkey_type = "Stok"
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/neaeracube
name = "neaera cube"
monkey_type = "Neara"
/obj/item/weapon/reagent_containers/food/snacks/monkeycube/wrapped/neaeracube
name = "neaera cube"
monkey_type = "Neara"
/obj/item/weapon/reagent_containers/food/snacks/spellburger
name = "Spell Burger"
@@ -20,6 +20,8 @@
var/locked = 0
var/scan_id = 1
var/is_secure = 0
var/can_dry = FALSE
var/drying = FALSE
var/datum/wires/smartfridge/wires = null
/obj/machinery/smartfridge/New()
@@ -195,7 +197,7 @@
/obj/machinery/smartfridge/default_deconstruction_screwdriver(mob/user, obj/item/weapon/screwdriver/S)
. = ..(user, icon_state, icon_state, S)
overlays.Cut()
if(panel_open)
overlays += image(icon, "[initial(icon_state)]-panel")
@@ -332,6 +334,8 @@
data["shoot_inventory"] = shoot_inventory
data["locked"] = locked
data["secure"] = is_secure
data["can_dry"] = can_dry
data["drying"] = drying
var/list/items[0]
for(var/i=1 to length(item_quants))
@@ -372,6 +376,7 @@
for(var/obj/O in contents)
if(O.name == K)
O.forceMove(loc)
update_icon()
i--
if(i <= 0)
return 1
@@ -394,6 +399,7 @@
if(T.name == O)
T.forceMove(loc)
throw_item = T
update_icon()
break
break
if(!throw_item)
@@ -416,7 +422,7 @@
active_power_usage = 200
icon_on = "drying_rack_on"
icon_off = "drying_rack"
var/drying = FALSE
can_dry = TRUE
/obj/machinery/smartfridge/drying_rack/New()
..()
@@ -443,6 +449,22 @@
/obj/machinery/smartfridge/drying_rack/default_deconstruction_crowbar(obj/item/weapon/crowbar/C, ignore_panel = 1)
..()
/obj/machinery/smartfridge/drying_rack/Topic(href, href_list)
if(..())
return 1
if(href_list["dryingOn"])
drying = TRUE
use_power = 2
update_icon()
return 1
if(href_list["dryingOff"])
drying = FALSE
use_power = 1
update_icon()
return 1
return 0
/obj/machinery/smartfridge/drying_rack/power_change()
if(powered() && anchored)
stat &= ~NOPOWER
@@ -451,9 +473,10 @@
toggle_drying(TRUE)
update_icon()
/obj/machinery/smartfridge/drying_rack/load() //For updating the filled overlay
..()
update_icon()
/obj/machinery/smartfridge/drying_rack/load(obj/I, mob/user) //For updating the filled overlay
if(..())
update_icon()
return 1
/obj/machinery/smartfridge/drying_rack/update_icon()
..()
@@ -470,11 +493,11 @@
update_icon()
/obj/machinery/smartfridge/drying_rack/accept_check(obj/item/O)
if(istype(O,/obj/item/weapon/reagent_containers/food/snacks/))
if(istype(O, /obj/item/weapon/reagent_containers/food/snacks))
var/obj/item/weapon/reagent_containers/food/snacks/S = O
if(S.dried_type)
return TRUE
if(istype(O,/obj/item/stack/sheet/wetleather/))
if(istype(O, /obj/item/stack/sheet/wetleather))
return TRUE
return FALSE
@@ -492,16 +515,21 @@
if(S.dried_type == S.type)//if the dried type is the same as the object's type, don't bother creating a whole new item...
S.color = "#ad7257"
S.dry = TRUE
item_quants[S.name]--
S.forceMove(get_turf(src))
else
var/dried = S.dried_type
new dried(loc)
item_quants[S.name]--
qdel(S)
nanomanager.update_uis(src)
return TRUE
for(var/obj/item/stack/sheet/wetleather/WL in contents)
var/obj/item/stack/sheet/leather/L = new(loc)
L.amount = WL.amount
item_quants[WL.name]--
qdel(WL)
nanomanager.update_uis(src)
return TRUE
return FALSE
@@ -509,21 +537,6 @@
..()
atmos_spawn_air(SPAWN_HEAT)
/obj/machinery/smartfridge/drying_rack/verb/adjust_drying()
set category = "Object"
set name = "Toggle Drying"
set src in view(1)
if(!iscarbon(usr))
to_chat(usr, "<span class='warning'>You can't do that!</span>")
return
if(usr.incapacitated())
return
toggle_drying(FALSE)
update_icon()
/************************
* Secure SmartFridges
*************************/
+2 -2
View File
@@ -219,10 +219,10 @@
var/S = 0
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/I in contents)
S += 5
if(I.reagents.get_reagent_amount("nutriment") < 0.1)
if(I.reagents.get_reagent_amount("nutriment")+I.reagents.get_reagent_amount("plantmatter") < 0.1)
points += 1*productivity
else
points += I.reagents.get_reagent_amount("nutriment")*10*productivity
points += (I.reagents.get_reagent_amount("nutriment")+I.reagents.get_reagent_amount("plantmatter"))*10*productivity
qdel(I)
if(S)
processing = 1
+3 -3
View File
@@ -23,7 +23,7 @@
icon_dead = "ambrosia-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/ambrosia/deus)
reagents_add = list("space_drugs" = 0.15, "bicaridine" = 0.1, "kelotane" = 0.1, "vitamin" = 0.04, "nutriment" = 0.05, "toxin" = 0.1)
reagents_add = list("space_drugs" = 0.15, "bicaridine" = 0.1, "kelotane" = 0.1, "vitamin" = 0.04, "plantmatter" = 0.05, "toxin" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/vulgaris
seed = /obj/item/seeds/ambrosia
@@ -40,7 +40,7 @@
plantname = "Ambrosia Deus"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/deus
mutatelist = list(/obj/item/seeds/ambrosia/gaia)
reagents_add = list("weak_omnizine" = 0.15, "synaptizine" = 0.15, "space_drugs" = 0.1, "vitamin" = 0.04, "nutriment" = 0.05)
reagents_add = list("weak_omnizine" = 0.15, "synaptizine" = 0.15, "space_drugs" = 0.1, "vitamin" = 0.04, "plantmatter" = 0.05)
rarity = 40
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/deus
@@ -80,7 +80,7 @@
product = /obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/cruciatus
potency = 10
mutatelist = list()
reagents_add = list("thc" = 0.15, "kelotane" = 0.15, "bicaridine" = 0.1, "bath_salts" = 0.20, "nutriment" = 0.05)
reagents_add = list("thc" = 0.15, "kelotane" = 0.15, "bicaridine" = 0.1, "bath_salts" = 0.20, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/ambrosia/cruciatus
seed = /obj/item/seeds/ambrosia/cruciatus
+3 -3
View File
@@ -14,7 +14,7 @@
icon_dead = "apple-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/apple/gold)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/apple
seed = /obj/item/seeds/apple
@@ -28,7 +28,7 @@
/obj/item/seeds/apple/poisoned
product = /obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned
mutatelist = list()
reagents_add = list("cyanide" = 0.5, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("cyanide" = 0.5, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 50 // Source of cyanide, and hard (almost impossible) to obtain normally.
/obj/item/weapon/reagent_containers/food/snacks/grown/apple/poisoned
@@ -45,7 +45,7 @@
maturation = 10
production = 10
mutatelist = list()
reagents_add = list("gold" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("gold" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 40 // Alchemy!
/obj/item/weapon/reagent_containers/food/snacks/grown/apple/gold
+2 -2
View File
@@ -12,7 +12,7 @@
icon_dead = "banana-dead"
genes = list(/datum/plant_gene/trait/slip, /datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/banana/mime, /obj/item/seeds/banana/bluespace)
reagents_add = list("banana" = 0.1, "potassium" = 0.1, "vitamin" = 0.04, "nutriment" = 0.02)
reagents_add = list("banana" = 0.1, "potassium" = 0.1, "vitamin" = 0.04, "plantmatter" = 0.02)
/obj/item/weapon/reagent_containers/food/snacks/grown/banana
seed = /obj/item/seeds/banana
@@ -92,7 +92,7 @@
product = /obj/item/weapon/reagent_containers/food/snacks/grown/banana/bluespace
mutatelist = list()
genes = list(/datum/plant_gene/trait/slip, /datum/plant_gene/trait/teleport, /datum/plant_gene/trait/repeated_harvest)
reagents_add = list("singulo" = 0.2, "banana" = 0.1, "vitamin" = 0.04, "nutriment" = 0.02)
reagents_add = list("singulo" = 0.2, "banana" = 0.1, "vitamin" = 0.04, "plantmatter" = 0.02)
rarity = 30
/obj/item/weapon/reagent_containers/food/snacks/grown/banana/bluespace
+2 -2
View File
@@ -15,7 +15,7 @@
icon_dead = "soybean-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/soya/koi)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.05)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/soybeans
seed = /obj/item/seeds/soya
@@ -36,7 +36,7 @@
product = /obj/item/weapon/reagent_containers/food/snacks/grown/koibeans
potency = 10
mutatelist = list()
reagents_add = list("carpotoxin" = 0.1, "vitamin" = 0.04, "nutriment" = 0.05)
reagents_add = list("carpotoxin" = 0.1, "vitamin" = 0.04, "plantmatter" = 0.05)
rarity = 20
/obj/item/weapon/reagent_containers/food/snacks/grown/koibeans
+8 -8
View File
@@ -15,7 +15,7 @@
icon_dead = "berry-dead" // Same for the dead icon
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/berry/glow, /obj/item/seeds/berry/poison)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/berries
seed = /obj/item/seeds/berry
@@ -35,7 +35,7 @@
plantname = "Poison-Berry Bush"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/berries/poison
mutatelist = list(/obj/item/seeds/berry/death)
reagents_add = list("cyanide" = 0.15, "tirizene" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("cyanide" = 0.15, "tirizene" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 10 // Mildly poisonous berries are common in reality
/obj/item/weapon/reagent_containers/food/snacks/grown/berries/poison
@@ -56,7 +56,7 @@
lifespan = 30
potency = 50
mutatelist = list()
reagents_add = list("coniine" = 0.08, "tirizene" = 0.1, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("coniine" = 0.08, "tirizene" = 0.1, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 30
/obj/item/weapon/reagent_containers/food/snacks/grown/berries/death
@@ -78,7 +78,7 @@
endurance = 25
mutatelist = list()
genes = list(/datum/plant_gene/trait/glow/berry , /datum/plant_gene/trait/noreact, /datum/plant_gene/trait/repeated_harvest)
reagents_add = list("uranium" = 0.25, "iodine" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("uranium" = 0.25, "iodine" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 20
/obj/item/weapon/reagent_containers/food/snacks/grown/berries/glow
@@ -108,7 +108,7 @@
icon_dead = "cherry-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/cherry/blue)
reagents_add = list("nutriment" = 0.07, "sugar" = 0.07)
reagents_add = list("plantmatter" = 0.07, "sugar" = 0.07)
/obj/item/weapon/reagent_containers/food/snacks/grown/cherries
seed = /obj/item/seeds/cherry
@@ -128,7 +128,7 @@
plantname = "Blue Cherry Tree"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/bluecherries
mutatelist = list()
reagents_add = list("nutriment" = 0.07, "sugar" = 0.07)
reagents_add = list("plantmatter" = 0.07, "sugar" = 0.07)
rarity = 10
/obj/item/weapon/reagent_containers/food/snacks/grown/bluecherries
@@ -158,7 +158,7 @@
icon_dead = "grape-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/grape/green)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1, "sugar" = 0.1)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.1, "sugar" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/grapes
seed = /obj/item/seeds/grape
@@ -177,7 +177,7 @@
species = "greengrape"
plantname = "Green-Grape Vine"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/grapes/green
reagents_add = list("kelotane" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1, "sugar" = 0.1)
reagents_add = list("kelotane" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1, "sugar" = 0.1)
// No rarity: technically it's a beneficial mutant, but it's not exactly "new"...
mutatelist = list()
+2 -1
View File
@@ -11,7 +11,7 @@
potency = 15
icon_dead = "wheat-dead"
mutatelist = list(/obj/item/seeds/wheat/oat, /obj/item/seeds/wheat/meat)
reagents_add = list("nutriment" = 0.04)
reagents_add = list("plantmatter" = 0.04)
/obj/item/weapon/reagent_containers/food/snacks/grown/wheat
seed = /obj/item/seeds/wheat
@@ -70,6 +70,7 @@
plantname = "Meatwheat"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/meatwheat
mutatelist = list()
reagents_add = list("protein" = 0.04)
/obj/item/weapon/reagent_containers/food/snacks/grown/meatwheat
name = "meatwheat"
+3 -3
View File
@@ -16,7 +16,7 @@
icon_dead = "chili-dead" // Same for the dead icon
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/chili/ice, /obj/item/seeds/chili/ghost)
reagents_add = list("capsaicin" = 0.25, "vitamin" = 0.04, "nutriment" = 0.04)
reagents_add = list("capsaicin" = 0.25, "vitamin" = 0.04, "plantmatter" = 0.04)
/obj/item/weapon/reagent_containers/food/snacks/grown/chili
seed = /obj/item/seeds/chili
@@ -39,7 +39,7 @@
production = 4
rarity = 20
mutatelist = list()
reagents_add = list("frostoil" = 0.25, "vitamin" = 0.02, "nutriment" = 0.02)
reagents_add = list("frostoil" = 0.25, "vitamin" = 0.02, "plantmatter" = 0.02)
/obj/item/weapon/reagent_containers/food/snacks/grown/icepepper
seed = /obj/item/seeds/chili/ice
@@ -64,7 +64,7 @@
yield = 3
rarity = 20
mutatelist = list()
reagents_add = list("condensedcapsaicin" = 0.3, "capsaicin" = 0.55, "nutriment" = 0.04)
reagents_add = list("condensedcapsaicin" = 0.3, "capsaicin" = 0.55, "plantmatter" = 0.04)
/obj/item/weapon/reagent_containers/food/snacks/grown/ghost_chili
seed = /obj/item/seeds/chili/ghost
+4 -4
View File
@@ -21,7 +21,7 @@
growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi'
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/orange)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.05)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/citrus/lime
seed = /obj/item/seeds/lime
@@ -47,7 +47,7 @@
icon_dead = "lime-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/lime)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.05)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/citrus/orange
seed = /obj/item/seeds/orange
@@ -72,7 +72,7 @@
icon_dead = "lime-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/firelemon)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.05)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/citrus/lemon
seed = /obj/item/seeds/lemon
@@ -96,7 +96,7 @@
lifespan = 55
endurance = 45
yield = 4
reagents_add = list("nutriment" = 0.05)
reagents_add = list("plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/firelemon
seed = /obj/item/seeds/firelemon
@@ -16,7 +16,7 @@
icon_dead = "cocoapod-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/cocoapod/vanillapod)
reagents_add = list("cocoa" = 0.25, "nutriment" = 0.1)
reagents_add = list("cocoa" = 0.25, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/cocoapod
seed = /obj/item/seeds/cocoapod
@@ -36,7 +36,7 @@
product = /obj/item/weapon/reagent_containers/food/snacks/grown/vanillapod
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list()
reagents_add = list("vanilla" = 0.25, "nutriment" = 0.1)
reagents_add = list("vanilla" = 0.25, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/vanillapod
seed = /obj/item/seeds/cocoapod/vanillapod
+1 -1
View File
@@ -13,7 +13,7 @@
icon_grow = "corn-grow" // Uses one growth icons set for all the subtypes
icon_dead = "corn-dead" // Same for the dead icon
mutatelist = list(/obj/item/seeds/corn/snapcorn)
reagents_add = list("cornoil" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("cornoil" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/corn
seed = /obj/item/seeds/corn
+1 -1
View File
@@ -13,7 +13,7 @@
icon_dead = "eggplant-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/eggplant/eggy)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/eggplant
seed = /obj/item/seeds/eggplant
+5 -5
View File
@@ -15,7 +15,7 @@
icon_grow = "poppy-grow"
icon_dead = "poppy-dead"
mutatelist = list(/obj/item/seeds/poppy/geranium, /obj/item/seeds/poppy/lily)
reagents_add = list("bicaridine" = 0.2, "nutriment" = 0.05)
reagents_add = list("bicaridine" = 0.2, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/poppy
seed = /obj/item/seeds/poppy
@@ -78,7 +78,7 @@
growthstages = 4
genes = list(/datum/plant_gene/trait/plant_type/weed_hardy)
growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi'
reagents_add = list("nutriment" = 0.04)
reagents_add = list("plantmatter" = 0.04)
/obj/item/weapon/reagent_containers/food/snacks/grown/harebell
seed = /obj/item/seeds/harebell
@@ -106,7 +106,7 @@
icon_grow = "sunflower-grow"
icon_dead = "sunflower-dead"
mutatelist = list(/obj/item/seeds/sunflower/moonflower, /obj/item/seeds/sunflower/novaflower)
reagents_add = list("cornoil" = 0.08, "nutriment" = 0.04)
reagents_add = list("cornoil" = 0.08, "plantmatter" = 0.04)
/obj/item/weapon/grown/sunflower // FLOWER POWER!
seed = /obj/item/seeds/sunflower
@@ -134,7 +134,7 @@
plantname = "Moonflowers"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/moonflower
mutatelist = list()
reagents_add = list("moonshine" = 0.2, "vitamin" = 0.02, "nutriment" = 0.02)
reagents_add = list("moonshine" = 0.2, "vitamin" = 0.02, "plantmatter" = 0.02)
rarity = 15
/obj/item/weapon/reagent_containers/food/snacks/grown/moonflower
@@ -155,7 +155,7 @@
plantname = "Novaflowers"
product = /obj/item/weapon/grown/novaflower
mutatelist = list()
reagents_add = list("condensedcapsaicin" = 0.25, "capsaicin" = 0.3, "nutriment" = 0)
reagents_add = list("condensedcapsaicin" = 0.25, "capsaicin" = 0.3, "plantmatter" = 0)
rarity = 20
/obj/item/weapon/grown/novaflower
@@ -16,7 +16,7 @@
icon_dead = "grass-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/grass/carpet)
reagents_add = list("nutriment" = 0.02, "hydrogen" = 0.05)
reagents_add = list("plantmatter" = 0.02, "hydrogen" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/grass
seed = /obj/item/seeds/grass
+2 -2
View File
@@ -9,7 +9,7 @@
maturation = 3
growthstages = 1
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
reagents_add = list("nutriment" = 0.1)
reagents_add = list("styptic_powder" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/comfrey
seed = /obj/item/seeds/comfrey
@@ -35,7 +35,7 @@
product = /obj/item/weapon/reagent_containers/food/snacks/grown/aloe
yield = 2
icon_dead = "ambrosia-dead"
reagents_add = list("nutriment" = 0.1)
reagents_add = list("silver_sulfadiazine" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/aloe
seed = /obj/item/seeds/aloe
+1 -1
View File
@@ -14,7 +14,7 @@
growthstages = 4
rarity = 30
var/list/mutations = list()
reagents_add = list("charcoal" = 0.04, "nutriment" = 0.02)
reagents_add = list("charcoal" = 0.04, "plantmatter" = 0.02)
/obj/item/seeds/kudzu/Copy()
var/obj/item/seeds/kudzu/S = ..()
+1 -1
View File
@@ -12,7 +12,7 @@
icon_dead = "watermelon-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/watermelon/holy)
reagents_add = list("water" = 0.2, "vitamin" = 0.04, "nutriment" = 0.2)
reagents_add = list("water" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.2)
/obj/item/weapon/reagent_containers/food/snacks/grown/watermelon
seed = /obj/item/seeds/watermelon
+2 -2
View File
@@ -32,7 +32,7 @@
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/replicapod)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/cabbage
seed = /obj/item/seeds/cabbage
@@ -106,7 +106,7 @@
plantname = "Cherry Bomb Tree"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/cherry_bomb
mutatelist = list()
reagents_add = list("nutriment" = 0.1, "sugar" = 0.1, "blackpowder" = 0.7)
reagents_add = list("plantmatter" = 0.1, "sugar" = 0.1, "blackpowder" = 0.7)
rarity = 60 //See above
/obj/item/weapon/reagent_containers/food/snacks/grown/cherry_bomb
+2 -2
View File
@@ -74,7 +74,7 @@
growthstages = 3
genes = list(/datum/plant_gene/trait/plant_type/fungal_metabolism)
growing_icon = 'icons/obj/hydroponics/growing_mushrooms.dmi'
reagents_add = list("psilocybin" = 0.04, "amanitin" = 0.1, "nutriment" = 0, "amanitin" = 0.2)
reagents_add = list("psilocybin" = 0.04, "nutriment" = 0, "amanitin" = 0.3)
rarity = 30
origin_tech = "biotech=5"
@@ -291,4 +291,4 @@
name = "fungus"
desc = "A fungus ideal for making antibacterials."
icon_state = "angel"
color = "#4f4331"
color = "#4f4331"
+1 -1
View File
@@ -10,7 +10,7 @@
maturation = 10
production = 1
yield = 1
reagents_add = list("nutriment" = 0.1)
reagents_add = list("plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/nymph_pod
seed = /obj/item/seeds/nymph
+1 -1
View File
@@ -15,7 +15,7 @@
icon_grow = "potato-grow"
icon_dead = "potato-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
reagents_add = list("nutriment" = 0.1)
reagents_add = list("plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/peanuts
seed = /obj/item/seeds/peanuts
+2 -2
View File
@@ -16,7 +16,7 @@
icon_dead = "potato-dead"
genes = list(/datum/plant_gene/trait/battery)
mutatelist = list(/obj/item/seeds/potato/sweet)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/potato
seed = /obj/item/seeds/potato
@@ -56,7 +56,7 @@
plantname = "Sweet Potato Plants"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/potato/sweet
mutatelist = list()
reagents_add = list("vitamin" = 0.1, "sugar" = 0.1, "nutriment" = 0.1)
reagents_add = list("vitamin" = 0.1, "sugar" = 0.1, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/potato/sweet
seed = /obj/item/seeds/potato/sweet
+2 -2
View File
@@ -14,7 +14,7 @@
icon_dead = "pumpkin-dead"
genes = list(/datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/pumpkin/blumpkin)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.2)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.2)
/obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin
seed = /obj/item/seeds/pumpkin
@@ -42,7 +42,7 @@
plantname = "Blumpkin Vines"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/blumpkin
mutatelist = list()
reagents_add = list("ammonia" = 0.2, "chlorine" = 0.1, "nutriment" = 0.2)
reagents_add = list("ammonia" = 0.2, "chlorine" = 0.1, "plasma" = 0.1, "plantmatter" = 0.2)
rarity = 20
/obj/item/weapon/reagent_containers/food/snacks/grown/blumpkin
@@ -91,6 +91,8 @@
podman.ckey = ckey_holder
podman.gender = blood_gender
podman.faction |= factions
podman.faction |= "plants"
podman.faction |= "vines" //Pod grown Diona are allied with plants and vines alike.
else //else, one packet of seeds. maybe two
var/seed_count = 1
+4 -4
View File
@@ -12,7 +12,7 @@
growthstages = 3
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
mutatelist = list(/obj/item/seeds/carrot/parsnip)
reagents_add = list("oculine" = 0.25, "vitamin" = 0.04, "nutriment" = 0.05)
reagents_add = list("oculine" = 0.25, "vitamin" = 0.04, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/carrot
seed = /obj/item/seeds/carrot
@@ -43,7 +43,7 @@
product = /obj/item/weapon/reagent_containers/food/snacks/grown/parsnip
icon_dead = "carrot-dead"
mutatelist = list()
reagents_add = list("vitamin" = 0.05, "nutriment" = 0.05)
reagents_add = list("vitamin" = 0.05, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/parsnip
seed = /obj/item/seeds/carrot/parsnip
@@ -67,7 +67,7 @@
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
icon_dead = "whitebeet-dead"
mutatelist = list(/obj/item/seeds/redbeet)
reagents_add = list("vitamin" = 0.04, "sugar" = 0.2, "nutriment" = 0.05)
reagents_add = list("vitamin" = 0.04, "sugar" = 0.2, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet
seed = /obj/item/seeds/whitebeet
@@ -91,7 +91,7 @@
growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi'
icon_dead = "whitebeet-dead"
genes = list(/datum/plant_gene/trait/maxchem)
reagents_add = list("vitamin" = 0.05, "nutriment" = 0.05)
reagents_add = list("vitamin" = 0.05, "plantmatter" = 0.05)
/obj/item/weapon/reagent_containers/food/snacks/grown/redbeet
seed = /obj/item/seeds/redbeet
+2 -2
View File
@@ -13,7 +13,7 @@
growthstages = 3
icon_dead = "tobacco-dead"
mutatelist = list(/obj/item/seeds/tobacco/space)
reagents_add = list("nicotine" = 0.03, "nutriment" = 0.03)
reagents_add = list("nicotine" = 0.03, "plantmatter" = 0.03)
/obj/item/weapon/reagent_containers/food/snacks/grown/tobacco
seed = /obj/item/seeds/tobacco
@@ -31,7 +31,7 @@
plantname = "Space Tobacco Plant"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/tobacco/space
mutatelist = list()
reagents_add = list("salbutamol" = 0.05, "nicotine" = 0.08, "nutriment" = 0.03)
reagents_add = list("salbutamol" = 0.05, "nicotine" = 0.08, "plantmatter" = 0.03)
rarity = 20
/obj/item/weapon/reagent_containers/food/snacks/grown/tobacco/space
+7 -6
View File
@@ -11,8 +11,8 @@
icon_grow = "tomato-grow"
icon_dead = "tomato-dead"
genes = list(/datum/plant_gene/trait/squash, /datum/plant_gene/trait/repeated_harvest)
mutatelist = list(/obj/item/seeds/tomato/blue, /obj/item/seeds/tomato/blood, /obj/item/seeds/tomato/killer)
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
mutatelist = list(/obj/item/seeds/tomato/blue, /obj/item/seeds/tomato/blood)
reagents_add = list("vitamin" = 0.04, "plantmatter" = 0.1)
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato
seed = /obj/item/seeds/tomato
@@ -31,8 +31,8 @@
species = "bloodtomato"
plantname = "Blood-Tomato Plants"
product = /obj/item/weapon/reagent_containers/food/snacks/grown/tomato/blood
mutatelist = list()
reagents_add = list("blood" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
mutatelist = list(/obj/item/seeds/tomato/killer)
reagents_add = list("blood" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 20
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato/blood
@@ -57,7 +57,7 @@
icon_grow = "bluetomato-grow"
mutatelist = list(/obj/item/seeds/tomato/blue/bluespace)
genes = list(/datum/plant_gene/trait/slip, /datum/plant_gene/trait/repeated_harvest)
reagents_add = list("lube" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("lube" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 20
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato/blue
@@ -80,7 +80,7 @@
yield = 2
mutatelist = list()
genes = list(/datum/plant_gene/trait/squash, /datum/plant_gene/trait/slip, /datum/plant_gene/trait/teleport, /datum/plant_gene/trait/repeated_harvest)
reagents_add = list("lube" = 0.2, "singulo" = 0.2, "vitamin" = 0.04, "nutriment" = 0.1)
reagents_add = list("lube" = 0.2, "singulo" = 0.2, "vitamin" = 0.04, "plantmatter" = 0.1)
rarity = 50
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato/blue/bluespace
@@ -106,6 +106,7 @@
icon_harvest = "killertomato-harvest"
icon_dead = "killertomato-dead"
mutatelist = list()
reagents_add = list("vitamin" = 0.04, "protein" = 0.1)
rarity = 30
/obj/item/weapon/reagent_containers/food/snacks/grown/tomato/killer
+34
View File
@@ -521,6 +521,12 @@
mutmod = 0
adjustNutri(round(S.get_reagent_amount("robustharvestnutriment") *1 ))
//Fish Water is both an excellent fertilizer and waters
if(S.has_reagent("fishwater", 1))
adjustNutri(round(S.get_reagent_amount("fishwater") * 0.75))
adjustWater(round(S.get_reagent_amount("fishwater") * 1))
// Antitoxin binds shit pretty well. So the tox goes significantly down
if(S.has_reagent("charcoal", 1))
adjustToxic(-round(S.get_reagent_amount("charcoal") * 2))
@@ -657,6 +663,10 @@
adjustHealth(round(S.get_reagent_amount("nutriment") * 0.5))
adjustNutri(round(S.get_reagent_amount("nutriment") * 1))
if(S.has_reagent("plantmatter", 1))
adjustHealth(round(S.get_reagent_amount("plantmatter") * 0.5))
adjustNutri(round(S.get_reagent_amount("plantmatter") * 1))
// Compost for EVERYTHING
if(S.has_reagent("virusfood", 1))
adjustNutri(round(S.get_reagent_amount("virusfood") * 0.5))
@@ -958,6 +968,30 @@
var/mob/living/simple_animal/hostile/C = new chosen
C.faction = list("plants")
///Diona Nymph Related Procs///
/obj/machinery/hydroponics/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) //So nymphs can climb over top of trays.
if(air_group || (height==0))
return 1
if(istype(mover) && mover.checkpass(PASSTABLE))
return 1
else
return 0
/obj/machinery/hydroponics/attack_animal(mob/living/user)
if(istype(user, /mob/living/simple_animal/diona))
if(weedlevel > 0)
user.nutrition += weedlevel * 15
adjustWeeds(-10)
update_icon()
visible_message("<span class='danger'>[user] begins rooting through [src], ripping out weeds and eating them noisily.</span>","<span class='danger'>You begin rooting through [src], ripping out weeds and eating them noisily.</span>")
else if(nutrilevel < 10)
user.nutrition -= ((10 - nutrilevel) * 5)
adjustNutri(10)
update_icon()
visible_message("<span class='danger'>[user] secretes a trickle of green liquid from its tail, refilling [src]'s nutrient tray.</span>","<span class='danger'>You secrete a trickle of green liquid from your tail, refilling [src]'s nutrient tray.</span>")
else
..()
///////////////////////////////////////////////////////////////////////////////
/obj/machinery/hydroponics/soil //Not actually hydroponics at all! Honk!
-257
View File
@@ -1,257 +0,0 @@
/datum/light_source
var/atom/top_atom
var/atom/source_atom
var/turf/source_turf
var/light_power
var/light_range
var/light_color // string, decomposed by parse_light_color()
var/lum_r
var/lum_g
var/lum_b
var/tmp/applied_lum_r
var/tmp/applied_lum_g
var/tmp/applied_lum_b
var/list/effect_str
var/list/effect_turf
var/applied
var/vis_update //Whetever we should smartly recalculate visibility. and then only update tiles that became (in) visible to us
var/needs_update
var/destroyed
var/force_update
/datum/light_source/New(atom/owner, atom/top)
source_atom = owner
if(!source_atom.light_sources) source_atom.light_sources = list()
source_atom.light_sources += src
top_atom = top
if(top_atom != source_atom)
if(!top.light_sources) top.light_sources = list()
top_atom.light_sources += src
source_turf = top_atom
light_power = source_atom.light_power
light_range = source_atom.light_range
light_color = source_atom.light_color
parse_light_color()
effect_str = list()
effect_turf = list()
update()
return ..()
/datum/light_source/proc/destroy()
destroyed = 1
force_update()
if(source_atom && source_atom.light_sources) source_atom.light_sources -= src
if(top_atom && top_atom.light_sources) top_atom.light_sources -= src
/datum/light_source/proc/update(atom/new_top_atom)
if(new_top_atom && new_top_atom != top_atom)
if(top_atom != source_atom) top_atom.light_sources -= src
top_atom = new_top_atom
if(top_atom != source_atom)
if(!top_atom.light_sources) top_atom.light_sources = list()
top_atom.light_sources += src
if(!needs_update) //Incase we're already updating either way.
lighting_update_lights += src
needs_update = 1
/datum/light_source/proc/force_update()
force_update = 1
if(!needs_update) //Incase we're already updating either way.
needs_update = 1
lighting_update_lights += src
/datum/light_source/proc/vis_update()
if(!needs_update)
needs_update = 1
lighting_update_lights += src
vis_update = 1
/datum/light_source/proc/check()
if(!source_atom || !light_range || !light_power)
destroy()
return 1
if(!top_atom)
top_atom = source_atom
. = 1
if(istype(top_atom, /turf))
if(source_turf != top_atom)
source_turf = top_atom
. = 1
else if(top_atom.loc != source_turf)
source_turf = top_atom.loc
. = 1
if(source_atom.light_power != light_power)
light_power = source_atom.light_power
. = 1
if(source_atom.light_range != light_range)
light_range = source_atom.light_range
. = 1
if(light_range && light_power && !applied)
. = 1
if(source_atom.light_color != light_color)
light_color = source_atom.light_color
parse_light_color()
. = 1
/datum/light_source/proc/parse_light_color()
if(light_color)
lum_r = color2R(light_color) / 255
lum_g = color2G(light_color) / 255
lum_b = color2B(light_color) / 255
else
lum_r = 1
lum_g = 1
lum_b = 1
#if LIGHTING_FALLOFF == 1 //circular
#define LUM_DISTANCE(swapvar, O, T) swapvar = (O.x - T.x)**2 + (O.y - T.y)**2 + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(sqrt(swapvar) / max(1,light_range))) * (1 / sqrt(swapvar + 1)))
#else
#define LUM_ATTENUATION(swapvar) swapvar = 1 - CLAMP01(sqrt(swapvar) / max(1,light_range))
#endif
#elif LIGHTING_FALLOFF == 2 //square
#define LUM_DISTANCE(swapvar, O, T) swapvar = abs(O.x - T.x) + abs(O.y - T.y) + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(swapvar / max(1,light_range))) * (1 / sqrt(swapvar**2 + 1)))
#else
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01(swapvar / max(1,light_range))
#endif
#endif
#define LUM_FALLOFF(swapvar, O, T) \
LUM_DISTANCE(swapvar, O, T); \
LUM_ATTENUATION(swapvar);
/datum/light_source/proc/apply_lum()
applied = 1
// Cache the applied lum counts.
applied_lum_r = lum_r
applied_lum_g = lum_g
applied_lum_b = lum_b
if(istype(source_turf))
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
if(T.lighting_overlay)
var/strength
LUM_FALLOFF(strength, T, source_turf)
strength *= light_power
if(!strength) //Don't add turfs that aren't affected to the affected turfs.
continue
strength = round(strength, LIGHTING_ROUND_VALUE) //Screw sinking points.
effect_str += strength
T.lighting_overlay.update_lumcount(
lum_r * strength,
lum_g * strength,
lum_b * strength
)
else
effect_str += 0
if(!T.affecting_lights)
T.affecting_lights = list()
T.affecting_lights += src
effect_turf += T
END_FOR_DVIEW
/datum/light_source/proc/remove_lum()
applied = 0
var/i = 1
for(var/turf/T in effect_turf)
if(T.affecting_lights)
T.affecting_lights -= src
if(T.lighting_overlay)
var/str = effect_str[i]
T.lighting_overlay.update_lumcount(-str * applied_lum_r, -str * applied_lum_g, -str * applied_lum_b)
i++
effect_str.Cut()
effect_turf.Cut()
/datum/light_source/proc/forget_turf(turf/T)
var/idx = effect_turf.Find(T)
effect_turf.Cut(idx, idx + 1)
effect_str.Cut(idx, idx + 1)
//Smartly updates the lighting, only removes lum from and adds lum to turfs that actually got changed.
//This is for lights that need to reconsider due to nearby opacity changes.
//Stupid dumb copy pasta because BYOND and speed.
/datum/light_source/proc/smart_vis_update()
var/list/view[0]
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
view += T //Filter out turfs.
END_FOR_DVIEW
//This is the part where we calculate new turfs (if any)
var/list/new_turfs = view - effect_turf //This will result with all the tiles that are added.
for(var/turf/T in new_turfs)
if(T.lighting_overlay)
LUM_FALLOFF(., T, source_turf)
. *= light_power
if(!.) //Don't add turfs that aren't affected to the affected turfs.
continue
. = round(., LIGHTING_ROUND_VALUE)
effect_str += .
T.lighting_overlay.update_lumcount(
lum_r * .,
lum_g * .,
lum_b * .
)
else
effect_str += 0
if(!T.affecting_lights)
T.affecting_lights = list()
T.affecting_lights += src
effect_turf += T
var/list/old_turfs = effect_turf - view
for(var/turf/T in old_turfs)
//Insert not-so-huge copy paste from remove_lum().
var/idx = effect_turf.Find(T) //Get the index, luckily Find() is cheap in small lists like this. (with small I mean under a couple thousand len)
if(T.affecting_lights)
T.affecting_lights -= src
if(T.lighting_overlay)
var/str = effect_str[idx]
T.lighting_overlay.update_lumcount(-str * lum_r, -str * lum_g, -str * lum_b)
effect_turf.Cut(idx, idx + 1)
effect_str.Cut(idx, idx + 1)
#undef LUM_FALLOFF
#undef LUM_DISTANCE
#undef LUM_ATTENUATION
+9
View File
@@ -0,0 +1,9 @@
/area
luminosity = TRUE
var/dynamic_lighting = TRUE
/area/New()
. = ..()
if(dynamic_lighting)
luminosity = FALSE
+34 -7
View File
@@ -1,19 +1,30 @@
/atom
var/light_power = 1 // intensity of the light
var/light_range = 0 // range in tiles of the light
var/light_color // RGB string representing the colour of the light
var/light_color // Hexadecimal RGB string representing the colour of the light
var/datum/light_source/light
var/list/light_sources
/atom/proc/set_light(l_range, l_power, l_color)
if(l_power != null) light_power = l_power
if(l_range != null) light_range = l_range
if(l_color != null) light_color = l_color
// Nonsensical value for l_color default, so we can detect if it gets set to null.
#define NONSENSICAL_VALUE -99999
/atom/proc/set_light(l_range, l_power, l_color = NONSENSICAL_VALUE)
if(l_power != null)
light_power = l_power
if(l_range != null)
light_range = l_range
if(l_color != NONSENSICAL_VALUE)
light_color = l_color
update_light()
#undef NONSENSICAL_VALUE
/atom/proc/update_light()
set waitfor = FALSE
if(!light_power || !light_range)
if(light)
light.destroy()
@@ -31,9 +42,14 @@
/atom/New()
. = ..()
if(light_power && light_range)
update_light()
if(opacity && isturf(loc))
var/turf/T = loc
T.has_opaque_atom = TRUE // No need to recalculate it in this case, it's guranteed to be on afterwards anyways.
/atom/Destroy()
if(light)
light.destroy()
@@ -62,11 +78,22 @@
new_loc.reconsider_lights()
/atom/proc/set_opacity(new_opacity)
var/old_opacity = opacity
if(new_opacity == opacity)
return
opacity = new_opacity
var/turf/T = loc
if(old_opacity != new_opacity && istype(T))
if(!isturf(T))
return
if(new_opacity == TRUE)
T.has_opaque_atom = TRUE
T.reconsider_lights()
else
var/old_has_opaque_atom = T.has_opaque_atom
T.recalc_atom_opacity()
if(old_has_opaque_atom != T.has_opaque_atom)
T.reconsider_lights()
/obj/item/equipped()
. = ..()
+125
View File
@@ -0,0 +1,125 @@
/var/list/datum/lighting_corner/all_lighting_corners = list()
/var/datum/lighting_corner/dummy/dummy_lighting_corner = new
// Because we can control each corner of every lighting overlay.
// And corners get shared between multiple turfs (unless you're on the corners of the map, then 1 corner doesn't).
// For the record: these should never ever ever be deleted, even if the turf doesn't have dynamic lighting.
// This list is what the code that assigns corners listens to, the order in this list is the order in which corners are added to the /turf/corners list.
/var/list/LIGHTING_CORNER_DIAGONAL = list(NORTHEAST, SOUTHEAST, SOUTHWEST, NORTHWEST)
/datum/lighting_corner
var/list/turf/masters = list()
var/list/datum/light_source/affecting = list() // Light sources affecting us.
var/active = FALSE // TRUE if one of our masters has dynamic lighting.
var/x = 0
var/y = 0
var/z = 0
var/lum_r = 0
var/lum_g = 0
var/lum_b = 0
var/needs_update = FALSE
var/cache_r = LIGHTING_SOFT_THRESHOLD
var/cache_g = LIGHTING_SOFT_THRESHOLD
var/cache_b = LIGHTING_SOFT_THRESHOLD
var/cache_mx = 0
var/update_gen = 0
/datum/lighting_corner/New(var/turf/new_turf, var/diagonal)
. = ..()
all_lighting_corners += src
masters[new_turf] = turn(diagonal, 180)
z = new_turf.z
var/vertical = diagonal & ~(diagonal - 1) // The horizontal directions (4 and 8) are bigger than the vertical ones (1 and 2), so we can reliably say the lsb is the horizontal direction.
var/horizontal = diagonal & ~vertical // Now that we know the horizontal one we can get the vertical one.
x = new_turf.x + (horizontal == EAST ? 0.5 : -0.5)
y = new_turf.y + (vertical == NORTH ? 0.5 : -0.5)
// My initial plan was to make this loop through a list of all the dirs (horizontal, vertical, diagonal).
// Issue being that the only way I could think of doing it was very messy, slow and honestly overengineered.
// So we'll have this hardcode instead.
var/turf/T
var/i
// Diagonal one is easy.
T = get_step(new_turf, diagonal)
if (T) // In case we're on the map's border.
if (!T.corners)
T.corners = list(null, null, null, null)
masters[T] = diagonal
i = LIGHTING_CORNER_DIAGONAL.Find(turn(diagonal, 180))
T.corners[i] = src
// Now the horizontal one.
T = get_step(new_turf, horizontal)
if (T) // Ditto.
if (!T.corners)
T.corners = list(null, null, null, null)
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
T.corners[i] = src
// And finally the vertical one.
T = get_step(new_turf, vertical)
if (T)
if (!T.corners)
T.corners = list(null, null, null, null)
masters[T] = ((T.x > x) ? EAST : WEST) | ((T.y > y) ? NORTH : SOUTH) // Get the dir based on coordinates.
i = LIGHTING_CORNER_DIAGONAL.Find(turn(masters[T], 180))
T.corners[i] = src
update_active()
/datum/lighting_corner/proc/update_active()
active = FALSE
for (var/turf/T in masters)
if (T.lighting_overlay)
active = TRUE
// God that was a mess, now to do the rest of the corner code! Hooray!
/datum/lighting_corner/proc/update_lumcount(var/delta_r, var/delta_g, var/delta_b)
lum_r += delta_r
lum_g += delta_g
lum_b += delta_b
if (!needs_update)
needs_update = TRUE
lighting_update_corners += src
/datum/lighting_corner/proc/update_overlays()
// Cache these values a head of time so 4 individual lighting overlays don't all calculate them individually.
var/mx = max(lum_r, lum_g, lum_b) // Scale it so 1 is the strongest lum, if it is above 1.
. = 1 // factor
if (mx > 1)
. = 1 / mx
else if (mx < LIGHTING_SOFT_THRESHOLD)
. = 0 // 0 means soft lighting.
cache_r = lum_r * . || LIGHTING_SOFT_THRESHOLD
cache_g = lum_g * . || LIGHTING_SOFT_THRESHOLD
cache_b = lum_b * . || LIGHTING_SOFT_THRESHOLD
cache_mx = mx
for (var/TT in masters)
var/turf/T = TT
if (T.lighting_overlay)
if (!T.lighting_overlay.needs_update)
T.lighting_overlay.needs_update = TRUE
lighting_update_overlays += T.lighting_overlay
/datum/lighting_corner/dummy/New()
return
+57 -68
View File
@@ -1,3 +1,4 @@
var/list/all_lighting_overlays = list() // Global list of lighting overlays.
/atom/movable/lighting_overlay
name = ""
mouse_opacity = 0
@@ -6,90 +7,75 @@
icon = LIGHTING_ICON
layer = LIGHTING_LAYER
invisibility = INVISIBILITY_LIGHTING
color = "#000000"
color = LIGHTING_BASE_MATRIX
icon_state = "light1"
auto_init = 0 // doesn't need special init
blend_mode = BLEND_MULTIPLY
var/lum_r
var/lum_g
var/lum_b
var/lum_r = 0
var/lum_g = 0
var/lum_b = 0
var/needs_update
var/needs_update = FALSE
/atom/movable/lighting_overlay/New()
/atom/movable/lighting_overlay/New(var/atom/loc, var/no_update = FALSE)
. = ..()
verbs.Cut()
global.all_lighting_overlays += src
var/turf/T = loc //If this runtimes atleast we'll know what's creating overlays outside of turfs.
T.lighting_overlay = src
T.luminosity = 0
/atom/movable/lighting_overlay/proc/get_clamped_lum(var/minlum = 0, var/maxlum = 1)
var/lum = max(lum_r, lum_g, lum_b)
if(lum <= minlum)
return 0
else if(lum >= maxlum)
return 1
else
return (lum - minlum) / (maxlum - minlum)
/atom/movable/lighting_overlay/proc/update_lumcount(delta_r, delta_g, delta_b)
if(!delta_r && !delta_g && !delta_b) //Nothing is being changed all together.
if(no_update)
return
var/should_update = 0
if(!needs_update) //If this isn't true, we're already updating anyways.
if(max(lum_r, lum_g, lum_b) < 1) //Any change that could happen WILL change appearance.
should_update = 1
else if(max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b) < 1) //The change would bring us under 1 max lum, again, guaranteed to change appearance.
should_update = 1
else //We need to make sure that the colour ratios won't change in this code block.
var/mx1 = max(lum_r, lum_g, lum_b)
var/mx2 = max(lum_r + delta_r, lum_g + delta_g, lum_b + delta_b)
if(lum_r / mx1 != (lum_r + delta_r) / mx2 || lum_g / mx1 != (lum_g + delta_g) / mx2 || lum_b / mx1 != (lum_b + delta_b) / mx2) //Stuff would change.
should_update = 1
lum_r = max(lum_r + delta_r, 0) //Lum shouldn't drop below 1
lum_g = max(lum_g + delta_g, 0)
lum_b = max(lum_b + delta_b, 0)
if(!needs_update && should_update)
needs_update = 1
lighting_update_overlays += src
update_overlay()
/atom/movable/lighting_overlay/proc/update_overlay()
set waitfor = FALSE
var/turf/T = loc
if(istype(T)) //Incase we're not on a turf, pool ourselves, something happened.
if(lum_r == lum_g && lum_r == lum_b) //greyscale
blend_mode = BLEND_OVERLAY
if(lum_r <= 0)
T.luminosity = 0
color = "#000000"
alpha = 255
else
T.luminosity = 1
color = "#000000"
alpha = (1 - min(lum_r, 1)) * 255
if(!istype(T))
if(loc)
log_debug("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : "null"]) in update_overlay() and got qdel'ed!")
else
alpha = 255
var/mx = max(lum_r, lum_g, lum_b)
. = 1 // factor
if(mx > 1)
. = 1/mx
blend_mode = BLEND_MULTIPLY
color = rgb(lum_r * 255 * ., lum_g * 255 * ., lum_b * 255 * .)
if(color != "#000000")
T.luminosity = 1
else //No light, set the turf's luminosity to 0 to remove it from view()
T.luminosity = 0
else
//warning("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : "null"]) in update_overlay() and got qdel'ed!") //fucking bullshit bugs means this spams when shuttles move, feel free to fix
log_debug("A lighting overlay realised its loc was NOT a turf (actual loc: [loc][loc ? ", " + loc.type : "null"]) in update_overlay() and got qdel'ed!")
log_debug("A lighting overlay realised it was in nullspace in update_overlay() and got pooled!")
qdel(src)
return
// To the future coder who sees this and thinks
// "Why didn't he just use a loop?"
// Well my man, it's because the loop performed like shit.
// And there's no way to improve it because
// without a loop you can make the list all at once which is the fastest you're gonna get.
// Oh it's also shorter line wise.
// Including with these comments.
// See LIGHTING_CORNER_DIAGONAL in lighting_corner.dm for why these values are what they are.
// No I seriously cannot think of a more efficient method, fuck off Comic.
var/datum/lighting_corner/cr = T.corners[3] || dummy_lighting_corner
var/datum/lighting_corner/cg = T.corners[2] || dummy_lighting_corner
var/datum/lighting_corner/cb = T.corners[4] || dummy_lighting_corner
var/datum/lighting_corner/ca = T.corners[1] || dummy_lighting_corner
var/max = max(cr.cache_mx, cg.cache_mx, cb.cache_mx, ca.cache_mx)
var/list/new_matrix = list(
cr.cache_r, cr.cache_g, cr.cache_b, 0,
cg.cache_r, cg.cache_g, cg.cache_b, 0,
cb.cache_r, cb.cache_g, cb.cache_b, 0,
ca.cache_r, ca.cache_g, ca.cache_b, 0,
0, 0, 0, 1
)
var/lum = max > LIGHTING_SOFT_THRESHOLD
if(lum)
luminosity = 1
animate(src, color = new_matrix, time = 5)
else
animate(src, color = new_matrix, time = 5)
animate(luminosity = 0, time = 0)
/atom/movable/lighting_overlay/singularity_act()
return
@@ -98,10 +84,13 @@
return
/atom/movable/lighting_overlay/Destroy()
lighting_update_overlays -= src
global.all_lighting_overlays -= src
global.lighting_update_overlays -= src
global.lighting_update_overlays_old -= src
var/turf/T = loc
if(istype(T))
T.lighting_overlay = null
T.luminosity = 1
return ..()
-35
View File
@@ -1,35 +0,0 @@
/datum/controller/process/lighting
var/last_light_count = 0
var/last_overlay_count = 0
/datum/controller/process/lighting/doWork()
var/list/lighting_update_lights_old = lighting_update_lights //We use a different list so any additions to the update lists during a delay from SCHECK don't cause things to be cut from the list without being updated.
last_light_count = lighting_update_lights.len
lighting_update_lights = null //Nulling it first because of http://www.byond.com/forum/?post=1854520
lighting_update_lights = list()
for(var/datum/light_source/L in lighting_update_lights_old)
if(L.destroyed || L.check() || L.force_update)
L.remove_lum()
if(!L.destroyed)
L.apply_lum()
else if(L.vis_update) //We smartly update only tiles that became (in) visible to use.
L.smart_vis_update()
L.vis_update = 0
L.force_update = 0
L.needs_update = 0
SCHECK
var/list/lighting_update_overlays_old = lighting_update_overlays //Same as above.
last_overlay_count = lighting_update_overlays.len
lighting_update_overlays = null //Same as above
lighting_update_overlays = list()
for(var/atom/movable/lighting_overlay/O in lighting_update_overlays_old)
O.update_overlay()
O.needs_update = 0
SCHECK
+16
View File
@@ -0,0 +1,16 @@
/proc/create_all_lighting_overlays()
for(var/zlevel = 1 to world.maxz)
create_lighting_overlays_zlevel(zlevel)
/proc/create_lighting_overlays_zlevel(var/zlevel)
ASSERT(zlevel)
for(var/turf/T in block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel)))
if(!T.dynamic_lighting)
continue
var/area/A = T.loc
if(!A.dynamic_lighting)
continue
new /atom/movable/lighting_overlay(T, TRUE)
+283
View File
@@ -0,0 +1,283 @@
// This is where the fun begins.
// These are the main datums that emit light.
/datum/light_source
var/atom/top_atom // The atom we're emitting light from(for example a mob if we're from a flashlight that's being held).
var/atom/source_atom // The atom that we belong to.
var/turf/source_turf // The turf under the above.
var/light_power // Intensity of the emitter light.
var/light_range // The range of the emitted light.
var/light_color // The colour of the light, string, decomposed by parse_light_color()
// Variables for keeping track of the colour.
var/lum_r
var/lum_g
var/lum_b
// The lumcount values used to apply the light.
var/tmp/applied_lum_r
var/tmp/applied_lum_g
var/tmp/applied_lum_b
var/list/datum/lighting_corner/effect_str // List used to store how much we're affecting corners.
var/list/turf/affecting_turfs
var/applied = FALSE // Whether we have applied our light yet or not.
var/vis_update // Whether we should smartly recalculate visibility. and then only update tiles that became(in)visible to us.
var/needs_update // Whether we are queued for an update.
var/destroyed // Whether we are destroyed and need to stop emitting light.
var/force_update
/datum/light_source/New(var/atom/owner, var/atom/top)
source_atom = owner // Set our new owner.
if(!source_atom.light_sources)
source_atom.light_sources = list()
source_atom.light_sources += src // Add us to the lights of our owner.
top_atom = top
if(top_atom != source_atom)
if(!top.light_sources)
top.light_sources = list()
top_atom.light_sources += src
source_turf = top_atom
light_power = source_atom.light_power
light_range = source_atom.light_range
light_color = source_atom.light_color
parse_light_color()
effect_str = list()
affecting_turfs = list()
update()
return ..()
// Kill ourselves.
/datum/light_source/proc/destroy()
destroyed = TRUE
force_update()
if(source_atom)
source_atom.light_sources -= src
if(top_atom)
top_atom.light_sources -= src
// Call it dirty, I don't care.
// This is here so there's no performance loss on non-instant updates from the fact that the engine can also do instant updates.
// If you're wondering what's with the "BYOND" argument: BYOND won't let me have a() macro that has no arguments :|.
#define effect_update(BYOND) \
if(!needs_update) \
{ \
lighting_update_lights += src; \
needs_update = TRUE; \
}
// This proc will cause the light source to update the top atom, and add itself to the update queue.
/datum/light_source/proc/update(var/atom/new_top_atom)
// This top atom is different.
if(new_top_atom && new_top_atom != top_atom)
if(top_atom != source_atom) // Remove ourselves from the light sources of that top atom.
top_atom.light_sources -= src
top_atom = new_top_atom
if(top_atom != source_atom)
if(!top_atom.light_sources)
top_atom.light_sources = list()
top_atom.light_sources += src // Add ourselves to the light sources of our new top atom.
effect_update(null)
// Will force an update without checking if it's actually needed.
/datum/light_source/proc/force_update()
force_update = 1
effect_update(null)
// Will cause the light source to recalculate turfs that were removed or added to visibility only.
/datum/light_source/proc/vis_update()
vis_update = 1
effect_update(null)
// Will check if we actually need to update, and update any variables that may need to be updated.
/datum/light_source/proc/check()
if(!source_atom || !light_range || !light_power)
destroy()
return 1
if(!top_atom)
top_atom = source_atom
. = 1
if(isturf(top_atom))
if(source_turf != top_atom)
source_turf = top_atom
. = 1
else if(top_atom.loc != source_turf)
source_turf = top_atom.loc
. = 1
if(source_atom.light_power != light_power)
light_power = source_atom.light_power
. = 1
if(source_atom.light_range != light_range)
light_range = source_atom.light_range
. = 1
if(light_range && light_power && !applied)
. = 1
if(source_atom.light_color != light_color)
light_color = source_atom.light_color
parse_light_color()
. = 1
// Decompile the hexadecimal colour into lumcounts of each perspective.
/datum/light_source/proc/parse_light_color()
if(light_color)
lum_r = GetRedPart (light_color) / 255
lum_g = GetGreenPart(light_color) / 255
lum_b = GetBluePart (light_color) / 255
else
lum_r = 1
lum_g = 1
lum_b = 1
// Macro that applies light to a new corner.
// It is a macro in the interest of speed, yet not having to copy paste it.
// If you're wondering what's with the backslashes, the backslashes cause BYOND to not automatically end the line.
// As such this all gets counted as a single line.
// The braces and semicolons are there to be able to do this on a single line.
#define APPLY_CORNER(C) \
. = LUM_FALLOFF(C, source_turf); \
\
. *= light_power; \
\
effect_str[C] = .; \
\
C.update_lumcount \
( \
. * applied_lum_r, \
. * applied_lum_g, \
. * applied_lum_b \
);
// I don't need to explain what this does, do I?
#define REMOVE_CORNER(C) \
. = -effect_str[C]; \
C.update_lumcount \
( \
. * applied_lum_r, \
. * applied_lum_g, \
. * applied_lum_b \
);
// This is the define used to calculate falloff.
#define LUM_FALLOFF(C, T)(1 - CLAMP01(sqrt((C.x - T.x) ** 2 +(C.y - T.y) ** 2 + LIGHTING_HEIGHT) / max(1, light_range)))
/datum/light_source/proc/apply_lum()
var/static/update_gen = 1
applied = 1
// Keep track of the last applied lum values so that the lighting can be reversed
applied_lum_r = lum_r
applied_lum_g = lum_g
applied_lum_b = lum_b
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
if(!T.lighting_corners_initialised)
T.generate_missing_corners()
for(var/datum/lighting_corner/C in T.get_corners())
if(C.update_gen == update_gen)
continue
C.update_gen = update_gen
C.affecting += src
if(!C.active)
effect_str[C] = 0
continue
APPLY_CORNER(C)
if(!T.affecting_lights)
T.affecting_lights = list()
T.affecting_lights += src
affecting_turfs += T
update_gen++
/datum/light_source/proc/remove_lum()
applied = FALSE
for(var/turf/T in affecting_turfs)
if(!T.affecting_lights)
T.affecting_lights = list()
else
T.affecting_lights -= src
affecting_turfs.Cut()
for(var/datum/lighting_corner/C in effect_str)
REMOVE_CORNER(C)
C.affecting -= src
effect_str.Cut()
/datum/light_source/proc/recalc_corner(var/datum/lighting_corner/C)
if(effect_str.Find(C)) // Already have one.
REMOVE_CORNER(C)
APPLY_CORNER(C)
/datum/light_source/proc/smart_vis_update()
var/list/datum/lighting_corner/corners = list()
var/list/turf/turfs = list()
FOR_DVIEW(var/turf/T, light_range, source_turf, 0)
if(!T.lighting_corners_initialised)
T.generate_missing_corners()
corners |= T.get_corners()
turfs += T
var/list/L = turfs - affecting_turfs // New turfs, add us to the affecting lights of them.
affecting_turfs += L
for(var/turf/T in L)
if(!T.affecting_lights)
T.affecting_lights = list(src)
else
T.affecting_lights += src
L = affecting_turfs - turfs // Now-gone turfs, remove us from the affecting lights.
affecting_turfs -= L
for(var/turf/T in L)
T.affecting_lights -= src
for(var/datum/lighting_corner/C in corners - effect_str) // New corners
C.affecting += src
if(!C.active)
effect_str[C] = 0
continue
APPLY_CORNER(C)
for(var/datum/lighting_corner/C in effect_str - corners) // Old, now gone, corners.
REMOVE_CORNER(C)
C.affecting -= src
effect_str -= C
#undef effect_update
#undef LUM_FALLOFF
#undef REMOVE_CORNER
#undef APPLY_CORNER
-25
View File
@@ -1,25 +0,0 @@
/var/list/lighting_update_lights = list()
/var/list/lighting_update_overlays = list()
/area/var/lighting_use_dynamic = 1
// duplicates lots of code, but this proc needs to be as fast as possible.
/proc/create_lighting_overlays(zlevel = 0)
var/area/A
if(zlevel == 0) // populate all zlevels
for(var/turf/T in world)
if(T.dynamic_lighting)
A = T.loc
if(A.lighting_use_dynamic)
var/atom/movable/lighting_overlay/O = new(T)
T.lighting_overlay = O
else
for(var/x = 1; x <= world.maxx; x++)
for(var/y = 1; y <= world.maxy; y++)
var/turf/T = locate(x, y, zlevel)
if(T.dynamic_lighting)
A = T.loc
if(A.lighting_use_dynamic)
var/atom/movable/lighting_overlay/O = new(T)
T.lighting_overlay = O
+89 -13
View File
@@ -1,26 +1,102 @@
/turf
var/list/affecting_lights
var/atom/movable/lighting_overlay/lighting_overlay
var/dynamic_lighting = TRUE
luminosity = 1
var/tmp/lighting_corners_initialised = FALSE
var/tmp/list/datum/light_source/affecting_lights // List of light sources affecting this turf.
var/tmp/atom/movable/lighting_overlay/lighting_overlay // Our lighting overlay.
var/tmp/list/datum/lighting_corner/corners
var/tmp/has_opaque_atom = FALSE // Not to be confused with opacity, this will be TRUE if there's any opaque atom on the tile.
/turf/New()
. = ..()
if(opacity)
has_opaque_atom = TRUE
// Causes any affecting light sources to be queued for a visibility update, for example a door got opened.
/turf/proc/reconsider_lights()
for(var/datum/light_source/L in affecting_lights)
L.vis_update()
/turf/proc/lighting_clear_overlays()
/turf/proc/lighting_clear_overlay()
if(lighting_overlay)
qdel(lighting_overlay)
/turf/proc/lighting_build_overlays()
for(var/datum/lighting_corner/C in corners)
C.update_active()
// Builds a lighting overlay for us, but only if our area is dynamic.
/turf/proc/lighting_build_overlay()
if(lighting_overlay)
return
var/area/A = loc
if(A.lighting_use_dynamic)
var/atom/movable/lighting_overlay/O = new(src)
lighting_overlay = O
// forcibly refresh lighting on this tile
// must make light forget tile or it wil remain
// convinced that it is already lighting it
for(var/datum/light_source/L in affecting_lights)
L.forget_turf(src)
L.vis_update()
if(A.dynamic_lighting)
if(!lighting_corners_initialised)
generate_missing_corners()
new /atom/movable/lighting_overlay(src)
for(var/datum/lighting_corner/C in corners)
if(!C.active) // We would activate the corner, calculate the lighting for it.
for(var/L in C.affecting)
var/datum/light_source/S = L
S.recalc_corner(C)
C.active = TRUE
// Used to get a scaled lumcount.
/turf/proc/get_lumcount(var/minlum = 0, var/maxlum = 1)
if(!lighting_overlay)
return 1
var/totallums = 0
for(var/datum/lighting_corner/L in corners)
totallums += max(L.lum_r, L.lum_g, L.lum_b)
totallums /= 4 // 4 corners, max channel selected, return the average
totallums =(totallums - minlum) /(maxlum - minlum)
return CLAMP01(totallums)
// Can't think of a good name, this proc will recalculate the has_opaque_atom variable.
/turf/proc/recalc_atom_opacity()
has_opaque_atom = FALSE
for(var/atom/A in src.contents + src) // Loop through every movable atom on our tile PLUS ourselves (we matter too...)
if(A.opacity)
has_opaque_atom = TRUE
// If an opaque movable atom moves around we need to potentially update visibility.
/turf/Entered(var/atom/movable/Obj, var/atom/OldLoc)
. = ..()
if(Obj && Obj.opacity)
has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case.
reconsider_lights()
/turf/Exited(var/atom/movable/Obj, var/atom/newloc)
. = ..()
if(Obj && Obj.opacity)
recalc_atom_opacity() // Make sure to do this before reconsider_lights(), incase we're on instant updates.
reconsider_lights()
/turf/proc/get_corners()
if(has_opaque_atom)
return null // Since this proc gets used in a for loop, null won't be looped though.
return corners
/turf/proc/generate_missing_corners()
lighting_corners_initialised = TRUE
if(!corners)
corners = list(null, null, null, null)
for(var/i = 1 to 4)
if(corners[i]) // Already have a corner on this direction.
continue
corners[i] = new /datum/lighting_corner(src, LIGHTING_CORNER_DIAGONAL[i])
+3 -5
View File
@@ -1,9 +1,7 @@
#undef LIGHTING_INTERVAL
#undef LIGHTING_FALLOFF
#undef LIGHTING_LAMBERTIAN
#undef LIGHTING_HEIGHT
#undef LIGHTING_RESOLUTION
#undef LIGHTING_LAYER
#undef LIGHTING_ICON
#undef LIGHTING_ICON
#undef LIGHTING_BASE_MATRIX
+1 -1
View File
@@ -63,7 +63,7 @@
if(57 to 58)
new /obj/item/toy/syndicateballoon(src)
if(59 to 60)
new /obj/item/weapon/gun/energy/kinetic_accelerator/hyper(src)
new /obj/item/borg/upgrade/modkit/aoe/mobs(src)
new /obj/item/clothing/suit/space(src)
new /obj/item/clothing/head/helmet/space(src)
if(61 to 62)
+20 -13
View File
@@ -313,7 +313,7 @@
anchored = 1.0
var/obj/item/weapon/card/id/inserted_id
var/list/prize_list = list(
new /datum/data/mining_equipment("Stimpack", /obj/item/weapon/reagent_containers/hypospray/autoinjector/stimpack, 50),
new /datum/data/mining_equipment("Stimpack", /obj/item/weapon/reagent_containers/hypospray/autoinjector/stimpack, 50),
new /datum/data/mining_equipment("Teporone MediPen", /obj/item/weapon/reagent_containers/hypospray/autoinjector/teporone, 50),
new /datum/data/mining_equipment("MediPen Bundle", /obj/item/weapon/storage/box/autoinjector/utility, 200),
new /datum/data/mining_equipment("Whiskey", /obj/item/weapon/reagent_containers/food/drinks/bottle/whiskey, 100),
@@ -324,10 +324,10 @@
new /datum/data/mining_equipment("Advanced Scanner", /obj/item/device/t_scanner/adv_mining_scanner, 400),
new /datum/data/mining_equipment("Hivelord Stabilizer", /obj/item/weapon/hivelordstabilizer, 400),
new /datum/data/mining_equipment("Mining Drone", /obj/item/weapon/mining_drone_cube, 500),
new /datum/data/mining_equipment("Drone Melee Upgrade", /obj/item/device/mine_bot_ugprade, 400),
new /datum/data/mining_equipment("Drone Health Upgrade",/obj/item/device/mine_bot_ugprade/health, 400),
new /datum/data/mining_equipment("Drone Ranged Upgrade",/obj/item/device/mine_bot_ugprade/cooldown, 600),
new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/weapon/twohanded/required/mining_hammer, 750),
new /datum/data/mining_equipment("Drone Melee Upgrade", /obj/item/device/mine_bot_upgrade, 400),
new /datum/data/mining_equipment("Drone Health Upgrade",/obj/item/device/mine_bot_upgrade/health, 400),
new /datum/data/mining_equipment("Drone Ranged Upgrade",/obj/item/device/mine_bot_upgrade/cooldown, 600),
new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/weapon/twohanded/required/mining_hammer, 750),
new /datum/data/mining_equipment("Drone AI Upgrade", /obj/item/slimepotion/sentience/mining, 1000),
new /datum/data/mining_equipment("GAR mesons", /obj/item/clothing/glasses/meson/gar, 500),
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/weapon/storage/firstaid/brute, 600),
@@ -342,7 +342,14 @@
new /datum/data/mining_equipment("Space Cash", /obj/item/weapon/spacecash/c1000, 2000),
new /datum/data/mining_equipment("Diamond Pickaxe", /obj/item/weapon/pickaxe/diamond, 2000),
new /datum/data/mining_equipment("Super Resonator", /obj/item/weapon/resonator/upgraded, 2500),
new /datum/data/mining_equipment("Super Accelerator", /obj/item/weapon/gun/energy/kinetic_accelerator/super, 3000),
new /datum/data/mining_equipment("KA White Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer, 100),
new /datum/data/mining_equipment("KA Adjustable Tracer Rounds", /obj/item/borg/upgrade/modkit/tracer/adjustable, 150),
new /datum/data/mining_equipment("KA Super Chassis", /obj/item/borg/upgrade/modkit/chassis_mod, 250),
new /datum/data/mining_equipment("KA Hyper Chassis", /obj/item/borg/upgrade/modkit/chassis_mod/orange, 300),
new /datum/data/mining_equipment("KA Range Increase", /obj/item/borg/upgrade/modkit/range, 1000),
new /datum/data/mining_equipment("KA Damage Increase", /obj/item/borg/upgrade/modkit/damage, 1000),
new /datum/data/mining_equipment("KA Cooldown Decrease",/obj/item/borg/upgrade/modkit/cooldown, 1000),
new /datum/data/mining_equipment("KA AoE Damage", /obj/item/borg/upgrade/modkit/aoe/mobs, 2000),
new /datum/data/mining_equipment("Point Transfer Card", /obj/item/weapon/card/mining_point_card, 500),
)
@@ -938,18 +945,18 @@
//Melee
/obj/item/device/mine_bot_ugprade
/obj/item/device/mine_bot_upgrade
name = "minebot melee upgrade"
desc = "A minebot upgrade."
icon_state = "door_electronics"
icon = 'icons/obj/doors/door_assembly.dmi'
/obj/item/device/mine_bot_ugprade/afterattack(mob/living/simple_animal/hostile/mining_drone/M, mob/user, proximity)
/obj/item/device/mine_bot_upgrade/afterattack(mob/living/simple_animal/hostile/mining_drone/M, mob/user, proximity)
if(!istype(M) || !proximity)
return
upgrade_bot(M, user)
/obj/item/device/mine_bot_ugprade/proc/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
/obj/item/device/mine_bot_upgrade/proc/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
if(M.melee_damage_upper != initial(M.melee_damage_upper))
to_chat(user, "[M] already has a combat upgrade installed!")
return
@@ -960,10 +967,10 @@
//Health
/obj/item/device/mine_bot_ugprade/health
/obj/item/device/mine_bot_upgrade/health
name = "minebot chassis upgrade"
/obj/item/device/mine_bot_ugprade/health/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
/obj/item/device/mine_bot_upgrade/health/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
if(M.maxHealth != initial(M.maxHealth))
to_chat(user, "[M] already has a reinforced chassis!")
return
@@ -974,10 +981,10 @@
//Cooldown
/obj/item/device/mine_bot_ugprade/cooldown
/obj/item/device/mine_bot_upgrade/cooldown
name = "minebot cooldown upgrade"
/obj/item/device/mine_bot_ugprade/cooldown/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
/obj/item/device/mine_bot_upgrade/cooldown/upgrade_bot(mob/living/simple_animal/hostile/mining_drone/M, mob/user)
if(M.ranged_cooldown_time != initial(M.ranged_cooldown_time))
to_chat(user, "[M] already has a decreased weapon cooldown!")
return
@@ -0,0 +1,217 @@
/obj/structure/closet/crate/necropolis/dragon
name = "dragon chest"
/obj/structure/closet/crate/necropolis/dragon/New()
..()
var/loot = rand(1,4)
switch(loot)
if(1)
new /obj/item/weapon/melee/ghost_sword(src)
if(2)
new /obj/item/weapon/lava_staff(src)
if(3)
new /obj/item/weapon/spellbook/oneuse/sacredflame(src)
new /obj/item/weapon/gun/magic/wand/fireball(src)
if(4)
new /obj/item/weapon/dragons_blood(src)
// Spectral Blade
/obj/item/weapon/melee/ghost_sword
name = "spectral blade"
desc = "A rusted and dulled blade. It doesn't look like it'd do much damage. It glows weakly."
icon_state = "spectral"
item_state = "spectral"
flags = CONDUCT
sharp = 1
edge = 1
w_class = 4
force = 1
throwforce = 1
hitsound = 'sound/effects/ghost2.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "rended")
var/summon_cooldown = 0
var/list/mob/dead/observer/spirits
/obj/item/weapon/melee/ghost_sword/New()
..()
spirits = list()
processing_objects.Add(src)
poi_list |= src
/obj/item/weapon/melee/ghost_sword/Destroy()
for(var/mob/dead/observer/G in spirits)
G.invisibility = initial(G.invisibility)
spirits.Cut()
processing_objects.Remove(src)
poi_list -= src
. = ..()
/obj/item/weapon/melee/ghost_sword/attack_self(mob/user)
if(summon_cooldown > world.time)
to_chat(user, "You just recently called out for aid. You don't want to annoy the spirits.")
return
to_chat(user, "You call out for aid, attempting to summon spirits to your side.")
notify_ghosts("[user] is raising their [src], calling for your help!", enter_link="<a href=?src=[UID()];follow=1>(Click to help)</a>", source = user, action = NOTIFY_FOLLOW)
summon_cooldown = world.time + 600
/obj/item/weapon/melee/ghost_sword/Topic(href, href_list)
if(href_list["follow"])
var/mob/dead/observer/ghost = usr
if(istype(ghost))
ghost.ManualFollow(src)
/obj/item/weapon/melee/ghost_sword/process()
ghost_check()
/obj/item/weapon/melee/ghost_sword/proc/ghost_check()
var/ghost_counter = 0
var/turf/T = get_turf(src)
var/list/contents = T.GetAllContents()
var/mob/dead/observer/current_spirits = list()
for(var/mob/dead/observer/O in player_list)
if(is_type_in_list(O.following, contents))
ghost_counter++
O.invisibility = 0
current_spirits |= O
for(var/mob/dead/observer/G in spirits - current_spirits)
G.invisibility = initial(G.invisibility)
spirits = current_spirits
return ghost_counter
/obj/item/weapon/melee/ghost_sword/attack(mob/living/target, mob/living/carbon/human/user)
force = 0
var/ghost_counter = ghost_check()
force = Clamp((ghost_counter * 4), 0, 75)
user.visible_message("<span class='danger'>[user] strikes with the force of [ghost_counter] vengeful spirits!</span>")
..()
/obj/item/weapon/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
var/ghost_counter = ghost_check()
final_block_chance += Clamp((ghost_counter * 5), 0, 75)
owner.visible_message("<span class='danger'>[owner] is protected by a ring of [ghost_counter] ghosts!</span>")
return ..()
// Blood
/obj/item/weapon/dragons_blood
name = "bottle of dragons blood"
desc = "You're not actually going to drink this, are you?"
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
/obj/item/weapon/dragons_blood/attack_self(mob/living/carbon/human/user)
if(!istype(user))
return
var/mob/living/carbon/human/H = user
var/random = rand(1,3)
switch(random)
if(1)
to_chat(user, "<span class='danger'>Your flesh begins to melt! Miraculously, you seem fine otherwise.</span>")
H.set_species("Skeleton")
if(2)
to_chat(user, "<span class='danger'>Power courses through you! You can now shift your form at will.")
if(user.mind)
var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new
user.mind.AddSpell(D)
if(3)
to_chat(user, "<span class='danger'>You feel like you could walk straight through lava now.</span>")
H.weather_immunities |= "lava"
playsound(user.loc,'sound/items/drink.ogg', rand(10,50), 1)
qdel(src)
/datum/disease/transformation/dragon
name = "dragon transformation"
cure_text = "nothing"
cures = list("adminordrazine")
agent = "dragon's blood"
desc = "What do dragons have to do with Space Station 13?"
stage_prob = 20
severity = BIOHAZARD
visibility_flags = 0
stage1 = list("Your bones ache.")
stage2 = list("Your skin feels scaley.")
stage3 = list("<span class='danger'>You have an overwhelming urge to terrorize some peasants.</span>", "<span class='danger'>Your teeth feel sharper.</span>")
stage4 = list("<span class='danger'>Your blood burns.</span>")
stage5 = list("<span class='danger'>You're a fucking dragon. However, any previous allegiances you held still apply. It'd be incredibly rude to eat your still human friends for no reason.</span>")
new_form = /mob/living/simple_animal/hostile/megafauna/dragon/lesser
//Lava Staff
/obj/item/weapon/lava_staff
name = "staff of lava"
desc = "The ability to fill the emergency shuttle with lava. What more could you want out of life?"
icon_state = "staffofstorms"
item_state = "staffofstorms"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
item_state = "staffofstorms"
w_class = 4
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
burn_state = LAVA_PROOF | FIRE_PROOF
unacidable = 1
var/turf_type = /turf/unsimulated/floor/lava // /turf/simulated/floor/plating/lava/smooth once Lavaland turfs are added
var/transform_string = "lava"
var/reset_turf_type = /turf/simulated/floor/plating/airless/asteroid // /turf/simulated/floor/plating/asteroid/basalt once Lavaland turfs are added
var/reset_string = "basalt"
var/create_cooldown = 100
var/create_delay = 30
var/reset_cooldown = 50
var/timer = 0
var/banned_turfs
/obj/item/weapon/lava_staff/New()
. = ..()
banned_turfs = typecacheof(list(/turf/space/transit, /turf/unsimulated))
/obj/item/weapon/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
..()
if(timer > world.time)
return
if(is_type_in_typecache(target, banned_turfs))
return
if(target in view(user.client.view, get_turf(user)))
var/turf/simulated/T = get_turf(target)
if(!istype(T))
return
if(!istype(T, turf_type))
var/obj/effect/overlay/temp/lavastaff/L = new /obj/effect/overlay/temp/lavastaff(T)
L.alpha = 0
animate(L, alpha = 255, time = create_delay)
user.visible_message("<span class='danger'>[user] points [src] at [T]!</span>")
timer = world.time + create_delay + 1
if(do_after(user, create_delay, target = T))
user.visible_message("<span class='danger'>[user] turns \the [T] into [transform_string]!</span>")
message_admins("[key_name_admin(user)] fired the lava staff at [get_area(target)] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>).")
log_game("[key_name(user)] fired the lava staff at [get_area(target)] ([T.x], [T.y], [T.z]).")
T.ChangeTurf(turf_type)
timer = world.time + create_cooldown
qdel(L)
else
timer = world.time
qdel(L)
return
else
user.visible_message("<span class='danger'>[user] turns \the [T] into [reset_string]!</span>")
T.ChangeTurf(reset_turf_type)
timer = world.time + reset_cooldown
playsound(T,'sound/magic/Fireball.ogg', 200, 1)
/obj/effect/overlay/temp/lavastaff
icon_state = "lavastaff_warn"
duration = 50
@@ -0,0 +1,81 @@
/obj/structure/closet/crate/necropolis/bubblegum
name = "bubblegum chest"
/obj/structure/closet/crate/necropolis/bubblegum/New()
..()
var/loot = rand(1,3)
switch(loot)
if(1)
new /obj/item/mayhem(src)
if(2)
new /obj/item/blood_contract(src)
if(3)
new /obj/item/weapon/gun/magic/staff/spellblade(src)
// Mayhem
/obj/item/mayhem
name = "mayhem in a bottle"
desc = "A magically infused bottle of blood, the scent of which will drive anyone nearby into a murderous frenzy."
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
/obj/item/mayhem/attack_self(mob/user)
for(var/mob/living/carbon/human/H in range(7,user))
spawn()
var/obj/effect/mine/pickup/bloodbath/B = new(H)
B.mineEffect(H)
to_chat(user, "<span class='notice'>You shatter the bottle!</span>")
playsound(user.loc, 'sound/effects/Glassbr1.ogg', 100, 1)
qdel(src)
// Blood Contract
/obj/item/blood_contract
name = "blood contract"
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
color = "#FF0000"
desc = "Mark your target for death."
var/used = FALSE
/obj/item/blood_contract/attack_self(mob/user)
if(used)
return
used = TRUE
var/choice = input(user,"Who do you want dead?","Choose Your Victim") as null|anything in player_list
if(!choice)
used = FALSE
return
else if(!isliving(choice))
to_chat(user, "[choice] is already dead!")
used = FALSE
return
else if(choice == user)
to_chat(user, "You feel like writing your own name into a cursed death warrant would be unwise.")
used = FALSE
return
else
var/mob/living/L = choice
message_admins("[key_name_admin(L)] has been marked for death by [key_name_admin(user)].")
log_admin("[key_name(L)] has been marked for death by [key_name(user)].")
var/datum/objective/survive/survive = new
survive.owner = L.mind
L.mind.objectives += survive
to_chat(L, "<span class='userdanger'>You've been marked for death! Don't let the demons get you!</span>")
L.color = "#FF0000"
spawn()
var/obj/effect/mine/pickup/bloodbath/B = new(L)
B.mineEffect(L)
for(var/mob/living/carbon/human/H in player_list)
if(H == L)
continue
to_chat(H, "<span class='userdanger'>You have an overwhelming desire to kill [L]. They have been marked red! Go kill them!</span>")
H.put_in_hands(new /obj/item/weapon/kitchen/knife/butcher(H))
qdel(src)
@@ -10,6 +10,7 @@
luminosity = 8
max_n_of_items = INFINITY
unacidable = 1
burn_state = LAVA_PROOF | FIRE_PROOF
pixel_y = -4
use_power = 0
var/memory_saved = FALSE
@@ -98,6 +99,7 @@
luminosity = 8
use_power = 0
density = 1
burn_state = LAVA_PROOF | FIRE_PROOF
unacidable = 1
var/activation_method = "touch"
var/activation_damage_type = null
@@ -0,0 +1,188 @@
/obj/item/weapon/hierophant_staff
name = "Hierophant's staff"
desc = "A large club with intense magic power infused into it."
icon_state = "hierophant_staff"
item_state = "hierophant_staff"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
w_class = 4
force = 20
hitsound = "swing_hit"
//hitsound = 'sound/weapons/sonic_jackhammer.ogg'
actions_types = list(/datum/action/item_action/vortex_recall, /datum/action/item_action/toggle_unfriendly_fire)
var/cooldown_time = 20 //how long the cooldown between non-melee ranged attacks is
var/chaser_cooldown = 101 //how long the cooldown between firing chasers at mobs is
var/chaser_timer = 0 //what our current chaser cooldown is
var/timer = 0 //what our current cooldown is
var/blast_range = 3 //how long the cardinal blast's walls are
var/obj/effect/hierophant/rune //the associated rune we teleport to
var/teleporting = FALSE //if we ARE teleporting
var/friendly_fire_check = FALSE //if the blasts we make will consider our faction against the faction of hit targets
/obj/item/weapon/hierophant_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
..()
var/turf/T = get_turf(target)
if(!T || timer > world.time)
return
timer = world.time + CLICK_CD_MELEE //by default, melee attacks only cause melee blasts, and have an accordingly short cooldown
if(proximity_flag)
spawn(0)
aoe_burst(T, user)
add_logs(user, target, "fired 3x3 blast at", src)
else
if(ismineralturf(target) && get_dist(user, target) < 6) //target is minerals, we can hit it(even if we can't see it)
spawn(0)
cardinal_blasts(T, user)
timer = world.time + cooldown_time
else if(target in view(5, get_turf(user))) //if the target is in view, hit it
timer = world.time + cooldown_time
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
chaser_timer = world.time + chaser_cooldown
new /obj/effect/overlay/temp/hierophant/chaser(get_turf(user), user, target, 1.5, friendly_fire_check)
add_logs(user, target, "fired a chaser at", src)
else
spawn(0)
cardinal_blasts(T, user) //otherwise, just do cardinal blast
add_logs(user, target, "fired cardinal blast at", src)
else
to_chat(user, "<span class='warning'>That target is out of range!</span>") //too far away
/obj/item/weapon/hierophant_staff/ui_action_click(mob/user, actiontype)
if(actiontype == /datum/action/item_action/toggle_unfriendly_fire) //toggle friendly fire...
friendly_fire_check = !friendly_fire_check
to_chat(user, "<span class='warning'>You toggle friendly fire [friendly_fire_check ? "off":"on"]!</span>")
return
if(user.get_active_hand() != src && user.get_inactive_hand() != src) //you need to hold the staff to teleport
to_chat(user, "<span class='warning'>You need to hold the staff in your hands to [rune ? "teleport with it" : "create a rune"]!</span>")
return
if(!rune)
if(isturf(user.loc))
user.visible_message("<span class='hierophant_warning'>[user] holds [src] carefully in front of them, moving it in a strange pattern...</span>", \
"<span class='notice'>You start creating a hierophant rune to teleport to...</span>")
timer = world.time + 51
if(do_after(user, 50, target = user))
var/turf/T = get_turf(user)
playsound(T,'sound/magic/Blind.ogg', 200, 1, -4)
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(T, user)
var/obj/effect/hierophant/H = new/obj/effect/hierophant(T)
rune = H
user.update_action_buttons_icon()
user.visible_message("<span class='hierophant_warning'>[user] creates a strange rune beneath them!</span>", \
"<span class='hierophant'>You create a hierophant rune, which you can teleport yourself and any allies to at any time!</span>\n\
<span class='notice'>You can remove the rune to place a new one by striking it with the staff.</span>")
else
timer = world.time
else
to_chat(user, "<span class='warning'>You need to be on solid ground to produce a rune!</span>")
return
if(get_dist(user, rune) <= 2) //rune too close abort
to_chat(user, "<span class='warning'>You are too close to the rune to teleport to it!</span>")
return
if(is_blocked_turf(get_turf(rune)))
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
return
teleporting = TRUE //start channel
user.update_action_buttons_icon()
user.visible_message("<span class='hierophant_warning'>[user] starts to glow faintly...</span>")
timer = world.time + 50
if(do_after(user, 40, target = user) && rune)
var/turf/T = get_turf(rune)
var/turf/source = get_turf(user)
if(is_blocked_turf(T))
teleporting = FALSE
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
user.update_action_buttons_icon()
return
new /obj/effect/overlay/temp/hierophant/telegraph(T, user)
new /obj/effect/overlay/temp/hierophant/telegraph(source, user)
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/magic/Wand_Teleport.ogg', 200, 1)
playsound(source,'sound/magic/blink.ogg', 200, 1)
//playsound(source,'sound/machines/AirlockOpen.ogg', 200, 1)
if(!do_after(user, 3, target = user) || !rune) //no walking away shitlord
teleporting = FALSE
if(user)
user.update_action_buttons_icon()
return
if(is_blocked_turf(T))
teleporting = FALSE
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
user.update_action_buttons_icon()
return
add_logs(user, rune, "teleported self from ([source.x],[source.y],[source.z]) to")
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(T, user)
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(source, user)
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE) //blasts produced will not hurt allies
B.damage = 30
for(var/t in RANGE_TURFS(1, source))
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE) //but absolutely will hurt enemies
B.damage = 30
for(var/mob/living/L in range(1, source))
spawn(0)
teleport_mob(source, L, T, user) //regardless, take all mobs near us along
sleep(6) //at this point the blasts detonate
else
timer = world.time
teleporting = FALSE
if(user)
user.update_action_buttons_icon()
/obj/item/weapon/hierophant_staff/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user)
var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster
if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to))
return
animate(M, alpha = 0, time = 2, easing = EASE_OUT) //fade out
sleep(1)
if(!M)
return
M.visible_message("<span class='hierophant_warning'>[M] fades out!</span>")
sleep(2)
if(!M)
return
M.forceMove(turf_to_teleport_to)
sleep(1)
if(!M)
return
animate(M, alpha = 255, time = 2, easing = EASE_IN) //fade IN
sleep(1)
if(!M)
return
M.visible_message("<span class='hierophant_warning'>[M] fades in!</span>")
if(user != M)
add_logs(user, M, "teleported", null, "from ([source.x],[source.y],[source.z])")
/obj/item/weapon/hierophant_staff/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay
if(!T)
return
new /obj/effect/overlay/temp/hierophant/telegraph/cardinal(T, user)
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
new /obj/effect/overlay/temp/hierophant/blast(T, user, friendly_fire_check)
for(var/d in cardinal)
spawn(0)
blast_wall(T, d, user)
/obj/item/weapon/hierophant_staff/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long
if(!T)
return
var/range = blast_range
var/turf/previousturf = T
var/turf/J = get_step(previousturf, dir)
for(var/i in 1 to range)
if(!J)
return
new /obj/effect/overlay/temp/hierophant/blast(J, user, friendly_fire_check)
previousturf = J
J = get_step(previousturf, dir)
/obj/item/weapon/hierophant_staff/proc/aoe_burst(turf/T, mob/living/user) //make a 3x3 blast around a target
if(!T)
return
new /obj/effect/overlay/temp/hierophant/telegraph(T, user)
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
for(var/t in RANGE_TURFS(1, T))
new /obj/effect/overlay/temp/hierophant/blast(t, user, friendly_fire_check)
@@ -0,0 +1,52 @@
/obj/item/weapon/staff/storm
name = "staff of storms"
desc = "An ancient staff retrieved from the remains of Legion. The wind stirs as you move it."
icon_state = "staffofstorms"
item_state = "staffofstorms"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
item_state = "staffofstorms"
w_class = 4
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
var/storm_type = /datum/weather/ash_storm
var/storm_cooldown = 0
/obj/item/weapon/staff/storm/attack_self(mob/user)
if(storm_cooldown > world.time)
to_chat(user, "<span class='warning'>The staff is still recharging!</span>")
return
var/area/user_area = get_area(user)
var/datum/weather/A
var/z_level_name = space_manager.levels_by_name[user.z]
for(var/V in weather_master.existing_weather)
var/datum/weather/W = V
if(W.target_z == z_level_name && W.area_type == user_area.type)
A = W
break
if(A)
if(A.stage != END_STAGE)
if(A.stage == WIND_DOWN_STAGE)
to_chat(user, "<span class='warning'>The storm is already ending! It would be a waste to use the staff now.</span>")
return
user.visible_message("<span class='warning'>[user] holds [src] skywards as an orange beam travels into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, dispelling the storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.wind_down()
return
else
A = new storm_type
A.name = "staff storm"
A.area_type = user_area.type
A.target_z = z_level_name
A.telegraph_duration = 100
A.end_duration = 100
user.visible_message("<span class='warning'>[user] holds [src] skywards as red lightning crackles into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, calling down a terrible storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.telegraph()
storm_cooldown = world.time + 200
@@ -0,0 +1,394 @@
//Shared Bag
//Internal
/obj/item/weapon/storage/backpack/shared
name = "paradox bag"
desc = "Somehow, it's in two places at once."
max_combined_w_class = 60
max_w_class = 3
//External
/obj/item/device/shared_storage
name = "paradox bag"
desc = "Somehow, it's in two places at once."
icon = 'icons/obj/storage.dmi'
icon_state = "cultpack"
slot_flags = SLOT_BACK
var/obj/item/weapon/storage/backpack/shared/bag
/obj/item/device/shared_storage/red
name = "paradox bag"
desc = "Somehow, it's in two places at once."
/obj/item/device/shared_storage/red/New()
..()
if(!bag)
var/obj/item/weapon/storage/backpack/shared/S = new(src)
var/obj/item/device/shared_storage/blue = new(loc)
bag = S
blue.bag = S
/obj/item/device/shared_storage/attackby(obj/item/W, mob/user, params)
if(bag)
bag.loc = user
bag.attackby(W, user, params)
/obj/item/device/shared_storage/attack_self(mob/living/carbon/user)
if(!iscarbon(user))
return
if(src == user.l_hand || src == user.r_hand)
if(bag)
bag.loc = user
bag.attack_hand(user)
else
..()
/obj/item/device/shared_storage/attack_hand(mob/living/carbon/user)
if(!iscarbon(user))
return
if(loc == user && user.back && user.back == src)
if(bag)
bag.loc = user
bag.attack_hand(user)
else
..()
/obj/item/device/shared_storage/MouseDrop(atom/over_object)
if(iscarbon(usr))
var/mob/M = usr
if(!over_object)
return
if(istype(M.loc, /obj/mecha))
return
if(!M.restrained() && !M.stat)
playsound(loc, "rustle", 50, 1, -5)
if(istype(over_object, /obj/screen/inventory/hand))
if(!M.unEquip(src))
return
M.put_in_active_hand(src)
else if(bag)
bag.loc = usr
bag.attack_hand(usr)
add_fingerprint(M)
//Potion of Flight: as we do not have the "Angel" species this currently does not work.
/obj/item/weapon/reagent_containers/glass/bottle/potion
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "potionflask"
/obj/item/weapon/reagent_containers/glass/bottle/potion/flight
name = "strange elixir"
desc = "A flask with an almost-holy aura emitting from it. The label on the bottle says: 'erqo'hyy tvi'rf lbh jv'atf'."
list_reagents = list("flightpotion" = 5)
/obj/item/weapon/reagent_containers/glass/bottle/potion/update_icon()
if(reagents.total_volume)
icon_state = "potionflask"
else
icon_state = "potionflask_empty"
/datum/reagent/flightpotion
name = "Flight Potion"
id = "flightpotion"
description = "Strange mutagenic compound of unknown origins."
reagent_state = LIQUID
color = "#FFEBEB"
/datum/reagent/flightpotion/reaction_mob(mob/living/M, method = TOUCH, reac_volume, show_message = 1)
to_chat(M, "<span class='warning'>This item is currently non-functional.</span>")
/*if(ishuman(M) && M.stat != DEAD)
var/mob/living/carbon/human/H = M
if(H.species.name != "Human" || reac_volume < 5) // implying xenohumans are holy
if(method == INGEST && show_message)
to_chat(H, "<span class='notice'><i>You feel nothing but a terrible aftertaste.</i></span>")
return ..()
to_chat(H, "<span class='userdanger'>A terrible pain travels down your back as wings burst out!</span>")
H.set_species("Angel")
playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1, -1)
H.adjustBruteLoss(20)
H.emote("scream")
..()*/
//Boat
/obj/vehicle/lavaboat
name = "lava boat"
desc = "A boat used for traversing lava."
icon_state = "goliath_boat"
icon = 'icons/obj/lavaland/dragonboat.dmi'
keytype = /obj/item/weapon/oar
burn_state = LAVA_PROOF | FIRE_PROOF
/obj/vehicle/lavaboat/relaymove(mob/user, direction)
var/turf/next = get_step(src, direction)
var/turf/current = get_turf(src)
if(istype(next, /turf/unsimulated/floor/lava) || istype(current, /turf/unsimulated/floor/lava)) //We can move from land to lava, or lava to land, but not from land to land
..()
else
to_chat(user, "<span class='warning'>Boats don't go on land!</span>")
return 0
/obj/item/weapon/oar
name = "oar"
icon = 'icons/obj/vehicles.dmi'
icon_state = "oar"
item_state = "rods"
desc = "Not to be confused with the kind Research hassles you for."
force = 12
w_class = 3
burn_state = LAVA_PROOF | FIRE_PROOF
/datum/crafting_recipe/oar
name = "goliath bone oar"
result = /obj/item/weapon/oar
reqs = list(/obj/item/stack/sheet/bone = 2)
time = 15
category = CAT_PRIMAL
/datum/crafting_recipe/boat
name = "goliath hide boat"
result = /obj/vehicle/lavaboat
reqs = list(/obj/item/stack/sheet/animalhide/goliath_hide = 3)
time = 50
category = CAT_PRIMAL
//Dragon Boat
/obj/item/ship_in_a_bottle
name = "ship in a bottle"
desc = "A tiny ship inside a bottle."
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "ship_bottle"
/obj/item/ship_in_a_bottle/attack_self(mob/user)
to_chat(user, "You're not sure how they get the ships in these things, but you're pretty sure you know how to get it out.")
playsound(user.loc, 'sound/effects/Glassbr1.ogg', 100, 1)
new /obj/vehicle/lavaboat/dragon(get_turf(src))
qdel(src)
/obj/vehicle/lavaboat/dragon
name = "mysterious boat"
desc = "This boat moves where you will it, without the need for an oar."
keytype = null
icon_state = "dragon_boat"
generic_pixel_y = 2
generic_pixel_x = 1
vehicle_move_delay = 1
// Wisp Lantern
/obj/item/device/wisp_lantern
name = "spooky lantern"
desc = "This lantern gives off no light, but is home to a friendly wisp."
icon = 'icons/obj/lighting.dmi'
icon_state = "lantern-blue"
var/obj/effect/wisp/wisp
/obj/item/device/wisp_lantern/attack_self(mob/user)
if(!wisp)
to_chat(user, "<span class='warning'>The wisp has gone missing!</span>")
return
if(wisp.loc == src)
to_chat(user, "<span class='notice'>You release the wisp. It begins to bob around your head.</span>")
user.sight |= SEE_MOBS
icon_state = "lantern"
wisp.orbit(user, 20, forceMove = TRUE)
feedback_add_details("wisp_lantern","F") // freed
else
to_chat(user, "<span class='notice'>You return the wisp to the lantern.</span>")
if(wisp.orbiting)
var/atom/A = wisp.orbiting
if(isliving(A))
var/mob/living/M = A
M.sight &= ~SEE_MOBS
to_chat(M, "<span class='notice'>Your vision returns to normal.</span>")
wisp.stop_orbit()
wisp.loc = src
icon_state = "lantern-blue"
feedback_add_details("wisp_lantern","R") // returned
/obj/item/device/wisp_lantern/New()
..()
wisp = new(src)
/obj/item/device/wisp_lantern/Destroy()
if(wisp)
if(wisp.loc == src)
qdel(wisp)
else
wisp.visible_message("<span class='notice'>[wisp] has a sad feeling for a moment, then it passes.</span>")
return ..()
/obj/effect/wisp
name = "friendly wisp"
desc = "Happy to light your way."
icon = 'icons/obj/lighting.dmi'
icon_state = "orb"
layer = ABOVE_ALL_MOB_LAYER
light_power = 1
light_range = 7
//Red/Blue Cubes
/obj/item/device/warp_cube
name = "blue cube"
desc = "A mysterious blue cube."
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "blue_cube"
var/obj/item/device/warp_cube/linked
/obj/item/device/warp_cube/Destroy()
if(linked)
linked.linked = null
linked = null
return ..()
/obj/item/device/warp_cube/attack_self(mob/user)
if(!linked)
to_chat(user, "[src] fizzles uselessly.")
return
var/datum/effect/system/harmless_smoke_spread/smoke = new /datum/effect/system/harmless_smoke_spread()
smoke.set_up(1, 0, user.loc)
smoke.start()
user.forceMove(get_turf(linked))
feedback_add_details("warp_cube","[src.type]")
var/datum/effect/system/harmless_smoke_spread/smoke2 = new /datum/effect/system/harmless_smoke_spread()
smoke2.set_up(1, 0, user.loc)
smoke2.start()
/obj/item/device/warp_cube/red
name = "red cube"
desc = "A mysterious red cube."
icon_state = "red_cube"
/obj/item/device/warp_cube/red/New()
..()
if(!linked)
var/obj/item/device/warp_cube/blue = new(src.loc)
linked = blue
blue.linked = src
//Meat Hook
/obj/item/weapon/gun/magic/hook
name = "meat hook"
desc = "Mid or feed."
ammo_type = /obj/item/ammo_casing/magic/hook
icon_state = "hook"
item_state = "chain"
fire_sound = 'sound/weapons/batonextend.ogg'
max_charges = 1
flags = NOBLUDGEON
force = 18
/obj/item/ammo_casing/magic/hook
name = "hook"
desc = "a hook."
projectile_type = /obj/item/projectile/hook
caliber = "hook"
icon_state = "hook"
/obj/item/projectile/hook
name = "hook"
icon_state = "hook"
icon = 'icons/obj/lavaland/artefacts.dmi'
pass_flags = PASSTABLE
damage = 25
armour_penetration = 100
damage_type = BRUTE
hitsound = 'sound/effects/splat.ogg'
weaken = 3
var/chain
/obj/item/projectile/hook/fire(setAngle)
if(firer)
chain = firer.Beam(src, icon_state = "chain", time = INFINITY, maxdistance = INFINITY)
..()
//TODO: root the firer until the chain returns
/obj/item/projectile/hook/on_hit(atom/target)
. = ..()
if(isliving(target))
var/mob/living/L = target
if(!L.anchored)
L.visible_message("<span class='danger'>[L] is snagged by [firer]'s hook!</span>")
L.forceMove(get_turf(firer))
/obj/item/projectile/hook/Destroy()
qdel(chain)
return ..()
//Immortality Talisman
/obj/item/device/immortality_talisman
name = "Immortality Talisman"
desc = "A dread talisman that can render you completely invulnerable."
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "talisman"
actions_types = list(/datum/action/item_action/immortality)
var/cooldown = 0
/datum/action/item_action/immortality
name = "Immortality"
/obj/item/device/immortality_talisman/Destroy(force)
if(force)
. = ..()
else
return QDEL_HINT_LETMELIVE
/obj/item/device/immortality_talisman/attack_self(mob/user)
if(cooldown < world.time)
feedback_add_details("immortality_talisman","U") // usage
cooldown = world.time + 600
user.visible_message("<span class='danger'>[user] vanishes from reality, leaving a a hole in their place!</span>")
var/obj/effect/immortality_talisman/Z = new(get_turf(src.loc))
Z.name = "hole in reality"
Z.desc = "It's shaped an awful lot like [user.name]."
Z.setDir(user.dir)
user.forceMove(Z)
user.notransform = 1
user.status_flags |= GODMODE
spawn(100)
user.status_flags &= ~GODMODE
user.notransform = 0
user.forceMove(get_turf(Z))
user.visible_message("<span class='danger'>[user] pops back into reality!</span>")
Z.can_destroy = TRUE
qdel(Z)
else
to_chat(user, "<span class'warning'>[src] is still recharging.</span>")
/obj/effect/immortality_talisman
icon_state = "blank"
icon = 'icons/effects/effects.dmi'
var/can_destroy = FALSE
/obj/effect/immortality_talisman/attackby()
return
/obj/effect/immortality_talisman/ex_act()
return
/obj/effect/immortality_talisman/singularity_pull()
return 0
/obj/effect/immortality_talisman/Destroy(force)
if(!can_destroy && !force)
return QDEL_HINT_LETMELIVE
else
. = ..()
+28 -574
View File
@@ -6,19 +6,21 @@
icon_state = "necrocrate"
icon_opened = "necrocrateopen"
icon_closed = "necrocrate"
burn_state = LAVA_PROOF | FIRE_PROOF
unacidable = 1
/obj/structure/closet/crate/necropolis/tendril
desc = "It's watching you suspiciously."
/obj/structure/closet/crate/necropolis/tendril/New()
..()
// uncomment me once these items are being implemented
/*var/loot = rand(1,25)
var/loot = rand(1,24)
switch(loot)
if(1)
new /obj/item/device/shared_storage/red(src)
if(2)
new /obj/item/clothing/suit/space/hardsuit/cult(src)
new /obj/item/clothing/head/helmet/space/cult(src)
new /obj/item/clothing/suit/space/cult(src)
if(3)
new /obj/item/device/soulstone/anybody(src)
if(4)
@@ -26,593 +28,45 @@
if(5)
new /obj/item/clothing/glasses/godeye(src)
if(6)
new /obj/item/weapon/reagent_containers/glass/bottle/potion/flight(src)
if(7)
new /obj/item/weapon/pickaxe/diamond(src)
if(8)
if(7)
new /obj/item/clothing/head/culthood(src)
new /obj/item/clothing/suit/cultrobes(src)
new /obj/item/clothing/suit/hooded/cultrobes(src)
new /obj/item/weapon/bedsheet/cult(src)
if(8)
new /obj/item/organ/internal/brain/xeno(src)
if(9)
new /obj/item/organ/brain/alien(src)
new /obj/item/organ/internal/heart/cursed(src)
if(10)
new /obj/item/organ/heart/cursed(src)
if(11)
new /obj/item/ship_in_a_bottle(src)
if(11)
new /obj/item/clothing/head/helmet/space/rig/ert/paranormal/berserker(src)
new /obj/item/clothing/suit/space/rig/ert/paranormal/berserker(src)
if(12)
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker(src)
if(13)
new /obj/item/weapon/sord(src)
if(14)
if(13)
new /obj/item/weapon/nullrod/scythe/talking(src)
if(15)
if(14)
new /obj/item/weapon/nullrod/armblade(src)
if(16)
if(15)
new /obj/item/weapon/guardiancreator(src)
if(17)
if(16)
new /obj/item/borg/upgrade/modkit/aoe/turfs/andmobs(src)
if(18)
if(17)
new /obj/item/device/warp_cube/red(src)
if(19)
if(18)
new /obj/item/device/wisp_lantern(src)
if(20)
if(19)
new /obj/item/device/immortality_talisman(src)
if(21)
if(20)
new /obj/item/weapon/gun/magic/hook(src)
if(22)
if(21)
new /obj/item/voodoo(src)
if(23)
if(22)
new /obj/item/weapon/grenade/clusterbuster/inferno(src)
if(24)
if(23)
new /obj/item/weapon/reagent_containers/food/drinks/bottle/holywater/hell(src)
new /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor(src)
if(25)
new /obj/item/weapon/spellbook/oneuse/summonitem(src)*/
///Bosses
//Dragon
/obj/structure/closet/crate/necropolis/dragon
name = "dragon chest"
/obj/structure/closet/crate/necropolis/dragon/New()
..()
var/loot = rand(1,4)
switch(loot)
if(1)
new /obj/item/weapon/melee/ghost_sword(src)
if(2)
new /obj/item/weapon/lava_staff(src)
if(3)
new /obj/item/weapon/spellbook/oneuse/sacredflame(src)
new /obj/item/weapon/gun/magic/wand/fireball(src)
if(4)
new /obj/item/weapon/dragons_blood(src)
/obj/item/weapon/melee/ghost_sword
name = "spectral blade"
desc = "A rusted and dulled blade. It doesn't look like it'd do much damage. It glows weakly."
icon_state = "spectral"
item_state = "spectral"
flags = CONDUCT
sharp = 1
edge = 1
w_class = 4
force = 1
throwforce = 1
hitsound = 'sound/effects/ghost2.ogg'
attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "rended")
var/summon_cooldown = 0
var/list/mob/dead/observer/spirits
/obj/item/weapon/melee/ghost_sword/New()
..()
spirits = list()
processing_objects.Add(src)
poi_list |= src
/obj/item/weapon/melee/ghost_sword/Destroy()
for(var/mob/dead/observer/G in spirits)
G.invisibility = initial(G.invisibility)
spirits.Cut()
processing_objects.Remove(src)
poi_list -= src
. = ..()
/obj/item/weapon/melee/ghost_sword/attack_self(mob/user)
if(summon_cooldown > world.time)
to_chat(user, "You just recently called out for aid. You don't want to annoy the spirits.")
return
to_chat(user, "You call out for aid, attempting to summon spirits to your side.")
notify_ghosts("[user] is raising their [src], calling for your help!", enter_link="<a href=?src=[UID()];follow=1>(Click to help)</a>", source = user, action = NOTIFY_FOLLOW)
summon_cooldown = world.time + 600
/obj/item/weapon/melee/ghost_sword/Topic(href, href_list)
if(href_list["follow"])
var/mob/dead/observer/ghost = usr
if(istype(ghost))
ghost.ManualFollow(src)
/obj/item/weapon/melee/ghost_sword/process()
ghost_check()
/obj/item/weapon/melee/ghost_sword/proc/ghost_check()
var/ghost_counter = 0
var/turf/T = get_turf(src)
var/list/contents = T.GetAllContents()
var/mob/dead/observer/current_spirits = list()
for(var/mob/dead/observer/O in player_list)
if(is_type_in_list(O.following, contents))
ghost_counter++
O.invisibility = 0
current_spirits |= O
for(var/mob/dead/observer/G in spirits - current_spirits)
G.invisibility = initial(G.invisibility)
spirits = current_spirits
return ghost_counter
/obj/item/weapon/melee/ghost_sword/attack(mob/living/target, mob/living/carbon/human/user)
force = 0
var/ghost_counter = ghost_check()
force = Clamp((ghost_counter * 4), 0, 75)
user.visible_message("<span class='danger'>[user] strikes with the force of [ghost_counter] vengeful spirits!</span>")
..()
/obj/item/weapon/melee/ghost_sword/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance, damage, attack_type)
var/ghost_counter = ghost_check()
final_block_chance += Clamp((ghost_counter * 5), 0, 75)
owner.visible_message("<span class='danger'>[owner] is protected by a ring of [ghost_counter] ghosts!</span>")
return ..()
// Blood
/obj/item/weapon/dragons_blood
name = "bottle of dragons blood"
desc = "You're not actually going to drink this, are you?"
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
/obj/item/weapon/dragons_blood/attack_self(mob/living/carbon/human/user)
if(!istype(user))
return
var/mob/living/carbon/human/H = user
var/random = rand(1,3)
switch(random)
if(1)
to_chat(user, "<span class='danger'>Your flesh begins to melt! Miraculously, you seem fine otherwise.</span>")
H.set_species("Skeleton")
if(2)
to_chat(user, "<span class='danger'>Power courses through you! You can now shift your form at will.")
if(user.mind)
var/obj/effect/proc_holder/spell/targeted/shapeshift/dragon/D = new
user.mind.AddSpell(D)
if(3)
to_chat(user, "<span class='danger'>You feel like you could walk straight through lava now.</span>")
H.weather_immunities |= "lava"
playsound(user.loc,'sound/items/drink.ogg', rand(10,50), 1)
qdel(src)
/datum/disease/transformation/dragon
name = "dragon transformation"
cure_text = "nothing"
cures = list("adminordrazine")
agent = "dragon's blood"
desc = "What do dragons have to do with Space Station 13?"
stage_prob = 20
severity = BIOHAZARD
visibility_flags = 0
stage1 = list("Your bones ache.")
stage2 = list("Your skin feels scaley.")
stage3 = list("<span class='danger'>You have an overwhelming urge to terrorize some peasants.</span>", "<span class='danger'>Your teeth feel sharper.</span>")
stage4 = list("<span class='danger'>Your blood burns.</span>")
stage5 = list("<span class='danger'>You're a fucking dragon. However, any previous allegiances you held still apply. It'd be incredibly rude to eat your still human friends for no reason.</span>")
new_form = /mob/living/simple_animal/hostile/megafauna/dragon/lesser
//Lava Staff
/obj/item/weapon/lava_staff
name = "staff of lava"
desc = "The ability to fill the emergency shuttle with lava. What more could you want out of life?"
icon_state = "staffofstorms"
item_state = "staffofstorms"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
item_state = "staffofstorms"
w_class = 4
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
var/turf_type = /turf/unsimulated/floor/lava // /turf/simulated/floor/plating/lava/smooth once Lavaland turfs are added
var/transform_string = "lava"
var/reset_turf_type = /turf/simulated/floor/plating/airless/asteroid // /turf/simulated/floor/plating/asteroid/basalt once Lavaland turfs are added
var/reset_string = "basalt"
var/create_cooldown = 100
var/create_delay = 30
var/reset_cooldown = 50
var/timer = 0
var/banned_turfs
/obj/item/weapon/lava_staff/New()
. = ..()
banned_turfs = typecacheof(list(/turf/space/transit, /turf/unsimulated))
/obj/item/weapon/lava_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
..()
if(timer > world.time)
return
if(is_type_in_typecache(target, banned_turfs))
return
if(target in view(user.client.view, get_turf(user)))
var/turf/simulated/T = get_turf(target)
if(!istype(T))
return
if(!istype(T, turf_type))
var/obj/effect/overlay/temp/lavastaff/L = new /obj/effect/overlay/temp/lavastaff(T)
L.alpha = 0
animate(L, alpha = 255, time = create_delay)
user.visible_message("<span class='danger'>[user] points [src] at [T]!</span>")
timer = world.time + create_delay + 1
if(do_after(user, create_delay, target = T))
user.visible_message("<span class='danger'>[user] turns \the [T] into [transform_string]!</span>")
message_admins("[key_name_admin(user)] fired the lava staff at [get_area(target)] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>).")
log_game("[key_name(user)] fired the lava staff at [get_area(target)] ([T.x], [T.y], [T.z]).")
T.ChangeTurf(turf_type)
timer = world.time + create_cooldown
qdel(L)
else
timer = world.time
qdel(L)
return
else
user.visible_message("<span class='danger'>[user] turns \the [T] into [reset_string]!</span>")
T.ChangeTurf(reset_turf_type)
timer = world.time + reset_cooldown
playsound(T,'sound/magic/Fireball.ogg', 200, 1)
/obj/effect/overlay/temp/lavastaff
icon_state = "lavastaff_warn"
duration = 50
// Bubblegum
/obj/structure/closet/crate/necropolis/bubblegum
name = "bubblegum chest"
/obj/structure/closet/crate/necropolis/bubblegum/New()
..()
var/loot = rand(1,3)
switch(loot)
if(1)
new /obj/item/mayhem(src)
if(2)
new /obj/item/blood_contract(src)
if(3)
new /obj/item/weapon/gun/magic/staff/spellblade(src)
// Mayhem
/obj/item/mayhem
name = "mayhem in a bottle"
desc = "A magically infused bottle of blood, the scent of which will drive anyone nearby into a murderous frenzy."
icon = 'icons/obj/wizard.dmi'
icon_state = "vial"
/obj/item/mayhem/attack_self(mob/user)
for(var/mob/living/carbon/human/H in range(7,user))
spawn()
var/obj/effect/mine/pickup/bloodbath/B = new(H)
B.mineEffect(H)
to_chat(user, "<span class='notice'>You shatter the bottle!</span>")
playsound(user.loc, 'sound/effects/Glassbr1.ogg', 100, 1)
qdel(src)
// Blood Contract
/obj/item/blood_contract
name = "blood contract"
icon = 'icons/obj/wizard.dmi'
icon_state = "scroll2"
color = "#FF0000"
desc = "Mark your target for death."
var/used = FALSE
/obj/item/blood_contract/attack_self(mob/user)
if(used)
return
used = TRUE
var/choice = input(user,"Who do you want dead?","Choose Your Victim") as null|anything in player_list
if(!choice)
used = FALSE
return
else if(!isliving(choice))
to_chat(user, "[choice] is already dead!")
used = FALSE
return
else
var/mob/living/L = choice
message_admins("[key_name_admin(L)] has been marked for death by [key_name_admin(user)].")
log_admin("[key_name(L)] has been marked for death by [key_name(user)].")
var/datum/objective/survive/survive = new
survive.owner = L.mind
L.mind.objectives += survive
to_chat(L, "<span class='userdanger'>You've been marked for death! Don't let the demons get you!</span>")
L.color = "#FF0000"
spawn()
var/obj/effect/mine/pickup/bloodbath/B = new(L)
B.mineEffect(L)
for(var/mob/living/carbon/human/H in player_list)
if(H == L)
continue
to_chat(H, "<span class='userdanger'>You have an overwhelming desire to kill [L]. They have been marked red! Go kill them!</span>")
H.put_in_hands(new /obj/item/weapon/kitchen/knife/butcher(H))
qdel(src)
// Legion
// Staff of Storms
/obj/item/weapon/staff/storm
name = "staff of storms"
desc = "An ancient staff retrieved from the remains of Legion. The wind stirs as you move it."
icon_state = "staffofstorms"
item_state = "staffofstorms"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
item_state = "staffofstorms"
w_class = 4
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
var/storm_type = /datum/weather/ash_storm
var/storm_cooldown = 0
/obj/item/weapon/staff/storm/attack_self(mob/user)
if(storm_cooldown > world.time)
to_chat(user, "<span class='warning'>The staff is still recharging!</span>")
return
var/area/user_area = get_area(user)
var/datum/weather/A
var/z_level_name = space_manager.levels_by_name[user.z]
for(var/V in weather_master.existing_weather)
var/datum/weather/W = V
if(W.target_z == z_level_name && W.area_type == user_area.type)
A = W
break
if(A)
if(A.stage != END_STAGE)
if(A.stage == WIND_DOWN_STAGE)
to_chat(user, "<span class='warning'>The storm is already ending! It would be a waste to use the staff now.</span>")
return
user.visible_message("<span class='warning'>[user] holds [src] skywards as an orange beam travels into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, dispelling the storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.wind_down()
return
else
A = new storm_type
A.name = "staff storm"
A.area_type = user_area.type
A.target_z = z_level_name
A.telegraph_duration = 100
A.end_duration = 100
user.visible_message("<span class='warning'>[user] holds [src] skywards as red lightning crackles into the sky!</span>", \
"<span class='notice'>You hold [src] skyward, calling down a terrible storm!</span>")
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
A.telegraph()
storm_cooldown = world.time + 200
// Hierophant
//Hierophant
/obj/item/weapon/hierophant_staff
name = "Hierophant's staff"
desc = "A large club with intense magic power infused into it."
icon_state = "hierophant_staff"
item_state = "hierophant_staff"
icon = 'icons/obj/guns/magic.dmi'
slot_flags = SLOT_BACK
w_class = 4
force = 20
hitsound = "swing_hit"
//hitsound = 'sound/weapons/sonic_jackhammer.ogg'
actions_types = list(/datum/action/item_action/vortex_recall, /datum/action/item_action/toggle_unfriendly_fire)
var/cooldown_time = 20 //how long the cooldown between non-melee ranged attacks is
var/chaser_cooldown = 101 //how long the cooldown between firing chasers at mobs is
var/chaser_timer = 0 //what our current chaser cooldown is
var/timer = 0 //what our current cooldown is
var/blast_range = 3 //how long the cardinal blast's walls are
var/obj/effect/hierophant/rune //the associated rune we teleport to
var/teleporting = FALSE //if we ARE teleporting
var/friendly_fire_check = FALSE //if the blasts we make will consider our faction against the faction of hit targets
/obj/item/weapon/hierophant_staff/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
..()
var/turf/T = get_turf(target)
if(!T || timer > world.time)
return
timer = world.time + CLICK_CD_MELEE //by default, melee attacks only cause melee blasts, and have an accordingly short cooldown
if(proximity_flag)
spawn(0)
aoe_burst(T, user)
add_logs(user, target, "fired 3x3 blast at", src)
else
if(ismineralturf(target) && get_dist(user, target) < 6) //target is minerals, we can hit it(even if we can't see it)
spawn(0)
cardinal_blasts(T, user)
timer = world.time + cooldown_time
else if(target in view(5, get_turf(user))) //if the target is in view, hit it
timer = world.time + cooldown_time
if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one!
chaser_timer = world.time + chaser_cooldown
new /obj/effect/overlay/temp/hierophant/chaser(get_turf(user), user, target, 1.5, friendly_fire_check)
add_logs(user, target, "fired a chaser at", src)
else
spawn(0)
cardinal_blasts(T, user) //otherwise, just do cardinal blast
add_logs(user, target, "fired cardinal blast at", src)
else
to_chat(user, "<span class='warning'>That target is out of range!</span>") //too far away
/obj/item/weapon/hierophant_staff/ui_action_click(mob/user, actiontype)
if(actiontype == /datum/action/item_action/toggle_unfriendly_fire) //toggle friendly fire...
friendly_fire_check = !friendly_fire_check
to_chat(user, "<span class='warning'>You toggle friendly fire [friendly_fire_check ? "off":"on"]!</span>")
return
if(user.get_active_hand() != src && user.get_inactive_hand() != src) //you need to hold the staff to teleport
to_chat(user, "<span class='warning'>You need to hold the staff in your hands to [rune ? "teleport with it" : "create a rune"]!</span>")
return
if(!rune)
if(isturf(user.loc))
user.visible_message("<span class='hierophant_warning'>[user] holds [src] carefully in front of them, moving it in a strange pattern...</span>", \
"<span class='notice'>You start creating a hierophant rune to teleport to...</span>")
timer = world.time + 51
if(do_after(user, 50, target = user))
var/turf/T = get_turf(user)
playsound(T,'sound/magic/Blind.ogg', 200, 1, -4)
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(T, user)
var/obj/effect/hierophant/H = new/obj/effect/hierophant(T)
rune = H
user.update_action_buttons_icon()
user.visible_message("<span class='hierophant_warning'>[user] creates a strange rune beneath them!</span>", \
"<span class='hierophant'>You create a hierophant rune, which you can teleport yourself and any allies to at any time!</span>\n\
<span class='notice'>You can remove the rune to place a new one by striking it with the staff.</span>")
else
timer = world.time
else
to_chat(user, "<span class='warning'>You need to be on solid ground to produce a rune!</span>")
return
if(get_dist(user, rune) <= 2) //rune too close abort
to_chat(user, "<span class='warning'>You are too close to the rune to teleport to it!</span>")
return
if(is_blocked_turf(get_turf(rune)))
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
return
teleporting = TRUE //start channel
user.update_action_buttons_icon()
user.visible_message("<span class='hierophant_warning'>[user] starts to glow faintly...</span>")
timer = world.time + 50
if(do_after(user, 40, target = user) && rune)
var/turf/T = get_turf(rune)
var/turf/source = get_turf(user)
if(is_blocked_turf(T))
teleporting = FALSE
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
user.update_action_buttons_icon()
return
new /obj/effect/overlay/temp/hierophant/telegraph(T, user)
new /obj/effect/overlay/temp/hierophant/telegraph(source, user)
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/magic/Wand_Teleport.ogg', 200, 1)
playsound(source,'sound/magic/blink.ogg', 200, 1)
//playsound(source,'sound/machines/AirlockOpen.ogg', 200, 1)
if(!do_after(user, 3, target = user) || !rune) //no walking away shitlord
teleporting = FALSE
if(user)
user.update_action_buttons_icon()
return
if(is_blocked_turf(T))
teleporting = FALSE
to_chat(user, "<span class='warning'>The rune is blocked by something, preventing teleportation!</span>")
user.update_action_buttons_icon()
return
add_logs(user, rune, "teleported self from ([source.x],[source.y],[source.z]) to")
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(T, user)
new /obj/effect/overlay/temp/hierophant/telegraph/teleport(source, user)
for(var/t in RANGE_TURFS(1, T))
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE) //blasts produced will not hurt allies
B.damage = 30
for(var/t in RANGE_TURFS(1, source))
var/obj/effect/overlay/temp/hierophant/blast/B = new /obj/effect/overlay/temp/hierophant/blast(t, user, TRUE) //but absolutely will hurt enemies
B.damage = 30
for(var/mob/living/L in range(1, source))
spawn(0)
teleport_mob(source, L, T, user) //regardless, take all mobs near us along
sleep(6) //at this point the blasts detonate
else
timer = world.time
teleporting = FALSE
if(user)
user.update_action_buttons_icon()
/obj/item/weapon/hierophant_staff/proc/teleport_mob(turf/source, mob/M, turf/target, mob/user)
var/turf/turf_to_teleport_to = get_step(target, get_dir(source, M)) //get position relative to caster
if(!turf_to_teleport_to || is_blocked_turf(turf_to_teleport_to))
return
animate(M, alpha = 0, time = 2, easing = EASE_OUT) //fade out
sleep(1)
if(!M)
return
M.visible_message("<span class='hierophant_warning'>[M] fades out!</span>")
sleep(2)
if(!M)
return
M.forceMove(turf_to_teleport_to)
sleep(1)
if(!M)
return
animate(M, alpha = 255, time = 2, easing = EASE_IN) //fade IN
sleep(1)
if(!M)
return
M.visible_message("<span class='hierophant_warning'>[M] fades in!</span>")
if(user != M)
add_logs(user, M, "teleported", null, "from ([source.x],[source.y],[source.z])")
/obj/item/weapon/hierophant_staff/proc/cardinal_blasts(turf/T, mob/living/user) //fire cardinal cross blasts with a delay
if(!T)
return
new /obj/effect/overlay/temp/hierophant/telegraph/cardinal(T, user)
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
new /obj/effect/overlay/temp/hierophant/blast(T, user, friendly_fire_check)
for(var/d in cardinal)
spawn(0)
blast_wall(T, d, user)
/obj/item/weapon/hierophant_staff/proc/blast_wall(turf/T, dir, mob/living/user) //make a wall of blasts blast_range tiles long
if(!T)
return
var/range = blast_range
var/turf/previousturf = T
var/turf/J = get_step(previousturf, dir)
for(var/i in 1 to range)
if(!J)
return
new /obj/effect/overlay/temp/hierophant/blast(J, user, friendly_fire_check)
previousturf = J
J = get_step(previousturf, dir)
/obj/item/weapon/hierophant_staff/proc/aoe_burst(turf/T, mob/living/user) //make a 3x3 blast around a target
if(!T)
return
new /obj/effect/overlay/temp/hierophant/telegraph(T, user)
playsound(T,'sound/magic/blink.ogg', 200, 1)
//playsound(T,'sound/effects/bin_close.ogg', 200, 1)
sleep(2)
for(var/t in RANGE_TURFS(1, T))
new /obj/effect/overlay/temp/hierophant/blast(t, user, friendly_fire_check)
new /obj/item/clothing/head/helmet/space/rig/ert/paranormal/inquisitor(src)
new /obj/item/clothing/suit/space/rig/ert/paranormal/inquisitor(src)
if(24)
new /obj/item/weapon/spellbook/oneuse/summonitem(src)
-1
View File
@@ -200,7 +200,6 @@
/obj/structure/closet/crate/miningcar
desc = "A mining car. This one doesn't work on rails, but has to be dragged."
name = "mining car (not for rails)"
icon = 'icons/obj/storage.dmi'
icon_state = "miningcar"
density = 1
icon_opened = "miningcaropen"
-4
View File
@@ -14,10 +14,6 @@
/mob/camera/experience_pressure_difference()
return
/mob/camera/Destroy()
..()
return QDEL_HINT_HARDDEL_NOW
/mob/camera/Login()
..()
update_interface()
+1 -1
View File
@@ -309,7 +309,7 @@
Stun(2)
var/obj/item/organ/internal/eyes/E = get_int_organ(/obj/item/organ/internal/eyes)
if(!E)
if(!E || (E && E.weld_proof))
return
switch(damage)
@@ -721,8 +721,6 @@
if(istype(id))
return id
/mob/living/carbon/human/update_sight()
if(!client)
return
@@ -1533,12 +1531,6 @@
if(species.default_language)
add_language(species.default_language)
see_in_dark = species.darksight
if(see_in_dark > 2)
see_invisible = SEE_INVISIBLE_LEVEL_ONE
else
see_invisible = SEE_INVISIBLE_LIVING
hunger_drain = species.hunger_drain
digestion_ratio = species.digestion_ratio
@@ -1608,8 +1600,17 @@
dna.real_name = real_name
species.handle_post_spawn(src)
see_in_dark = species.get_resultant_darksight(src)
if(see_in_dark > 2)
see_invisible = SEE_INVISIBLE_LEVEL_ONE
else
see_invisible = SEE_INVISIBLE_LIVING
species.handle_dna(src) //Give them whatever special dna business they got.
update_client_colour(0)
spawn(0)
overlays.Cut()
update_mutantrace(1)
@@ -1632,7 +1633,6 @@
return null
return species.default_language ? all_languages[species.default_language] : null
/mob/living/carbon/human/proc/bloody_doodle()
set category = "IC"
set name = "Write in blood"
@@ -119,6 +119,7 @@
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
update_sight()
update_inv_glasses()
update_client_colour()
else if(I == head)
head = null
if(I.flags & BLOCKHAIR || I.flags & BLOCKHEADHAIR)
@@ -271,6 +272,7 @@
if(G.vision_flags || G.darkness_view || G.invis_override || G.invis_view)
update_sight()
update_inv_glasses(redraw_mob)
update_client_colour()
if(slot_gloves)
gloves = W
update_inv_gloves(redraw_mob)
@@ -7,8 +7,16 @@
language = "Abductor Mindlink"
default_language = "Abductor Mindlink"
unarmed_type = /datum/unarmed_attack/punch
darksight = 3
eyes = "blank_eyes"
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"liver" = /obj/item/organ/internal/liver,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/abductor //3 darksight.
)
flags = HAS_LIPS | NO_BLOOD | NO_BREATHE
@@ -9,7 +9,6 @@
punchdamagelow = 0
punchdamagehigh = 1
//primitive = /mob/living/carbon/monkey/wryn
darksight = 3
slowdown = 1
warning_low_pressure = -300
hazard_low_pressure = 1
@@ -32,7 +31,7 @@
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"brain" = /obj/item/organ/internal/brain,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes/wryn, //3 darksight.
"appendix" = /obj/item/organ/internal/appendix,
"antennae" = /obj/item/organ/internal/wryn/hivenode
)
@@ -89,7 +88,7 @@
name_plural = "Nucleations"
icobase = 'icons/mob/human_races/r_nucleation.dmi'
unarmed_type = /datum/unarmed_attack/punch
blurb = "A sub-race of unforunates who have been exposed to too much supermatter radiation. As a result, \
blurb = "A sub-race of unfortunates who have been exposed to too much supermatter radiation. As a result, \
supermatter crystal clusters have begun to grow across their bodies. Research to find a cure for this ailment \
has been slow, and so this is a common fate for veteran engineers. The supermatter crystals produce oxygen, \
negating the need for the individual to breathe. Their massive change in biology, however, renders most medicines \
@@ -109,8 +108,8 @@
reagent_tag = PROCESS_ORG
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"crystalized brain" = /obj/item/organ/internal/brain/crystal,
"eyes" = /obj/item/organ/internal/eyes/luminescent_crystal,
"crystallized brain" = /obj/item/organ/internal/brain/crystal,
"eyes" = /obj/item/organ/internal/eyes/luminescent_crystal, //Standard darksight of 2.
"strange crystal" = /obj/item/organ/internal/nucleation/strange_crystal,
"resonant crystal" = /obj/item/organ/internal/nucleation/resonant_crystal
)
@@ -40,7 +40,8 @@
has_organ = list(
"brain" = /obj/item/organ/internal/brain/golem
)
) //Has standard darksight of 2.
suicide_messages = list(
"is crumbling into dust!",
"is smashing their body apart!")
@@ -26,6 +26,7 @@
tail = "chimptail"
bodyflags = FEET_PADDED | HAS_TAIL
reagent_tag = PROCESS_ORG
//Has standard darksight of 2.
//unarmed_types = list(/datum/unarmed_attack/bite, /datum/unarmed_attack/claws)
//inherent_verbs = list(/mob/living/proc/ventcrawl)
@@ -54,7 +55,7 @@
/datum/species/monkey/handle_dna(var/mob/living/carbon/human/H)
H.dna.SetSEState(MONKEYBLOCK,1)
genemutcheck(H, MONKEYBLOCK)
genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED)
/datum/species/monkey/handle_can_equip(obj/item/I, slot, disable_warning = 0, mob/living/carbon/human/user)
switch(slot)
@@ -105,6 +106,15 @@
base_color = "#000000"
tail = "farwatail"
reagent_tag = PROCESS_ORG
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"liver" = /obj/item/organ/internal/liver/tajaran,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/tajaran/farwa //Tajara monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
/datum/species/monkey/vulpkanin
@@ -120,6 +130,15 @@
base_color = "#000000"
tail = "wolpintail"
reagent_tag = PROCESS_ORG
has_organ = list(
"heart" = /obj/item/organ/internal/heart,
"lungs" = /obj/item/organ/internal/lungs,
"liver" = /obj/item/organ/internal/liver/vulpkanin,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes/vulpkanin/wolpin //Vulpkanin monkey-forms are uniquely colourblind and have excellent darksight, which is why they need a subtype of their greater-form's organ..
)
/datum/species/monkey/skrell
@@ -20,6 +20,8 @@
heat_level_2 = 400 // Heat damage level 2 above this point.
heat_level_3 = 500 // Heat damage level 3 above this point.
//Has default darksight of 2.
suicide_messages = list(
"is twisting their own neck!",
"is letting some O2 in!",
@@ -7,15 +7,14 @@
default_language = "Galactic Common"
unarmed_type = /datum/unarmed_attack/claws
darksight = 8
ignored_by = list(/mob/living/simple_animal/hostile/faithless)
blood_color = "#CCCCCC"
flesh_color = "#AAAAAA"
has_organ = list(
"brain" = /obj/item/organ/internal/brain
"brain" = /obj/item/organ/internal/brain,
"eyes" = /obj/item/organ/internal/eyes/shadow //8 darksight.
)
flags = NO_BLOOD | NO_BREATHE | RADIMMUNE
@@ -23,7 +22,7 @@
oxy_mod = 0
virus_immune = 1
dietflags = DIET_OMNI //the mutation process allowed you to now digest all foods regardless of initial race
reagent_tag = PROCESS_ORG
suicide_messages = list(
@@ -31,10 +30,10 @@
"is jamming their claws into their eye sockets!",
"is twisting their own neck!",
"is staring into the closest light source!")
var/grant_vision_toggle = 1
var/datum/action/innate/shadow/darkvision/vision_toggle
/datum/action/innate/shadow/darkvision //Darkvision toggle so shadowpeople can actually see where darkness is
name = "Toggle Darkvision"
check_flags = AB_CHECK_CONSCIOUS
@@ -49,13 +48,13 @@
else
H.vision_type = null
to_chat(H, "<span class='notice'>You adjust your vision to recognize the shadows.</span>")
/datum/species/shadow/grant_abilities(var/mob/living/carbon/human/H)
. = ..()
if(grant_vision_toggle)
vision_toggle = new
vision_toggle.Grant(H)
/datum/species/shadow/remove_abilities(var/mob/living/carbon/human/H)
. = ..()
if(grant_vision_toggle && vision_toggle)
@@ -41,7 +41,7 @@
"is twisting their skull off!")
has_organ = list(
"brain" = /obj/item/organ/internal/brain/golem,
)
) //Has default darksight of 2.
/datum/species/skeleton/handle_reagents(var/mob/living/carbon/human/H, var/datum/reagent/R)
// Crazylemon is still silly
@@ -49,8 +49,7 @@
var/siemens_coeff = 1 //base electrocution coefficient
var/invis_sight = SEE_INVISIBLE_LIVING
var/darksight = 2
var/hazard_high_pressure = HAZARD_HIGH_PRESSURE // Dangerously high pressure.
var/warning_high_pressure = WARNING_HIGH_PRESSURE // High pressure warning.
var/warning_low_pressure = WARNING_LOW_PRESSURE // Low pressure warning.
@@ -85,7 +84,7 @@
var/ventcrawler = 0 //Determines if the mob can go through the vents.
var/has_fine_manipulation = 1 // Can use small items.
var/mob/living/list/ignored_by = list() // list of mobs that will ignore this species
var/list/allowed_consumed_mobs = list() //If a species can consume mobs, put the type of mobs it can consume here.
@@ -588,12 +587,23 @@ It'll return null if the organ doesn't correspond, so include null checks when u
return null
return has_organ[organ_slot]
/datum/species/proc/get_resultant_darksight(mob/living/carbon/human/H) //Returns default value of 2 if the mob doesn't have eyes, otherwise it grabs the eyes darksight.
var/resultant_darksight = 2
var/obj/item/organ/internal/eyes/eyes = H.get_int_organ(/obj/item/organ/internal/eyes)
if(eyes)
resultant_darksight = eyes.get_dark_view()
return resultant_darksight
/datum/species/proc/update_sight(mob/living/carbon/human/H)
H.sight = initial(H.sight)
H.see_in_dark = darksight
H.see_in_dark = get_resultant_darksight(H)
H.see_invisible = invis_sight
if(H.see_in_dark > 2) //Preliminary see_invisible handling as per set_species() in code\modules\mob\living\carbon\human\human.dm.
H.see_invisible = SEE_INVISIBLE_LEVEL_ONE
else
H.see_invisible = SEE_INVISIBLE_LIVING
if(H.client.eye != H)
var/atom/A = H.client.eye
if(A.update_remote_sight(H)) //returns 1 if we override all other sight updates.
@@ -644,7 +654,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u
if(rig.visor && rig.visor.vision && rig.visor.active && rig.visor.vision.glasses)
var/obj/item/clothing/glasses/G = rig.visor.vision.glasses
if(istype(G))
H.see_in_dark = (G.darkness_view ? G.darkness_view : darksight) // Otherwise we keep our darkness view with togglable nightvision.
H.see_in_dark = (G.darkness_view ? G.darkness_view : get_resultant_darksight(H)) // Otherwise we keep our darkness view with togglable nightvision.
if(G.vision_flags) // MESONS
H.sight |= G.vision_flags
@@ -654,7 +664,7 @@ It'll return null if the organ doesn't correspond, so include null checks when u
H.see_in_dark = max(lesser_darkview_bonus, H.see_in_dark)
if(H.vision_type)
H.see_in_dark = max(H.see_in_dark, H.vision_type.see_in_dark, darksight)
H.see_in_dark = max(H.see_in_dark, H.vision_type.see_in_dark, get_resultant_darksight(H))
H.see_invisible = H.vision_type.see_invisible
if(H.vision_type.light_sensitive)
H.weakeyes = 1
@@ -18,6 +18,7 @@
worlds tumultous at best."
reagent_tag = PROCESS_ORG
//Has standard darksight of 2.
/datum/species/unathi
name = "Unathi"
@@ -30,7 +31,6 @@
tail = "sogtail"
unarmed_type = /datum/unarmed_attack/claws
primitive_form = "Stok"
darksight = 3
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
Uuosa-Eso system, which roughly translates to 'burning mother'.<br/><br/>Coming from a harsh, radioactive \
@@ -66,7 +66,7 @@
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes/unathi //3 darksight.
)
allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken,
@@ -91,7 +91,6 @@
language = "Siik'tajr"
tail = "tajtail"
unarmed_type = /datum/unarmed_attack/claws
darksight = 8
blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \
S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \
@@ -126,7 +125,8 @@
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes/tajaran /*Most Tajara see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2)
unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/
)
allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/chick, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/parrot,
@@ -152,7 +152,6 @@
primitive_form = "Wolpin"
tail = "vulptail"
unarmed_type = /datum/unarmed_attack/claws
darksight = 8
blurb = "Vulpkanin are a species of sharp-witted canine-pideds residing on the planet Altam just barely within the \
dual-star Vazzend system. Their politically de-centralized society and independent natures have led them to become a species and \
@@ -176,7 +175,8 @@
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes/vulpkanin /*Most Vulpkanin see in full colour as a result of genetic augmentation, although it cost them their darksight (darksight = 2)
unless they choose otherwise by selecting the colourblind disability in character creation (darksight = 8 but colourblind).*/
)
allowed_consumed_mobs = list(/mob/living/simple_animal/mouse, /mob/living/simple_animal/lizard, /mob/living/simple_animal/chick, /mob/living/simple_animal/chicken,
@@ -226,7 +226,7 @@
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes //Default darksight of 2.
)
suicide_messages = list(
@@ -315,7 +315,7 @@
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2.
"stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used
) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ.
@@ -439,7 +439,7 @@
"liver" = /obj/item/organ/internal/liver,
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes, //Default darksight of 2.
"stack" = /obj/item/organ/internal/stack/vox //Not the same as the cortical stack implant Vox Raiders spawn with. The cortical stack implant is used
) //for determining the success of the heist game-mode's 'leave nobody behind' objective, while this is just an organ.
@@ -478,7 +478,7 @@
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes //Default darksight of 2.
)
allowed_consumed_mobs = list(/mob/living/simple_animal/diona)
@@ -517,6 +517,7 @@
exotic_blood = "water"
//ventcrawler = 1 //ventcrawling commented out
butt_sprite = "slime"
//Has default darksight of 2.
has_organ = list(
"brain" = /obj/item/organ/internal/brain/slime
@@ -685,7 +686,6 @@
default_language = "Galactic Common"
language = "Psionic Communication"
unarmed_type = /datum/unarmed_attack/punch
darksight = 5 // BOOSTED from 2
eyes = "grey_eyes_s"
butt_sprite = "grey"
@@ -696,7 +696,7 @@
"kidneys" = /obj/item/organ/internal/kidneys,
"brain" = /obj/item/organ/internal/brain/grey,
"appendix" = /obj/item/organ/internal/appendix,
"eyes" = /obj/item/organ/internal/eyes,
"eyes" = /obj/item/organ/internal/eyes/grey //5 darksight.
)
brute_mod = 1.25 //greys are fragile
@@ -714,11 +714,9 @@
/datum/species/grey/handle_dna(var/mob/living/carbon/C, var/remove)
if(!remove)
C.dna.SetSEState(REMOTETALKBLOCK,1,1)
C.mutations |= REMOTE_TALK
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
else
C.dna.SetSEState(REMOTETALKBLOCK,0,1)
C.mutations -= REMOTE_TALK
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
..()
@@ -771,13 +769,13 @@
has_organ = list(
"nutrient channel" = /obj/item/organ/internal/liver/diona,
"neural strata" = /obj/item/organ/internal/heart/diona,
"receptor node" = /obj/item/organ/internal/diona_receptor,
"receptor node" = /obj/item/organ/internal/eyes/diona, //Default darksight of 2.
"gas bladder" = /obj/item/organ/internal/brain/diona,
"polyp segment" = /obj/item/organ/internal/kidneys/diona,
"anchoring ligament" = /obj/item/organ/internal/appendix/diona
)
vision_organ = /obj/item/organ/internal/diona_receptor
vision_organ = /obj/item/organ/internal/eyes/diona
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest/diona),
"groin" = list("path" = /obj/item/organ/external/groin/diona),
@@ -883,10 +881,10 @@
has_organ = list(
"brain" = /obj/item/organ/internal/brain/mmi_holder/posibrain,
"cell" = /obj/item/organ/internal/cell,
"optics" = /obj/item/organ/internal/optical_sensor
"optics" = /obj/item/organ/internal/eyes/optical_sensor //Default darksight of 2.
)
vision_organ = /obj/item/organ/internal/optical_sensor
vision_organ = /obj/item/organ/internal/eyes/optical_sensor
has_limbs = list(
"chest" = list("path" = /obj/item/organ/external/chest/ipc),
"groin" = list("path" = /obj/item/organ/external/groin/ipc),
@@ -932,7 +930,6 @@
language = "Orluum"
unarmed_type = /datum/unarmed_attack/punch
eyes = "drask_eyes_s"
darksight = 5
speech_sounds = list('sound/voice/DraskTalk.ogg')
speech_chance = 20
@@ -982,7 +979,7 @@
"heart" = /obj/item/organ/internal/heart/drask,
"lungs" = /obj/item/organ/internal/lungs/drask,
"metabolic strainer" = /obj/item/organ/internal/liver/drask,
"eyes" = /obj/item/organ/internal/eyes/drask,
"eyes" = /obj/item/organ/internal/eyes/drask, //5 darksight.
"brain" = /obj/item/organ/internal/brain/drask
)
+22 -21
View File
@@ -2,9 +2,8 @@
/mob/living/Destroy()
if(ranged_ability)
ranged_ability.remove_ranged_ability(src)
..()
return QDEL_HINT_HARDDEL_NOW
return ..()
/mob/living/ghostize(can_reenter_corpse = 1)
var/prev_client = client
if(..())
@@ -48,14 +47,14 @@
set category = "Object"
if(AM.Adjacent(src))
src.start_pulling(AM)
start_pulling(AM)
return
//same as above
/mob/living/pointed(atom/A as mob|obj|turf in view())
if(incapacitated())
return 0
if(src.status_flags & FAKEDEATH)
if(status_flags & FAKEDEATH)
return 0
if(!..())
return 0
@@ -78,7 +77,7 @@
to_chat(src, "<span class='notice'>You have given up life and succumbed to death.</span>")
/mob/living/proc/InCritical()
return (src.health < 0 && src.health > -95.0 && stat == UNCONSCIOUS)
return (health < 0 && health > -95.0 && stat == UNCONSCIOUS)
/mob/living/ex_act(severity)
..()
@@ -114,7 +113,7 @@
if(actual < desired)
temperature = desired
// if(istype(src, /mob/living/carbon/human))
// to_chat(world, "[src] ~ [src.bodytemperature] ~ [temperature]")
// to_chat(world, "[src] ~ [bodytemperature] ~ [temperature]")
return temperature
@@ -228,29 +227,31 @@
else
L += src.contents
for(var/obj/item/weapon/storage/S in src.contents) //Check for storage items
L += contents
for(var/obj/item/weapon/storage/S in contents) //Check for storage items
L += get_contents(S)
for(var/obj/item/clothing/suit/storage/S in src.contents)//Check for labcoats and jackets
for(var/obj/item/clothing/suit/storage/S in contents)//Check for labcoats and jackets
L += get_contents(S)
for(var/obj/item/clothing/accessory/storage/S in src.contents)//Check for holsters
for(var/obj/item/clothing/accessory/storage/S in contents)//Check for holsters
L += get_contents(S)
for(var/obj/item/weapon/gift/G in src.contents) //Check for gift-wrapped items
for(var/obj/item/weapon/implant/storage/I in contents) //Check for storage implants.
L += I.get_contents()
for(var/obj/item/weapon/gift/G in contents) //Check for gift-wrapped items
L += G.gift
if(istype(G.gift, /obj/item/weapon/storage))
L += get_contents(G.gift)
for(var/obj/item/smallDelivery/D in src.contents) //Check for package wrapped items
for(var/obj/item/smallDelivery/D in contents) //Check for package wrapped items
L += D.wrapped
if(istype(D.wrapped, /obj/item/weapon/storage)) //this should never happen
L += get_contents(D.wrapped)
for(var/obj/item/weapon/folder/F in src.contents)
for(var/obj/item/weapon/folder/F in contents)
L += F.contents //Folders can't store any storage items.
return L
/mob/living/proc/check_contents_for(A)
var/list/L = src.get_contents()
var/list/L = get_contents()
for(var/obj/B in L)
if(B.type == A)
@@ -273,27 +274,27 @@
/mob/living/proc/heal_organ_damage(var/brute, var/burn)
adjustBruteLoss(-brute)
adjustFireLoss(-burn)
src.updatehealth()
updatehealth()
// damage ONE external organ, organ gets randomly selected from damaged ones.
/mob/living/proc/take_organ_damage(var/brute, var/burn)
if(status_flags & GODMODE) return 0 //godmode
adjustBruteLoss(brute)
adjustFireLoss(burn)
src.updatehealth()
updatehealth()
// heal MANY external organs, in random order
/mob/living/proc/heal_overall_damage(var/brute, var/burn)
adjustBruteLoss(-brute)
adjustFireLoss(-burn)
src.updatehealth()
updatehealth()
// damage MANY external organs, in random order
/mob/living/proc/take_overall_damage(var/brute, var/burn, var/used_weapon = null)
if(status_flags & GODMODE) return 0 //godmode
adjustBruteLoss(brute)
adjustFireLoss(burn)
src.updatehealth()
updatehealth()
/mob/living/proc/has_organic_damage()
return (maxHealth - health)
@@ -367,7 +368,7 @@
if(buckled) //Unbuckle the mob and clear the alerts.
buckled.buckled_mob = null
buckled = null
anchored = initial(src.anchored)
anchored = initial(anchored)
update_canmove()
clear_alert("buckled")
post_buckle_mob(src)
@@ -655,7 +656,7 @@
// The src mob is trying to place an item on someone
// Override if a certain mob should be behave differently when placing items (can't, for example)
/mob/living/stripPanelEquip(obj/item/what, mob/who, where, var/silent = 0)
what = src.get_active_hand()
what = get_active_hand()
if(what && (what.flags & NODROP))
to_chat(src, "<span class='warning'>You can't put \the [what.name] on [who], it's stuck to your hand!</span>")
return
+3 -1
View File
@@ -52,5 +52,7 @@
var/list/surgeries = list() //a list of surgery datums. generally empty, they're added when the player wants them.
var/gene_stability = DEFAULT_GENE_STABILITY
var/obj/effect/proc_holder/ranged_ability //Any ranged ability the mob has, as a click override
var/list/say_log = list() //a log of what we've said, plain text, no spans or junk, essentially just each individual "message"
+4 -1
View File
@@ -149,7 +149,7 @@ proc/get_radio_key_from_channel(var/channel)
if(speaking && (speaking.flags & HIVEMIND))
speaking.broadcast(src,trim(message))
return 1
if(message_mode == "cords")
if(iscarbon(src))
var/mob/living/carbon/C = src
@@ -282,6 +282,9 @@ proc/get_radio_key_from_channel(var/channel)
if(O) //It's possible that it could be deleted in the meantime.
O.hear_talk(src, message, verb, speaking)
//Log of what we've said, plain message, no spans or junk
say_log += message
log_say("[name]/[key] : [message]")
return 1
@@ -47,17 +47,17 @@
real_name = name
add_language("Rootspeak")
src.verbs += /mob/living/simple_animal/diona/proc/merge
verbs += /mob/living/simple_animal/diona/proc/merge
/mob/living/simple_animal/diona/attack_hand(mob/living/carbon/human/M as mob)
/mob/living/simple_animal/diona/attack_hand(mob/living/carbon/human/M)
//Let people pick the little buggers up.
if(M.a_intent == I_HELP)
if(M.species && M.species.name == "Diona")
to_chat(M, "You feel your being twine with that of [src] as it merges with your biomass.")
to_chat(src, "You feel your being twine with that of [M] as you merge with its biomass.")
src.verbs += /mob/living/simple_animal/diona/proc/split
src.verbs -= /mob/living/simple_animal/diona/proc/merge
src.forceMove(M)
verbs += /mob/living/simple_animal/diona/proc/split
verbs -= /mob/living/simple_animal/diona/proc/merge
forceMove(M)
else
get_scooped(M)
@@ -68,32 +68,34 @@
set name = "Merge with gestalt"
set desc = "Merge with another diona."
if(istype(src.loc,/mob/living/carbon))
src.verbs -= /mob/living/simple_animal/diona/proc/merge
if(iscarbon(loc))
verbs -= /mob/living/simple_animal/diona/proc/merge
return
var/list/choices = list()
for(var/mob/living/carbon/C in view(1,src))
if(!(src.Adjacent(C)) || !(C.client)) continue
if(!(Adjacent(C)) || !(C.client))
continue
if(istype(C,/mob/living/carbon/human))
if(ishuman(C))
var/mob/living/carbon/human/D = C
if(D.species && D.species.name == "Diona")
choices += C
var/mob/living/M = input(src,"Who do you wish to merge with?") in null|choices
if(!M || !src || !(src.Adjacent(M))) return
if(!M || !src || !(Adjacent(M)))
return
if(istype(M,/mob/living/carbon/human))
if(ishuman(M))
to_chat(M, "You feel your being twine with that of [src] as it merges with your biomass.")
M.status_flags |= PASSEMOTES
to_chat(src, "You feel your being twine with that of [M] as you merge with its biomass.")
src.loc = M
src.verbs += /mob/living/simple_animal/diona/proc/split
src.verbs -= /mob/living/simple_animal/diona/proc/merge
forceMove(M)
verbs += /mob/living/simple_animal/diona/proc/split
verbs -= /mob/living/simple_animal/diona/proc/merge
else
return
@@ -102,61 +104,25 @@
set name = "Split from gestalt"
set desc = "Split away from your gestalt as a lone nymph."
if(!(istype(src.loc,/mob/living/carbon)))
src.verbs -= /mob/living/simple_animal/diona/proc/split
if(!(iscarbon(loc)))
verbs -= /mob/living/simple_animal/diona/proc/split
return
to_chat(src.loc, "You feel a pang of loss as [src] splits away from your biomass.")
to_chat(src, "You wiggle out of the depths of [src.loc]'s biomass and plop to the ground.")
to_chat(loc, "You feel a pang of loss as [src] splits away from your biomass.")
to_chat(src, "You wiggle out of the depths of [loc]'s biomass and plop to the ground.")
var/mob/living/M = src.loc
var/mob/living/M = loc
src.loc = get_turf(src)
src.verbs -= /mob/living/simple_animal/diona/proc/split
src.verbs += /mob/living/simple_animal/diona/proc/merge
forceMove(get_turf(src))
verbs -= /mob/living/simple_animal/diona/proc/split
verbs += /mob/living/simple_animal/diona/proc/merge
if(istype(M))
for(var/atom/A in M.contents)
if(istype(A,/mob/living/simple_animal/borer) || istype(A,/obj/item/weapon/holder))
if(istype(A, /mob/living/simple_animal/borer) || istype(A, /obj/item/weapon/holder))
return
M.status_flags &= ~PASSEMOTES
/mob/living/simple_animal/diona/verb/fertilize_plant()
set category = "Diona"
set name = "Fertilize plant"
set desc = "Turn your food into nutrients for plants."
var/list/trays = list()
for(var/obj/machinery/hydroponics/tray in range(1))
if(tray.nutrilevel < 10)
trays += tray
var/obj/machinery/hydroponics/target = input("Select a tray:") as null|anything in trays
if(!src || !target || target.nutrilevel == 10) return //Sanity check.
src.nutrition -= ((10-target.nutrilevel)*5)
target.adjustNutri(10)
src.visible_message("<span class='danger'>[src] secretes a trickle of green liquid from its tail, refilling [target]'s nutrient tray.","\red You secrete a trickle of green liquid from your tail, refilling [target]'s nutrient tray.</span>")
/mob/living/simple_animal/diona/verb/eat_weeds()
set category = "Diona"
set name = "Eat Weeds"
set desc = "Clean the weeds out of soil or a hydroponics tray."
var/list/trays = list()
for(var/obj/machinery/hydroponics/tray in range(1))
if(tray.weedlevel > 0)
trays += tray
var/obj/machinery/hydroponics/target = input("Select a tray:") as null|anything in trays
if(!src || !target || target.weedlevel == 0) return //Sanity check.
src.nutrition += target.weedlevel * 15
target.adjustWeeds(-10)
src.visible_message("<span class='danger'>[src] begins rooting through [target], ripping out weeds and eating them noisily.</span>","<span class='danger'>You begin rooting through [target], ripping out weeds and eating them noisily.</span>")
/mob/living/simple_animal/diona/verb/evolve()
set category = "Diona"
set name = "Evolve"
@@ -170,15 +136,15 @@
to_chat(src, "<span class='warning'>You need to binge on weeds in order to have the energy to grow...</span>")
return
src.split()
src.visible_message("<span class='danger'>[src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.</span>","<span class='danger'>You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.</span>")
split()
visible_message("<span class='danger'>[src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.</span>","<span class='danger'>You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.</span>")
var/mob/living/carbon/human/diona/adult = new(get_turf(src.loc))
var/mob/living/carbon/human/diona/adult = new(get_turf(loc))
adult.set_species("Diona")
if(istype(loc,/obj/item/weapon/holder/diona))
if(istype(loc, /obj/item/weapon/holder/diona))
var/obj/item/weapon/holder/diona/L = loc
src.loc = L.loc
forceMove(L.loc)
qdel(L)
for(var/datum/language/L in languages)
@@ -187,12 +153,12 @@
adult.name = "diona ([rand(100,999)])"
adult.real_name = adult.name
adult.ckey = src.ckey
adult.ckey = ckey
adult.real_name = pick(diona_names) //I hate this being here of all places but unfortunately dna is based on real_name!
adult.rename_self("diona")
for(var/obj/item/W in src.contents)
src.unEquip(W)
for(var/obj/item/W in contents)
unEquip(W)
qdel(src)
@@ -207,7 +173,8 @@
var/mob/living/carbon/human/M = input(src,"Who do you wish to take a sample from?") in null|choices
if(!M || !src) return
if(!M || !src)
return
if(M.species.flags & NO_BLOOD)
to_chat(src, "<span class='warning'>That donor has no blood to take.</span>")
@@ -217,7 +184,7 @@
to_chat(src, "<span class='warning'>That donor offers you nothing new.</span>")
return
src.visible_message("<span class='danger'>[src] flicks out a feeler and neatly steals a sample of [M]'s blood.</span>","<span class='danger'>You flick out a feeler and neatly steal a sample of [M]'s blood.</span>")
visible_message("<span class='danger'>[src] flicks out a feeler and neatly steals a sample of [M]'s blood.</span>","<span class='danger'>You flick out a feeler and neatly steal a sample of [M]'s blood.</span>")
donors += M.real_name
for(var/datum/language/L in M.languages)
if(!(L.flags & HIVEMIND))
@@ -241,7 +208,7 @@
/mob/living/simple_animal/diona/put_in_hands(obj/item/W)
W.loc = get_turf(src)
W.forceMove(get_turf(src))
W.layer = initial(W.layer)
W.plane = initial(W.plane)
W.dropped()
@@ -250,7 +217,7 @@
to_chat(src, "<span class='warning'>You don't have any hands!</span>")
return
/mob/living/simple_animal/diona/emote(var/act, var/m_type=1, var/message = null)
/mob/living/simple_animal/diona/emote(act, m_type=1, message = null)
if(stat)
return
@@ -95,7 +95,8 @@
visible_message(
"<span class='danger'>[src] devours [L]!</span>",
"<span class='userdanger'>You feast on [L], restoring your health!</span>")
adjustBruteLoss(-L.maxHealth/2)
if(!is_station_level(z) && !client) //NPC monsters won't heal while on station
adjustBruteLoss(-L.maxHealth/2)
L.gib()
/mob/living/simple_animal/hostile/megafauna/ex_act(severity, target)
@@ -1,7 +1,7 @@
/mob/living/simple_animal/hostile/mimic
name = "crate"
desc = "A rectangular steel crate."
icon = 'icons/obj/storage.dmi'
icon = 'icons/obj/crates.dmi'
icon_state = "crate"
icon_living = "crate"
@@ -138,7 +138,7 @@ var/global/list/ts_spiderlist = list()
else if(istype(target, /obj/machinery/door/firedoor))
var/obj/machinery/door/firedoor/F = target
if(F.density)
if(F.blocked)
if(F.welded)
to_chat(src, "The fire door is welded shut.")
else
visible_message("<span class='danger'>\The [src] pries open the firedoor!</span>")
@@ -293,7 +293,7 @@ var/global/list/ts_spiderlist = list()
try_open_airlock(L)
if(istype(A, /obj/machinery/door/firedoor))
var/obj/machinery/door/firedoor/F = A
if(F.density && !F.blocked)
if(F.density && !F.welded)
F.open()
..()
@@ -103,7 +103,7 @@
dir = possessed_item.dir
color = possessed_item.color
overlays = possessed_item.overlays
opacity = possessed_item.opacity
set_opacity(possessed_item.opacity)
visible_message("<span class='warning'>[src] rises into the air and begins to float!</span>") // Inform those around us that shit's gettin' spooky.
animate_ghostly_presence(src, -1, 20, 1)
+26
View File
@@ -95,3 +95,29 @@
/mob/living/proc/update_stamina()
return
/mob/living/on_varedit(modified_var)
switch(modified_var)
if("weakened")
SetWeakened(weakened)
if("stunned")
SetStunned(stunned)
if("paralysis")
SetParalysis(paralysis)
if("sleeping")
SetSleeping(sleeping)
if("eye_blind")
SetEyeBlind(eye_blind)
if("eye_blurry")
SetEyeBlurry(eye_blurry)
if("ear_deaf")
SetEarDeaf(ear_deaf)
if("ear_damage")
SetEarDamage(ear_damage)
if("druggy")
SetDruggy(druggy)
if("maxHealth")
updatehealth()
if("resize")
update_transform()
..()
+2
View File
@@ -72,6 +72,8 @@
for(var/datum/alternate_appearance/AA in viewing_alternate_appearances)
AA.display_to(list(src))
update_client_colour(0)
callHook("mob_login", list("client" = client, "mob" = src))
// Calling update_interface() in /mob/Login() causes the Cyborg to immediately be ghosted; because of winget().
+2 -1
View File
@@ -19,7 +19,8 @@
for(var/datum/alternate_appearance/AA in viewing_alternate_appearances)
AA.viewers -= src
viewing_alternate_appearances = null
return ..()
..()
return QDEL_HINT_HARDDEL_NOW
/mob/New()
mob_list += src
+10 -10
View File
@@ -194,7 +194,7 @@
animate(affecting, pixel_x = 0, pixel_y = 0, 5, 1, LINEAR_EASING)
return //KJK
/* if(force_down) //THIS GOES ABOVE THE RETURN LABELED KJK
affecting.set_dir(SOUTH)*///This shows how you can apply special directions based on a variable. //face up
affecting.setDir(SOUTH)*///This shows how you can apply special directions based on a variable. //face up
var/shift = 0
var/adir = get_dir(assailant, affecting)
@@ -204,18 +204,18 @@
shift = 8
if(dancing) //look at partner
shift = 10
assailant.set_dir(get_dir(assailant, affecting))
assailant.setDir(get_dir(assailant, affecting))
if(GRAB_AGGRESSIVE)
shift = 12
if(GRAB_NECK, GRAB_UPGRADING)
shift = -10
adir = assailant.dir
affecting.set_dir(assailant.dir)
affecting.setDir(assailant.dir)
affecting.loc = assailant.loc
if(GRAB_KILL)
shift = 0
adir = 1
affecting.set_dir(SOUTH)//face up
affecting.setDir(SOUTH)//face up
affecting.loc = assailant.loc
switch(adir)
@@ -254,8 +254,8 @@
force_down = 1
affecting.Weaken(3)
step_to(assailant, affecting)
assailant.set_dir(EAST) //face the victim
affecting.set_dir(SOUTH) //face up //This is an example of a new feature based on the context of the location of the victim.
assailant.setDir(EAST) //face the victim
affecting.setDir(SOUTH) //face up //This is an example of a new feature based on the context of the location of the victim.
*/ //It means that upgrading while someone is lying on the ground would cause you to go into pin mode.
state = GRAB_AGGRESSIVE
icon_state = "grabbed1"
@@ -268,7 +268,7 @@
assailant.visible_message("<span class='warning'>[assailant] has reinforced \his grip on [affecting] (now neck)!</span>")
state = GRAB_NECK
icon_state = "grabbed+1"
assailant.set_dir(get_dir(assailant, affecting))
assailant.setDir(get_dir(assailant, affecting))
affecting.create_attack_log("<font color='orange'>Has had their neck grabbed by [assailant.name] ([assailant.ckey])</font>")
assailant.create_attack_log("<font color='red'>Grabbed the neck of [affecting.name] ([affecting.ckey])</font>")
log_attack("<font color='red'>[assailant.name] ([assailant.ckey]) grabbed the neck of [affecting.name] ([affecting.ckey])</font>")
@@ -291,7 +291,7 @@
assailant.next_move = world.time + 10
affecting.AdjustLoseBreath(1)
affecting.set_dir(WEST)
affecting.setDir(WEST)
adjust_position()
//This is used to make sure the victim hasn't managed to yackety sax away before using the grab.
@@ -378,8 +378,8 @@
affecting.Weaken(3)
affecting.lying = 1
step_to(assailant, affecting)
assailant.set_dir(EAST) //face the victim
affecting.set_dir(SOUTH) //face up
assailant.setDir(EAST) //face the victim
affecting.setDir(SOUTH) //face up
return
else
to_chat(assailant, "<span class='warning'>You are already pinning [affecting] to the ground.</span>")
+21 -2
View File
@@ -22,6 +22,25 @@
return 0
return 1
/mob/proc/get_screen_colour()
/mob/proc/update_client_colour(var/time = 10) //Update the mob's client.color with an animation the specified time in length.
if(!client) //No client_colour without client. If the player logs back in they'll be back through here anyway.
return
client.colour_transition(get_screen_colour(), time = time) //Get the colour matrix we're going to transition to depending on relevance (magic glasses first, eyes second).
/mob/living/carbon/human/get_screen_colour() //Fetch the colour matrix from wherever (e.g. eyes) so it can be compared to client.color.
. = ..()
if(.)
return .
var/obj/item/clothing/glasses/worn_glasses = glasses
var/obj/item/organ/internal/eyes/eyes = get_int_organ(/obj/item/organ/internal/eyes)
if(istype(worn_glasses) && worn_glasses.color_view) //Check to see if they got those magic glasses and they're augmenting the colour of what the wearer sees. If they're not, color_view should be null.
return worn_glasses.color_view
else if(eyes) //If they're not, check to see if their eyes got one of them there colour matrices. Will be null if eyes are robotic/the mob isn't colourblind and they have no default colour matrix.
return eyes.get_colourmatrix()
/proc/isloyal(A) //Checks to see if the person contains a mindshield implant, then checks that the implant is actually inside of them
for(var/obj/item/weapon/implant/loyalty/L in A)
if(L && L.implanted)
@@ -291,10 +310,10 @@ proc/muffledspeech(phrase)
/mob/proc/abiotic(var/full_body = 0)
if(full_body && ((src.l_hand && !(src.l_hand.flags & ABSTRACT)) || (src.r_hand && !(src.r_hand.flags & ABSTRACT)) || (src.back || src.wear_mask)))
if(full_body && ((l_hand && !(l_hand.flags & ABSTRACT)) || (r_hand && !(r_hand.flags & ABSTRACT)) || (back || wear_mask)))
return 1
if((src.l_hand && !(src.l_hand.flags & ABSTRACT)) || (src.r_hand && !(src.r_hand.flags & ABSTRACT)))
if((l_hand && !(l_hand.flags & ABSTRACT)) || (r_hand && !(r_hand.flags & ABSTRACT)))
return 1
return 0
+1 -1
View File
@@ -276,7 +276,7 @@
for(var/obj/item/weapon/grab/G in mob)
if(G.state == GRAB_NECK)
mob.set_dir(reverse_dir[direct])
mob.setDir(reverse_dir[direct])
G.adjust_position()
for(var/obj/item/weapon/grab/G in mob.grabbed_by)
G.adjust_position()
+1 -1
View File
@@ -1,7 +1,7 @@
/mob/living/carbon/human/proc/monkeyize()
var/mob/H = src
H.dna.SetSEState(MONKEYBLOCK,1)
domutcheck(H, null)
genemutcheck(H,MONKEYBLOCK,null,MUTCHK_FORCED)
/mob/new_player/AIize()
spawning = 1
@@ -319,7 +319,7 @@ field_generator power level display
if(O.last_warning && temp)
if((world.time - O.last_warning) > 50) //to stop message-spam
temp = 0
message_admins("A singulo exists and a containment field has failed.",1)
message_admins("A singulo exists and a containment field has failed. Location: [get_area(src)] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[x];Y=[y];Z=[z]'>JMP</A>)",1)
investigate_log("has <font color='red'>failed</font> whilst a singulo exists.","singulo")
O.last_warning = world.time
+1 -1
View File
@@ -49,7 +49,7 @@
icon_state = "smatter"
temperature = T20C+80
density = 1
opacity = 1
set_opacity(1)
blocks_air = 1
spawn(2)
@@ -118,18 +118,6 @@
projectile_type = /obj/item/projectile/meteor
select_name = "goddamn meteor"
/obj/item/ammo_casing/energy/kinetic
projectile_type = /obj/item/projectile/kinetic
select_name = "kinetic"
e_cost = 5000
fire_sound = 'sound/weapons/Kenetic_accel.ogg' // fine spelling there chap
/obj/item/ammo_casing/energy/kinetic/super
projectile_type = /obj/item/projectile/kinetic/super
/obj/item/ammo_casing/energy/kinetic/hyper
projectile_type = /obj/item/projectile/kinetic/hyper
/obj/item/ammo_casing/energy/disabler
projectile_type = /obj/item/projectile/beam/disabler
select_name = "disable"
+17 -17
View File
@@ -45,7 +45,7 @@
lefthand_file = 'icons/mob/inhands/guns_lefthand.dmi'
righthand_file = 'icons/mob/inhands/guns_righthand.dmi'
var/obj/item/device/flashlight/F = null
var/obj/item/device/flashlight/gun_light = null
var/can_flashlight = 0
var/list/upgrades = list()
@@ -63,7 +63,7 @@
/obj/item/weapon/gun/New()
..()
if(F)
if(gun_light)
verbs += /obj/item/weapon/gun/proc/toggle_gunlight
build_zooming()
@@ -241,27 +241,27 @@ obj/item/weapon/gun/proc/newshot()
if(istype(I, /obj/item/device/flashlight/seclite))
var/obj/item/device/flashlight/seclite/S = I
if(can_flashlight)
if(!F)
if(!gun_light)
if(!user.unEquip(I))
return
to_chat(user, "<span class='notice'>You click [S] into place on [src].</span>")
if(S.on)
set_light(0)
F = S
gun_light = S
I.loc = src
update_icon()
update_gunlight(user)
update_gun_light(user)
var/datum/action/A = new /datum/action/item_action/toggle_gunlight(src)
if(loc == user)
A.Grant(user)
if(istype(I, /obj/item/weapon/screwdriver))
if(F && can_flashlight)
if(gun_light && can_flashlight)
for(var/obj/item/device/flashlight/seclite/S in src)
to_chat(user, "<span class='notice'>You unscrew the seclite from [src].</span>")
F = null
gun_light = null
S.loc = get_turf(user)
update_gunlight(user)
update_gun_light(user)
S.update_brightness(user)
update_icon()
for(var/datum/action/item_action/toggle_gunlight/TGL in actions)
@@ -273,26 +273,26 @@ obj/item/weapon/gun/proc/newshot()
..()
/obj/item/weapon/gun/proc/toggle_gunlight()
set name = "Toggle Gunlight"
set name = "Toggle Gun Light"
set category = "Object"
set desc = "Click to toggle your weapon's attached flashlight."
if(!F)
if(!gun_light)
return
var/mob/living/carbon/human/user = usr
if(!isturf(user.loc))
to_chat(user, "<span class='warning'>You cannot turn the light on while in this [user.loc]!</span>")
F.on = !F.on
to_chat(user, "<span class='notice'>You toggle the gunlight [F.on ? "on":"off"].</span>")
gun_light.on = !gun_light.on
to_chat(user, "<span class='notice'>You toggle the gun light [gun_light.on ? "on":"off"].</span>")
playsound(user, 'sound/weapons/empty.ogg', 100, 1)
update_gunlight(user)
update_gun_light(user)
/obj/item/weapon/gun/proc/update_gunlight(mob/user = null)
if(F)
if(F.on)
set_light(F.brightness_on)
/obj/item/weapon/gun/proc/update_gun_light(mob/user = null)
if(gun_light)
if(gun_light.on)
set_light(gun_light.brightness_on)
else
set_light(0)
update_icon()
+16 -5
View File
@@ -30,6 +30,12 @@
else
power_supply = new(src)
power_supply.give(power_supply.maxcharge)
update_ammo_types()
if(selfcharge)
processing_objects.Add(src)
update_icon()
/obj/item/weapon/gun/energy/proc/update_ammo_types()
var/obj/item/ammo_casing/energy/shot
for(var/i = 1, i <= ammo_type.len, i++)
var/shottype = ammo_type[i]
@@ -38,9 +44,6 @@
shot = ammo_type[select]
fire_sound = shot.fire_sound
fire_delay = shot.delay
if(selfcharge)
processing_objects.Add(src)
update_icon()
/obj/item/weapon/gun/energy/Destroy()
if(selfcharge)
@@ -129,9 +132,9 @@
overlays += image(icon = icon, icon_state = iconState, pixel_x = ammo_x_offset * (i -1))
else
overlays += image(icon = icon, icon_state = "[icon_state]_[modifystate ? "[shot.select_name]_" : ""]charge[ratio]")
if(F && can_flashlight)
if(gun_light && can_flashlight)
var/iconF = "flight"
if(F.on)
if(gun_light.on)
iconF = "flight_on"
overlays += image(icon = icon, icon_state = iconF, pixel_x = flight_x_offset, pixel_y = flight_y_offset)
if(itemState)
@@ -160,6 +163,14 @@
playsound(loc, 'sound/weapons/empty.ogg', 50, 1, -1)
return (OXYLOSS)
/obj/item/weapon/gun/energy/on_varedit(modified_var)
if(modified_var == "selfcharge")
if(selfcharge)
processing_objects.Add(src)
else
processing_objects.Remove(src)
..()
/obj/item/weapon/gun/energy/proc/robocharge()
if(isrobot(loc))
var/mob/living/silicon/robot/R = loc
@@ -0,0 +1,416 @@
/obj/item/weapon/gun/energy/kinetic_accelerator
name = "proto-kinetic accelerator"
desc = "A self recharging, ranged mining tool that does increased damage in low pressure. Capable of holding up to six slots worth of mod kits."
icon_state = "kineticgun"
item_state = "kineticgun"
ammo_type = list(/obj/item/ammo_casing/energy/kinetic)
cell_type = /obj/item/weapon/stock_parts/cell/emproof
needs_permit = 0
unique_rename = 1
origin_tech = "combat=3;powerstorage=3;engineering=3"
weapon_weight = WEAPON_LIGHT
can_flashlight = 1
flight_x_offset = 15
flight_y_offset = 9
var/overheat_time = 16
var/holds_charge = FALSE
var/unique_frequency = FALSE // modified by KA modkits
var/overheat = FALSE
var/max_mod_capacity = 100
var/list/modkits = list()
var/empty_state = "kineticgun_empty"
/obj/item/weapon/gun/energy/kinetic_accelerator/examine(mob/user)
if(..(user, 1))
if(max_mod_capacity)
to_chat(user, "<b>[get_remaining_mod_capacity()]%</b> mod capacity remaining.")
for(var/A in get_modkits())
var/obj/item/borg/upgrade/modkit/M = A
to_chat(user, "<span class='notice'>There is a [M.name] mod installed, using <b>[M.cost]%</b> capacity.</span>")
/obj/item/weapon/gun/energy/kinetic_accelerator/attackby(obj/item/A, mob/user)
if(istype(A, /obj/item/weapon/crowbar))
if(modkits.len)
to_chat(user, "<span class='notice'>You pry the modifications out.</span>")
playsound(loc, 'sound/items/Crowbar.ogg', 100, 1)
for(var/obj/item/borg/upgrade/modkit/M in modkits)
M.uninstall(src)
else
to_chat(user, "<span class='notice'>There are no modifications currently installed.</span>")
else if(istype(A, /obj/item/borg/upgrade/modkit))
var/obj/item/borg/upgrade/modkit/MK = A
MK.install(src, user)
else
..()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/get_remaining_mod_capacity()
var/current_capacity_used = 0
for(var/A in get_modkits())
var/obj/item/borg/upgrade/modkit/M = A
current_capacity_used += M.cost
return max_mod_capacity - current_capacity_used
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/get_modkits()
. = list()
for(var/A in modkits)
. += A
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/modify_projectile(obj/item/projectile/kinetic/K)
for(var/A in get_modkits())
var/obj/item/borg/upgrade/modkit/M = A
M.modify_projectile(K)
/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg
holds_charge = TRUE
unique_frequency = TRUE
max_mod_capacity = 80
/obj/item/weapon/gun/energy/kinetic_accelerator/New()
. = ..()
if(!holds_charge)
empty()
/obj/item/weapon/gun/energy/kinetic_accelerator/shoot_live_shot()
. = ..()
attempt_reload()
/obj/item/weapon/gun/energy/kinetic_accelerator/equipped(mob/user)
. = ..()
if(!can_shoot())
attempt_reload()
/obj/item/weapon/gun/energy/kinetic_accelerator/dropped()
. = ..()
if(!holds_charge)
// Put it on a delay because moving item from slot to hand
// calls dropped().
spawn(2)
empty_if_not_held()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/empty_if_not_held()
if(!ismob(loc))
empty()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/empty()
power_supply.use(5000)
update_icon()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/attempt_reload()
if(overheat)
return
overheat = TRUE
var/carried = 0
if(!unique_frequency)
for(var/obj/item/weapon/gun/energy/kinetic_accelerator/K in \
loc.GetAllContents())
carried++
carried = max(carried, 1)
else
carried = 1
spawn(overheat_time * carried)
reload()
/obj/item/weapon/gun/energy/kinetic_accelerator/emp_act(severity)
return
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/reload()
power_supply.give(5000)
if(!suppressed)
playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
else if(isliving(loc))
to_chat(loc, "<span class='warning'>[src] silently charges up.<span>")
update_icon()
overheat = FALSE
/obj/item/weapon/gun/energy/kinetic_accelerator/update_icon()
overlays.Cut()
if(empty_state && !can_shoot())
overlays += empty_state
if(gun_light && can_flashlight)
var/iconF = "flight"
if(gun_light.on)
iconF = "flight_on"
overlays += image(icon = icon, icon_state = iconF, pixel_x = flight_x_offset, pixel_y = flight_y_offset)
//Casing
/obj/item/ammo_casing/energy/kinetic
projectile_type = /obj/item/projectile/kinetic
select_name = "kinetic"
e_cost = 5000
fire_sound = 'sound/weapons/Kenetic_accel.ogg' // fine spelling there chap
/obj/item/ammo_casing/energy/kinetic/ready_proj(atom/target, mob/living/user, quiet, zone_override = "")
..()
if(loc && istype(loc, /obj/item/weapon/gun/energy/kinetic_accelerator))
var/obj/item/weapon/gun/energy/kinetic_accelerator/KA = loc
KA.modify_projectile(BB)
var/turf/proj_turf = get_turf(BB)
if(!isturf(proj_turf))
return
var/datum/gas_mixture/environment = proj_turf.return_air()
var/pressure = environment.return_pressure()
if(pressure > 50)
BB.name = "weakened [BB.name]"
var/obj/item/projectile/kinetic/K = BB
K.damage *= K.pressure_decrease
//Projectiles
/obj/item/projectile/kinetic
name = "kinetic force"
icon_state = null
damage = 40
damage_type = BRUTE
flag = "bomb"
range = 3
log_override = TRUE
var/pressure_decrease = 0.25
var/turf_aoe = FALSE
var/mob_aoe = 0
var/list/hit_overlays = list()
/obj/item/projectile/kinetic/on_range()
strike_thing()
..()
/obj/item/projectile/kinetic/on_hit(atom/target)
strike_thing(target)
. = ..()
/obj/item/projectile/kinetic/proc/strike_thing(atom/target)
var/turf/target_turf = get_turf(target)
if(!target_turf)
target_turf = get_turf(src)
if(ismineralturf(target_turf))
var/turf/simulated/mineral/M = target_turf
M.gets_drilled(firer)
var/obj/effect/overlay/temp/kinetic_blast/K = new /obj/effect/overlay/temp/kinetic_blast(target_turf)
K.color = color
for(var/type in hit_overlays)
new type(target_turf)
if(turf_aoe)
for(var/T in RANGE_TURFS(1, target_turf) - target_turf)
if(ismineralturf(T))
var/turf/simulated/mineral/M = T
M.gets_drilled(firer)
if(mob_aoe)
for(var/mob/living/L in range(1, target_turf) - firer - target)
var/armor = L.run_armor_check(def_zone, flag, "", "", armour_penetration)
L.apply_damage(damage*mob_aoe, damage_type, def_zone, armor)
to_chat(L, "<span class='userdanger'>You're struck by a [name]!</span>")
//Modkits
/obj/item/borg/upgrade/modkit
name = "modification kit"
desc = "An upgrade for kinetic accelerators."
icon = 'icons/obj/objects.dmi'
icon_state = "modkit"
origin_tech = "programming=2;materials=2;magnets=4"
require_module = 1
module_type = /obj/item/weapon/robot_module/miner
var/denied_type = null
var/maximum_of_type = 1
var/cost = 30
var/modifier = 1 //For use in any mod kit that has numerical modifiers
/obj/item/borg/upgrade/modkit/examine(mob/user)
if(..(user, 1))
to_chat(user, "<span class='notice'>Occupies <b>[cost]%</b> of mod capacity.</span>")
/obj/item/borg/upgrade/modkit/attackby(obj/item/A, mob/user)
if(istype(A, /obj/item/weapon/gun/energy/kinetic_accelerator) && !issilicon(user))
install(A, user)
else
..()
/obj/item/borg/upgrade/modkit/action(mob/living/silicon/robot/R)
if(..())
return
for(var/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg/H in R.module.modules)
return install(H, usr)
/obj/item/borg/upgrade/modkit/proc/install(obj/item/weapon/gun/energy/kinetic_accelerator/KA, mob/user)
. = TRUE
if(denied_type)
var/number_of_denied = 0
for(var/A in KA.get_modkits())
var/obj/item/borg/upgrade/modkit/M = A
if(istype(M, denied_type))
number_of_denied++
if(number_of_denied >= maximum_of_type)
. = FALSE
break
if(KA.get_remaining_mod_capacity() >= cost)
if(.)
to_chat(user, "<span class='notice'>You install the modkit.</span>")
playsound(loc, 'sound/items/Screwdriver.ogg', 100, 1)
user.unEquip(src)
forceMove(KA)
KA.modkits += src
else
to_chat(user, "<span class='notice'>The modkit you're trying to install would conflict with an already installed modkit. Use a crowbar to remove existing modkits.</span>")
else
to_chat(user, "<span class='notice'>You don't have room(<b>[KA.get_remaining_mod_capacity()]%</b> remaining, [cost]% needed) to install this modkit. Use a crowbar to remove existing modkits.</span>")
. = FALSE
/obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/weapon/gun/energy/kinetic_accelerator/KA)
forceMove(get_turf(KA))
KA.modkits -= src
/obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K)
//Range
/obj/item/borg/upgrade/modkit/range
name = "range increase"
desc = "Increases the range of a kinetic accelerator when installed."
modifier = 1
cost = 24 //so you can fit four plus a tracer cosmetic
/obj/item/borg/upgrade/modkit/range/modify_projectile(obj/item/projectile/kinetic/K)
K.range += modifier
//Damage
/obj/item/borg/upgrade/modkit/damage
name = "damage increase"
desc = "Increases the damage of kinetic accelerator when installed."
modifier = 10
/obj/item/borg/upgrade/modkit/damage/modify_projectile(obj/item/projectile/kinetic/K)
K.damage += modifier
//Cooldown
/obj/item/borg/upgrade/modkit/cooldown
name = "cooldown decrease"
desc = "Decreases the cooldown of a kinetic accelerator."
modifier = 2.5
/obj/item/borg/upgrade/modkit/cooldown/install(obj/item/weapon/gun/energy/kinetic_accelerator/KA, mob/user)
. = ..()
if(.)
KA.overheat_time -= modifier
/obj/item/borg/upgrade/modkit/cooldown/uninstall(obj/item/weapon/gun/energy/kinetic_accelerator/KA)
KA.overheat_time += modifier
..()
//AoE blasts
/obj/item/borg/upgrade/modkit/aoe
modifier = 0
/obj/item/borg/upgrade/modkit/aoe/modify_projectile(obj/item/projectile/kinetic/K)
K.name = "kinetic explosion"
if(!K.turf_aoe && !K.mob_aoe)
K.hit_overlays += /obj/effect/overlay/temp/explosion/fast
K.mob_aoe += modifier
/obj/item/borg/upgrade/modkit/aoe/turfs
name = "mining explosion"
desc = "Causes the kinetic accelerator to destroy rock in an AoE."
denied_type = /obj/item/borg/upgrade/modkit/aoe/turfs
/obj/item/borg/upgrade/modkit/aoe/turfs/modify_projectile(obj/item/projectile/kinetic/K)
..()
K.turf_aoe = TRUE
/obj/item/borg/upgrade/modkit/aoe/turfs/andmobs
name = "offensive mining explosion"
desc = "Causes the kinetic accelerator to destroy rock and damage mobs in an AoE."
maximum_of_type = 3
modifier = 0.25
/obj/item/borg/upgrade/modkit/aoe/mobs
name = "offensive explosion"
desc = "Causes the kinetic accelerator to damage mobs in an AoE."
modifier = 0.2
//Indoors
/obj/item/borg/upgrade/modkit/indoors
name = "decrease pressure penalty"
desc = "Increases the damage a kinetic accelerator does in a high pressure environment."
modifier = 2
denied_type = /obj/item/borg/upgrade/modkit/indoors
maximum_of_type = 2
cost = 40
/obj/item/borg/upgrade/modkit/indoors/modify_projectile(obj/item/projectile/kinetic/K)
K.pressure_decrease *= modifier
//Trigger Guard
/obj/item/borg/upgrade/modkit/trigger_guard
name = "modified trigger guard"
desc = "Allows creatures normally incapable of firing guns to operate the weapon when installed."
cost = 20
denied_type = /obj/item/borg/upgrade/modkit/trigger_guard
/obj/item/borg/upgrade/modkit/trigger_guard/install(obj/item/weapon/gun/energy/kinetic_accelerator/KA, mob/user)
. = ..()
if(.)
KA.trigger_guard = TRIGGER_GUARD_ALLOW_ALL
/obj/item/borg/upgrade/modkit/trigger_guard/uninstall(obj/item/weapon/gun/energy/kinetic_accelerator/KA)
KA.trigger_guard = TRIGGER_GUARD_NORMAL
..()
//Cosmetic
/obj/item/borg/upgrade/modkit/chassis_mod
name = "super chassis"
desc = "Makes your KA yellow. All the fun of having a more powerful KA without actually having a more powerful KA."
cost = 0
denied_type = /obj/item/borg/upgrade/modkit/chassis_mod
var/chassis_icon = "kineticgun_u"
var/chassis_name = "super-kinetic accelerator"
/obj/item/borg/upgrade/modkit/chassis_mod/install(obj/item/weapon/gun/energy/kinetic_accelerator/KA, mob/user)
. = ..()
if(.)
KA.icon_state = chassis_icon
KA.name = chassis_name
/obj/item/borg/upgrade/modkit/chassis_mod/uninstall(obj/item/weapon/gun/energy/kinetic_accelerator/KA)
KA.icon_state = initial(KA.icon_state)
KA.name = initial(KA.name)
..()
/obj/item/borg/upgrade/modkit/chassis_mod/orange
name = "hyper chassis"
desc = "Makes your KA orange. All the fun of having explosive blasts without actually having explosive blasts."
chassis_icon = "kineticgun_h"
chassis_name = "hyper-kinetic accelerator"
/obj/item/borg/upgrade/modkit/tracer
name = "white tracer bolts"
desc = "Causes kinetic accelerator bolts to have a white tracer trail and explosion."
cost = 0
denied_type = /obj/item/borg/upgrade/modkit/tracer
var/bolt_color = "#FFFFFF"
/obj/item/borg/upgrade/modkit/tracer/modify_projectile(obj/item/projectile/kinetic/K)
K.icon_state = "ka_tracer"
K.color = bolt_color
/obj/item/borg/upgrade/modkit/tracer/adjustable
name = "adjustable tracer bolts"
desc = "Causes kinetic accelerator bolts to have a adjustably-colored tracer trail and explosion. Use in-hand to change color."
/obj/item/borg/upgrade/modkit/tracer/adjustable/attack_self(mob/user)
bolt_color = input(user,"Choose Color") as color
@@ -37,14 +37,14 @@
can_flashlight = 0 // Can't attach or detach the flashlight, and override it's icon update
/obj/item/weapon/gun/energy/gun/mini/New()
F = new /obj/item/device/flashlight/seclite(src)
gun_light = new /obj/item/device/flashlight/seclite(src)
..()
power_supply.maxcharge = 6000
power_supply.charge = 6000
/obj/item/weapon/gun/energy/gun/mini/update_icon()
..()
if(F && F.on)
if(gun_light && gun_light.on)
overlays += "mini-light"
/obj/item/weapon/gun/energy/gun/hos
+3 -135
View File
@@ -84,141 +84,6 @@
ammo_type = list(/obj/item/ammo_casing/energy/mindflayer)
ammo_x_offset = 2
/obj/item/weapon/gun/energy/kinetic_accelerator
name = "proto-kinetic accelerator"
desc = "In the year 2544, only a year after the discovery of a potentially \
world-changing substance, now colloquially referred to as plasma, the \
Nanotrasen-UEG mining conglomerate introduced a prototype of a gun-like \
device intended for quick, effective mining of plasma in the low \
pressures of the solar system. Included in this presentation were \
demonstrations of the gun being fired at collections of rocks contained \
in vacuumed environments, obliterating them instantly while maintaining \
the structure of the ores buried within them. Additionally, volunteers \
were called from the crowd to have the gun used on them, only proving that \
the gun caused little harm to objects in standard pressure. \n\
An official from an unnamed, now long dissipated company observed this \
presentation and offered to share their self-recharger cells, powered \
by the user's bioelectrical field, another new and unknown technology. \
They warned that the cells were incredibly experimental and several times \
had injured workers, but the scientists as Nanotrasen were unable to resist \
the money-saving potential of self recharging cells. Upon accepting this \
offer, it took only a matter of days to prove the volatility of these cells, \
as they exploded left and right whenever inserted into the prototype devices, \
only throwing more money in the bin. \n\
Whenever the Nanotrasen scientists were on the edge of giving up, a \
breakthrough was made by head researcher Miles Parks McCollum, who \
demonstrated that the cells could be stabilized when exposed to radium \
then cooled with cryostylane. After this discovery, the low pressure gun, \
now named the Kinetic Accelerator, was hastily completed and made compatible \
with the self-recharging cells. As a result of poor testing, the currently \
used guns lose their charge when not in use, and when two Kinetic Accelerators \
come in proximity of one another, they will interfere with each other. Despite \
this, the shoddy guns still see use in the mining of plasma to this day."
icon_state = "kineticgun"
item_state = "kineticgun"
ammo_type = list(/obj/item/ammo_casing/energy/kinetic)
cell_type = /obj/item/weapon/stock_parts/cell/emproof
// Apparently these are safe to carry? I'm sure goliaths would disagree.
needs_permit = 0
unique_rename = 1
origin_tech = "combat=3;powerstorage=3;engineering=3"
weapon_weight = WEAPON_LIGHT
can_flashlight = 1
flight_x_offset = 15
flight_y_offset = 9
var/overheat_time = 16
var/holds_charge = FALSE
var/unique_frequency = FALSE // modified by KA modkits
var/overheat = FALSE
/obj/item/weapon/gun/energy/kinetic_accelerator/super
name = "super-kinetic accelerator"
desc = "An upgraded, superior version of the proto-kinetic accelerator."
icon_state = "kineticgun_u"
ammo_type = list(/obj/item/ammo_casing/energy/kinetic/super)
overheat_time = 15
origin_tech = "combat=3;powerstorage=2"
/obj/item/weapon/gun/energy/kinetic_accelerator/hyper
name = "hyper-kinetic accelerator"
desc = "An upgraded, even more superior version of the proto-kinetic accelerator."
icon_state = "kineticgun_h"
ammo_type = list(/obj/item/ammo_casing/energy/kinetic/hyper)
overheat_time = 14
origin_tech = "combat=4;powerstorage=3"
/obj/item/weapon/gun/energy/kinetic_accelerator/cyborg
holds_charge = TRUE
unique_frequency = TRUE
/obj/item/weapon/gun/energy/kinetic_accelerator/hyper/cyborg
holds_charge = TRUE
unique_frequency = TRUE
/obj/item/weapon/gun/energy/kinetic_accelerator/New()
. = ..()
if(!holds_charge)
empty()
/obj/item/weapon/gun/energy/kinetic_accelerator/shoot_live_shot()
. = ..()
attempt_reload()
/obj/item/weapon/gun/energy/kinetic_accelerator/equipped(mob/user)
. = ..()
if(!can_shoot())
attempt_reload()
/obj/item/weapon/gun/energy/kinetic_accelerator/dropped()
. = ..()
if(!holds_charge)
// Put it on a delay because moving item from slot to hand
// calls dropped().
spawn(1)
if(!ismob(loc))
empty()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/empty()
power_supply.use(5000)
update_icon()
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/attempt_reload()
if(overheat)
return
overheat = TRUE
var/carried = 0
if(!unique_frequency)
for(var/obj/item/weapon/gun/energy/kinetic_accelerator/K in \
loc.GetAllContents())
carried++
carried = max(carried, 1)
else
carried = 1
spawn(overheat_time * carried)
reload()
overheat = FALSE
/obj/item/weapon/gun/energy/kinetic_accelerator/emp_act(severity)
return
/obj/item/weapon/gun/energy/kinetic_accelerator/proc/reload()
power_supply.give(5000)
if(!suppressed)
playsound(loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
else if(ismob(loc))
to_chat(loc, "<span class='warning'>[src] silently charges up.<span>")
update_icon()
/obj/item/weapon/gun/energy/kinetic_accelerator/update_icon()
if(!can_shoot())
icon_state = "[initial(icon_state)]_empty"
else
icon_state = initial(icon_state)
/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow
name = "mini energy crossbow"
desc = "A weapon favored by syndicate stealth specialists."
@@ -234,6 +99,9 @@
overheat_time = 20
holds_charge = TRUE
unique_frequency = TRUE
can_flashlight = 0
max_mod_capacity = 0
empty_state = null
/obj/item/weapon/gun/energy/kinetic_accelerator/crossbow/ninja
name = "energy dart thrower"

Some files were not shown because too many files have changed in this diff Show More