"
-
- if(sprite)
- body += "| [bicon(D, use_class=0)] | "
+ if(!islist)
+ refid = "[D.UID()]"
else
- body += ""
-
- var/formatted_type = text("[D.type]")
+ var/formatted_type = "[type]"
if(length(formatted_type) > 25)
var/middle_point = length(formatted_type) / 2
- var/splitpoint = findtext(formatted_type,"/",middle_point)
+ var/splitpoint = findtext(formatted_type, "/", middle_point)
if(splitpoint)
- formatted_type = "[copytext(formatted_type,1,splitpoint)] [copytext(formatted_type,splitpoint)]"
+ formatted_type = "[copytext(formatted_type, 1, splitpoint)] [copytext(formatted_type, splitpoint)]"
else
formatted_type = "Type too long" //No suitable splitpoint (/) found.
- body += "[formatted_type]"
- if(src.holder && src.holder.marked_datum && src.holder.marked_datum == D)
- body += " Marked Object"
+ var/marked
+ if(holder.marked_datum && holder.marked_datum == D)
+ marked = " Marked Object"
- if(D.var_edited)
- body += " Var Edited"
- if(istype(D, /atom))
+ var/varedited_line = ""
+ if(isatom(D))
var/atom/A = D
if(A.admin_spawned)
- body += " Admin Spawned"
-
- body += " "
-
- body += " | "
-
- body += "Refresh"
-
- body += {" "
-
- body += " |
"
-
- body += "E - Edit, tries to determine the variable type by itself. "
- body += "C - Change, asks you for the var type first. "
- body += "M - Mass modify: changes this variable for all objects of this type. "
-
- body += "
"
-
- body += ""
var/list/names = list()
- for(var/V in D.vars)
- names += V
+ if(!islist)
+ for(var/V in D.vars)
+ names += V
- names = sortList(names)
- for(var/V in names)
- body += debug_variable(V, D.vars[V], 0, D)
+ sleep(1) // Without a sleep here, VV sometimes disconnects clients
- body += " "
- var/html = ""
- if(title)
- html += "[title]"
- html += {""}
- html += ""
- html += body.Join("")
+ var/list/variable_html = list()
+ if(islist)
+ var/list/L = D
+ for(var/i in 1 to L.len)
+ var/key = L[i]
+ var/value
+ if(IS_NORMAL_LIST(L) && !isnum(key))
+ value = L[key]
+ variable_html += debug_variable(i, value, 0, D)
+ else
+ names = sortList(names)
+ for(var/V in names)
+ if(D.can_vv_get(V))
+ variable_html += D.vv_get_var(V)
- html += {"
+ var/html = {"
+
+
+ [title]
+
+
+
+
+
+
+
+
+
+
+ |
+ [sprite_text]
+
+ [atomsnowflake.Join()]
+
+ |
+
+
+
+ [formatted_type]
+ [marked]
+ [varedited_line]
+
+ |
+
+
+ |
+
+
+
+
+
+ E - Edit, tries to determine the variable type by itself.
+ C - Change, asks you for the var type first.
+ M - Mass modify: changes this variable for all objects of this type.
+
+
+
+
+
+ [variable_html.Join()]
+
+
+
"}
- html += ""
-
- usr << browse(html, "window=variables[D.UID()];size=475x650")
-
- return
-
-/client/proc/debug_variable(name, value, level, var/datum/DA = null)
- var/list/html = list()
+ usr << browse(html, "window=variables[refid];size=475x650")
+#define VV_HTML_ENCODE(thing) ( sanitize ? html_encode(thing) : thing )
+/proc/debug_variable(name, value, level, var/datum/DA = null, sanitize = TRUE)
+ var/header
if(DA)
- html += "(E) (C) (M) "
+ if(islist(DA))
+ var/index = name
+ if(value)
+ name = DA[name] // name is really the index until this line
+ else
+ value = DA[name]
+ header = "(E) (C) (-) "
+ else
+ header = "(E) (C) (M) "
else
- html += ""
+ header = ""
+ var/item
if(isnull(value))
- html += "[name] = null"
+ item = "[VV_HTML_ENCODE(name)] = null"
else if(istext(value))
- html += "[name] = \"[value]\""
+ item = "[VV_HTML_ENCODE(name)] = \"[VV_HTML_ENCODE(value)]\""
else if(isicon(value))
#ifdef VARSICON
- html += "[name] = /icon ([value]) [bicon(value, use_class=0)]"
+ item = "[name] = /icon ([value]) [bicon(value, use_class=0)]"
#else
- html += "[name] = /icon ([value])"
+ item = "[name] = /icon ([value])"
#endif
else if(istype(value, /image))
var/image/I = value
#ifdef VARSICON
- html += "[name] \ref[value] = /image ([value]) [bicon(value, use_class=0)]"
+ item = "[name] \ref[value] = /image ([value]) [bicon(value, use_class=0)]"
#else
- html += "[name] \ref[value] = /image ([value])"
+ item = "[name] \ref[value] = /image ([value])"
#endif
else if(isfile(value))
- html += "[name] = '[value]'"
+ item = "[VV_HTML_ENCODE(name)] = '[value]'"
else if(istype(value, /datum))
var/datum/D = value
- html += "[name] \ref[value] = [D.type]"
+ item = "[VV_HTML_ENCODE(name)] \ref[value] = [D.type]"
else if(istype(value, /client))
var/client/C = value
- html += "[name] \ref[value] = [C] [C.type]"
+ item = "[VV_HTML_ENCODE(name)] \ref[value] = [C] [C.type]"
//
- else if(istype(value, /list))
+ else if(islist(value))
var/list/L = value
- html += "[name] = /list ([L.len])"
+ var/list/items = list()
- if(L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > 500))
- // not sure if this is completely right...
- if(0) //(L.vars.len > 0)
- html += ""
- html += " "
- else
- html += ""
- var/index = 1
- for(var/entry in L)
- if(istext(entry))
- html += debug_variable(entry, L[entry], level + 1)
- else
- html += debug_variable(index, L[index], level + 1)
- index++
- html += " "
+ if(L.len > 0 && !(name == "underlays" || name == "overlays" || name == "vars" || L.len > (IS_NORMAL_LIST(L) ? 250 : 300)))
+ for(var/i in 1 to L.len)
+ var/key = L[i]
+ var/val
+ if(IS_NORMAL_LIST(L) && !isnum(key))
+ val = L[key]
+ if(!val)
+ val = key
+ key = i
+
+ items += debug_variable(key, val, level + 1, sanitize = sanitize)
+
+ item = "[VV_HTML_ENCODE(name)] = /list ([L.len])"
+
+ else
+ item = "[VV_HTML_ENCODE(name)] = /list ([L.len])"
else
- html += "[name] = [value]"
- /*
- // Bitfield stuff
- if(round(value)==value) // Require integers.
- var/idx=0
- var/bit=0
- var/bv=0
- html += ""
- for(var/block=0;block<8;block++)
- html += " "
- for(var/i=0;i<4;i++)
- idx=(block*4)+i
- to_chat(bit=1, idx)
- bv=value & bit
- html += "[bv?1:0]"
- html += ""
- html += " "
- */
- html += ""
+ item = "[VV_HTML_ENCODE(name)] = [VV_HTML_ENCODE(value)]"
- return html.Join("")
+ return "[header][item]"
+
+#undef VV_HTML_ENCODE
/client/proc/view_var_Topic(href, href_list, hsrc)
//This should all be moved over to datum/admins/Topic() or something ~Carn
if(!check_rights(R_ADMIN|R_MOD))
return
+ if(view_var_Topic_list(href, href_list, hsrc)) // done because you can't use UIDs with lists and I don't want to snowflake into the below check to supress warnings
+ return
+
// Correct and warn about any VV topic links that aren't using UIDs
for(var/paramname in href_list)
if(findtext(href_list[paramname], "]_"))
@@ -516,6 +601,7 @@ body
cmd_mass_modify_object_variables(A, href_list["varnamemass"])
+
else if(href_list["mob_player_panel"])
if(!check_rights(R_ADMIN|R_MOD)) return
@@ -645,6 +731,16 @@ body
to_chat(M, "There were no ghosts willing to take control.")
message_admins("No ghosts were willing to take control of [key_name_admin(M)])")
+ else if(href_list["delete"])
+ if(!check_rights(R_DEBUG, 0))
+ return
+
+ var/datum/D = locateUID(href_list["delete"])
+ if(!D)
+ to_chat(usr, "Unable to locate item!")
+ admin_delete(D)
+ href_list["datumrefresh"] = href_list["delete"]
+
else if(href_list["delall"])
if(!check_rights(R_DEBUG|R_SERVER)) return
@@ -1099,6 +1195,7 @@ body
if("oxygen")L.adjustOxyLoss(amount)
if("brain") L.adjustBrainLoss(amount)
if("clone") L.adjustCloneLoss(amount)
+ if("stamina") L.adjustStaminaLoss(amount)
else
to_chat(usr, "You caused an error. DEBUG: Text:[Text] Mob:[L]")
return
@@ -1110,8 +1207,123 @@ body
if(href_list["datumrefresh"])
var/datum/DAT = locateUID(href_list["datumrefresh"])
- if(!istype(DAT, /datum))
+ if(!istype(DAT, /datum) && !isclient(DAT))
return
src.debug_variables(DAT)
return
+
+/client/proc/view_var_Topic_list(href, href_list, hsrc)
+ if(href_list["VarsList"])
+ debug_variables(locate(href_list["VarsList"]))
+ return TRUE
+
+ if(href_list["listedit"] && href_list["index"])
+ var/index = text2num(href_list["index"])
+ if(!index)
+ return TRUE
+
+ var/list/L = locate(href_list["listedit"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return
+
+ mod_list(L, null, "list", "contents", index, autodetect_class = TRUE)
+ return TRUE
+
+ if(href_list["listchange"] && href_list["index"])
+ var/index = text2num(href_list["index"])
+ if(!index)
+ return TRUE
+
+ var/list/L = locate(href_list["listchange"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return
+
+ mod_list(L, null, "list", "contents", index, autodetect_class = FALSE)
+ return TRUE
+
+ if(href_list["listremove"] && href_list["index"])
+ var/index = text2num(href_list["index"])
+ if(!index)
+ return TRUE
+
+ var/list/L = locate(href_list["listremove"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return
+
+ var/variable = L[index]
+ var/prompt = alert("Do you want to remove item number [index] from list?", "Confirm", "Yes", "No")
+ if(prompt != "Yes")
+ return
+ L.Cut(index, index+1)
+ log_to_dd("### ListVarEdit by [src]: /list's contents: REMOVED=[html_encode("[variable]")]")
+ log_admin("[key_name(src)] modified list's contents: REMOVED=[variable]")
+ message_admins("[key_name_admin(src)] modified list's contents: REMOVED=[variable]")
+ return TRUE
+
+ if(href_list["listadd"])
+ var/list/L = locate(href_list["listadd"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return TRUE
+
+ mod_list_add(L, null, "list", "contents")
+ return TRUE
+
+ if(href_list["listdupes"])
+ var/list/L = locate(href_list["listdupes"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return TRUE
+
+ uniqueList_inplace(L)
+ log_to_dd("### ListVarEdit by [src]: /list contents: CLEAR DUPES")
+ log_admin("[key_name(src)] modified list's contents: CLEAR DUPES")
+ message_admins("[key_name_admin(src)] modified list's contents: CLEAR DUPES")
+ return TRUE
+
+ if(href_list["listnulls"])
+ var/list/L = locate(href_list["listnulls"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return TRUE
+
+ listclearnulls(L)
+ log_to_dd("### ListVarEdit by [src]: /list contents: CLEAR NULLS")
+ log_admin("[key_name(src)] modified list's contents: CLEAR NULLS")
+ message_admins("[key_name_admin(src)] modified list's contents: CLEAR NULLS")
+ return TRUE
+
+ if(href_list["listlen"])
+ var/list/L = locate(href_list["listlen"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return TRUE
+ var/value = vv_get_value(VV_NUM)
+ if(value["class"] != VV_NUM)
+ return TRUE
+
+ L.len = value["value"]
+ log_to_dd("### ListVarEdit by [src]: /list len: [L.len]")
+ log_admin("[key_name(src)] modified list's len: [L.len]")
+ message_admins("[key_name_admin(src)] modified list's len: [L.len]")
+ return TRUE
+
+ if(href_list["listshuffle"])
+ var/list/L = locate(href_list["listshuffle"])
+ if(!istype(L))
+ to_chat(usr, "This can only be used on instances of type /list")
+ return TRUE
+
+ shuffle_inplace(L)
+ log_to_dd("### ListVarEdit by [src]: /list contents: SHUFFLE")
+ log_admin("[key_name(src)] modified list's contents: SHUFFLE")
+ message_admins("[key_name_admin(src)] modified list's contents: SHUFFLE")
+ return TRUE
+
+ if(href_list["listrefresh"])
+ debug_variables(locate(href_list["listrefresh"]))
+ return TRUE
\ No newline at end of file
diff --git a/code/datums/diseases/_MobProcs.dm b/code/datums/diseases/_MobProcs.dm
index 48e4366c825..86c2337c827 100644
--- a/code/datums/diseases/_MobProcs.dm
+++ b/code/datums/diseases/_MobProcs.dm
@@ -134,7 +134,7 @@
/mob/living/carbon/human/CanContractDisease(datum/disease/D)
- if(species.virus_immune && !D.bypasses_immunity)
+ if((VIRUSIMMUNE in species.species_traits) && !D.bypasses_immunity)
return 0
for(var/thing in D.required_organs)
if(!((locate(thing) in bodyparts) || (locate(thing) in internal_organs)))
diff --git a/code/datums/mixed.dm b/code/datums/mixed.dm
index 31f7d67af36..391b7090ad4 100644
--- a/code/datums/mixed.dm
+++ b/code/datums/mixed.dm
@@ -1,5 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
/datum/data
var/name = "data"
var/size = 1.0
diff --git a/code/datums/outfits/outfit_admin.dm b/code/datums/outfits/outfit_admin.dm
index d70fc1ca4ac..717599f112c 100644
--- a/code/datums/outfits/outfit_admin.dm
+++ b/code/datums/outfits/outfit_admin.dm
@@ -17,8 +17,6 @@
if(special_icon)
I.icon_state = special_icon
-/datum/outfit/admin
-
/datum/outfit/admin/syndicate
name = "Syndicate Agent"
@@ -451,7 +449,8 @@
r_hand = /obj/item/weapon/twohanded/fireaxe
backpack_contents = list(
/obj/item/weapon/storage/box/survival = 1,
- /obj/item/device/flashlight = 1
+ /obj/item/device/flashlight = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofbanana = 1
)
/datum/outfit/admin/tunnel_clown/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
@@ -1042,7 +1041,7 @@
apply_to_card(I, H, get_all_accesses(), "Singuloth Knight")
/datum/outfit/admin/assassin
- name = "Assassin"
+ name = "Syndicate Assassin"
uniform = /obj/item/clothing/under/suit_jacket
suit = /obj/item/clothing/suit/wcoat
@@ -1053,35 +1052,18 @@
glasses = /obj/item/clothing/glasses/sunglasses
id = /obj/item/weapon/card/id/syndicate
l_pocket = /obj/item/weapon/melee/energy/sword/saber
- l_hand = /obj/item/weapon/storage/secure/briefcase
+ l_hand = /obj/item/weapon/storage/secure/briefcase/reaper
pda = /obj/item/device/pda/heads
backpack_contents = list(
/obj/item/weapon/storage/box/survival = 1,
/obj/item/device/flashlight = 1
)
- var/briefcase_contents = list(
- /obj/item/stack/spacecash/c1000 = 3,
- /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow = 1,
- /obj/item/weapon/gun/projectile/revolver/mateba = 1,
- /obj/item/ammo_box/a357 = 1,
- /obj/item/weapon/grenade/plastic/c4 = 1
- )
-
/datum/outfit/admin/assassin/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
. = ..()
if(visualsOnly)
return
- var/obj/item/weapon/storage/secure/briefcase/B = H.l_hand
- if(istype(B))
- for(var/obj/item/I in B)
- qdel(I)
- for(var/path in briefcase_contents)
- var/number = backpack_contents[path]
- for(var/i = 0, i < number, i++)
- B.handle_item_insertion(new path(B), 1)
-
var/obj/item/weapon/implant/dust/D = new /obj/item/weapon/implant/dust(H)
D.implant(H)
diff --git a/code/datums/shuttles.dm b/code/datums/shuttles.dm
index 3d0f877a3aa..d20255bc57c 100644
--- a/code/datums/shuttles.dm
+++ b/code/datums/shuttles.dm
@@ -45,6 +45,13 @@
description = "Features include: areas for each department, and a small bar."
admin_notes = "Designed to reduce chaos. Each dept requires dept access."
+/datum/map_template/shuttle/emergency/military
+ suffix = "mil"
+ name = "emergency shuttle (military)"
+ description = "Troop transport with point defense turrets."
+ admin_notes = "Designed to ensure a safe evacuation during xeno outbreaks."
+
+
/datum/map_template/shuttle/emergency/clown
suffix = "clown"
name = "Snappop(tm)!"
diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index d32d5bac058..6dba2d9990b 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -13,7 +13,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
to_chat(user, "[user.ranged_ability.name] has been disabled.")
user.ranged_ability.remove_ranged_ability(user)
return TRUE //TRUE for failed, FALSE for passed.
- user.next_click = world.time + CLICK_CD_CLICK_ABILITY
+ user.changeNext_click(CLICK_CD_CLICK_ABILITY)
user.face_atom(A)
return FALSE
diff --git a/code/datums/spells/cluwne.dm b/code/datums/spells/cluwne.dm
index fe0e02bda6d..a3b730cec77 100644
--- a/code/datums/spells/cluwne.dm
+++ b/code/datums/spells/cluwne.dm
@@ -13,7 +13,11 @@
/mob/living/carbon/human/proc/makeCluwne()
to_chat(src, "You feel funny.")
- adjustBrainLoss(80)
+ if(!get_int_organ(/obj/item/organ/internal/brain/cluwne))
+ var/obj/item/organ/internal/brain/cluwne/idiot_brain = new
+ idiot_brain.insert(src, make_cluwne = 0)
+ idiot_brain.dna = dna.Clone()
+ setBrainLoss(80)
nutrition = 9000
overeatduration = 9000
Confused(30)
@@ -25,8 +29,7 @@
mutations.Add(NERVOUS)
dna.SetSEState(NERVOUSBLOCK, 1, 1)
genemutcheck(src, NERVOUSBLOCK, null, MUTCHK_FORCED)
-
- animate_clownspell(src)
+ rename_character(real_name, "cluwne")
unEquip(w_uniform, 1)
unEquip(shoes, 1)
@@ -37,7 +40,6 @@
equip_to_slot_if_possible(new /obj/item/clothing/gloves/cursedclown, slot_gloves, 1, 1, 1)
equip_to_slot_if_possible(new /obj/item/clothing/mask/cursedclown, slot_wear_mask, 1, 1, 1)
equip_to_slot_if_possible(new /obj/item/clothing/shoes/cursedclown, slot_shoes, 1, 1, 1)
- real_name = "cluwne"
/mob/living/carbon/human/proc/makeAntiCluwne()
to_chat(src, "You don't feel very funny.")
@@ -51,8 +53,7 @@
var/obj/item/organ/internal/honktumor/cursed/tumor = get_int_organ(/obj/item/organ/internal/honktumor/cursed)
if(tumor)
- tumor.remove(src, clean_remove = 1)
- qdel(tumor)
+ tumor.remove(src)
else
mutations.Remove(CLUMSY)
mutations.Remove(COMICBLOCK)
@@ -64,8 +65,6 @@
dna.SetSEState(NERVOUSBLOCK, 0)
genemutcheck(src, NERVOUSBLOCK, null, MUTCHK_FORCED)
- animate_clownspell(src)
-
var/obj/item/clothing/under/U = w_uniform
unEquip(w_uniform, 1)
if(U)
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index 674f5bb8106..15d78f37276 100644
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -949,7 +949,8 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
contains = list(/obj/item/pizzabox/margherita,
/obj/item/pizzabox/mushroom,
/obj/item/pizzabox/meat,
- /obj/item/pizzabox/vegetable)
+ /obj/item/pizzabox/vegetable,
+ /obj/item/pizzabox/hawaiian)
cost = 60
containername = "Pizza crate"
@@ -1248,7 +1249,7 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/datum/supply_packs/misc/watertank
name = "Water Tank Crate"
contains = list(/obj/structure/reagent_dispensers/watertank)
- cost = 6
+ cost = 8
containertype = /obj/structure/largecrate
containername = "water tank crate"
@@ -1423,7 +1424,9 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
/obj/item/clothing/mask/gas/mime,
/obj/item/clothing/head/beret,
/obj/item/clothing/suit/suspenders,
- /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing)
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofnothing,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofbanana
+ )
cost = 10
containertype = /obj/structure/closet/crate/secure
containername = "standard costumes"
@@ -1511,6 +1514,22 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
containername = "foam force pistols crate"
contraband = 1
+/datum/supply_packs/misc/bigband
+ name = "Big band instrument collection"
+ contains = list(/obj/item/device/instrument/violin,
+ /obj/item/device/instrument/guitar,
+ /obj/item/device/instrument/eguitar,
+ /obj/item/device/instrument/glockenspiel,
+ /obj/item/device/instrument/accordion,
+ /obj/item/device/instrument/saxophone,
+ /obj/item/device/instrument/trombone,
+ /obj/item/device/instrument/recorder,
+ /obj/item/device/instrument/harmonica,
+ /obj/item/device/instrument/xylophone,
+ /obj/structure/piano)
+ cost = 50
+ containername = "Big band musical instruments collection"
+
/datum/supply_packs/misc/randomised/contraband
num_contained = 5
contains = list(/obj/item/weapon/storage/pill_bottle/random_drug_bottle,
@@ -1644,6 +1663,26 @@ var/list/all_supply_groups = list(supply_emergency,supply_security,supply_engine
)
containername = "shield control board crate"
+///////////// Bathroom Fixtures
+
+/datum/supply_packs/misc/toilet
+ name = "Lavatory Crate"
+ cost = 10
+ contains = list(
+ /obj/item/weapon/bathroom_parts,
+ /obj/item/weapon/bathroom_parts/urinal
+ )
+ containername = "lavatory crate"
+
+/datum/supply_packs/misc/hygiene
+ name = "Hygiene Station Crate"
+ cost = 10
+ contains = list(
+ /obj/item/weapon/bathroom_parts/sink,
+ /obj/item/mounted/shower
+ )
+ containername = "hygiene station crate"
+
//////////////////////////////////////////////////////////////////////////////
//////////////////////////// Vending /////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 14732318aab..8d0e1b408f4 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -863,6 +863,7 @@ var/list/uplink_items = list()
reference = "NNSSS"
cost = 4 //but they aren't
gamemodes = list(/datum/game_mode/nuclear)
+ excludefrom = list()
/datum/uplink_item/stealthy_tools/agent_card
name = "Agent ID Card"
diff --git a/code/defines/procs/dbcore.dm b/code/defines/procs/dbcore.dm
index 35470e8c598..b04a4c3b93a 100644
--- a/code/defines/procs/dbcore.dm
+++ b/code/defines/procs/dbcore.dm
@@ -1,5 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
//cursors
#define Default_Cursor 0
#define Client_Cursor 1
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index d5a6fb13941..24cd0fa6bce 100644
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -30,6 +30,8 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
luminosity = 0
mouse_opacity = 0
invisibility = INVISIBILITY_LIGHTING
+ var/valid_territory = TRUE //used for cult summoning areas on station zlevel
+ var/map_name // Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
var/lightswitch = 1
var/eject = null
@@ -122,6 +124,7 @@ var/list/ghostteleportlocs = list()
power_light = 0
power_equip = 0
power_environ = 0
+ valid_territory = FALSE
outdoors = 1
ambientsounds = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/traitor.ogg')
@@ -150,6 +153,7 @@ var/list/ghostteleportlocs = list()
/area/shuttle
no_teleportlocs = 1
requires_power = 0
+ valid_territory = FALSE
/area/shuttle/arrival
name = "\improper Arrival Shuttle"
@@ -557,6 +561,7 @@ var/list/ghostteleportlocs = list()
name = "\improper Asteroid"
icon_state = "asteroid"
requires_power = 0
+ valid_territory = FALSE
/area/asteroid/cave // -- TLE
name = "\improper Asteroid - Underground"
@@ -884,6 +889,7 @@ var/list/ghostteleportlocs = list()
//Maintenance
/area/maintenance
ambientsounds = list('sound/ambience/ambimaint1.ogg', 'sound/ambience/ambimaint2.ogg', 'sound/ambience/ambimaint3.ogg', 'sound/ambience/ambimaint4.ogg', 'sound/ambience/ambimaint5.ogg')
+ valid_territory = FALSE
/area/maintenance/atmos_control
name = "Atmospherics Maintenance"
@@ -1148,6 +1154,7 @@ var/list/ghostteleportlocs = list()
/area/crew_quarters/sleep
name = "\improper Dormitories"
icon_state = "Sleep"
+ valid_territory = FALSE
/area/crew_quarters/sleep_male
name = "\improper Male Dorm"
@@ -1399,6 +1406,7 @@ var/list/ghostteleportlocs = list()
/area/solar
requires_power = 0
dynamic_lighting = 0
+ valid_territory = FALSE
auxport
name = "\improper Fore Port Solar Array"
@@ -1907,6 +1915,7 @@ area/security/podbay
/area/toxins/test_area
name = "\improper Toxins Test Area"
icon_state = "toxtest"
+ valid_territory = FALSE
/area/toxins/mixing
name = "\improper Toxins Mixing Room"
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 140b6116cd6..723d26a451a 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -25,6 +25,7 @@
layer = 10
uid = ++global_uid
all_areas += src
+ map_name = name // Save the initial (the name set in the map) name of the area.
if(type == /area) // override defaults for space. TODO: make space areas of type /area/space rather than /area
requires_power = 1
@@ -313,14 +314,15 @@
// Ambience goes down here -- make sure to list each area seperately for ease of adding things in later, thanks! Note: areas adjacent to each other should have the same sounds to prevent cutoff when possible.- LastyScratch
if(L && L.client && !L.client.ambience_playing && (L.client.prefs.sound & SOUND_BUZZ)) //split off the white noise from the rest of the ambience because of annoyance complaints - Kluys
L.client.ambience_playing = 1
- L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2)
- else if(L && L.client && !(L.client.prefs.sound & SOUND_BUZZ)) L.client.ambience_playing = 0
+ L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = CHANNEL_BUZZ)
+ else if(L && L.client && !(L.client.prefs.sound & SOUND_BUZZ))
+ L.client.ambience_playing = 0
if(prob(35) && L && L.client && (L.client.prefs.sound & SOUND_AMBIENCE))
var/sound = pick(ambientsounds)
if(!L.client.played)
- L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = 1)
+ L << sound(sound, repeat = 0, wait = 0, volume = 25, channel = CHANNEL_AMBIENCE)
L.client.played = 1
spawn(600) //ewww - this is very very bad
if(L.&& L.client)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 8c12e452d1d..22cadfaa659 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -616,7 +616,20 @@ var/list/blood_splatter_icons = list()
/atom/proc/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
return
-/atom/on_varedit(modified_var)
+/atom/vv_edit_var(var_name, var_value)
if(!Debug2)
admin_spawned = TRUE
- ..()
+ . = ..()
+ switch(var_name)
+ if("light_power", "light_range", "light_color")
+ update_light()
+
+
+/atom/vv_get_dropdown()
+ . = ..()
+ var/turf/curturf = get_turf(src)
+ if(curturf)
+ .["Jump to turf"] = "?_src_=holder;adminplayerobservecoodjump=1;X=[curturf.x];Y=[curturf.y];Z=[curturf.z]"
+ .["Add reagent"] = "?_src_=vars;addreagent=[UID()]"
+ .["Trigger explosion"] = "?_src_=vars;explode=[UID()]"
+ .["Trigger EM pulse"] = "?_src_=vars;emp=[UID()]"
\ No newline at end of file
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 906706de62e..1ce51657e85 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -138,12 +138,12 @@
return
/atom/movable/Bump(atom/A, yes) //the "yes" arg is to differentiate our Bump proc from byond's, without it every Bump() call would become a double Bump().
- if(A && yes)
- if(throwing)
- throwing.hit_atom(A)
- . = 1
- if(!A || qdeleted(A))
- return
+ if(A && yes)
+ if(throwing)
+ throwing.hit_atom(A)
+ . = 1
+ if(!A || qdeleted(A))
+ return
A.Bumped(src)
/atom/movable/proc/forceMove(atom/destination)
@@ -359,3 +359,14 @@
dense_object_backup = AM
break
. = dense_object_backup
+
+/atom/movable/proc/transfer_prints_to(atom/movable/target = null, overwrite = FALSE)
+ if(!target)
+ return
+ if(overwrite)
+ target.fingerprints = fingerprints
+ target.fingerprintshidden = fingerprintshidden
+ else
+ target.fingerprints += fingerprints
+ target.fingerprintshidden += fingerprintshidden
+ target.fingerprintslast = fingerprintslast
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 7052b62e97f..604e92a47e0 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -148,7 +148,7 @@
holder.icon_state = "hudxeno"
else if(check_virus())
holder.icon_state = "hudill"
- else if(has_brain_worms() && B != null && B.controlling)
+ else if(B && B.controlling)
holder.icon_state = "hudbrainworm"
else
holder.icon_state = "hudhealthy"
@@ -197,6 +197,9 @@
var/datum/data/record/R = find_record("name", perpname, data_core.security)
if(R)
switch(R.fields["criminal"])
+ if("*Execute*")
+ holder.icon_state = "hudexecute"
+ return
if("*Arrest*")
holder.icon_state = "hudwanted"
return
diff --git a/code/game/dna/dna2.dm b/code/game/dna/dna2.dm
index a9e0c49a122..f21c2948b01 100644
--- a/code/game/dna/dna2.dm
+++ b/code/game/dna/dna2.dm
@@ -159,9 +159,9 @@ var/global/list/bad_blocks[0]
head_traits_to_dna(H)
eye_color_to_dna(eyes_organ)
- SetUIValueRange(DNA_UI_SKIN_R, character.r_skin, 255, 1)
- SetUIValueRange(DNA_UI_SKIN_G, character.g_skin, 255, 1)
- SetUIValueRange(DNA_UI_SKIN_B, character.b_skin, 255, 1)
+ SetUIValueRange(DNA_UI_SKIN_R, color2R(character.skin_colour), 255, 1)
+ SetUIValueRange(DNA_UI_SKIN_G, color2G(character.skin_colour), 255, 1)
+ SetUIValueRange(DNA_UI_SKIN_B, color2B(character.skin_colour), 255, 1)
SetUIValueRange(DNA_UI_HEAD_MARK_R, color2R(character.m_colours["head"]), 255, 1)
SetUIValueRange(DNA_UI_HEAD_MARK_G, color2G(character.m_colours["head"]), 255, 1)
diff --git a/code/game/dna/dna2_domutcheck.dm b/code/game/dna/dna2_domutcheck.dm
index 6175d547d63..f2ad2b2fe03 100644
--- a/code/game/dna/dna2_domutcheck.dm
+++ b/code/game/dna/dna2_domutcheck.dm
@@ -16,7 +16,7 @@
/proc/genemutcheck(var/mob/living/M, var/block, var/connected=null, var/flags=0)
if(ishuman(M)) // Would've done this via species instead of type, but the basic mob doesn't have a species, go figure.
var/mob/living/carbon/human/H = M
- if(H.species.flags & NO_DNA)
+ if(NO_DNA in H.species.species_traits)
return
if(!M)
return
diff --git a/code/game/dna/dna2_helpers.dm b/code/game/dna/dna2_helpers.dm
index c5f9ce2b7fe..6c05dfd6f2b 100644
--- a/code/game/dna/dna2_helpers.dm
+++ b/code/game/dna/dna2_helpers.dm
@@ -134,13 +134,13 @@
var/obj/item/organ/external/head/head_organ = H.get_organ("head")
var/obj/item/organ/internal/eyes/eye_organ = H.get_int_organ(/obj/item/organ/internal/eyes)
var/datum/species/S = H.species
- dna.write_head_attributes(head_organ)
- dna.write_eyes_attributes(eye_organ)
+ if(istype(head_organ))
+ dna.write_head_attributes(head_organ)
+ if(istype(eye_organ))
+ dna.write_eyes_attributes(eye_organ)
H.update_eyes()
- H.r_skin = dna.GetUIValueRange(DNA_UI_SKIN_R, 255)
- H.g_skin = dna.GetUIValueRange(DNA_UI_SKIN_G, 255)
- H.b_skin = dna.GetUIValueRange(DNA_UI_SKIN_B, 255)
+ H.skin_colour = rgb(dna.GetUIValueRange(DNA_UI_SKIN_R, 255), dna.GetUIValueRange(DNA_UI_SKIN_G, 255), dna.GetUIValueRange(DNA_UI_SKIN_B, 255))
H.m_colours["head"] = rgb(dna.GetUIValueRange(DNA_UI_HEAD_MARK_R, 255), dna.GetUIValueRange(DNA_UI_HEAD_MARK_G, 255), dna.GetUIValueRange(DNA_UI_HEAD_MARK_B, 255))
H.m_colours["body"] = rgb(dna.GetUIValueRange(DNA_UI_BODY_MARK_R, 255), dna.GetUIValueRange(DNA_UI_BODY_MARK_G, 255), dna.GetUIValueRange(DNA_UI_BODY_MARK_B, 255))
@@ -185,50 +185,31 @@
/datum/dna/proc/write_head_attributes(obj/item/organ/external/head/head_organ)
//Hair
- var/hair = GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_list.len)
- if((hair > 0) && (hair <= hair_styles_list.len))
- head_organ.h_style = hair_styles_list[hair]
+ var/hair = GetUIValueRange(DNA_UI_HAIR_STYLE,hair_styles_full_list.len)
+ if((hair > 0) && (hair <= hair_styles_full_list.len))
+ head_organ.h_style = hair_styles_full_list[hair]
- head_organ.r_hair = GetUIValueRange(DNA_UI_HAIR_R, 255)
- head_organ.g_hair = GetUIValueRange(DNA_UI_HAIR_G, 255)
- head_organ.b_hair = GetUIValueRange(DNA_UI_HAIR_B, 255)
-
- head_organ.r_hair_sec = GetUIValueRange(DNA_UI_HAIR2_R, 255)
- head_organ.g_hair_sec = GetUIValueRange(DNA_UI_HAIR2_G, 255)
- head_organ.b_hair_sec = GetUIValueRange(DNA_UI_HAIR2_B, 255)
+ head_organ.hair_colour = rgb(head_organ.dna.GetUIValueRange(DNA_UI_HAIR_R, 255), head_organ.dna.GetUIValueRange(DNA_UI_HAIR_G, 255), head_organ.dna.GetUIValueRange(DNA_UI_HAIR_B, 255))
+ head_organ.sec_hair_colour = rgb(head_organ.dna.GetUIValueRange(DNA_UI_HAIR2_R, 255), head_organ.dna.GetUIValueRange(DNA_UI_HAIR2_G, 255), head_organ.dna.GetUIValueRange(DNA_UI_HAIR2_B, 255))
//Facial Hair
var/beard = GetUIValueRange(DNA_UI_BEARD_STYLE,facial_hair_styles_list.len)
if((beard > 0) && (beard <= facial_hair_styles_list.len))
head_organ.f_style = facial_hair_styles_list[beard]
- head_organ.r_facial = GetUIValueRange(DNA_UI_BEARD_R, 255)
- head_organ.g_facial = GetUIValueRange(DNA_UI_BEARD_G, 255)
- head_organ.b_facial = GetUIValueRange(DNA_UI_BEARD_B, 255)
-
- head_organ.r_facial_sec = GetUIValueRange(DNA_UI_BEARD2_R, 255)
- head_organ.g_facial_sec = GetUIValueRange(DNA_UI_BEARD2_G, 255)
- head_organ.b_facial_sec = GetUIValueRange(DNA_UI_BEARD2_B, 255)
+ head_organ.facial_colour = rgb(head_organ.dna.GetUIValueRange(DNA_UI_BEARD_R, 255), head_organ.dna.GetUIValueRange(DNA_UI_BEARD_G, 255), head_organ.dna.GetUIValueRange(DNA_UI_BEARD_B, 255))
+ head_organ.sec_facial_colour = rgb(head_organ.dna.GetUIValueRange(DNA_UI_BEARD2_R, 255), head_organ.dna.GetUIValueRange(DNA_UI_BEARD2_G, 255), head_organ.dna.GetUIValueRange(DNA_UI_BEARD2_B, 255))
//Head Accessories
var/headacc = GetUIValueRange(DNA_UI_HACC_STYLE,head_accessory_styles_list.len)
if((headacc > 0) && (headacc <= head_accessory_styles_list.len))
head_organ.ha_style = head_accessory_styles_list[headacc]
- head_organ.r_headacc = GetUIValueRange(DNA_UI_HACC_R, 255)
- head_organ.g_headacc = GetUIValueRange(DNA_UI_HACC_G, 255)
- head_organ.b_headacc = GetUIValueRange(DNA_UI_HACC_B, 255)
+ head_organ.headacc_colour = rgb(head_organ.dna.GetUIValueRange(DNA_UI_HACC_R, 255), head_organ.dna.GetUIValueRange(DNA_UI_HACC_G, 255), head_organ.dna.GetUIValueRange(DNA_UI_HACC_B, 255))
// This proc gives the DNA info for eye color to the given eyes
/datum/dna/proc/write_eyes_attributes(obj/item/organ/internal/eyes/eyes_organ)
- var/red = GetUIValueRange(DNA_UI_EYES_R, 255)
- var/green = GetUIValueRange(DNA_UI_EYES_G, 255)
- var/blue = GetUIValueRange(DNA_UI_EYES_B, 255)
- eyes_organ.eye_colour = list(
- red,
- green,
- blue
- )
+ eyes_organ.eye_colour = rgb(eyes_organ.dna.GetUIValueRange(DNA_UI_EYES_R, 255), eyes_organ.dna.GetUIValueRange(DNA_UI_EYES_G, 255), eyes_organ.dna.GetUIValueRange(DNA_UI_EYES_B, 255))
/*
TRAIT CHANGING PROCS
@@ -238,51 +219,48 @@
// In absence of eyes, possibly randomize the eye color DNA?
return
- var/eye_red = eyes_organ.eye_colour[1]
- var/eye_green = eyes_organ.eye_colour[2]
- var/eye_blue = eyes_organ.eye_colour[3]
- SetUIValueRange(DNA_UI_EYES_R, eye_red, 255, 1)
- SetUIValueRange(DNA_UI_EYES_G, eye_green, 255, 1)
- SetUIValueRange(DNA_UI_EYES_B, eye_blue, 255, 1)
+ SetUIValueRange(DNA_UI_EYES_R, color2R(eyes_organ.eye_colour), 255, 1)
+ SetUIValueRange(DNA_UI_EYES_G, color2G(eyes_organ.eye_colour), 255, 1)
+ SetUIValueRange(DNA_UI_EYES_B, color2B(eyes_organ.eye_colour), 255, 1)
-/datum/dna/proc/head_traits_to_dna(obj/item/organ/external/head/H)
- if(!H)
+/datum/dna/proc/head_traits_to_dna(obj/item/organ/external/head/head_organ)
+ if(!head_organ)
log_runtime(EXCEPTION("Attempting to reset DNA from a missing head!"), src)
return
- if(!H.h_style)
- H.h_style = "Skinhead"
- var/hair = hair_styles_list.Find(H.h_style)
+ if(!head_organ.h_style)
+ head_organ.h_style = "Skinhead"
+ var/hair = hair_styles_full_list.Find(head_organ.h_style)
// Facial Hair
- if(!H.f_style)
- H.f_style = "Shaved"
- var/beard = facial_hair_styles_list.Find(H.f_style)
+ if(!head_organ.f_style)
+ head_organ.f_style = "Shaved"
+ var/beard = facial_hair_styles_list.Find(head_organ.f_style)
// Head Accessory
- if(!H.ha_style)
- H.ha_style = "None"
- var/headacc = head_accessory_styles_list.Find(H.ha_style)
+ if(!head_organ.ha_style)
+ head_organ.ha_style = "None"
+ var/headacc = head_accessory_styles_list.Find(head_organ.ha_style)
- SetUIValueRange(DNA_UI_HAIR_R, H.r_hair, 255, 1)
- SetUIValueRange(DNA_UI_HAIR_G, H.g_hair, 255, 1)
- SetUIValueRange(DNA_UI_HAIR_B, H.b_hair, 255, 1)
+ SetUIValueRange(DNA_UI_HAIR_R, color2R(head_organ.hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR_G, color2G(head_organ.hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR_B, color2B(head_organ.hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR2_R, H.r_hair_sec, 255, 1)
- SetUIValueRange(DNA_UI_HAIR2_G, H.g_hair_sec, 255, 1)
- SetUIValueRange(DNA_UI_HAIR2_B, H.b_hair_sec, 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_R, color2R(head_organ.sec_hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_G, color2G(head_organ.sec_hair_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HAIR2_B, color2B(head_organ.sec_hair_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD_R, H.r_facial, 255, 1)
- SetUIValueRange(DNA_UI_BEARD_G, H.g_facial, 255, 1)
- SetUIValueRange(DNA_UI_BEARD_B, H.b_facial, 255, 1)
+ SetUIValueRange(DNA_UI_BEARD_R, color2R(head_organ.facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD_G, color2G(head_organ.facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD_B, color2B(head_organ.facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_BEARD2_R, H.r_facial_sec, 255, 1)
- SetUIValueRange(DNA_UI_BEARD2_G, H.g_facial_sec, 255, 1)
- SetUIValueRange(DNA_UI_BEARD2_B, H.b_facial_sec, 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_R, color2R(head_organ.sec_facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_G, color2G(head_organ.sec_facial_colour), 255, 1)
+ SetUIValueRange(DNA_UI_BEARD2_B, color2B(head_organ.sec_facial_colour), 255, 1)
- SetUIValueRange(DNA_UI_HACC_R, H.r_headacc, 255, 1)
- SetUIValueRange(DNA_UI_HACC_G, H.g_headacc, 255, 1)
- SetUIValueRange(DNA_UI_HACC_B, H.b_headacc, 255, 1)
+ SetUIValueRange(DNA_UI_HACC_R, color2R(head_organ.headacc_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HACC_G, color2G(head_organ.headacc_colour), 255, 1)
+ SetUIValueRange(DNA_UI_HACC_B, color2B(head_organ.headacc_colour), 255, 1)
- SetUIValueRange(DNA_UI_HAIR_STYLE, hair, hair_styles_list.len, 1)
+ SetUIValueRange(DNA_UI_HAIR_STYLE, hair, hair_styles_full_list.len, 1)
SetUIValueRange(DNA_UI_BEARD_STYLE, beard, facial_hair_styles_list.len, 1)
SetUIValueRange(DNA_UI_HACC_STYLE, headacc, head_accessory_styles_list.len, 1)
diff --git a/code/game/dna/dna_modifier.dm b/code/game/dna/dna_modifier.dm
index 0533afe2911..43054c24923 100644
--- a/code/game/dna/dna_modifier.dm
+++ b/code/game/dna/dna_modifier.dm
@@ -327,7 +327,7 @@
if(ishuman(occupant))
var/mob/living/carbon/human/H = occupant
- if((H.species.flags & NO_DNA))
+ if(NO_DNA in H.species.species_traits)
return 1
var/radiation_protection = occupant.run_armor_check(null, "rad", "Your clothes feel warm.", "Your clothes feel warm.")
diff --git a/code/game/dna/genes/goon_disabilities.dm b/code/game/dna/genes/goon_disabilities.dm
index 11da3ad6c07..e59dd3fc558 100644
--- a/code/game/dna/genes/goon_disabilities.dm
+++ b/code/game/dna/genes/goon_disabilities.dm
@@ -44,7 +44,7 @@
return 0
if(ishuman(M))
var/mob/living/carbon/human/H = M
- if(H.species && H.species.flags & RADIMMUNE && !(flags & MUTCHK_FORCED))
+ if((RADIMMUNE in H.species.species_traits) && !(flags & MUTCHK_FORCED))
return 0
return 1
diff --git a/code/game/dna/genes/vg_powers.dm b/code/game/dna/genes/vg_powers.dm
index 32a6a58cbb3..f33ab1e2dfe 100644
--- a/code/game/dna/genes/vg_powers.dm
+++ b/code/game/dna/genes/vg_powers.dm
@@ -45,16 +45,9 @@
else
M.change_gender(FEMALE)
- var/eyes_red = 0
- var/eyes_green = 0
- var/eyes_blue = 0
- if(eyes_organ)
- eyes_red = eyes_organ.eye_colour[1]
- eyes_green = eyes_organ.eye_colour[2]
- eyes_blue = eyes_organ.eye_colour[3]
- var/new_eyes = input("Please select eye color.", "Character Generation", rgb(eyes_red,eyes_green,eyes_blue)) as null|color
+ var/new_eyes = input("Please select eye color.", "Character Generation", eyes_organ.eye_colour) as null|color
if(new_eyes)
- M.change_eye_color(color2R(new_eyes), color2G(new_eyes), color2B(new_eyes))
+ M.change_eye_color(new_eyes)
//Alt heads.
if(head_organ.species.bodyflags & HAS_ALT_HEADS)
@@ -71,15 +64,15 @@
if(new_style)
M.change_hair(new_style)
- var/new_hair = input("Please select hair color.", "Character Generation", rgb(head_organ.r_hair, head_organ.g_hair, head_organ.b_hair)) as null|color
+ var/new_hair = input("Please select hair color.", "Character Generation", head_organ.hair_colour) as null|color
if(new_hair)
- M.change_hair_color(color2R(new_hair), color2G(new_hair), color2B(new_hair))
+ M.change_hair_color(new_hair)
- var/datum/sprite_accessory/hair_style = hair_styles_list[head_organ.h_style]
+ var/datum/sprite_accessory/hair_style = hair_styles_public_list[head_organ.h_style]
if(hair_style.secondary_theme && !hair_style.no_sec_colour)
- new_hair = input("Please select secondary hair color.", "Character Generation", rgb(head_organ.r_hair_sec, head_organ.g_hair_sec, head_organ.b_hair_sec)) as null|color
+ new_hair = input("Please select secondary hair color.", "Character Generation", head_organ.sec_hair_colour) as null|color
if(new_hair)
- M.change_hair_color(color2R(new_hair), color2G(new_hair), color2B(new_hair), 1)
+ M.change_hair_color(new_hair, 1)
// facial hair
var/list/valid_facial_hairstyles = M.generate_valid_facial_hairstyles()
@@ -88,15 +81,15 @@
if(new_style)
M.change_facial_hair(new_style)
- var/new_facial = input("Please select facial hair color.", "Character Generation", rgb(head_organ.r_facial, head_organ.g_facial, head_organ.b_facial)) as null|color
+ var/new_facial = input("Please select facial hair color.", "Character Generation", head_organ.facial_colour) as null|color
if(new_facial)
- M.change_facial_hair_color(color2R(new_facial), color2G(new_facial), color2B(new_facial))
+ M.change_facial_hair_color(new_facial)
var/datum/sprite_accessory/facial_hair_style = facial_hair_styles_list[head_organ.f_style]
if(facial_hair_style.secondary_theme && !facial_hair_style.no_sec_colour)
- new_facial = input("Please select secondary facial hair color.", "Character Generation", rgb(head_organ.r_facial_sec, head_organ.g_facial_sec, head_organ.b_facial_sec)) as null|color
+ new_facial = input("Please select secondary facial hair color.", "Character Generation", head_organ.sec_facial_colour) as null|color
if(new_facial)
- M.change_facial_hair_color(color2R(new_facial), color2G(new_facial), color2B(new_facial), 1)
+ M.change_facial_hair_color(new_facial, 1)
//Head accessory.
if(head_organ.species.bodyflags & HAS_HEAD_ACCESSORY)
@@ -105,9 +98,9 @@
if(new_head_accessory)
M.change_head_accessory(new_head_accessory)
- var/new_head_accessory_colour = input("Please select head accessory colour.", "Character Generation", rgb(head_organ.r_headacc, head_organ.g_headacc, head_organ.b_headacc)) as null|color
+ var/new_head_accessory_colour = input("Please select head accessory colour.", "Character Generation", head_organ.headacc_colour) as null|color
if(new_head_accessory_colour)
- M.change_head_accessory_color(color2R(new_head_accessory_colour), color2G(new_head_accessory_colour), color2B(new_head_accessory_colour))
+ M.change_head_accessory_color(new_head_accessory_colour)
//Body accessory.
if(M.species.tail && M.species.bodyflags & HAS_TAIL)
@@ -174,9 +167,9 @@
//Skin colour.
if(M.species.bodyflags & HAS_SKIN_COLOR)
- var/new_body_colour = input("Please select body colour.", "Character Generation", rgb(M.r_skin, M.g_skin, M.b_skin)) as null|color
+ var/new_body_colour = input("Please select body colour.", "Character Generation", M.skin_colour) as null|color
if(new_body_colour)
- M.change_skin_color(color2R(new_body_colour), color2G(new_body_colour), color2B(new_body_colour))
+ M.change_skin_color(new_body_colour)
M.update_dna()
diff --git a/code/game/gamemodes/blob/blob.dm b/code/game/gamemodes/blob/blob.dm
index 336d66b8df8..f36e763a4a0 100644
--- a/code/game/gamemodes/blob/blob.dm
+++ b/code/game/gamemodes/blob/blob.dm
@@ -1,5 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
//Few global vars to track the blob
var/list/blobs = list()
var/list/blob_cores = list()
diff --git a/code/game/gamemodes/blob/blob_report.dm b/code/game/gamemodes/blob/blob_report.dm
index 4c0e3dc3921..d4a458f8f78 100644
--- a/code/game/gamemodes/blob/blob_report.dm
+++ b/code/game/gamemodes/blob/blob_report.dm
@@ -1,5 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
/datum/game_mode/blob/proc/send_intercept(var/report = 1)
var/intercepttext = ""
var/interceptname = ""
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 5c3f94a44a3..a9c5882094d 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -1,3 +1,7 @@
+#define LING_FAKEDEATH_TIME 400 //40 seconds
+#define LING_DEAD_GENETICDAMAGE_HEAL_CAP 50 //The lowest value of geneticdamage handle_changeling() can take it to while dead.
+#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
+
var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon","Zeta","Eta","Theta","Iota","Kappa","Lambda","Mu","Nu","Xi","Omicron","Pi","Rho","Sigma","Tau","Upsilon","Phi","Chi","Psi","Omega")
/datum/game_mode
@@ -253,9 +257,14 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
else
changelingID = "[honorific] [rand(1,999)]"
-/datum/changeling/proc/regenerate()
- chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
- geneticdamage = max(0, geneticdamage-1)
+/datum/changeling/proc/regenerate(mob/living/carbon/the_ling)
+ if(istype(the_ling))
+ if(the_ling.stat == DEAD)
+ chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), (chem_storage*0.5))
+ geneticdamage = max(LING_DEAD_GENETICDAMAGE_HEAL_CAP,geneticdamage-1)
+ else //not dead? no chem/geneticdamage caps.
+ chem_charges = min(max(0, chem_charges + chem_recharge_rate - chem_recharge_slowdown), chem_storage)
+ geneticdamage = max(0, geneticdamage-1)
/datum/changeling/proc/GetDNA(dna_owner)
for(var/datum/dna/DNA in (absorbed_dna + protected_dna))
@@ -307,7 +316,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
to_chat(user, "DNA of [target] is ruined beyond usability!")
return
- if(T.species.flags & NO_DNA)
+ if(NO_DNA in T.species.species_traits)
to_chat(user, "This creature does not have DNA!")
return
@@ -317,4 +326,4 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
return 1
/proc/can_absorb_species(datum/species/S)
- return !(S.flags & NO_DNA)
+ return !(NO_DNA in S.species_traits)
\ No newline at end of file
diff --git a/code/game/gamemodes/changeling/changeling_power.dm b/code/game/gamemodes/changeling/changeling_power.dm
index 6d03a864692..c01f335ba08 100644
--- a/code/game/gamemodes/changeling/changeling_power.dm
+++ b/code/game/gamemodes/changeling/changeling_power.dm
@@ -15,6 +15,7 @@
var/req_stat = CONSCIOUS // CONSCIOUS, UNCONSCIOUS or DEAD
var/genetic_damage = 0 // genetic damage caused by using the sting. Nothing to do with cloneloss.
var/max_genetic_damage = 100 // hard counter for spamming abilities. Not used/balanced much yet.
+ var/always_keep = 0 // important for abilities like regenerate that screw you if you lose them.
/obj/effect/proc_holder/changeling/proc/on_purchase(var/mob/user)
return
diff --git a/code/game/gamemodes/changeling/evolution_menu.dm b/code/game/gamemodes/changeling/evolution_menu.dm
index 4a6b3a2bd2c..d690f095236 100644
--- a/code/game/gamemodes/changeling/evolution_menu.dm
+++ b/code/game/gamemodes/changeling/evolution_menu.dm
@@ -407,7 +407,7 @@ var/list/sting_paths
mind.changeling.changeling_speak = 0
mind.changeling.reset()
for(var/obj/effect/proc_holder/changeling/p in mind.changeling.purchasedpowers)
- if(p.dna_cost == 0 && keep_free_powers)
+ if((p.dna_cost == 0 && keep_free_powers) || p.always_keep)
continue
mind.changeling.purchasedpowers -= p
p.on_refund(src)
diff --git a/code/game/gamemodes/changeling/powers/absorb.dm b/code/game/gamemodes/changeling/powers/absorb.dm
index 06402a584b7..50b17dfa6ea 100644
--- a/code/game/gamemodes/changeling/powers/absorb.dm
+++ b/code/game/gamemodes/changeling/powers/absorb.dm
@@ -1,5 +1,3 @@
-#define LING_ABSORB_RECENT_SPEECH 8 //The amount of recent spoken lines to gain on absorbing a mob
-
/obj/effect/proc_holder/changeling/absorbDNA
name = "Absorb DNA"
desc = "Absorb the DNA of our victim."
diff --git a/code/game/gamemodes/changeling/powers/biodegrade.dm b/code/game/gamemodes/changeling/powers/biodegrade.dm
new file mode 100644
index 00000000000..5e4b0e7fa12
--- /dev/null
+++ b/code/game/gamemodes/changeling/powers/biodegrade.dm
@@ -0,0 +1,82 @@
+/obj/effect/proc_holder/changeling/biodegrade
+ name = "Biodegrade"
+ desc = "Dissolves restraints or other objects preventing free movement."
+ helptext = "This is obvious to nearby people, and can destroy standard restraints and closets."
+ chemical_cost = 30 //High cost to prevent spam
+ dna_cost = 2
+ req_human = 1
+
+/obj/effect/proc_holder/changeling/biodegrade/sting_action(mob/living/carbon/human/user)
+ var/used = FALSE // only one form of shackles removed per use
+ if(!user.restrained() && !istype(user.loc, /obj/structure/closet) && !istype(user.loc, /obj/structure/spider/cocoon))
+ to_chat(user, "We are already free!")
+ return FALSE
+
+ if(user.handcuffed)
+ var/obj/O = user.get_item_by_slot(slot_handcuffed)
+ if(!istype(O))
+ return FALSE
+ user.visible_message("[user] vomits a glob of acid on \his [O]!", \
+ "We vomit acidic ooze onto our restraints!")
+ addtimer(src, "dissolve_handcuffs", 30, FALSE, user, O)
+ used = TRUE
+
+ if(user.wear_suit && user.wear_suit.breakouttime && !used)
+ var/obj/item/clothing/suit/S = user.get_item_by_slot(slot_wear_suit)
+ if(!istype(S))
+ return FALSE
+ user.visible_message("[user] vomits a glob of acid across the front of \his [S]!", \
+ "We vomit acidic ooze onto our straight jacket!")
+ addtimer(src, "dissolve_straightjacket", 30, FALSE, user, S)
+ used = TRUE
+
+
+ if(istype(user.loc, /obj/structure/closet) && !used)
+ var/obj/structure/closet/C = user.loc
+ if(!istype(C))
+ return FALSE
+ C.visible_message("[C]'s hinges suddenly begin to melt and run!")
+ to_chat(user, "We vomit acidic goop onto the interior of [C]!")
+ addtimer(src, "open_closet", 70, FALSE, user, C)
+ used = TRUE
+
+ if(istype(user.loc, /obj/structure/spider/cocoon) && !used)
+ var/obj/structure/spider/cocoon/C = user.loc
+ if(!istype(C))
+ return FALSE
+ C.visible_message("[src] shifts and starts to fall apart!")
+ to_chat(user, "We secrete acidic enzymes from our skin and begin melting our cocoon...")
+ addtimer(src, "dissolve_cocoon", 25, FALSE, user, C) //Very short because it's just webs
+ used = TRUE
+
+ if(used)
+ feedback_add_details("changeling_powers","BD")
+ return TRUE
+
+/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_handcuffs(mob/living/carbon/human/user, obj/O)
+ if(O && user.handcuffed == O)
+ user.unEquip(O)
+ O.visible_message("[O] dissolves into a puddle of sizzling goop.")
+ O.forceMove(get_turf(user))
+ qdel(O)
+
+/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_straightjacket(mob/living/carbon/human/user, obj/S)
+ if(S && user.wear_suit == S)
+ user.unEquip(S)
+ S.visible_message("[S] dissolves into a puddle of sizzling goop.")
+ S.forceMove(get_turf(user))
+ qdel(S)
+
+/obj/effect/proc_holder/changeling/biodegrade/proc/open_closet(mob/living/carbon/human/user, obj/structure/closet/C)
+ if(C && user.loc == C)
+ C.visible_message("[C]'s door breaks and opens!")
+ C.welded = FALSE
+ C.locked = FALSE
+ C.broken = TRUE
+ C.open()
+ to_chat(user, "We open the container restraining us!")
+
+/obj/effect/proc_holder/changeling/biodegrade/proc/dissolve_cocoon(mob/living/carbon/human/user, obj/structure/spider/cocoon/C)
+ if(C && user.loc == C)
+ qdel(C) //The cocoon's destroy will move the changeling outside of it without interference
+ to_chat(user, "We dissolve the cocoon!")
diff --git a/code/game/gamemodes/changeling/powers/chameleon_skin.dm b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
new file mode 100644
index 00000000000..07340cf3e84
--- /dev/null
+++ b/code/game/gamemodes/changeling/powers/chameleon_skin.dm
@@ -0,0 +1,27 @@
+/obj/effect/proc_holder/changeling/chameleon_skin
+ name = "Chameleon Skin"
+ desc = "Our skin pigmentation rapidly changes to suit our current environment."
+ helptext = "Allows us to become invisible after a few seconds of standing still. Can be toggled on and off."
+ dna_cost = 2
+ chemical_cost = 25
+ req_human = 1
+
+/obj/effect/proc_holder/changeling/chameleon_skin/sting_action(mob/user)
+ var/mob/living/carbon/human/H = user //SHOULD always be human, because req_human = 1
+ if(!istype(H)) // req_human could be done in can_sting stuff.
+ return
+ if(H.dna.GetSEState(CHAMELEONBLOCK))
+ H.dna.SetSEState(CHAMELEONBLOCK, 0)
+ genemutcheck(H, CHAMELEONBLOCK, null, MUTCHK_FORCED)
+ else
+ H.dna.SetSEState(CHAMELEONBLOCK, 1)
+ genemutcheck(H, CHAMELEONBLOCK, null, MUTCHK_FORCED)
+
+ feedback_add_details("changeling_powers","CS")
+ return TRUE
+
+/obj/effect/proc_holder/changeling/chameleon_skin/on_refund(mob/user)
+ var/mob/living/carbon/C = user
+ if(C.dna.GetSEState(CHAMELEONBLOCK))
+ C.dna.SetSEState(CHAMELEONBLOCK, 0)
+ genemutcheck(C, CHAMELEONBLOCK, null, MUTCHK_FORCED)
diff --git a/code/game/gamemodes/changeling/powers/fakedeath.dm b/code/game/gamemodes/changeling/powers/fakedeath.dm
index dc7454ff7eb..156e8ffb896 100644
--- a/code/game/gamemodes/changeling/powers/fakedeath.dm
+++ b/code/game/gamemodes/changeling/powers/fakedeath.dm
@@ -7,30 +7,31 @@
req_stat = DEAD
max_genetic_damage = 100
-
//Fake our own death and fully heal. You will appear to be dead but regenerate fully after a short delay.
/obj/effect/proc_holder/changeling/fakedeath/sting_action(var/mob/living/user)
to_chat(user, "We begin our stasis, preparing energy to arise once more.")
-
- user.status_flags |= FAKEDEATH //play dead
- user.update_canmove()
-
if(user.stat != DEAD)
user.emote("deathgasp")
user.timeofdeath = world.time
+ user.status_flags |= FAKEDEATH //play dead
+ user.update_canmove()
- spawn(800)
- if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers)
- to_chat(user, "We are ready to regenerate.")
- user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
-
+ addtimer(src, "ready_to_regenerate", LING_FAKEDEATH_TIME, FALSE, user)
feedback_add_details("changeling_powers","FD")
return 1
+/obj/effect/proc_holder/changeling/fakedeath/proc/ready_to_regenerate(mob/user)
+ if(user && user.mind && user.mind.changeling && user.mind.changeling.purchasedpowers)
+ to_chat(user, "We are ready to regenerate.")
+ user.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/revive(null)
+
/obj/effect/proc_holder/changeling/fakedeath/can_sting(var/mob/user)
if(user.status_flags & FAKEDEATH)
+ to_chat(user, "We are already regenerating.")
return
- if(!user.stat && alert("Are we sure we wish to fake our death?",,"Yes","No") == "No")//Confirmation for living changelings if they want to fake their death
- return
+ if(!user.stat)//Confirmation for living changelings if they want to fake their death
+ switch(alert("Are we sure we wish to fake our death?",,"Yes","No"))
+ if("No")
+ return
return ..()
diff --git a/code/game/gamemodes/changeling/powers/fleshmend.dm b/code/game/gamemodes/changeling/powers/fleshmend.dm
index e6ccafcffa0..08786b6d6db 100644
--- a/code/game/gamemodes/changeling/powers/fleshmend.dm
+++ b/code/game/gamemodes/changeling/powers/fleshmend.dm
@@ -2,22 +2,54 @@
name = "Fleshmend"
desc = "Our flesh rapidly regenerates, healing our wounds."
helptext = "Heals a moderate amount of damage over a short period of time. Can be used while unconscious."
- chemical_cost = 25
+ chemical_cost = 20
dna_cost = 2
req_stat = UNCONSCIOUS
+ var/recent_uses = 1 //The factor of which the healing should be divided by
+ var/healing_ticks = 10
+ // The ideal total healing amount,
+ // divided by healing_ticks to get heal/tick
+ var/total_healing = 100
+
+/obj/effect/proc_holder/changeling/fleshmend/New()
+ ..()
+ processing_objects.Add(src)
+
+/obj/effect/proc_holder/changeling/fleshmend/Destroy()
+ processing_objects.Remove(src)
+ return ..()
+
+/obj/effect/proc_holder/changeling/fleshmend/process()
+ if(recent_uses > 1)
+ recent_uses = max(1, recent_uses - (1 / healing_ticks))
//Starts healing you every second for 10 seconds. Can be used whilst unconscious.
/obj/effect/proc_holder/changeling/fleshmend/sting_action(var/mob/living/user)
to_chat(user, "We begin to heal rapidly.")
+ if(recent_uses > 1)
+ to_chat(user, "Our healing's effectiveness is reduced \
+ by quick repeated use!")
+
+ recent_uses++
+ addtimer(src, "fleshmend", 0, FALSE, user)
+ feedback_add_details("changeling_powers","RR")
+ return TRUE
+
+/obj/effect/proc_holder/changeling/fleshmend/proc/fleshmend(mob/living/user)
+
+ // The healing itself - doesn't heal toxin damage
+ // (that's anatomic panacea) and the effectiveness decreases with
+ // each use in a short timespan
if(ishuman(user))
var/mob/living/carbon/human/H = user
- H.restore_blood()
H.shock_stage = 0
- spawn(0)
- for(var/i = 0, i<10,i++)
- user.heal_overall_damage(10, 10)
- user.adjustOxyLoss(-10)
- sleep(10)
-
- feedback_add_details("changeling_powers","RR")
- return 1
\ No newline at end of file
+ for(var/i in 1 to healing_ticks)
+ if(user)
+ var/healpertick = -(total_healing / healing_ticks)
+ user.heal_overall_damage((-healpertick/recent_uses), (-healpertick/recent_uses))
+ user.adjustOxyLoss(healpertick/recent_uses)
+ user.blood_volume += 30
+ user.updatehealth()
+ else
+ break
+ sleep(10)
diff --git a/code/game/gamemodes/changeling/powers/headcrab.dm b/code/game/gamemodes/changeling/powers/headcrab.dm
index 4adbc39e7fc..16ad41a36ea 100644
--- a/code/game/gamemodes/changeling/powers/headcrab.dm
+++ b/code/game/gamemodes/changeling/powers/headcrab.dm
@@ -20,7 +20,7 @@
H.EyeBlurry(20)
var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes)
if(istype(E))
- E.damage = max(E.damage+5, 0)
+ E.take_damage(5, 1)
H.AdjustConfused(3)
for(var/mob/living/silicon/S in range(2,user))
to_chat(S, "Your sensors are disabled by a shower of blood!")
diff --git a/code/game/gamemodes/changeling/powers/mutations.dm b/code/game/gamemodes/changeling/powers/mutations.dm
index 943b15a6172..18fcd4ebcce 100644
--- a/code/game/gamemodes/changeling/powers/mutations.dm
+++ b/code/game/gamemodes/changeling/powers/mutations.dm
@@ -167,7 +167,7 @@
user.visible_message("[user] jams [src] into the airlock and starts prying it open!", "We start forcing the airlock open.", \
"You hear a metal screeching sound.")
playsound(A, 'sound/machines/airlock_alien_prying.ogg', 150, 1)
- if(!do_after(user, 150, target = A))
+ if(!do_after(user, 100, target = A))
return
//user.say("Heeeeeeeeeerrre's Johnny!")
diff --git a/code/game/gamemodes/changeling/powers/panacea.dm b/code/game/gamemodes/changeling/powers/panacea.dm
index 5b11d2ba656..8f4fe0ac394 100644
--- a/code/game/gamemodes/changeling/powers/panacea.dm
+++ b/code/game/gamemodes/changeling/powers/panacea.dm
@@ -1,6 +1,6 @@
/obj/effect/proc_holder/changeling/panacea
name = "Anatomic Panacea"
- desc = "Expels impurifications from our form; curing diseases, removing toxins and radiation, and resetting our genetic code completely."
+ desc = "Expels impurifications from our form; curing diseases, removing parasites, sobering us, purging toxins and radiation, and resetting our genetic code completely."
helptext = "Can be used while unconscious."
chemical_cost = 20
dna_cost = 1
@@ -13,8 +13,6 @@
var/mob/living/simple_animal/borer/B = user.has_brain_worms()
if(B)
- if(B.controlling)
- B.detach()
B.leave_host()
if(iscarbon(user))
var/mob/living/carbon/C = user
@@ -32,6 +30,8 @@
user.reagents.add_reagent("mutadone", 10)
user.reagents.add_reagent("potass_iodide", 10)
user.reagents.add_reagent("charcoal", 20)
+ user.reagents.add_reagent("antihol", 10)
+ user.reagents.add_reagent("mannitol", 25)
for(var/thing in user.viruses)
var/datum/disease/D = thing
diff --git a/code/game/gamemodes/changeling/powers/revive.dm b/code/game/gamemodes/changeling/powers/revive.dm
index 376e6d5a148..23efc38b403 100644
--- a/code/game/gamemodes/changeling/powers/revive.dm
+++ b/code/game/gamemodes/changeling/powers/revive.dm
@@ -2,6 +2,7 @@
name = "Regenerate"
desc = "We regenerate, healing all damage from our form."
req_stat = DEAD
+ always_keep = 1
//Revive from regenerative stasis
/obj/effect/proc_holder/changeling/revive/sting_action(var/mob/living/carbon/user)
@@ -24,11 +25,11 @@
user.reagents.clear_reagents()
user.germ_level = 0
user.next_pain_time = 0
- user.traumatic_shock = 0
user.timeofdeath = 0
if(ishuman(user))
var/mob/living/carbon/human/H = user
H.restore_blood()
+ H.traumatic_shock = 0
H.shock_stage = 0
H.species.create_organs(H)
// Now that recreating all organs is necessary, the rest of this organ stuff probably
@@ -42,15 +43,13 @@
O.damage_state = "00"
O.germ_level = 0
QDEL_NULL(O.hidden)
- O.number_wounds = 0
O.open = 0
+ O.internal_bleeding = FALSE
O.perma_injury = 0
O.status = 0
O.trace_chemicals.Cut()
- QDEL_LIST(O.wounds)
- O.wound_update_accuracy = 1
for(var/obj/item/organ/internal/IO in H.internal_organs)
- IO.damage = 0
+ IO.rejuvenate()
IO.trace_chemicals.Cut()
H.remove_all_embedded_objects()
H.updatehealth()
diff --git a/code/game/gamemodes/changeling/powers/swap_form.dm b/code/game/gamemodes/changeling/powers/swap_form.dm
index 82baf6d5293..cb67858bb2e 100644
--- a/code/game/gamemodes/changeling/powers/swap_form.dm
+++ b/code/game/gamemodes/changeling/powers/swap_form.dm
@@ -17,7 +17,7 @@
if((NOCLONE || SKELETON || HUSK) in target.mutations)
to_chat(user, "DNA of [target] is ruined beyond usability!")
return
- if(!istype(target) || issmall(target) || target.species.flags & NO_DNA)
+ if(!istype(target) || issmall(target) || NO_DNA in target.species.species_traits)
to_chat(user, "[target] is not compatible with this ability.")
return
return 1
diff --git a/code/game/gamemodes/changeling/powers/tiny_prick.dm b/code/game/gamemodes/changeling/powers/tiny_prick.dm
index 648d8ac1cbb..e972af4ce23 100644
--- a/code/game/gamemodes/changeling/powers/tiny_prick.dm
+++ b/code/game/gamemodes/changeling/powers/tiny_prick.dm
@@ -81,7 +81,7 @@
if(!selected_dna)
return
var/datum/species/newspecies = all_species[selected_dna.species]
- if((newspecies.flags & NOTRANSSTING) || newspecies.is_small)
+ if((NOTRANSSTING in newspecies.species_traits) || newspecies.is_small)
to_chat(user, "The selected DNA is incompatible with our sting.")
return
..()
@@ -94,7 +94,7 @@
return FALSE
if(ishuman(target))
var/mob/living/carbon/human/H = target
- if(H.species.flags & NO_DNA)
+ if(NO_DNA in H.species.species_traits)
to_chat(user, "This won't work on a creature without DNA.")
return FALSE
return TRUE
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index 4f4152e2e22..2ac7d46dfba 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -1,4 +1,4 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+#define SUMMON_POSSIBILITIES 3
var/global/list/all_cults = list()
/datum/game_mode
@@ -107,6 +107,12 @@ var/global/list/all_cults = list()
modePlayer += cult
acolytes_needed = acolytes_needed + round((num_players_started() / 10))
+ if(!summon_spots.len)
+ while(summon_spots.len < SUMMON_POSSIBILITIES)
+ var/area/summon = pick(return_sorted_areas() - summon_spots)
+ if(summon && is_station_level(summon.z) && summon.valid_territory)
+ summon_spots += summon
+
for(var/datum/mind/cult_mind in cult)
equip_cultist(cult_mind.current)
cult_mind.current.faction |= "cult"
@@ -136,7 +142,7 @@ var/global/list/all_cults = list()
else
explanation = "Free objective."
if("eldergod")
- explanation = "Summon [ticker.mode.cultdat.entity_name]. It will only work if nine cultists stand on and around it."
+ explanation = "Summon [ticker.mode.cultdat.entity_name] by invoking the 'Tear Reality' rune.The summoning can only be accomplished in [english_list(summon_spots)] - where the veil is weak enough for the ritual to begin."
to_chat(cult_mind.current, "Objective #[obj_count]: [explanation]")
cult_mind.memory += "Objective #[obj_count]: [explanation] "
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 289ae7e4656..876748838ae 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -41,15 +41,13 @@
force = 15
throwforce = 25
embed_chance = 75
- var/cooldown = 0
-/obj/item/weapon/melee/cultblade/dagger/afterattack(mob/living/target as mob, mob/living/carbon/human/user as mob)
+/obj/item/weapon/melee/cultblade/dagger/attack(atom/target, mob/living/carbon/human/user)
..()
- var/mob/living/carbon/human/bleeder = target
- if(!(cooldown > world.time) && ((bleeder.stat != DEAD) && !(bleeder.species.flags & NO_BLOOD)))
- user.visible_message("The runes on the blade absorb the blood of [target]!")
- bleeder.bleed(5000)
- cooldown = world.time + 2400
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ if((H.stat != DEAD) && !(NO_BLOOD in H.species.species_traits))
+ H.bleed(50)
/obj/item/weapon/restraints/legcuffs/bola/cult
name = "runed bola"
@@ -194,13 +192,15 @@
/obj/item/weapon/whetstone/cult
name = "eldritch whetstone"
desc = "A block, empowered by dark magic. Sharp weapons will be enhanced when used on the stone."
- icon = 'icons/obj/cult.dmi'
- icon_state = "cultstone"
+ icon_state = "cult_sharpener"
used = 0
increment = 5
max = 40
prefix = "darkened"
+/obj/item/weapon/whetstone/cult/update_icon()
+ icon_state = "cult_sharpener[used ? "_used" : ""]"
+
/obj/item/weapon/reagent_containers/food/drinks/bottle/unholywater
name = "flask of unholy water"
desc = "Toxic to nonbelievers; this water renews and reinvigorates the faithful of a cult."
diff --git a/code/game/gamemodes/cult/cult_objectives.dm b/code/game/gamemodes/cult/cult_objectives.dm
index c9e951cf940..69b6de0c73e 100644
--- a/code/game/gamemodes/cult/cult_objectives.dm
+++ b/code/game/gamemodes/cult/cult_objectives.dm
@@ -109,10 +109,10 @@
if(prob(40))//split the chance of this
objectives += "eldergod"
- explanation = "Summon [ticker.mode.cultdat.entity_name] on the Station via the use of the Tear Reality rune."
+ explanation = "Summon [ticker.mode.cultdat.entity_name] on the Station via the use of the Tear Reality rune. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
else
objectives += "slaughter"
- explanation = "Bring the Slaughter via the rune 'Bring forth the slaughter'."
+ explanation = "Bring the Slaughter via the rune 'Bring forth the slaughter'. The veil is weak enough in [english_list(summon_spots)] for the ritual to begin."
for(var/datum/mind/cult_mind in cult)
to_chat(cult_mind.current, "You and your acolytes have succeeded in preparing the station for the ultimate ritual!")
diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm
index 60b9fcb2c85..10f6b92f517 100644
--- a/code/game/gamemodes/cult/cult_structures.dm
+++ b/code/game/gamemodes/cult/cult_structures.dm
@@ -65,6 +65,23 @@
else
return ..()
+/obj/structure/cult/functional/proc/updatehealth()
+ if(health <= 0)
+ destroy_structure()
+
+/obj/structure/cult/functional/proc/take_damage(damage, damage_type = BRUTE)
+ if(damage_type == BRUTE || damage_type == BURN)
+ health -= damage
+ updatehealth()
+
+/obj/structure/cult/functional/attackby(obj/item/I, mob/living/user)
+ ..()
+ take_damage(I.force, I.damtype)
+ playsound(loc, I.hitsound, 80, 1)
+
+/obj/structure/cult/functional/bullet_act(var/obj/item/projectile/P)
+ take_damage(P.damage, P.damage_type)
+
/obj/structure/cult/functional/attack_hand(mob/living/user)
if(!iscultist(user))
to_chat(user, "[heathen_message]")
@@ -142,6 +159,8 @@
C.apply_damage(30, BURN, "head") //30 fire damage because it's FUCKING LAVA
head.disfigure("burn") //Your face is unrecognizable because it's FUCKING LAVA
return 1
+ else
+ ..()
var/list/blacklisted_pylon_turfs = typecacheof(list(
/turf/simulated/floor/engine/cult,
diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm
index 1553ec0aa94..55d2a51de61 100644
--- a/code/game/gamemodes/cult/ritual.dm
+++ b/code/game/gamemodes/cult/ritual.dm
@@ -1,4 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:32
#define CULT_ELDERGOD "eldergod"
#define CULT_SLAUGHTER "slaughter"
@@ -202,6 +201,7 @@
/obj/item/weapon/tome/proc/finale_runes_ok(mob/living/user, obj/effect/rune/rune_to_scribe)
var/datum/game_mode/cult/cult_mode = ticker.mode
+ var/area/A = get_area(src)
if(GAMEMODE_IS_CULT)
if(!canbypass)//not an admin-tome, check things
if(!cult_mode.narsie_condition_cleared)
@@ -216,6 +216,9 @@
if(!((CULT_ELDERGOD in cult_mode.objectives) || (CULT_SLAUGHTER in cult_mode.objectives)))
to_chat(user, "[cult_mode.cultdat.entity_name]'s power does not wish to be unleashed!")
return 0
+ if(!(A in summon_spots))
+ to_chat(user, "[cult_mode.cultdat.entity_name] can only be summoned where the veil is weak - in [english_list(summon_spots)]!")
+ return 0
var/confirm_final = alert(user, "This is the FINAL step to summon your deities power, it is a long, painful ritual and the crew will be alerted to your presence", "Are you prepared for the final battle?", "My life for [cult_mode.cultdat.entity_name]!", "No")
if(confirm_final == "No" || confirm_final == null)
to_chat(user, "You decide to prepare further before scribing the rune.")
@@ -237,6 +240,7 @@
var/entered_rune_name
var/list/possible_runes = list()
var/list/shields = list()
+ var/area/A = get_area(src)
if(locate(/obj/effect/rune) in runeturf)
to_chat(user, "There is already a rune here.")
return
@@ -262,6 +266,7 @@
if(!rune_to_scribe)
return
runeturf = get_turf(user) //we may have moved. adjust as needed...
+ A = get_area(src)
if(locate(/obj/effect/rune) in runeturf)
to_chat(user, "There is already a rune here.")
return
@@ -269,7 +274,11 @@
return
if(ispath(rune_to_scribe, /obj/effect/rune/narsie) || ispath(rune_to_scribe, /obj/effect/rune/slaughter))//may need to change this - Fethas
if(finale_runes_ok(user,rune_to_scribe))
- command_announcement.Announce("Figments from an eldritch god are being summoned somwhere on the station from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg')
+ A = get_area(src)
+ if(!(A in summon_spots)) // Check again to make sure they didn't move
+ to_chat(user, "The ritual can only begin where the veil is weak - in [english_list(summon_spots)]!")
+ return
+ command_announcement.Announce("Figments from an eldritch god are being summoned somewhere on the station from an unknown dimension. Disrupt the ritual at all costs!","Central Command Higher Dimensional Affairs", 'sound/AI/spanomalies.ogg')
for(var/B in spiral_range_turfs(1, user, 1))
var/turf/T = B
var/obj/machinery/shield/N = new(T)
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index c6e64c4665c..892a5e7a204 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -636,17 +636,17 @@ var/list/teleport_runes = list()
log_game("Raise Dead rune failed - no catalyst corpse")
return
mob_to_sacrifice = input(user, "Choose a corpse to sacrifice.", "Corpse to Sacrifice") as null|anything in potential_sacrifice_mobs
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || !mob_to_revive || !mob_to_sacrifice || rune_in_use)
+ if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || !mob_to_sacrifice || rune_in_use)
return
for(var/mob/living/M in T.contents)
if(M.stat == DEAD)
potential_revive_mobs.Add(M)
if(!potential_revive_mobs.len)
to_chat(user, "There is no eligible revival target on the rune!")
- log_game("Raise Dead rune failed - no corpse to revived")
+ log_game("Raise Dead rune failed - no corpse to revive")
return
mob_to_revive = input(user, "Choose a corpse to revive.", "Corpse to Revive") as null|anything in potential_revive_mobs
- if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || rune_in_use)
+ if(!Adjacent(user) || !src || qdeleted(src) || user.incapacitated() || rune_in_use || !mob_to_revive)
return
if(!in_range(mob_to_sacrifice,src))
to_chat(user, "The sacrificial target has been moved!")
diff --git a/code/game/gamemodes/cult/talisman.dm b/code/game/gamemodes/cult/talisman.dm
index 4bf4bd9f9e7..7d046c82180 100644
--- a/code/game/gamemodes/cult/talisman.dm
+++ b/code/game/gamemodes/cult/talisman.dm
@@ -148,8 +148,9 @@
var/input_rune_key = input(user, "Choose a rune to teleport to.", "Rune to Teleport to") as null|anything in potential_runes //we know what key they picked
var/obj/effect/rune/teleport/actual_selected_rune = potential_runes[input_rune_key] //what rune does that key correspond to?
- if(!actual_selected_rune)
+ if(!src || qdeleted(src) || !user || user.l_hand != src && user.r_hand != src || user.incapacitated() || !actual_selected_rune)
return ..(user, 0)
+
user.visible_message("Dust flows from [user]'s hand, and they disappear in a flash of red light!", \
"You speak the words of the talisman and find yourself somewhere else!")
user.forceMove(get_turf(actual_selected_rune))
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index fc2ad7d62f9..7f8a7c4a3dc 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -1,5 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
/*
* GAMEMODES (by Rastaf0)
*
@@ -575,5 +573,5 @@ proc/display_roundstart_logout_report()
to_chat(M, "You suddenly remember \an [adjective] note you received earlier informing you that a chance to [action_words] may present itself today. An agent of the [organization] may contact you for help.")
to_chat(M, "The note had the words \"[my_word]\" and \"[my_reply]\" written at the bottom, which you memorized just in case.")
- to_chat(M, "You are NOT an antagonist, so self-antagging rules still apply to you. Use your good judgement and ahelp if you are unsure of what you are allowed to do.")
+ to_chat(M, "Unless stated otherwise; you are NOT an antagonist, so self-antagging rules may still apply to you. Use your good judgement and ahelp if you are unsure of what you are allowed to do.")
M.mind.store_memory("Important Words: \"[my_word]\", \"[my_reply]\"")
diff --git a/code/game/gamemodes/heist/heist.dm b/code/game/gamemodes/heist/heist.dm
index 70ebd23912f..341d674cab8 100644
--- a/code/game/gamemodes/heist/heist.dm
+++ b/code/game/gamemodes/heist/heist.dm
@@ -122,7 +122,7 @@ var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind'
vox.update_eyes()
for(var/obj/item/organ/external/limb in vox.bodyparts)
- limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT)
+ limb.status &= ~ORGAN_ROBOT
//Now apply cortical stack.
var/obj/item/weapon/implant/cortical/I = new(vox)
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 4377a0038eb..c014db18e34 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -171,14 +171,18 @@
/obj/effect/meteor/proc/meteor_effect(var/sound=1)
if(sound)
- for(var/mob/M in player_list)
+ var/sound/meteor_sound = sound(meteorsound)
+ var/random_frequency = get_rand_frequency()
+
+ for(var/P in player_list)
+ var/mob/M = P
var/turf/T = get_turf(M)
if(!T || T.z != src.z)
continue
var/dist = get_dist(M.loc, src.loc)
if(prob(50))
shake_camera(M, dist > 20 ? 3 : 5, dist > 20 ? 1 : 3)
- M.playsound_local(src.loc, meteorsound, 50, 1, get_rand_frequency(), 10)
+ M.playsound_local(src.loc, null, 50, 1, random_frequency, 10, S = meteor_sound)
///////////////////////
//Meteor types
diff --git a/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm b/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm
index 18d073d6077..64b77d3b374 100644
--- a/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm
+++ b/code/game/gamemodes/miniantags/abduction/abduction_surgery.dm
@@ -11,7 +11,7 @@
var/obj/item/organ/external/affected = H.get_organ(target_zone)
if(!affected)
return 0
- if(affected.status & ORGAN_ROBOT) //Maybe add in a machine version, later?
+ if(affected.status & ORGAN_ROBOT)
return 0
var/mob/living/carbon/human/H = user
// You must either: Be of the abductor species, or contain an abductor implant
@@ -37,7 +37,7 @@
/datum/surgery_step/internal/extract_organ/end_step(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery)
var/mob/living/carbon/human/AB = target
- if(AB.species.flags & NO_INTORGANS)
+ if(NO_INTORGANS in AB.species.species_traits)
user.visible_message("[user] prepares [target]'s [target_zone] for further dissection!", "You prepare [target]'s [target_zone] for further dissection.")
return 1
if(IC)
@@ -64,3 +64,31 @@
var/obj/item/organ/internal/heart/gland/gland = tool
gland.insert(target, 2)
return 1
+
+//IPC Gland Surgery//
+
+/datum/surgery/organ_extraction/synth
+ name = "experimental robotic dissection"
+ steps = list(/datum/surgery_step/robotics/external/unscrew_hatch,/datum/surgery_step/robotics/external/open_hatch,/datum/surgery_step/internal/extract_organ/synth,/datum/surgery_step/internal/gland_insert,/datum/surgery_step/robotics/external/close_hatch)
+ possible_locs = list("chest")
+ requires_organic_bodypart = 0
+
+/datum/surgery/organ_extraction/synth/can_start(mob/user, mob/living/carbon/target, target_zone, obj/item/tool,datum/surgery/surgery)
+ if(!ishuman(user))
+ return FALSE
+ if(ishuman(target))
+ var/mob/living/carbon/human/H = target
+ var/obj/item/organ/external/affected = H.get_organ(target_zone)
+ if(!affected)
+ return FALSE
+ if(!(affected.status & ORGAN_ROBOT))
+ return FALSE
+ var/mob/living/carbon/human/H = user
+ // You must either: Be of the abductor species, or contain an abductor implant
+ if((H.get_species() == "Abductor" || (locate(/obj/item/weapon/implant/abductor) in H)))
+ return TRUE
+ return FALSE
+
+/datum/surgery_step/internal/extract_organ/synth
+ name = "remove cell"
+ organ_types = list(/obj/item/organ/internal/cell)
\ No newline at end of file
diff --git a/code/game/gamemodes/miniantags/abduction/gland.dm b/code/game/gamemodes/miniantags/abduction/gland.dm
index e98dd1de388..29ca0a9a707 100644
--- a/code/game/gamemodes/miniantags/abduction/gland.dm
+++ b/code/game/gamemodes/miniantags/abduction/gland.dm
@@ -12,8 +12,8 @@
var/uses // -1 For inifinite
var/human_only = 0
var/active = 0
- tough = 1 //not easily broken by combat damage
- sterile = 1 //not very germy
+ tough = TRUE //not easily broken by combat damage
+ sterile = TRUE //not very germy
/obj/item/organ/internal/heart/gland/proc/ownerCheck()
if(ishuman(owner))
@@ -180,7 +180,7 @@
uses = -1
/obj/item/organ/internal/heart/gland/bloody/activate()
- owner.blood_volume -= 20
+ owner.blood_volume = max(owner.blood_volume - 20, 0)
owner.visible_message("[owner]'s skin erupts with blood!",\
"Blood pours from your skin!")
diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm
index a98090d186a..245da95e23a 100644
--- a/code/game/gamemodes/miniantags/borer/borer.dm
+++ b/code/game/gamemodes/miniantags/borer/borer.dm
@@ -351,7 +351,7 @@
to_chat(src, "They are no longer in range!")
return
-/mob/living/simple_animal/borer/proc/perform_infestation(var/mob/living/carbon/M)
+/mob/living/simple_animal/borer/proc/perform_infestation(mob/living/carbon/M)
if(!M)
return
@@ -359,6 +359,7 @@
to_chat(src, "[M] is already infested!")
return
host = M
+ M.borer = src
forceMove(M)
host.status_flags |= PASSEMOTES
@@ -564,7 +565,8 @@
host.reset_perspective(null)
host.machine = null
- var/mob/living/H = host
+ var/mob/living/carbon/H = host
+ H.borer = null
H.verbs -= /mob/living/proc/borer_comm
talk_to_borer_action.Remove(host)
H.status_flags &= ~PASSEMOTES
@@ -704,10 +706,12 @@
//Check for brain worms in head.
/mob/proc/has_brain_worms()
+ return FALSE
- for(var/I in contents)
- if(istype(I,/mob/living/simple_animal/borer))
- return I
+/mob/living/carbon/has_brain_worms()
+
+ if(borer)
+ return borer
return FALSE
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
index 680cb183e86..d7fa1b4c9f2 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer.dm
@@ -1,16 +1,18 @@
////Deactivated swarmer shell////
-/obj/item/unactivated_swarmer
+/obj/item/device/unactivated_swarmer
name = "unactivated swarmer"
desc = "A currently unactivated swarmer. Swarmers can self activate at any time, it would be wise to immediately dispose of this."
icon = 'icons/mob/swarmer.dmi'
icon_state = "swarmer_unactivated"
origin_tech = "bluespace=4;materials=4;programming=7"
+ materials = list(MAT_METAL=100, MAT_GLASS=400)
-/obj/item/unactivated_swarmer/New()
- notify_ghosts("An unactivated swarmer has been created in [get_area(src)]!", enter_link = "(Click to enter)", source = src, action = NOTIFY_ATTACK)
+/obj/item/device/unactivated_swarmer/New()
+ if(!crit_fail)
+ notify_ghosts("An unactivated swarmer has been created in [get_area(src)]!", enter_link = "(Click to enter)", source = src, action = NOTIFY_ATTACK)
..()
-/obj/item/unactivated_swarmer/Topic(href, href_list)
+/obj/item/device/unactivated_swarmer/Topic(href, href_list)
if(..())
return 1
if(href_list["ghostjoin"])
@@ -18,10 +20,33 @@
if(istype(ghost))
attack_ghost(ghost)
-/obj/item/unactivated_swarmer/attack_ghost(mob/user as mob)
+/obj/item/device/unactivated_swarmer/attackby(obj/item/weapon/W, mob/user, params)
+ ..()
+ if(istype(W, /obj/item/weapon/screwdriver) && !crit_fail)
+ user.visible_message("[usr.name] deactivates [src].",
+ "After some fiddling, you find a way to disable [src]'s power source.",
+ "You hear clicking.")
+ name = "deactivated swarmer"
+ desc = "A shell of swarmer that was completely powered down. It can no longer activate itself."
+ crit_fail = 1
+
+/obj/item/device/unactivated_swarmer/attack_ghost(mob/user as mob)
+
+ if(crit_fail)
+ to_chat(user, "This swarmer shell is completely depowered. You cannot activate it.")
+ return
+
var/be_swarmer = alert("Become a swarmer? (Warning, You can no longer be cloned!)",,"Yes","No")
if(be_swarmer == "No")
return
+
+ if(jobban_isbanned(user, "Syndicate"))
+ to_chat(user, "You are banned from antagonists!")
+ return
+
+ if(crit_fail)//in case it depowers while ghost is looking at yes/no
+ to_chat(user, "This swarmer shell is completely depowered. You cannot activate it.")
+ return
if(qdeleted(src))
to_chat(user, "Swarmer has been occupied by someone else.")
return
@@ -29,6 +54,18 @@
S.key = user.key
qdel(src)
+/obj/item/device/unactivated_swarmer/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
+ if(S.resources + 50 > S.max_resources)
+ to_chat(S, "We have too many resources to reconsume this shell. Aborting.")
+ else
+ ..()
+ S.resources += 49 //refund the whole thing
+
+/obj/item/device/unactivated_swarmer/deactivated
+ name = "deactivated swarmer"
+ desc = "A shell of swarmer that was completely powered down. It no longer can activate itself."
+ crit_fail = 1
+
////The Mob itself////
/mob/living/simple_animal/hostile/swarmer
@@ -64,20 +101,24 @@
mob_size = MOB_SIZE_TINY
ventcrawler = 2
ranged = 1
+ light_color = LIGHT_COLOR_CYAN
ranged_cooldown_time = 20
universal_speak = 0
universal_understand = 0
projectilesound = 'sound/weapons/taser2.ogg'
AIStatus = AI_OFF
var/resources = 0 //Resource points, generated by consuming metal/glass
+ var/max_resources = 100
loot = list(/obj/effect/decal/cleanable/blood/gibs/robot, /obj/item/weapon/ore/bluespace_crystal/artificial)
+ deathmessage = "The swarmer explodes with a sharp pop!"
del_on_death = 1
/mob/living/simple_animal/hostile/swarmer/Login()
..()
to_chat(src, "You are a swarmer, a weapon of a long dead civilization. Until further orders from your original masters are received, you must continue to consume and replicate.")
- to_chat(src, "Ctrl + Click provides most of your swarmer specific interactions, such as cannibalizing metal or glass, destroying the environment, or teleporting mobs away from you.")
- to_chat(src, "Objectives:")
+ to_chat(src, "Clicking on any object will try to consume it, either deconstructing it into its components, destroying it, or integrating any materials it has into you if successful.")
+ to_chat(src, "Ctrl-Clicking on a mob will attempt to remove it from the area and place it in a safe environment for storage.")
+ to_chat(src, "Prime Directives:")
to_chat(src, "1. Consume resources and replicate until there are no more resources left.")
to_chat(src, "2. Ensure that the station is fit for invasion at a later date, do not perform actions that would render it dangerous or inhospitable.")
to_chat(src, "3. Biological and Sentient resources will be harvested at a later date, do not harm them.")
@@ -110,7 +151,14 @@
real_name = "Swarmer [rand(100,999)]-[pick("kappa","sigma","beta","omicron","iota","epsilon","omega","gamma","delta","tau","alpha")]"
name = real_name
+
////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S////
+/mob/living/simple_animal/hostile/swarmer/AttackingTarget()
+ if(!isliving(target))
+ target.swarmer_act(src)
+ else
+ ..()
+
/mob/living/simple_animal/hostile/swarmer/CtrlClickOn(atom/A)
face_atom(A)
if(!isturf(loc))
@@ -248,6 +296,7 @@
/mob/living/carbon/slime/swarmer_act(mob/living/simple_animal/hostile/swarmer/S)
to_chat(S, "This biological resource is somehow resisting our bluespace transceiver. Aborting.")
+
////END CTRL CLICK FOR SWARMERS////
/mob/living/simple_animal/hostile/swarmer/proc/Fabricate(var/atom/fabrication_object,var/fabrication_cost = 0)
@@ -262,7 +311,7 @@
return 1
/mob/living/simple_animal/hostile/swarmer/proc/Integrate(var/obj/item/target)
- if(resources >= 100)
+ if(resources >= max_resources)
to_chat(src, "We cannot hold more materials!")
return
//Check if any entries are either MAT_METAL or MAT_GLASS
@@ -308,7 +357,7 @@
var/pressure = A.return_pressure()
if((pressure > 20) && (pressure < 550))//Account for crushing pressure or vaccuums
if(ishuman(target))//If we're getting rid of a human, slap some zipties on them to keep them away from us a little longer
- var/obj/item/weapon/restraints/handcuffs/cable/zipties/Z = new /obj/item/weapon/restraints/handcuffs/cable/zipties(src)
+ var/obj/item/weapon/restraints/handcuffs/energy/used/Z = new /obj/item/weapon/restraints/handcuffs/energy/used(src)
Z.apply_cuffs(target, src)
do_teleport(target, F, 0)
playsound(src,'sound/effects/sparks4.ogg',50,1)
@@ -355,6 +404,12 @@
light_range = 1
mouse_opacity = 1
var/health = 30
+ light_color = LIGHT_COLOR_CYAN
+ var/lon_range = 1
+
+/obj/structure/swarmer/New()
+ . = ..()
+ set_light(lon_range)
/obj/structure/swarmer/disintegration
icon_state = "disintegrate"
@@ -422,6 +477,7 @@
desc = "A quickly assembled trap that electrifies living beings and overwhelms machine sensors. Will not retain its form if damaged enough."
icon_state = "trap"
light_range = 1
+ light_color = LIGHT_COLOR_CYAN
health = 10
/obj/structure/swarmer/trap/Crossed(var/atom/movable/AM)
@@ -462,6 +518,7 @@
desc = "A quickly assembled energy blockade. Will not retain its form if damaged enough, but disabler beams and swarmers pass right through."
icon_state = "barricade"
light_range = 1
+ light_color = LIGHT_COLOR_CYAN
health = 50
density = 1
anchored = 1
@@ -484,7 +541,7 @@
to_chat(src, "This is not a suitable location for replicating ourselves. We need more room.")
return
if(do_mob(src, src, 100))
- if(Fabricate(/obj/item/unactivated_swarmer, 50))
+ if(Fabricate(/obj/item/device/unactivated_swarmer, 50))
playsound(loc,'sound/items/poster_being_created.ogg',50, 1, -1)
/mob/living/simple_animal/hostile/swarmer/proc/RepairSelf()
diff --git a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
index 7a16ef17857..ba461fafb80 100644
--- a/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
+++ b/code/game/gamemodes/miniantags/bot_swarm/swarmer_event.dm
@@ -15,7 +15,7 @@
return 0
if(!the_gateway)
return 0
- new /obj/item/unactivated_swarmer(get_turf(the_gateway))
+ new /obj/item/device/unactivated_swarmer(get_turf(the_gateway))
/datum/event/spawn_swarmer/proc/find_swarmer()
diff --git a/code/game/gamemodes/miniantags/guardian/guardian.dm b/code/game/gamemodes/miniantags/guardian/guardian.dm
index 4825dea6ebb..b6f240b8319 100644
--- a/code/game/gamemodes/miniantags/guardian/guardian.dm
+++ b/code/game/gamemodes/miniantags/guardian/guardian.dm
@@ -39,40 +39,43 @@
var/bio_fluff_string = "Your scarabs fail to mutate. This shouldn't happen! Submit a bug report!"
var/admin_fluff_string = "URK URF!"//the wheels on the bus...
var/adminseal = FALSE
+ var/name_color = "white"//only used with protector shields for the time being
/mob/living/simple_animal/hostile/guardian/Life() //Dies if the summoner dies
..()
if(summoner)
if(summoner.stat == DEAD)
to_chat(src, "Your summoner has died!")
- visible_message("The [src] dies along with its user!")
+ visible_message("The [src] dies along with its user!")
ghostize()
qdel(src)
- if(summoner)
- if(get_dist(get_turf(summoner),get_turf(src)) <= range)
- return
- else
- to_chat(src, "You moved out of range, and were pulled back! You can only move [range] meters from [summoner.real_name]")
- visible_message("The [src] jumps back to its user.")
- Recall()
+ snapback()
if(summoned && !summoner && !adminseal)
to_chat(src, "You somehow lack a summoner! As a result, you dispel!")
ghostize()
qdel()
-/mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range
- ..()
+/mob/living/simple_animal/hostile/guardian/proc/snapback()
if(summoner)
if(get_dist(get_turf(summoner),get_turf(src)) <= range)
return
else
- to_chat(src, "You moved out of range, and were pulled back! You can only move [range] meters from [summoner.real_name]")
- visible_message("The [src] jumps back to its user.")
- Recall()
+ to_chat(src, "You moved out of range, and were pulled back! You can only move [range] meters from [summoner.real_name]!")
+ visible_message("\The [src] jumps back to its user.")
+ if(istype(summoner.loc, /obj/effect))
+ Recall(TRUE)
+ else
+ new /obj/effect/overlay/temp/guardian/phase/out(loc)
+ forceMove(summoner.loc) //move to summoner's tile, don't recall
+ new /obj/effect/overlay/temp/guardian/phase(loc)
+
+/mob/living/simple_animal/hostile/guardian/Move() //Returns to summoner if they move out of range
+ ..()
+ snapback()
/mob/living/simple_animal/hostile/guardian/death(gibbed)
..()
- to_chat(summoner, "Your [name] died somehow!")
+ to_chat(summoner, "Your [name] died somehow!")
summoner.death()
@@ -93,10 +96,10 @@
return
summoner.adjustBruteLoss(damage)
if(damage)
- to_chat(summoner, "Your [name] is under attack! You take damage!")
- summoner.visible_message("Blood sprays from [summoner] as [src] takes damage!")
+ to_chat(summoner, "Your [name] is under attack! You take damage!")
+ summoner.visible_message("Blood sprays from [summoner] as [src] takes damage!")
if(summoner.stat == UNCONSCIOUS)
- to_chat(summoner, "Your body can't take the strain of sustaining [src] in this condition, it begins to fall apart!")
+ to_chat(summoner, "Your body can't take the strain of sustaining [src] in this condition, it begins to fall apart!")
summoner.adjustCloneLoss(damage/2)
/mob/living/simple_animal/hostile/guardian/ex_act(severity, target)
@@ -112,7 +115,7 @@
/mob/living/simple_animal/hostile/guardian/gib()
if(summoner)
- to_chat(summoner, "Your [src] was blown up!")
+ to_chat(summoner, "Your [src] was blown up!")
summoner.Weaken(10)// your fermillier has died! ROLL FOR CON LOSS!
ghostize()
qdel(src)
@@ -128,8 +131,8 @@
src.client.eye = loc
cooldown = world.time + 30
-/mob/living/simple_animal/hostile/guardian/proc/Recall()
- if(cooldown > world.time)
+/mob/living/simple_animal/hostile/guardian/proc/Recall(forced = FALSE)
+ if(cooldown > world.time && !forced)
return
if(!summoner) return
new /obj/effect/overlay/temp/guardian/phase/out(get_turf(src))
@@ -141,7 +144,6 @@
var/input = stripped_input(src, "Please enter a message to tell your summoner.", "Guardian", "")
if(!input) return
-
for(var/mob/M in mob_list)
if(M == summoner)
to_chat(M, "[src]: [input]")
@@ -151,7 +153,7 @@
to_chat(src, "[src]: [input]")
/mob/living/simple_animal/hostile/guardian/proc/ToggleMode()
- to_chat(src, "You dont have another mode!")
+ to_chat(src, "You dont have another mode!")
/mob/living/proc/guardian_comm()
@@ -212,456 +214,6 @@
to_chat(src, "You deactivate your light.")
light_on = !light_on
-//////////////////////////TYPES OF GUARDIANS
-
-
-//Fire. Low damage, low resistance, sets mobs on fire when bumping
-
-/mob/living/simple_animal/hostile/guardian/fire
- a_intent = INTENT_HELP
- melee_damage_lower = 10
- melee_damage_upper = 10
- attack_sound = 'sound/items/Welder.ogg'
- attacktext = "sears"
- damage_transfer = 0.8
- range = 10
- playstyle_string = "As a Chaos type, you have only light damage resistance, but will ignite any enemy you bump into. In addition, your melee attacks will randomly teleport enemies."
- environment_smash = 1
- magic_fluff_string = "..And draw the Wizard, bringer of endless chaos!"
- tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to sow havoc at random."
- var/toggle = FALSE
-
-/mob/living/simple_animal/hostile/guardian/fire/Life() //Dies if the summoner dies
- ..()
- if(summoner)
- summoner.ExtinguishMob()
- summoner.adjust_fire_stacks(-20)
-
-/mob/living/simple_animal/hostile/guardian/fire/ToggleMode()
- if(src.loc == summoner)
- if(toggle)
- to_chat(src, "You switch to dispersion mode, and will teleport victims away from your master.")
- toggle = FALSE
- else
- to_chat(src, "You switch to deception mode, and will turn your victims against their allies.")
- toggle = TRUE
-
-/mob/living/simple_animal/hostile/guardian/fire/AttackingTarget()
- if(..())
- if(toggle)
- if(ishuman(target) && !summoner)
- spawn(0)
- new /obj/effect/hallucination/delusion(target.loc, target, force_kind="custom", duration=200, skip_nearby=0, custom_icon = src.icon_state, custom_icon_file = src.icon)
- else
- if(prob(45))
- if(istype(target, /atom/movable))
- var/atom/movable/M = target
- if(!M.anchored && M != summoner)
- new /obj/effect/overlay/temp/guardian/phase/out(get_turf(M))
- do_teleport(M, M, 10)
- new /obj/effect/overlay/temp/guardian/phase/out(get_turf(M))
-
-/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj)
- ..()
- collision_ignite(AM)
-
-/mob/living/simple_animal/hostile/guardian/fire/Bumped(AM as mob|obj)
- ..()
- collision_ignite(AM)
-
-/mob/living/simple_animal/hostile/guardian/fire/Bump(AM as mob|obj)
- ..()
- collision_ignite(AM)
-
-/mob/living/simple_animal/hostile/guardian/fire/proc/collision_ignite(AM as mob|obj)
- if(istype(AM, /mob/living/))
- var/mob/living/M = AM
- if(AM != summoner && M.fire_stacks < 7)
- M.fire_stacks = 7
- M.IgniteMob()
-
-/mob/living/simple_animal/hostile/guardian/fire/Bump(AM as mob|obj)
- ..()
- collision_ignite(AM)
-//Standard
-
-/mob/living/simple_animal/hostile/guardian/punch
- melee_damage_lower = 20
- melee_damage_upper = 20
- damage_transfer = 0.5
- playstyle_string = "As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls."
- environment_smash = 2
- magic_fluff_string = "..And draw the Assistant, faceless and generic, but never to be underestimated."
- tech_fluff_string = "Boot sequence complete. Standard combat modules loaded. Holoparasite swarm online."
- bio_fluff_string = "Your scarab swarm stirs to life, ready to tear apart your enemies."
- var/battlecry = "AT"
-
-
-/mob/living/simple_animal/hostile/guardian/punch/sealpunch
- name = "Seal Sprit"
- real_name = "Seal Sprit"
- icon = 'icons/mob/animal.dmi'
- icon_living = "seal"
- icon_state = "seal"
- attacktext = "slaps"
- speak_emote = list("barks")
- melee_damage_lower = 0
- melee_damage_upper = 0
- melee_damage_type = STAMINA
- damage_transfer = 0
- playstyle_string = "As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls."
- environment_smash = 2
- battlecry = "URK"
- adminseal = TRUE
-
-/mob/living/simple_animal/hostile/guardian/punch/verb/Battlecry()
- set name = "Set Battlecry"
- set category = "Guardian"
- set desc = "Choose what you shout as you punch"
- var/input = stripped_input(src,"What do you want your battlecry to be? Max length of 5 characters.", ,"", 6)
- if(input)
- battlecry = input
-
-
-
-/mob/living/simple_animal/hostile/guardian/punch/AttackingTarget()
- ..()
- if(iscarbon(target) && target != summoner)
- if(length(battlecry) > 11)//no more then 11 letters in a battle cry.
- src.visible_message("[src] punches [target]!")
- else
- src.say("[src.battlecry][src.battlecry][src.battlecry][src.battlecry][src.battlecry]")
- playsound(loc, src.attack_sound, 50, 1, 1)
- playsound(loc, src.attack_sound, 50, 1, 1)
- playsound(loc, src.attack_sound, 50, 1, 1)
- playsound(loc, src.attack_sound, 50, 1, 1)
-
-//Healer
-
-/mob/living/simple_animal/hostile/guardian/healer
- a_intent = INTENT_HARM
- friendly = "heals"
- speed = 0
- melee_damage_lower = 15
- melee_damage_upper = 15
- playstyle_string = "As a Support type, you may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent mob will warp them to your bluespace beacon after a short delay."
- magic_fluff_string = "..And draw the CMO, a potent force of life...and death."
- tech_fluff_string = "Boot sequence complete. Medical modules active. Bluespace modules activated. Holoparasite swarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of mending wounds and travelling via bluespace."
- var/turf/simulated/floor/beacon
- var/beacon_cooldown = 0
- var/toggle = FALSE
- var/heal_cooldown = 0
-
-/mob/living/simple_animal/hostile/guardian/healer/sealhealer
- name = "Seal Sprit"
- real_name = "Seal Sprit"
- icon = 'icons/mob/animal.dmi'
- icon_living = "seal"
- icon_state = "seal"
- attacktext = "slaps"
- speak_emote = list("barks")
- a_intent = INTENT_HARM
- friendly = "heals"
- speed = 0
- melee_damage_lower = 0
- melee_damage_upper = 0
- melee_damage_type = STAMINA
- adminseal = TRUE
-
-
-/mob/living/simple_animal/hostile/guardian/healer/New()
- ..()
-
-/mob/living/simple_animal/hostile/guardian/healer/Life()
- ..()
- var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
- medsensor.add_hud_to(src)
-
-/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
- ..()
- if(toggle == TRUE)
- if(src.loc == summoner)
- to_chat(src, "You must be manifested to heal!")
- return
- if(iscarbon(target))
- src.changeNext_move(CLICK_CD_MELEE)
- if(heal_cooldown <= world.time && !stat)
- var/mob/living/carbon/C = target
- C.adjustBruteLoss(-5)
- C.adjustFireLoss(-5)
- C.adjustOxyLoss(-5)
- C.adjustToxLoss(-5)
- heal_cooldown = world.time + 20
-
-/mob/living/simple_animal/hostile/guardian/healer/ToggleMode()
- if(src.loc == summoner)
- if(toggle)
- a_intent = INTENT_HARM
- speed = 0
- damage_transfer = 0.7
- if(src.adminseal)
- damage_transfer = 0
- melee_damage_lower = 15
- melee_damage_upper = 15
- to_chat(src, "You switch to combat mode.")
- toggle = FALSE
- else
- a_intent = INTENT_HELP
- speed = 1
- damage_transfer = 1
- if(src.adminseal)
- damage_transfer = 0
- melee_damage_lower = 0
- melee_damage_upper = 0
- to_chat(src, "You switch to healing mode.")
- toggle = TRUE
- else
- to_chat(src, "You have to be recalled to toggle modes!")
-
-
-/mob/living/simple_animal/hostile/guardian/healer/verb/Beacon()
- set name = "Place Bluespsace Beacon"
- set category = "Guardian"
- set desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon will not work in unfavorable atmospheric conditions."
- if(beacon_cooldownBeacon placed! You may now warp targets to it, including your user, via Alt+Click. ")
- if(beacon)
- beacon.ChangeTurf(/turf/simulated/floor/plating)
- beacon = F
- beacon_cooldown = world.time+3000
-
- else
- to_chat(src, "Your power is on cooldown. You must wait five minutes between placing beacons.")
-
-/mob/living/simple_animal/hostile/guardian/healer/AltClickOn(atom/movable/A)
- if(!istype(A))
- return
- if(src.loc == summoner)
- to_chat(src, "You must be manifested to warp a target!")
- return
- if(!beacon)
- to_chat(src, "You need a beacon placed to warp things!")
- return
- if(!Adjacent(A))
- to_chat(src, "You must be adjacent to your target!")
- return
- if((A.anchored))
- to_chat(src, "Your target can not be anchored!")
- return
- to_chat(src, "You begin to warp [A]")
- if(do_mob(src, A, 50))
- if(!A.anchored)
- if(src.beacon) //Check that the beacon still exists and is in a safe place. No instant kills.
- if(beacon.air)
- var/datum/gas_mixture/Z = beacon.air
- if(Z.oxygen >= 16 && !Z.toxins && Z.carbon_dioxide < 10 && !Z.trace_gases.len)
- if((Z.temperature > 270) && (Z.temperature < 360))
- var/pressure = Z.return_pressure()
- if((pressure > 20) && (pressure < 550))
- new /obj/effect/overlay/temp/guardian/phase/out(get_turf(A))
- do_teleport(A, beacon, 0)
- new /obj/effect/overlay/temp/guardian/phase(get_turf(A))
- else
- to_chat(src, "The beacon isn't in a safe location!")
- else
- to_chat(src, "The beacon isn't in a safe location!")
- else
- to_chat(src, "You need a beacon to warp things!")
- else
- to_chat(src, "You need to hold still!")
-
-
-///////////////////Ranged
-
-/obj/item/projectile/guardian
- name = "crystal spray"
- icon_state = "guardian"
- damage = 5
- damage_type = BRUTE
- armour_penetration = 100
-
-/mob/living/simple_animal/hostile/guardian/ranged
- a_intent = INTENT_HELP
- friendly = "quietly assesses"
- melee_damage_lower = 10
- melee_damage_upper = 10
- damage_transfer = 0.9
- projectiletype = /obj/item/projectile/guardian
- ranged_cooldown_time = 10
- projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
- ranged = 1
- rapid = 1
- range = 13
- see_invisible = SEE_INVISIBLE_MINIMUM
- see_in_dark = 8
- playstyle_string = "As a ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit."
- magic_fluff_string = "..And draw the Sentinel, an alien master of ranged combat."
- tech_fluff_string = "Boot sequence complete. Ranged combat modules active. Holoparasite swarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of spraying shards of crystal."
- var/list/snares = list()
- var/toggle = FALSE
-
-/mob/living/simple_animal/hostile/guardian/ranged/ToggleMode()
- if(src.loc == summoner)
- if(toggle)
- ranged = 1
- melee_damage_lower = 10
- melee_damage_upper = 10
- alpha = 255
- range = 13
- incorporeal_move = 0
- to_chat(src, "You switch to combat mode.")
- toggle = FALSE
- else
- ranged = 0
- melee_damage_lower = 0
- melee_damage_upper = 0
- alpha = 60
- range = 255
- incorporeal_move = 1
- to_chat(src, "You switch to scout mode.")
- toggle = TRUE
- else
- to_chat(src, "You have to be recalled to toggle modes!")
-
-/mob/living/simple_animal/hostile/guardian/ranged/ToggleLight()
- if(see_invisible == SEE_INVISIBLE_MINIMUM)
- to_chat(src, "You deactivate your night vision.")
- see_invisible = SEE_INVISIBLE_LIVING
- else
- to_chat(src, "You activate your night vision.")
- see_invisible = SEE_INVISIBLE_MINIMUM
-
-/mob/living/simple_animal/hostile/guardian/ranged/verb/Snare()
- set name = "Set Surveillance Trap"
- set category = "Guardian"
- set desc = "Set an invisible trap that will alert you when living creatures walk over it. Max of 5"
- if(src.snares.len <6)
- var/turf/snare_loc = get_turf(src.loc)
- var/obj/item/effect/snare/S = new /obj/item/effect/snare(snare_loc)
- S.spawner = src
- S.name = "[get_area(snare_loc)] trap ([rand(1, 1000)])"
- src.snares |= S
- to_chat(src, "Surveillance trap deployed!")
- else
- to_chat(src, "You have too many traps deployed. Delete some first.")
-
-/mob/living/simple_animal/hostile/guardian/ranged/verb/DisarmSnare()
- set name = "Remove Surveillance Trap"
- set category = "Guardian"
- set desc = "Disarm unwanted surveillance traps."
- var/picked_snare = input(src, "Pick which trap to disarm", "Disarm Trap") as null|anything in src.snares
- if(picked_snare)
- src.snares -= picked_snare
- qdel(picked_snare)
- to_chat(src, "Snare disarmed.")
-
-/obj/item/effect/snare
- name = "snare"
- desc = "You shouldn't be seeing this!"
- var/mob/living/spawner
- invisibility = 1
-
-
-/obj/item/effect/snare/Crossed(AM as mob|obj)
- if(istype(AM, /mob/living/))
- var/turf/snare_loc = get_turf(src.loc)
- if(spawner)
- to_chat(spawner, "[AM] has crossed your surveillance trap at [get_area(snare_loc)].")
- if(istype(spawner, /mob/living/simple_animal/hostile/guardian))
- var/mob/living/simple_animal/hostile/guardian/G = spawner
- if(G.summoner)
- to_chat(G.summoner, "[AM] has crossed your surveillance trap at [get_area(snare_loc)].")
-
-////Bomb
-
-/mob/living/simple_animal/hostile/guardian/bomb
- melee_damage_lower = 15
- melee_damage_upper = 15
- damage_transfer = 0.6
- range = 13
- playstyle_string = "As an explosive type, you have only moderate close combat abilities, but are capable of converting any adjacent item into a disguised bomb via alt click."
- magic_fluff_string = "..And draw the Scientist, master of explosive death."
- tech_fluff_string = "Boot sequence complete. Explosive modules active. Holoparasite swarm online."
- bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of stealthily booby trapping items."
- var/bomb_cooldown = 0
-
-/mob/living/simple_animal/hostile/guardian/bomb/AltClickOn(atom/movable/A)
- if(!istype(A))
- return
- if(src.loc == summoner)
- to_chat(src, "You must be manifested to create bombs!")
- return
- if(istype(A, /obj/))
- if(bomb_cooldown <= world.time && !stat)
- var/obj/item/weapon/guardian_bomb/B = new /obj/item/weapon/guardian_bomb(get_turf(A))
- to_chat(src, "Success! Bomb on \the [A] armed!")
- if(summoner)
- to_chat(summoner, "Your guardian has primed \the [A] to explode!")
- bomb_cooldown = world.time + 200
- B.spawner = src
- B.disguise (A)
- else
- to_chat(src, "Your powers are on cooldown! You must wait 20 seconds between bombs.")
-
-/obj/item/weapon/guardian_bomb
- name = "bomb"
- desc = "You shouldn't be seeing this!"
- var/obj/stored_obj
- var/mob/living/spawner
-
-
-/obj/item/weapon/guardian_bomb/proc/disguise(var/obj/A)
- A.loc = src
- stored_obj = A
- anchored = A.anchored
- density = A.density
- appearance = A.appearance
- spawn(600)
- if(src)
- stored_obj.loc = get_turf(src.loc)
- if(spawner)
- to_chat(spawner, "Failure! Your trap on \the [stored_obj] didn't catch anyone this time.")
- qdel(src)
-
-/obj/item/weapon/guardian_bomb/proc/detonate(var/mob/living/user)
- to_chat(user, "The [src] was boobytrapped!")
- if(istype(spawner, /mob/living/simple_animal/hostile/guardian))
- var/mob/living/simple_animal/hostile/guardian/G = spawner
- if(user == G.summoner)
- to_chat(user, "You knew this because of your link with your guardian, so you smartly defuse the bomb.")
- stored_obj.loc = get_turf(src.loc)
- qdel(src)
- return
- to_chat(spawner, "Success! Your trap on \the [src] caught [user]!")
- stored_obj.loc = get_turf(src.loc)
- playsound(get_turf(src),'sound/effects/Explosion2.ogg', 200, 1)
- user.ex_act(2)
- qdel(src)
-
-/obj/item/weapon/guardian_bomb/attackby(mob/living/user)
- detonate(user)
- return
-
-/obj/item/weapon/guardian_bomb/pickup(mob/living/user)
- detonate(user)
- return
-
-/obj/item/weapon/guardian_bomb/examine(mob/user)
- stored_obj.examine(user)
- if(get_dist(user,src)<=2)
- to_chat(user, "Looks odd!")
-
-
////////Creation
/obj/item/weapon/guardiancreator
@@ -676,7 +228,7 @@
var/used_message = "All the cards seem to be blank now."
var/failure_message = "..And draw a card! It's...blank? Maybe you should try again later."
var/ling_failure = "The deck refuses to respond to a souless creature such as you."
- var/list/possible_guardians = list("Chaos", "Standard", "Ranged", "Support", "Explosive")
+ var/list/possible_guardians = list("Chaos", "Standard", "Ranged", "Support", "Explosive", "Assassin", "Lightning", "Charger", "Protector")
var/random = TRUE
/obj/item/weapon/guardiancreator/attack_self(mob/living/user)
@@ -727,6 +279,18 @@
if("Explosive")
pickedtype = /mob/living/simple_animal/hostile/guardian/bomb
+ if("Assassin")
+ pickedtype = /mob/living/simple_animal/hostile/guardian/assassin
+
+ if("Lightning")
+ pickedtype = /mob/living/simple_animal/hostile/guardian/beam
+
+ if("Charger")
+ pickedtype = /mob/living/simple_animal/hostile/guardian/charger
+
+ if("Protector")
+ pickedtype = /mob/living/simple_animal/hostile/guardian/protector
+
var/mob/living/simple_animal/hostile/guardian/G = new pickedtype(user)
G.summoner = user
G.summoned = TRUE
@@ -741,12 +305,33 @@
user.verbs += /mob/living/proc/guardian_reset
var/color
+
+ //names and their RGB
+ var/magic_list = list("Pink" = "#FFC0CB", \
+ "Red" = "#FF0000", \
+ "Orange" = "#FFA500", \
+ "Green" = "#008000", \
+ "Blue" = "#0000FF")
+
+ var/tech_list = list("Rose" = "#F62C6B", \
+ "Peony" = "#E54750", \
+ "Lily" = "#F6562C", \
+ "Daisy" = "#ECCD39", \
+ "Zinnia" = "#89F62C", \
+ "Ivy" = "#5DF62C", \
+ "Iris" = "#2CF6B8", \
+ "Petunia" = "#51A9D4", \
+ "Violet" = "#8A347C", \
+ "Lilac" = "#C7A0F6", \
+ "Orchid" = "#F62CF5")
+
var/picked_name
var/picked_color = pick("#FFFFFF","#000000","#808080","#A52A2A","#FF0000","#8B0000","#DC143C","#FFA500","#FFFF00","#008000","#00FF00","#006400","#00FFFF","#0000FF","#000080","#008080","#800080","#4B0082")
switch(theme)
if("magic")
- color = pick("Pink", "Red", "Orange", "Green", "Blue")
+ color = pick(magic_list)
+ G.name_color = magic_list[color]
picked_name = pick("Aries", "Leo", "Sagittarius", "Taurus", "Virgo", "Capricorn", "Gemini", "Libra", "Aquarius", "Cancer", "Scorpio", "Pisces")
G.name = "[picked_name] [color]"
@@ -757,7 +342,8 @@
to_chat(user, "[G.magic_fluff_string].")
if("tech")
- color = pick("Rose", "Peony", "Lily", "Daisy", "Zinnia", "Ivy", "Iris", "Petunia", "Violet", "Lilac", "Orchid") //technically not colors, just flowers that can be specific colors
+ color = pick(tech_list) //technically not colors, just flowers that can be specific colors
+ G.name_color = tech_list[color]
picked_name = pick("Gallium", "Indium", "Thallium", "Bismuth", "Aluminium", "Mercury", "Iron", "Silver", "Zinc", "Titanium", "Chromium", "Nickel", "Platinum", "Tellurium", "Palladium", "Rhodium", "Cobalt", "Osmium", "Tungsten", "Iridium")
G.name = "[picked_name] [color]"
@@ -769,6 +355,7 @@
to_chat(user, "[G.tech_fluff_string].")
G.speak_emote = list("states")
if("bio")
+ G.name_color = picked_color
G.icon = 'icons/mob/mob.dmi'
picked_name = pick("brood", "hive", "nest")
to_chat(user, "[G.bio_fluff_string].")
diff --git a/code/game/gamemodes/miniantags/guardian/types/assassin.dm b/code/game/gamemodes/miniantags/guardian/types/assassin.dm
new file mode 100644
index 00000000000..39ea9992308
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/assassin.dm
@@ -0,0 +1,89 @@
+/mob/living/simple_animal/hostile/guardian/assassin
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ armour_penetration = 0
+ damage_transfer = 0.6
+ playstyle_string = "As an Assassin type you do medium damage and have no damage resistance, but can enter stealth, massively increasing the damage of your next attack and causing it to ignore armor. Stealth is broken when you attack or take damage."
+ magic_fluff_string = "..And draw the Space Ninja, a lethal, invisible assassin."
+ tech_fluff_string = "Boot sequence complete. Assassin modules loaded. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of sneaking and stealthy attacks."
+ var/toggle = FALSE
+ var/stealthcooldown = 0
+ var/default_stealth_cooldown = 16 SECONDS
+ var/obj/screen/alert/canstealthalert
+ var/obj/screen/alert/instealthalert
+
+/mob/living/simple_animal/hostile/guardian/assassin/Life()
+ . = ..()
+ updatestealthalert()
+ if(loc == summoner && toggle)
+ ToggleMode(0)
+
+/mob/living/simple_animal/hostile/guardian/assassin/Stat()
+ ..()
+ if(statpanel("Status"))
+ if(stealthcooldown >= world.time)
+ stat(null, "Stealth Cooldown Remaining: [max(round((stealthcooldown - world.time)*0.1, 0.1), 0)] seconds")
+
+/mob/living/simple_animal/hostile/guardian/assassin/AttackingTarget()
+ ..()
+ if(toggle && (isliving(target) || istype(target, /obj/structure/window) || istype(target, /obj/structure/grille)))
+ ToggleMode(1)
+
+/mob/living/simple_animal/hostile/guardian/assassin/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
+ . = ..()
+ if(. > 0 && toggle)
+ ToggleMode(1)
+
+/mob/living/simple_animal/hostile/guardian/assassin/Recall()
+ ..()
+ if(toggle)
+ ToggleMode(0)
+
+/mob/living/simple_animal/hostile/guardian/assassin/ToggleMode(forced = 0)
+ if(toggle)
+ melee_damage_lower = initial(melee_damage_lower)
+ melee_damage_upper = initial(melee_damage_upper)
+ armour_penetration = initial(armour_penetration)
+ alpha = initial(alpha)
+ if(!forced)
+ to_chat(src, "You exit stealth.")
+ else
+ visible_message("[src] suddenly appears!")
+ stealthcooldown = world.time + default_stealth_cooldown //we were forced out of stealth and go on cooldown
+ cooldown = world.time + 40 //can't recall for 4 seconds
+ updatestealthalert()
+ toggle = FALSE
+ else if(stealthcooldown <= world.time)
+ if(loc == summoner)
+ to_chat(src, "You have to be manifested to enter stealth!")
+ return
+ melee_damage_lower = 50
+ melee_damage_upper = 50
+ armour_penetration = 100
+ new /obj/effect/overlay/temp/guardian/phase(get_turf(src))
+ alpha = 15
+ if(!forced)
+ to_chat(src, "You enter stealth, empowering your next attack.")
+ updatestealthalert()
+ toggle = TRUE
+ else if(!forced)
+ to_chat(src, "You cannot yet enter stealth, wait another [max(round((stealthcooldown - world.time)*0.1, 0.1), 0)] seconds!")
+
+/mob/living/simple_animal/hostile/guardian/assassin/proc/updatestealthalert()
+ if(stealthcooldown <= world.time)
+ if(toggle)
+ if(!instealthalert)
+ instealthalert = throw_alert("instealth", /obj/screen/alert/instealth)
+ clear_alert("canstealth")
+ canstealthalert = null
+ else
+ if(!canstealthalert)
+ canstealthalert = throw_alert("canstealth", /obj/screen/alert/canstealth)
+ clear_alert("instealth")
+ instealthalert = null
+ else
+ clear_alert("instealth")
+ instealthalert = null
+ clear_alert("canstealth")
+ canstealthalert = null
\ No newline at end of file
diff --git a/code/game/gamemodes/miniantags/guardian/types/bomb.dm b/code/game/gamemodes/miniantags/guardian/types/bomb.dm
new file mode 100644
index 00000000000..6a4c74ff1a3
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/bomb.dm
@@ -0,0 +1,76 @@
+/mob/living/simple_animal/hostile/guardian/bomb
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ damage_transfer = 0.6
+ range = 13
+ playstyle_string = "As an Explosive type, you have only moderate close combat abilities, but are capable of converting any adjacent item into a disguised bomb via alt click."
+ magic_fluff_string = "..And draw the Scientist, master of explosive death."
+ tech_fluff_string = "Boot sequence complete. Explosive modules active. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of stealthily booby trapping items."
+ var/bomb_cooldown = 0
+
+/mob/living/simple_animal/hostile/guardian/bomb/AltClickOn(atom/movable/A)
+ if(!istype(A))
+ return
+ if(get_dist(get_turf(src), get_turf(A)) > 1)
+ to_chat(src, "You're too far from [A] to disguise it as a bomb.")
+ return
+ if(istype(A, /obj/))
+ if(bomb_cooldown <= world.time && !stat)
+ var/obj/item/weapon/guardian_bomb/B = new /obj/item/weapon/guardian_bomb(get_turf(A))
+ to_chat(src, "Success! Bomb on [A] armed!")
+ if(summoner)
+ to_chat(summoner, "Your guardian has primed [A] to explode!")
+ bomb_cooldown = world.time + 200
+ B.spawner = src
+ B.disguise (A)
+ else
+ to_chat(src, "Your powers are on cooldown! You must wait 20 seconds between bombs.")
+
+/obj/item/weapon/guardian_bomb
+ name = "bomb"
+ desc = "You shouldn't be seeing this!"
+ var/obj/stored_obj
+ var/mob/living/spawner
+
+
+/obj/item/weapon/guardian_bomb/proc/disguise(var/obj/A)
+ A.forceMove(src)
+ stored_obj = A
+ anchored = A.anchored
+ density = A.density
+ appearance = A.appearance
+ spawn(600)
+ if(src)
+ stored_obj.loc = get_turf(loc)
+ if(spawner)
+ to_chat(spawner, "Failure! Your trap on [stored_obj] didn't catch anyone this time.")
+ qdel(src)
+
+/obj/item/weapon/guardian_bomb/proc/detonate(var/mob/living/user)
+ to_chat(user, "The [src] was boobytrapped!")
+ if(istype(spawner, /mob/living/simple_animal/hostile/guardian))
+ var/mob/living/simple_animal/hostile/guardian/G = spawner
+ if(user == G.summoner)
+ to_chat(user, "You knew this because of your link with your guardian, so you smartly defuse the bomb.")
+ stored_obj.loc = get_turf(loc)
+ qdel(src)
+ return
+ to_chat(spawner, "Success! Your trap on [src] caught [user]!")
+ stored_obj.loc = get_turf(loc)
+ playsound(get_turf(src),'sound/effects/Explosion2.ogg', 200, 1)
+ user.ex_act(2)
+ qdel(src)
+
+/obj/item/weapon/guardian_bomb/attackby(mob/living/user)
+ detonate(user)
+ return
+
+/obj/item/weapon/guardian_bomb/pickup(mob/living/user)
+ detonate(user)
+ return
+
+/obj/item/weapon/guardian_bomb/examine(mob/user)
+ stored_obj.examine(user)
+ if(get_dist(user,src) <= 2)
+ to_chat(user, "Looks odd!")
diff --git a/code/game/gamemodes/miniantags/guardian/types/charger.dm b/code/game/gamemodes/miniantags/guardian/types/charger.dm
new file mode 100644
index 00000000000..39bf995967e
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/charger.dm
@@ -0,0 +1,72 @@
+/mob/living/simple_animal/hostile/guardian/charger
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ ranged = 1 //technically
+ ranged_message = "charges"
+ ranged_cooldown_time = 40
+ speed = -1
+ damage_transfer = 0.6
+ playstyle_string = "As a Charger type you do medium damage, have medium damage resistance, move very fast, and can charge at a location, damaging any target hit and forcing them to drop any items they are holding."
+ magic_fluff_string = "..And draw the Hunter, an alien master of rapid assault."
+ tech_fluff_string = "Boot sequence complete. Charge modules loaded. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to deal damage."
+ var/charging = 0
+ var/obj/screen/alert/chargealert
+
+/mob/living/simple_animal/hostile/guardian/charger/Life()
+ . = ..()
+ if(ranged_cooldown <= world.time)
+ if(!chargealert)
+ chargealert = throw_alert("charge", /obj/screen/alert/cancharge)
+ else
+ clear_alert("charge")
+ chargealert = null
+
+/mob/living/simple_animal/hostile/guardian/charger/OpenFire(atom/A)
+ if(!charging)
+ visible_message("[src] [ranged_message] at [A]!")
+ ranged_cooldown = world.time + ranged_cooldown_time
+ clear_alert("charge")
+ chargealert = null
+ Shoot(A)
+
+/mob/living/simple_animal/hostile/guardian/charger/Shoot(atom/targeted_atom)
+ charging = 1
+ throw_at(targeted_atom, range, 1, src, 0, callback = CALLBACK(src, .proc/charging_end))
+
+/mob/living/simple_animal/hostile/guardian/charger/proc/charging_end()
+ charging = 0
+
+/mob/living/simple_animal/hostile/guardian/charger/Move()
+ if(charging)
+ new /obj/effect/overlay/temp/decoy/fading(loc,src)
+ . = ..()
+
+/mob/living/simple_animal/hostile/guardian/charger/snapback()
+ if(!charging)
+ ..()
+
+/mob/living/simple_animal/hostile/guardian/charger/throw_impact(atom/A)
+ if(!charging)
+ return ..()
+
+ else if(A)
+ if(isliving(A) && A != summoner)
+ var/mob/living/L = A
+ var/blocked = FALSE
+ var/mob/living/simple_animal/hostile/guardian/G = A
+ if(istype(G) && G.summoner == summoner) //if the summoner matches don't hurt them
+ blocked = TRUE
+ if(ishuman(A))
+ var/mob/living/carbon/human/H = A
+ if(H.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK))
+ blocked = TRUE
+ if(!blocked)
+ L.Stun(1)
+ L.visible_message("[src] slams into [L]!", "[src] slams into you!")
+ L.apply_damage(20, BRUTE)
+ playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1)
+ shake_camera(L, 4, 3)
+ shake_camera(src, 2, 3)
+
+ charging = 0
\ No newline at end of file
diff --git a/code/game/gamemodes/miniantags/guardian/types/fire.dm b/code/game/gamemodes/miniantags/guardian/types/fire.dm
new file mode 100644
index 00000000000..1447f36e739
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/fire.dm
@@ -0,0 +1,67 @@
+/mob/living/simple_animal/hostile/guardian/fire
+ a_intent = INTENT_HELP
+ melee_damage_lower = 10
+ melee_damage_upper = 10
+ attack_sound = 'sound/items/Welder.ogg'
+ attacktext = "sears"
+ damage_transfer = 0.8
+ range = 10
+ playstyle_string = "As a Chaos type, you have only light damage resistance, but will ignite any enemy you bump into. In addition, your melee attacks will randomly teleport enemies."
+ environment_smash = 1
+ magic_fluff_string = "..And draw the Wizard, bringer of endless chaos!"
+ tech_fluff_string = "Boot sequence complete. Crowd control modules activated. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to sow havoc at random."
+ var/toggle = FALSE
+
+/mob/living/simple_animal/hostile/guardian/fire/Life() //Dies if the summoner dies
+ ..()
+ if(summoner)
+ summoner.ExtinguishMob()
+ summoner.adjust_fire_stacks(-20)
+
+/mob/living/simple_animal/hostile/guardian/fire/ToggleMode()
+ if(loc == summoner)
+ if(toggle)
+ to_chat(src, "You switch to dispersion mode, and will teleport victims away from your master.")
+ toggle = FALSE
+ else
+ to_chat(src, "You switch to deception mode, and will turn your victims against their allies.")
+ toggle = TRUE
+
+/mob/living/simple_animal/hostile/guardian/fire/AttackingTarget()
+ if(..())
+ if(toggle)
+ if(ishuman(target) && !summoner)
+ spawn(0)
+ new /obj/effect/hallucination/delusion(target.loc, target, force_kind = "custom", duration = 200, skip_nearby = 0, custom_icon = icon_state, custom_icon_file = icon)
+ else
+ if(prob(45))
+ if(ismovableatom(target))
+ var/atom/movable/M = target
+ if(!M.anchored && M != summoner)
+ new /obj/effect/overlay/temp/guardian/phase/out(get_turf(M))
+ do_teleport(M, M, 10)
+ new /obj/effect/overlay/temp/guardian/phase/out(get_turf(M))
+
+/mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj)
+ ..()
+ collision_ignite(AM)
+
+/mob/living/simple_animal/hostile/guardian/fire/Bumped(AM as mob|obj)
+ ..()
+ collision_ignite(AM)
+
+/mob/living/simple_animal/hostile/guardian/fire/Bump(AM as mob|obj)
+ ..()
+ collision_ignite(AM)
+
+/mob/living/simple_animal/hostile/guardian/fire/proc/collision_ignite(AM as mob|obj)
+ if(isliving(AM))
+ var/mob/living/M = AM
+ if(AM != summoner && M.fire_stacks < 7)
+ M.fire_stacks = 7
+ M.IgniteMob()
+
+/mob/living/simple_animal/hostile/guardian/fire/Bump(AM as mob|obj)
+ ..()
+ collision_ignite(AM)
diff --git a/code/game/gamemodes/miniantags/guardian/types/healer.dm b/code/game/gamemodes/miniantags/guardian/types/healer.dm
new file mode 100644
index 00000000000..0a6efb45d06
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/healer.dm
@@ -0,0 +1,138 @@
+/mob/living/simple_animal/hostile/guardian/healer
+ a_intent = INTENT_HARM
+ friendly = "heals"
+ speed = 0
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ playstyle_string = "As a Support type, you may toggle your basic attacks to a healing mode. In addition, Alt-Clicking on an adjacent mob will warp them to your bluespace beacon after a short delay."
+ magic_fluff_string = "..And draw the CMO, a potent force of life...and death."
+ tech_fluff_string = "Boot sequence complete. Medical modules active. Bluespace modules activated. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of mending wounds and travelling via bluespace."
+ var/turf/simulated/floor/beacon
+ var/beacon_cooldown = 0
+ var/toggle = FALSE
+ var/heal_cooldown = 0
+
+/mob/living/simple_animal/hostile/guardian/healer/sealhealer
+ name = "Seal Sprit"
+ real_name = "Seal Sprit"
+ icon = 'icons/mob/animal.dmi'
+ icon_living = "seal"
+ icon_state = "seal"
+ attacktext = "slaps"
+ speak_emote = list("barks")
+ a_intent = INTENT_HARM
+ friendly = "heals"
+ speed = 0
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ melee_damage_type = STAMINA
+ adminseal = TRUE
+
+/mob/living/simple_animal/hostile/guardian/healer/New()
+ ..()
+
+/mob/living/simple_animal/hostile/guardian/healer/Life()
+ ..()
+ var/datum/atom_hud/medsensor = huds[DATA_HUD_MEDICAL_ADVANCED]
+ medsensor.add_hud_to(src)
+
+/mob/living/simple_animal/hostile/guardian/healer/AttackingTarget()
+ ..()
+ if(toggle == TRUE)
+ if(loc == summoner)
+ to_chat(src, "You must be manifested to heal!")
+ return
+ if(iscarbon(target))
+ changeNext_move(CLICK_CD_MELEE)
+ if(heal_cooldown <= world.time && !stat)
+ var/mob/living/carbon/C = target
+ C.adjustBruteLoss(-5)
+ C.adjustFireLoss(-5)
+ C.adjustOxyLoss(-5)
+ C.adjustToxLoss(-5)
+ heal_cooldown = world.time + 20
+
+/mob/living/simple_animal/hostile/guardian/healer/ToggleMode()
+ if(loc == summoner)
+ if(toggle)
+ a_intent = INTENT_HARM
+ speed = 0
+ damage_transfer = 0.7
+ if(adminseal)
+ damage_transfer = 0
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ to_chat(src, "You switch to combat mode.")
+ toggle = FALSE
+ else
+ a_intent = INTENT_HELP
+ speed = 1
+ damage_transfer = 1
+ if(adminseal)
+ damage_transfer = 0
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ to_chat(src, "You switch to healing mode.")
+ toggle = TRUE
+ else
+ to_chat(src, "You have to be recalled to toggle modes!")
+
+
+/mob/living/simple_animal/hostile/guardian/healer/verb/Beacon()
+ set name = "Place Bluespsace Beacon"
+ set category = "Guardian"
+ set desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon will not work in unfavorable atmospheric conditions."
+ if(beacon_cooldown < world.time)
+ var/turf/beacon_loc = get_turf(loc)
+ if(istype(beacon_loc, /turf/simulated/floor))
+ var/turf/simulated/floor/F = beacon_loc
+ F.icon = 'icons/turf/floors.dmi'
+ F.name = "bluespace recieving pad"
+ F.desc = "A recieving zone for bluespace teleportations. Building a wall over it should disable it."
+ F.icon_state = "light_on-w"
+ to_chat(src, "Beacon placed! You may now warp targets to it, including your user, via Alt+Click. ")
+ if(beacon)
+ beacon.ChangeTurf(/turf/simulated/floor/plating)
+ beacon = F
+ beacon_cooldown = world.time+3000
+
+ else
+ to_chat(src, "Your power is on cooldown. You must wait five minutes between placing beacons.")
+
+/mob/living/simple_animal/hostile/guardian/healer/AltClickOn(atom/movable/A)
+ if(!istype(A))
+ return
+ if(loc == summoner)
+ to_chat(src, "You must be manifested to warp a target!")
+ return
+ if(!beacon)
+ to_chat(src, "You need a beacon placed to warp things!")
+ return
+ if(!Adjacent(A))
+ to_chat(src, "You must be adjacent to your target!")
+ return
+ if((A.anchored))
+ to_chat(src, "Your target can not be anchored!")
+ return
+ to_chat(src, "You begin to warp [A]")
+ if(do_mob(src, A, 50))
+ if(!A.anchored)
+ if(beacon) //Check that the beacon still exists and is in a safe place. No instant kills.
+ if(beacon.air)
+ var/datum/gas_mixture/Z = beacon.air
+ if(Z.oxygen >= 16 && !Z.toxins && Z.carbon_dioxide < 10 && !Z.trace_gases.len)
+ if((Z.temperature > 270) && (Z.temperature < 360))
+ var/pressure = Z.return_pressure()
+ if((pressure > 20) && (pressure < 550))
+ new /obj/effect/overlay/temp/guardian/phase/out(get_turf(A))
+ do_teleport(A, beacon, 0)
+ new /obj/effect/overlay/temp/guardian/phase(get_turf(A))
+ else
+ to_chat(src, "The beacon isn't in a safe location!")
+ else
+ to_chat(src, "The beacon isn't in a safe location!")
+ else
+ to_chat(src, "You need a beacon to warp things!")
+ else
+ to_chat(src, "You need to hold still!")
diff --git a/code/game/gamemodes/miniantags/guardian/types/lightning.dm b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
new file mode 100644
index 00000000000..ea11fc5cfdd
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/lightning.dm
@@ -0,0 +1,109 @@
+/obj/effect/ebeam/chain
+ name = "lightning chain"
+ layer = LYING_MOB_LAYER
+
+/mob/living/simple_animal/hostile/guardian/beam
+ melee_damage_lower = 7
+ melee_damage_upper = 7
+ attacktext = "shocks"
+ melee_damage_type = BURN
+ attack_sound = 'sound/machines/defib_zap.ogg'
+ damage_transfer = 0.7
+ range = 7
+ playstyle_string = "As a Lightning type, you will apply lightning chains to targets on attack and have a lightning chain to your summoner. Lightning chains will shock anyone near them."
+ magic_fluff_string = "..And draw the Tesla, a shocking, lethal source of power."
+ tech_fluff_string = "Boot sequence complete. Lightning modules active. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to electrify your enemies."
+ var/datum/beam/summonerchain
+ var/list/enemychains = list()
+ var/successfulshocks = 0
+
+/mob/living/simple_animal/hostile/guardian/beam/AttackingTarget()
+ ..()
+ if(isliving(target) && target != src && target != summoner)
+ cleardeletedchains()
+ for(var/chain in enemychains)
+ var/datum/beam/B = chain
+ if(B.target == target)
+ return //oh this guy already HAS a chain, let's not chain again
+ if(enemychains.len > 2)
+ var/datum/beam/C = pick(enemychains)
+ qdel(C)
+ enemychains -= C
+ enemychains += Beam(target, "lightning[rand(1,12)]", 'icons/effects/effects.dmi', time=70, maxdistance=7, beam_type=/obj/effect/ebeam/chain)
+
+/mob/living/simple_animal/hostile/guardian/beam/Destroy()
+ removechains()
+ return ..()
+
+/mob/living/simple_animal/hostile/guardian/beam/Manifest()
+ ..()
+ if(summoner)
+ summonerchain = Beam(summoner, "lightning[rand(1,12)]", 'icons/effects/effects.dmi', time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain)
+ while(loc != summoner)
+ if(successfulshocks > 5)
+ successfulshocks = 0
+ if(shockallchains())
+ successfulshocks++
+ sleep(3)
+
+/mob/living/simple_animal/hostile/guardian/beam/Recall()
+ . = ..()
+ if(.)
+ removechains()
+
+/mob/living/simple_animal/hostile/guardian/beam/proc/cleardeletedchains()
+ if(summonerchain && qdeleted(summonerchain))
+ summonerchain = null
+ if(enemychains.len)
+ for(var/chain in enemychains)
+ var/datum/cd = chain
+ if(!chain || qdeleted(cd))
+ enemychains -= chain
+
+/mob/living/simple_animal/hostile/guardian/beam/proc/shockallchains()
+ . = 0
+ cleardeletedchains()
+ if(summoner)
+ if(!summonerchain)
+ summonerchain = Beam(summoner, "lightning[rand(1,12)]", 'icons/effects/effects.dmi', time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam/chain)
+ . += chainshock(summonerchain)
+ if(enemychains.len)
+ for(var/chain in enemychains)
+ . += chainshock(chain)
+
+/mob/living/simple_animal/hostile/guardian/beam/proc/removechains()
+ if(summonerchain)
+ QDEL_NULL(summonerchain)
+ if(enemychains.len)
+ for(var/chain in enemychains)
+ qdel(chain)
+ enemychains = list()
+
+/mob/living/simple_animal/hostile/guardian/beam/proc/chainshock(datum/beam/B)
+ . = 0
+ var/list/turfs = list()
+ for(var/E in B.elements)
+ var/obj/effect/ebeam/chainpart = E
+ if(chainpart && chainpart.x && chainpart.y && chainpart.z)
+ var/turf/T = get_turf_pixel(chainpart)
+ turfs |= T
+ if(T != get_turf(B.origin) && T != get_turf(B.target))
+ for(var/turf/TU in circlerange(T, 1))
+ turfs |= TU
+ for(var/turf in turfs)
+ var/turf/T = turf
+ for(var/mob/living/L in T)
+ if(L.stat != DEAD && L != src && L != summoner)
+ var/mob/living/simple_animal/hostile/guardian/G = L
+ if(istype(G) && G.summoner == summoner)
+ continue
+ if(successfulshocks > 4)
+ //L.electrocute_act(30, src) //shocks for 30 burn damage
+ L.visible_message(
+ "[L] was shocked by the lightning chain!", \
+ "You are shocked by the lightning chain!", \
+ "You hear a heavy electrical crack." \
+ )
+ L.adjustFireLoss(1.2) //adds up very rapidly
+ . = 1
\ No newline at end of file
diff --git a/code/game/gamemodes/miniantags/guardian/types/protector.dm b/code/game/gamemodes/miniantags/guardian/types/protector.dm
new file mode 100644
index 00000000000..aa8bcaf09dc
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/protector.dm
@@ -0,0 +1,57 @@
+/mob/living/simple_animal/hostile/guardian/protector
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ range = 15 //worse for it due to how it leashes
+ damage_transfer = 0.4
+ playstyle_string = "As a Protector type you cause your summoner to leash to you instead of you leashing to them and have two modes; Combat Mode, where you do and take medium damage, and Protection Mode, where you do and take almost no damage, but move slightly slower."
+ magic_fluff_string = "..And draw the Guardian, a stalwart protector that never leaves the side of its charge."
+ tech_fluff_string = "Boot sequence complete. Protector modules loaded. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, ready to defend you."
+ var/toggle = FALSE
+
+/mob/living/simple_animal/hostile/guardian/protector/ex_act(severity)
+ if(severity == 1)
+ adjustBruteLoss(400) //if in protector mode, will do 20 damage and not actually necessarily kill the summoner
+ else
+ ..()
+ if(toggle)
+ visible_message("The explosion glances off [src]'s energy shielding!")
+
+/mob/living/simple_animal/hostile/guardian/protector/ToggleMode()
+ if(cooldown > world.time)
+ return 0
+ cooldown = world.time + 10
+ if(toggle)
+ overlays.Cut()
+ melee_damage_lower = initial(melee_damage_lower)
+ melee_damage_upper = initial(melee_damage_upper)
+ speed = initial(speed)
+ damage_transfer = 0.4
+ to_chat(src, "You switch to combat mode.")
+ toggle = FALSE
+ else
+ var/icon/shield_overlay = icon('icons/effects/effects.dmi', "shield-grey")
+ shield_overlay *= name_color
+ overlays.Add(shield_overlay)
+ melee_damage_lower = 2
+ melee_damage_upper = 2
+ speed = 1
+ damage_transfer = 0.05 //damage? what's damage?
+ to_chat(src, "You switch to protection mode.")
+ toggle = TRUE
+
+/mob/living/simple_animal/hostile/guardian/protector/snapback() //snap to what? snap to the guardian!
+ if(summoner)
+ if(get_dist(get_turf(summoner),get_turf(src)) <= range)
+ return
+ else
+ if(istype(summoner.loc, /obj/effect))
+ to_chat(src, "You moved out of range, and were pulled back! You can only move [range] meters from [summoner.real_name]!")
+ visible_message("[src] jumps back to its user.")
+ Recall(TRUE)
+ else
+ to_chat(summoner, "You moved out of range, and were pulled back! You can only move [range] meters from [src]!")
+ summoner.visible_message("[summoner] jumps back to their protector.")
+ new /obj/effect/overlay/temp/guardian/phase/out(get_turf(summoner))
+ summoner.forceMove(get_turf(src))
+ new /obj/effect/overlay/temp/guardian/phase(get_turf(summoner))//Protector
\ No newline at end of file
diff --git a/code/game/gamemodes/miniantags/guardian/types/ranged.dm b/code/game/gamemodes/miniantags/guardian/types/ranged.dm
new file mode 100644
index 00000000000..648339743fd
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/ranged.dm
@@ -0,0 +1,99 @@
+/obj/item/projectile/guardian
+ name = "crystal spray"
+ icon_state = "guardian"
+ damage = 5
+ damage_type = BRUTE
+ armour_penetration = 100
+
+/mob/living/simple_animal/hostile/guardian/ranged
+ a_intent = INTENT_HELP
+ friendly = "quietly assesses"
+ melee_damage_lower = 10
+ melee_damage_upper = 10
+ damage_transfer = 0.9
+ projectiletype = /obj/item/projectile/guardian
+ ranged_cooldown_time = 10
+ projectilesound = 'sound/effects/hit_on_shattered_glass.ogg'
+ ranged = 1
+ rapid = 1
+ range = 13
+ see_invisible = SEE_INVISIBLE_MINIMUM
+ see_in_dark = 8
+ playstyle_string = "As a Ranged type, you have only light damage resistance, but are capable of spraying shards of crystal at incredibly high speed. You can also deploy surveillance snares to monitor enemy movement. Finally, you can switch to scout mode, in which you can't attack, but can move without limit."
+ magic_fluff_string = "..And draw the Sentinel, an alien master of ranged combat."
+ tech_fluff_string = "Boot sequence complete. Ranged combat modules active. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm finishes mutating and stirs to life, capable of spraying shards of crystal."
+ var/list/snares = list()
+ var/toggle = FALSE
+
+/mob/living/simple_animal/hostile/guardian/ranged/ToggleMode()
+ if(loc == summoner)
+ if(toggle)
+ ranged = 1
+ melee_damage_lower = 10
+ melee_damage_upper = 10
+ alpha = 255
+ range = 13
+ incorporeal_move = 0
+ to_chat(src, "You switch to combat mode.")
+ toggle = FALSE
+ else
+ ranged = 0
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ alpha = 60
+ range = 255
+ incorporeal_move = 1
+ to_chat(src, "You switch to scout mode.")
+ toggle = TRUE
+ else
+ to_chat(src, "You have to be recalled to toggle modes!")
+
+/mob/living/simple_animal/hostile/guardian/ranged/ToggleLight()
+ if(see_invisible == SEE_INVISIBLE_MINIMUM)
+ to_chat(src, "You deactivate your night vision.")
+ see_invisible = SEE_INVISIBLE_LIVING
+ else
+ to_chat(src, "You activate your night vision.")
+ see_invisible = SEE_INVISIBLE_MINIMUM
+
+/mob/living/simple_animal/hostile/guardian/ranged/verb/Snare()
+ set name = "Set Surveillance Trap"
+ set category = "Guardian"
+ set desc = "Set an invisible trap that will alert you when living creatures walk over it. Max of 5"
+ if(snares.len <6)
+ var/turf/snare_loc = get_turf(loc)
+ var/obj/item/effect/snare/S = new /obj/item/effect/snare(snare_loc)
+ S.spawner = src
+ S.name = "[get_area(snare_loc)] trap ([rand(1, 1000)])"
+ snares |= S
+ to_chat(src, "Surveillance trap deployed!")
+ else
+ to_chat(src, "You have too many traps deployed. Delete some first.")
+
+/mob/living/simple_animal/hostile/guardian/ranged/verb/DisarmSnare()
+ set name = "Remove Surveillance Trap"
+ set category = "Guardian"
+ set desc = "Disarm unwanted surveillance traps."
+ var/picked_snare = input(src, "Pick which trap to disarm", "Disarm Trap") as null|anything in snares
+ if(picked_snare)
+ snares -= picked_snare
+ qdel(picked_snare)
+ to_chat(src, "Snare disarmed.")
+
+/obj/item/effect/snare
+ name = "snare"
+ desc = "You shouldn't be seeing this!"
+ var/mob/living/spawner
+ invisibility = 1
+
+
+/obj/item/effect/snare/Crossed(AM as mob|obj)
+ if(isliving(AM))
+ var/turf/snare_loc = get_turf(loc)
+ if(spawner)
+ to_chat(spawner, "[AM] has crossed your surveillance trap at [get_area(snare_loc)].")
+ if(istype(spawner, /mob/living/simple_animal/hostile/guardian))
+ var/mob/living/simple_animal/hostile/guardian/G = spawner
+ if(G.summoner)
+ to_chat(G.summoner, "[AM] has crossed your surveillance trap at [get_area(snare_loc)].")
diff --git a/code/game/gamemodes/miniantags/guardian/types/standard.dm b/code/game/gamemodes/miniantags/guardian/types/standard.dm
new file mode 100644
index 00000000000..10327778a65
--- /dev/null
+++ b/code/game/gamemodes/miniantags/guardian/types/standard.dm
@@ -0,0 +1,47 @@
+/mob/living/simple_animal/hostile/guardian/punch
+ melee_damage_lower = 20
+ melee_damage_upper = 20
+ damage_transfer = 0.4
+ playstyle_string = "As a Standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls."
+ environment_smash = 2
+ magic_fluff_string = "..And draw the Assistant, faceless and generic, but never to be underestimated."
+ tech_fluff_string = "Boot sequence complete. Standard combat modules loaded. Holoparasite swarm online."
+ bio_fluff_string = "Your scarab swarm stirs to life, ready to tear apart your enemies."
+ var/battlecry = "AT"
+
+/mob/living/simple_animal/hostile/guardian/punch/verb/Battlecry()
+ set name = "Set Battlecry"
+ set category = "Guardian"
+ set desc = "Choose what you shout as you punch"
+ var/input = stripped_input(src,"What do you want your battlecry to be? Max length of 5 characters.", ,"", 6)
+ if(input)
+ battlecry = input
+
+/mob/living/simple_animal/hostile/guardian/punch/AttackingTarget()
+ ..()
+ if(iscarbon(target) && target != summoner)
+ if(length(battlecry) > 11)//no more then 11 letters in a battle cry.
+ visible_message("[src] punches [target]!")
+ else
+ say("[battlecry][battlecry][battlecry][battlecry][battlecry]")
+ playsound(loc, attack_sound, 50, 1, 1)
+ playsound(loc, attack_sound, 50, 1, 1)
+ playsound(loc, attack_sound, 50, 1, 1)
+ playsound(loc, attack_sound, 50, 1, 1)
+
+/mob/living/simple_animal/hostile/guardian/punch/sealpunch
+ name = "Seal Sprit"
+ real_name = "Seal Sprit"
+ icon = 'icons/mob/animal.dmi'
+ icon_living = "seal"
+ icon_state = "seal"
+ attacktext = "slaps"
+ speak_emote = list("barks")
+ melee_damage_lower = 0
+ melee_damage_upper = 0
+ melee_damage_type = STAMINA
+ damage_transfer = 0
+ playstyle_string = "As a standard type you have no special abilities, but have a high damage resistance and a powerful attack capable of smashing through walls."
+ environment_smash = 2
+ battlecry = "URK"
+ adminseal = TRUE
\ No newline at end of file
diff --git a/code/game/gamemodes/nations/nations.dm b/code/game/gamemodes/nations/nations.dm
index 15f5493543e..43db22601af 100644
--- a/code/game/gamemodes/nations/nations.dm
+++ b/code/game/gamemodes/nations/nations.dm
@@ -135,7 +135,7 @@ datum/game_mode/nations
AI.show_laws()
for(var/mob/living/silicon/robot/R in AI.connected_robots)
var/obj/item/device/mmi/oldmmi = R.mmi
- R.change_mob_type(/mob/living/silicon/robot/peacekeeper, null, null, 1, 1 )
+ R.change_mob_type(/mob/living/silicon/robot/nations, null, null, 1, 1 )
R.lawsync()
R.show_laws()
qdel(oldmmi)
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index 6c28b9ade28..8b0565c432e 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -153,13 +153,11 @@ proc/issyndicate(mob/living/M as mob)
var/hair_c = pick("#8B4513","#000000","#FF4500","#FFD700") // Brown, black, red, blonde
var/eye_c = pick("#000000","#8B4513","1E90FF") // Black, brown, blue
var/skin_tone = pick(-50, -30, -10, 0, 0, 0, 10) // Caucasian/black
- head_organ.r_facial = color2R(hair_c)
- head_organ.g_facial = color2G(hair_c)
- head_organ.b_facial = color2B(hair_c)
- head_organ.r_hair = color2R(hair_c)
- head_organ.g_hair = color2G(hair_c)
- head_organ.b_hair = color2B(hair_c)
- M.change_eye_color(color2R(eye_c), color2G(eye_c), color2B(eye_c))
+ head_organ.facial_colour = hair_c
+ head_organ.sec_facial_colour = hair_c
+ head_organ.hair_colour = hair_c
+ head_organ.sec_hair_colour = hair_c
+ M.change_eye_color(eye_c)
M.s_tone = skin_tone
head_organ.h_style = random_hair_style(M.gender, head_organ.species.name)
head_organ.f_style = random_facial_hair_style(M.gender, head_organ.species.name)
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 7a85467667e..6e085df1a5c 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -155,7 +155,8 @@ var/bomb_set
..()
/obj/machinery/nuclearbomb/attack_ghost(mob/user as mob)
- attack_hand(user)
+ if(extended)
+ attack_hand(user)
/obj/machinery/nuclearbomb/attack_hand(mob/user as mob)
if(extended)
diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm
index e34174f2beb..01d4e0ed3a7 100644
--- a/code/game/gamemodes/objective.dm
+++ b/code/game/gamemodes/objective.dm
@@ -1,12 +1,6 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
var/global/list/all_objectives = list()
-var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) \
- - /datum/theft_objective/steal \
- - /datum/theft_objective/special \
- - /datum/theft_objective/number \
- - /datum/theft_objective/number/special \
- - /datum/theft_objective/number/coins
+var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) - /datum/theft_objective/steal - /datum/theft_objective/number - /datum/theft_objective/unique
/datum/objective
var/datum/mind/owner = null //Who owns the objective.
@@ -287,7 +281,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) \
for(var/datum/mind/possible_target in ticker.minds)
if(possible_target != owner && ishuman(possible_target.current) && (possible_target.current.stat != DEAD) && possible_target.current.client)
var/mob/living/carbon/human/H = possible_target.current
- if(!(H.species.flags & NO_DNA))
+ if(!(NO_DNA in H.species.species_traits))
possible_targets += possible_target
if(possible_targets.len > 0)
target = pick(possible_targets)
@@ -341,7 +335,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) \
var/datum/theft_objective/steal_target
martyr_compatible = 0
-/datum/objective/steal/find_target(var/special_only=0)
+/datum/objective/steal/find_target()
var/loop=50
while(!steal_target && loop > 0)
loop--
@@ -349,12 +343,6 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) \
var/datum/theft_objective/O = new thefttype
if(owner.assigned_role in O.protected_jobs)
continue
- if(special_only)
- if(!(O.flags & 1)) // THEFT_FLAG_SPECIAL
- continue
- else
- if(O.flags & 1) // THEFT_FLAG_SPECIAL
- continue
if(O.flags & 2)
continue
steal_target=O
@@ -457,7 +445,7 @@ var/list/potential_theft_objectives = subtypesof(/datum/theft_objective) \
n_p++
else if(ticker.current_state == GAME_STATE_PLAYING)
for(var/mob/living/carbon/human/P in player_list)
- if(P.species.flags & NO_DNA)
+ if(NO_DNA in P.species.species_traits)
continue
if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner)
n_p++
diff --git a/code/game/gamemodes/shadowling/shadowling.dm b/code/game/gamemodes/shadowling/shadowling.dm
index 97f609ca9ff..1e4671998e8 100644
--- a/code/game/gamemodes/shadowling/shadowling.dm
+++ b/code/game/gamemodes/shadowling/shadowling.dm
@@ -305,7 +305,7 @@ Made by Xhuis
blood_color = "#555555"
flesh_color = "#222222"
- flags = NO_BLOOD | NO_BREATHE | RADIMMUNE | NOGUNS //Can't use guns due to muzzle flash
+ species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE, NOGUNS) //Can't use guns due to muzzle flash
burn_mod = 1.5 //1.5x burn damage, 2x is excessive
oxy_mod = 0
hot_env_multiplier = 1.5
@@ -329,9 +329,15 @@ Made by Xhuis
H << 'sound/weapons/sear.ogg'
else if(light_amount < LIGHT_HEAL_THRESHOLD)
H.clear_alert("lightexposure")
+ var/obj/item/organ/internal/eyes/E = H.get_int_organ(/obj/item/organ/internal/eyes)
+ if(istype(E))
+ E.take_damage(-1)
H.heal_overall_damage(5, 5)
H.adjustToxLoss(-5)
H.adjustBrainLoss(-25) //Shad O. Ling gibbers, "CAN U BE MY THRALL?!!"
+ H.AdjustEyeBlurry(-1)
+ H.CureNearsighted()
+ H.CureBlind()
H.adjustCloneLoss(-1)
H.SetWeakened(0)
H.SetStunned(0)
@@ -346,7 +352,7 @@ Made by Xhuis
blood_color = "#CCCCCC"
flesh_color = "#AAAAAA"
- flags = NO_BLOOD | NO_BREATHE | RADIMMUNE
+ species_traits = list(NO_BLOOD, NO_BREATHE, RADIMMUNE)
burn_mod = 1.1
oxy_mod = 0
hot_env_multiplier = 1.1
@@ -378,4 +384,4 @@ Made by Xhuis
/datum/game_mode/proc/update_shadow_icons_removed(datum/mind/shadow_mind) //This should never actually occur, but it's here anyway.
var/datum/atom_hud/antag/shadow_hud = huds[ANTAG_HUD_SHADOW]
shadow_hud.leave_hud(shadow_mind.current)
- set_antag_hud(shadow_mind.current, null)
\ No newline at end of file
+ set_antag_hud(shadow_mind.current, null)
diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm
index 55d1a2f8db7..2965456c99b 100644
--- a/code/game/gamemodes/shadowling/shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm
@@ -363,7 +363,7 @@
var/mob/living/carbon/human/H = target
H.visible_message("[H]'s skin suddenly bubbles and shifts around their body!", \
"You regenerate your protective armor and cleanse your form of defects.")
- H.adjustCloneLoss(target.getCloneLoss())
+ H.adjustCloneLoss(-target.getCloneLoss())
H.equip_to_slot_or_del(new /obj/item/clothing/under/shadowling(H), slot_w_uniform)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/shadowling(H), slot_shoes)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/space/shadowling(H), slot_wear_suit)
diff --git a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
index cfe4de51e4f..353fd328f4c 100644
--- a/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
+++ b/code/game/gamemodes/shadowling/special_shadowling_abilities.dm
@@ -96,6 +96,7 @@ var/list/possibleShadowlingNames = list("U'ruan", "Y`shej", "Nex", "Hel-uae", "N
sleep(10)
to_chat(H, "Your powers are awoken. You may now live to your fullest extent. Remember your goal. Cooperate with your thralls and allies.")
+ H.ExtinguishMob()
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/shadow_vision(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/enthrall(null))
H.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/glare(null))
diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm
index 92573fcc17e..bc2a585f7b3 100644
--- a/code/game/gamemodes/steal_items.dm
+++ b/code/game/gamemodes/steal_items.dm
@@ -2,12 +2,12 @@
//
// Separated into datums so we can prevent roles from getting certain objectives.
-#define THEFT_FLAG_SPECIAL 1
+#define THEFT_FLAG_SPECIAL 1//unused, maybe someone will use it some day, I'll leave it here for the children
#define THEFT_FLAG_UNIQUE 2
/datum/theft_objective
- var/name = ""
- var/typepath=/atom
+ var/name = "this objective is impossible, yell at a coder"
+ var/typepath=/obj/effect/debugging
var/list/protected_jobs = list()
var/list/altitems = list()
var/flags = 0
@@ -31,6 +31,11 @@
typepath = /obj/item/weapon/gun/energy/laser/captain
protected_jobs = list("Captain")
+/datum/theft_objective/captains_jetpack
+ name = "the captain's deluxe jetpack"
+ typepath = /obj/item/weapon/tank/jetpack/oxygen/captain
+ protected_jobs = list("Captain")
+
/datum/theft_objective/hoslaser
name = "the head of security's recreated antique laser gun"
typepath = /obj/item/weapon/gun/energy/gun/hos
@@ -41,11 +46,6 @@
typepath = /obj/item/weapon/hand_tele
protected_jobs = list("Captain", "Research Director")
-/datum/theft_objective/jetpack
- name = "a jetpack"
- typepath = /obj/item/weapon/tank/jetpack
- protected_jobs = list("Chief Engineer")
-
/datum/theft_objective/ai
name = "a functional AI"
typepath = /obj/item/device/aicard
@@ -173,32 +173,6 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/device/aicard/C)
/datum/theft_objective/number/plasma_gas/getAmountStolen(var/obj/item/I)
return I:air_contents:toxins
-/datum/theft_objective/number/coins
- name = "credits of coins (in bag)"
- min=1000
- max=5000
- step=500
-
-/datum/theft_objective/number/coins/check_completion(var/datum/mind/owner)
- if(!owner.current)
- return 0
- if(!isliving(owner.current))
- return 0
- var/list/all_items = owner.current.get_contents()
- var/found_amount=0.0
- for(var/obj/item/weapon/moneybag/B in all_items)
- if(B)
- for(var/obj/item/weapon/coin/C in B)
- found_amount += C.credits
- return found_amount >= required_amount
-
-
-////////////////////////////////
-// SPECIAL OBJECTIVES
-////////////////////////////////
-/datum/theft_objective/special
- flags = THEFT_FLAG_SPECIAL
-
/datum/theft_objective/unique
flags = THEFT_FLAG_UNIQUE
@@ -209,47 +183,3 @@ datum/theft_objective/ai/check_special_completion(var/obj/item/device/aicard/C)
/datum/theft_objective/unique/docs_blue
name = "the \"Blue\" secret documents"
typepath = /obj/item/documents/syndicate/blue
-
-/datum/theft_objective/special/pinpointer
- name = "the captain's pinpointer"
- typepath = /obj/item/weapon/pinpointer
-
-/datum/theft_objective/special/nuke_gun
- name = "advanced energy gun"
- typepath = /obj/item/weapon/gun/energy/gun/nuclear
-
-/datum/theft_objective/special/diamond_drill
- name = "diamond drill"
- typepath = /obj/item/weapon/pickaxe/drill/diamonddrill
-
-/datum/theft_objective/special/boh
- name = "bag of holding"
- typepath = /obj/item/weapon/storage/backpack/holding
-
-/datum/theft_objective/special/hyper_cell
- name = "hyper-capacity cell"
- typepath = /obj/item/weapon/stock_parts/cell/hyper
-
-/datum/theft_objective/number/special
- flags = THEFT_FLAG_SPECIAL
-
-/datum/theft_objective/number/special/diamonds
- name = "diamonds"
- typepath = /obj/item/stack/sheet/mineral/diamond
- min=5
- max=10
- step=5
-
-/datum/theft_objective/number/special/gold
- name = "gold bars"
- typepath = /obj/item/stack/sheet/mineral/gold
- min=10
- max=50
- step=10
-
-/datum/theft_objective/number/special/uranium
- name = "refined uranium bars"
- typepath = /obj/item/stack/sheet/mineral/uranium
- min=10
- max=30
- step=5
diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm
index 6e0cc7ebd22..94b75646bf5 100644
--- a/code/game/gamemodes/vampire/vampire.dm
+++ b/code/game/gamemodes/vampire/vampire.dm
@@ -297,12 +297,12 @@ You are weak to holy things and starlight. Don't go into space and avoid the Cha
bloodtotal += blood / 2 //divide by 2 to counted the double suction since removing cloneloss -Melandor0
bloodusable += blood / 2
else
- blood = min(5, H.blood_volume) // The dead only give 5 bloods
+ blood = min(5, H.blood_volume) // The dead only give 5 blood
bloodtotal += blood
if(old_bloodtotal != bloodtotal)
to_chat(owner, "You have accumulated [bloodtotal] [bloodtotal > 1 ? "units" : "unit"] of blood[bloodusable != old_bloodusable ? ", and have [bloodusable] left to use" : ""].")
check_vampire_upgrade()
- H.blood_volume -= 25
+ H.blood_volume = max(H.blood_volume - 25, 0)
if(ishuman(owner))
var/mob/living/carbon/human/V = owner
V.nutrition = min(NUTRITION_LEVEL_WELL_FED, V.nutrition + (blood / 2))
diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm
index c66a0304316..9509316f787 100644
--- a/code/game/gamemodes/vampire/vampire_powers.dm
+++ b/code/game/gamemodes/vampire/vampire_powers.dm
@@ -236,10 +236,16 @@
/obj/effect/proc_holder/spell/vampire/self/shapeshift/cast(list/targets, mob/user = usr)
user.visible_message("[user] transforms!")
- user.client.prefs.real_name = user.generate_name()
- user.client.prefs.random_character()
- user.client.prefs.copy_to(user)
- user.regenerate_icons()
+ if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ scramble(1, H, 100)
+ H.real_name = random_name(H.gender, H.species.name) //Give them a name that makes sense for their species.
+ H.sync_organ_dna(assimilate = 1)
+ H.update_body(0)
+ H.reset_hair() //No more winding up with hairstyles you're not supposed to have, and blowing your cover.
+ H.reset_markings() //...Or markings.
+ H.dna.ResetUIFrom(H)
+ user.update_icons()
/obj/effect/proc_holder/spell/vampire/self/screech
name = "Chiropteran Screech (30)"
@@ -313,6 +319,7 @@
return 0
if(!affects(C))
C.visible_message("[C] seems to resist the takeover!", "Your faith of [ticker.Bible_deity_name] has kept your mind clear of all evil.")
+ return 0
if(!ishuman(C))
to_chat(user, "You can only enthrall humans!")
return 0
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index 2f0e9ab849a..39e9451ac22 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -1,5 +1,3 @@
-//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
-
/var/const/access_security = 1 // Security equipment
/var/const/access_brig = 2 // Brig timers and permabrig
/var/const/access_armory = 3
diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm
index ce410dea69e..477321a69ec 100644
--- a/code/game/jobs/job/engineering.dm
+++ b/code/game/jobs/job/engineering.dm
@@ -112,9 +112,9 @@
id = /obj/item/weapon/card/id/engineering
pda = /obj/item/device/pda/atmos
- backpack = /obj/item/weapon/storage/backpack/industrial
- satchel = /obj/item/weapon/storage/backpack/satchel_eng
- dufflebag = /obj/item/weapon/storage/backpack/duffel/engineering
+ backpack = /obj/item/weapon/storage/backpack/industrial
+ satchel = /obj/item/weapon/storage/backpack/satchel_eng
+ dufflebag = /obj/item/weapon/storage/backpack/duffel/atmos
box = /obj/item/weapon/storage/box/engineer
/datum/job/mechanic
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index 60f1bd541a8..573f8e72c94 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -215,16 +215,18 @@
uniform = /obj/item/clothing/under/rank/clown
shoes = /obj/item/clothing/shoes/clown_shoes
mask = /obj/item/clothing/mask/gas/clown_hat
+ l_pocket = /obj/item/weapon/bikehorn
l_ear = /obj/item/device/radio/headset/headset_service
id = /obj/item/weapon/card/id/clown
pda = /obj/item/device/pda/clown
backpack_contents = list(
/obj/item/weapon/reagent_containers/food/snacks/grown/banana = 1,
- /obj/item/weapon/bikehorn = 1,
/obj/item/weapon/stamp/clown = 1,
/obj/item/toy/crayon/rainbow = 1,
/obj/item/weapon/storage/fancy/crayons = 1,
- /obj/item/weapon/reagent_containers/spray/waterflower = 1
+ /obj/item/weapon/reagent_containers/spray/waterflower = 1,
+ /obj/item/weapon/reagent_containers/food/drinks/bottle/bottleofbanana = 1,
+ /obj/item/device/instrument/bikehorn = 1
)
backpack = /obj/item/weapon/storage/backpack/clown
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 5bd5b69d9dd..3c56199513e 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -92,7 +92,7 @@
if(filtering > 0)
if(beaker)
// To prevent runtimes from drawing blood from runtime, and to prevent getting IPC blood.
- if(!istype(occupant) || !occupant.dna || (occupant.species && occupant.species.flags & NO_BLOOD))
+ if(!istype(occupant) || !occupant.dna || (NO_BLOOD in occupant.species.species_traits))
filtering = 0
return
@@ -197,7 +197,7 @@
crisis = (occupant.health < min_health)
// I'm not sure WHY you'd want to put a simple_animal in a sleeper, but precedent is precedent
// Runtime is aptly named, isn't she?
- if(ishuman(occupant) && !(occupant.species && occupant.species.flags & NO_BLOOD))
+ if(ishuman(occupant) && !(NO_BLOOD in occupant.species.species_traits))
occupantData["pulse"] = occupant.get_pulse(GETPULSE_TOOL)
occupantData["hasBlood"] = 1
occupantData["bloodLevel"] = round(occupant.blood_volume)
diff --git a/code/game/machinery/adv_med.dm b/code/game/machinery/adv_med.dm
index c97836990d1..3b20943e46d 100644
--- a/code/game/machinery/adv_med.dm
+++ b/code/game/machinery/adv_med.dm
@@ -220,7 +220,7 @@
active_power_usage = 500
var/printing = null
var/printing_text = null
- var/known_implants = list(/obj/item/weapon/implant/chem, /obj/item/weapon/implant/death_alarm, /obj/item/weapon/implant/mindshield, /obj/item/weapon/implant/tracking)
+ var/known_implants = list(/obj/item/weapon/implant/chem, /obj/item/weapon/implant/death_alarm, /obj/item/weapon/implant/mindshield, /obj/item/weapon/implant/tracking, /obj/item/weapon/implant/health)
/obj/machinery/body_scanconsole/power_change()
if(stat & BROKEN)
@@ -371,7 +371,7 @@
var/bloodData[0]
bloodData["hasBlood"] = 0
- if(ishuman(H) && !(H.species && H.species.flags & NO_BLOOD))
+ if(ishuman(H) && !(NO_BLOOD in H.species.species_traits))
bloodData["hasBlood"] = 1
bloodData["volume"] = H.blood_volume
bloodData["percent"] = round(((H.blood_volume / BLOOD_VOLUME_NORMAL)*100))
@@ -413,16 +413,12 @@
organData["shrapnel_len"] = shrapnelData.len
var/organStatus[0]
- if(E.status & ORGAN_DESTROYED)
- organStatus["destroyed"] = 1
if(E.status & ORGAN_BROKEN)
organStatus["broken"] = E.broken_description
if(E.status & ORGAN_ROBOT)
organStatus["robotic"] = 1
if(E.status & ORGAN_SPLINTED)
organStatus["splinted"] = 1
- if(E.status & ORGAN_BLEEDING)
- organStatus["bleeding"] = 1
if(E.status & ORGAN_DEAD)
organStatus["dead"] = 1
@@ -431,10 +427,8 @@
if(istype(E, /obj/item/organ/external/chest) && H.is_lung_ruptured())
organData["lungRuptured"] = 1
- for(var/datum/wound/W in E.wounds)
- if(W.internal)
- organData["internalBleeding"] = 1
- break
+ if(E.internal_bleeding)
+ organData["internalBleeding"] = 1
extOrganData.Add(list(organData))
@@ -582,15 +576,12 @@
var/splint = ""
var/internal_bleeding = ""
var/lung_ruptured = ""
- for(var/datum/wound/W in e.wounds) if(W.internal)
+ if(e.internal_bleeding)
internal_bleeding = " Internal bleeding"
- break
if(istype(e, /obj/item/organ/external/chest) && occupant.is_lung_ruptured())
lung_ruptured = "Lung ruptured:"
if(e.status & ORGAN_SPLINTED)
splint = "Splinted:"
- if(e.status & ORGAN_BLEEDING)
- bled = "Bleeding:"
if(e.status & ORGAN_BROKEN)
AN = "[e.broken_description]:"
if(e.status & ORGAN_ROBOT)
@@ -621,10 +612,7 @@
imp += "Unknown body present:"
if(!AN && !open && !infected & !imp)
AN = "None:"
- if(!(e.status & ORGAN_DESTROYED))
- dat += " | [e.name] | [e.burn_dam] | [e.brute_dam] | [robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured] | "
- else
- dat += "[e.name] | - | - | Not Found | "
+ dat += "[e.name] | [e.burn_dam] | [e.brute_dam] | [robot][bled][AN][splint][open][infected][imp][internal_bleeding][lung_ruptured] | "
dat += "
"
for(var/obj/item/organ/internal/i in occupant.internal_organs)
var/mech = i.desc
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index b85fb249c2e..ccfa885a5d2 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -167,24 +167,6 @@
..(user)
to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
-
-//Health Tracker Implant
-
-/obj/item/weapon/implant/health
- name = "health implant"
- var/healthstring = ""
-
-/obj/item/weapon/implant/health/proc/sensehealth()
- if(!implanted)
- return "ERROR"
- else
- if(isliving(implanted))
- var/mob/living/L = implanted
- healthstring = "[round(L.getOxyLoss())] - [round(L.getFireLoss())] - [round(L.getToxLoss())] - [round(L.getBruteLoss())]"
- if(!healthstring)
- healthstring = "ERROR"
- return healthstring
-
//Clonepod
/obj/machinery/clonepod/examine(mob/user)
@@ -473,11 +455,11 @@
update_clone_antag(occupant)
to_chat(occupant, "