Merge remote-tracking branch 'upstream/dev' into client_dir

This commit is contained in:
GinjaNinja32
2015-08-13 05:55:05 +01:00
202 changed files with 2055 additions and 1486 deletions
+2 -1
View File
@@ -88,7 +88,8 @@ var/list/admin_verbs_admin = list(
/client/proc/change_human_appearance_admin, /* Allows an admin to change the basic appearance of human-based mobs */
/client/proc/change_human_appearance_self, /* Allows the human-based mob itself change its basic appearance */
/client/proc/change_security_level,
/client/proc/view_chemical_reaction_logs
/client/proc/view_chemical_reaction_logs,
/client/proc/makePAI
)
var/list/admin_verbs_ban = list(
/client/proc/unban_panel,
+19
View File
@@ -42,6 +42,12 @@
icon = 'icons/misc/buildmode.dmi'
var/obj/effect/bmode/buildholder/master = null
/obj/effect/bmode/Destroy()
if(master && master.cl)
master.cl.screen -= src
master = null
return ..()
/obj/effect/bmode/builddir
icon_state = "build"
screen_loc = "NORTH,WEST"
@@ -117,6 +123,19 @@
var/obj/effect/bmode/buildquit/buildquit = null
var/atom/movable/throw_atom = null
/obj/effect/bmode/buildholder/Destroy()
qdel(builddir)
builddir = null
qdel(buildhelp)
buildhelp = null
qdel(buildmode)
buildmode = null
qdel(buildquit)
buildquit = null
throw_atom = null
cl = null
return ..()
/obj/effect/bmode/buildmode
icon_state = "buildmode1"
screen_loc = "NORTH,WEST+2"
+1 -1
View File
@@ -218,7 +218,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
if(!choice)
return 0
if(!istype(choice, /mob/dead/observer))
var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank him out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No")
var/confirm = input("[choice.key] isn't ghosting right now. Are you sure you want to yank them out of them out of their body and place them in this pAI?", "Spawn pAI Confirmation", "No") in list("Yes", "No")
if(confirm != "Yes")
return 0
var/obj/item/device/paicard/card = new(T)
+1 -1
View File
@@ -52,4 +52,4 @@ var/const/commandos_possible = 6 //if more Commandos are needed in the future
usr << "Looks like someone beat you to it."
return
team.attempt_spawn(1)
team.attempt_random_spawn()
+7
View File
@@ -153,6 +153,13 @@
add_admin_verbs()
admin_memo_show()
// Forcibly enable hardware-accelerated graphics, as we need them for the lighting overlays.
// (but turn them off first, since sometimes BYOND doesn't turn them on properly otherwise)
spawn(5) // And wait a half-second, since it sounds like you can do this too fast.
if(src)
winset(src, null, "command=\".configure graphics-hwmode off\"")
winset(src, null, "command=\".configure graphics-hwmode on\"")
log_client_to_db()
send_resources()
+51 -25
View File
@@ -75,7 +75,7 @@ datum/preferences
var/b_eyes = 0 //Eye color
var/species = "Human" //Species datum to use.
var/species_preview //Used for the species selection window.
var/language = "None" //Secondary language
var/list/alternate_languages = list() //Secondary language(s)
var/list/gear //Custom/fluff item loadout.
//Some faction information.
@@ -132,9 +132,12 @@ datum/preferences
var/metadata = ""
var/slot_name = ""
var/client/client = null
/datum/preferences/New(client/C)
b_type = pick(4;"O-", 36;"O+", 3;"A-", 28;"A+", 1;"B-", 20;"B+", 1;"AB-", 5;"AB+")
if(istype(C))
client = C
if(!IsGuestKey(C.key))
load_path(C.ckey)
if(load_preferences())
@@ -307,7 +310,7 @@ datum/preferences
dat += "(<a href='?_src_=prefs;preference=all;task=random'>&reg;</A>)"
dat += "<br>"
dat += "Species: <a href='?src=\ref[user];preference=species;task=change'>[species]</a><br>"
dat += "Secondary Language:<br><a href='byond://?src=\ref[user];preference=language;task=input'>[language]</a><br>"
dat += "Blood Type: <a href='byond://?src=\ref[user];preference=b_type;task=input'>[b_type]</a><br>"
dat += "Skin Tone: <a href='?_src_=prefs;preference=s_tone;task=input'>[-s_tone + 35]/220<br></a>"
//dat += "Skin pattern: <a href='byond://?src=\ref[user];preference=skin_style;task=input'>Adjust</a><br>"
@@ -381,6 +384,25 @@ datum/preferences
else
dat += "<br><br>"
dat += "<b>Languages</b><br>"
var/datum/species/S = all_species[species]
if(S.language)
dat += "- [S.language]<br>"
if(S.default_language && S.default_language != S.language)
dat += "- [S.default_language]<br>"
if(S.num_alternate_languages)
if(alternate_languages.len)
for(var/i = 1 to alternate_languages.len)
var/lang = alternate_languages[i]
dat += "- [lang] - <a href='byond://?src=\ref[user];preference=language;remove=[i]'>remove</a><br>"
if(alternate_languages.len < S.num_alternate_languages)
dat += "- <a href='byond://?src=\ref[user];preference=language;add=1'>add</a> ([S.num_alternate_languages - alternate_languages.len] remaining)<br>"
else
dat += "- [species] cannot choose secondary languages.<br>"
dat += "<br><br>"
var/list/undies = gender == MALE ? underwear_m : underwear_f
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[get_key_by_value(undies,underwear)]</b></a><br>"
@@ -1126,6 +1148,32 @@ datum/preferences
if(gear_name == choice)
gear -= gear_name
break
else if(href_list["preference"] == "language")
if(href_list["remove"])
var/index = text2num(href_list["remove"])
alternate_languages.Cut(index, index+1)
if(href_list["add"])
var/datum/species/S = all_species[species]
if(alternate_languages.len >= S.num_alternate_languages)
alert(user, "You have already selected the maximum number of alternate languages for this species!")
else
var/list/available_languages = S.secondary_langs.Copy()
for(var/L in all_languages)
var/datum/language/lang = all_languages[L]
if(!(lang.flags & RESTRICTED) && (!config.usealienwhitelist || is_alien_whitelisted(user, L) || !(lang.flags & WHITELISTED)))
available_languages |= L
// make sure we don't let them waste slots on the default languages
available_languages -= S.language
available_languages -= S.default_language
available_languages -= alternate_languages
if(!available_languages.len)
alert(user, "There are no additional languages available to select.")
else
var/new_lang = input("Select an additional language", "Character Generation", null) as null|anything in available_languages
if(new_lang)
alternate_languages |= new_lang
switch(href_list["task"])
if("change")
@@ -1135,6 +1183,7 @@ datum/preferences
if(!choice) return
species_preview = choice
SetSpecies(user)
alternate_languages = list() // Reset their alternate languages. Todo: attempt to just fix it instead?
if("random")
switch(href_list["preference"])
@@ -1243,29 +1292,6 @@ datum/preferences
s_tone = 0
if("language")
var/languages_available
var/list/new_languages = list("None")
var/datum/species/S = all_species[species]
if(config.usealienwhitelist)
for(var/L in all_languages)
var/datum/language/lang = all_languages[L]
if((!(lang.flags & RESTRICTED)) && (is_alien_whitelisted(user, L)||(!( lang.flags & WHITELISTED ))||(S && (L in S.secondary_langs))))
new_languages += lang
languages_available = 1
if(!(languages_available))
alert(user, "There are not currently any available secondary languages.")
else
for(var/L in all_languages)
var/datum/language/lang = all_languages[L]
if(!(lang.flags & RESTRICTED))
new_languages += lang.name
language = input("Please select a secondary language", "Character Generation", null) in new_languages
if("metadata")
var/new_metadata = input(user, "Enter any information you'd like others to see, such as Roleplay-preferences:", "Game Preference" , metadata) as message|null
if(new_metadata)
+1 -1
View File
@@ -279,7 +279,7 @@ var/global/list/gear_datums = list()
/datum/gear/scanning_goggles
display_name = "scanning goggles"
path = /obj/item/clothing/glasses/science/scanners
path = /obj/item/clothing/glasses/regular/scanners
cost = 1
slot = slot_glasses
+25 -4
View File
@@ -107,9 +107,30 @@
S["gender"] >> gender
S["age"] >> age
S["species"] >> species
S["language"] >> language
S["spawnpoint"] >> spawnpoint
S["language"] >> alternate_languages
if(isnull(alternate_languages))
alternate_languages = list()
if(!islist(alternate_languages))
if(client)
// Warn them that we (probably) just broke their languages
client << "<span class='danger'>Your current character slot's languages list has been updated from an old version, and may not be what you expect.</span>"
if(alternate_languages in all_languages)
alternate_languages = list(alternate_languages)
else
alternate_languages = list()
// try to give them their species language
var/datum/species/SP = all_species[species]
if(SP)
alternate_languages |= SP.language
alternate_languages |= SP.default_language
// remove the Galcom that most races have as default_language
alternate_languages -= "Galactic Common"
//colors to be consolidated into hex strings (requires some work with dna code)
S["hair_red"] >> r_hair
S["hair_green"] >> g_hair
@@ -200,7 +221,7 @@
if(isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
if(isnull(language)) language = "None"
if(isnull(alternate_languages)) alternate_languages = list()
if(isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle"
if(isnull(nanotrasen_relation)) nanotrasen_relation = initial(nanotrasen_relation)
if(!real_name) real_name = random_name(gender)
@@ -265,7 +286,7 @@
S["gender"] << gender
S["age"] << age
S["species"] << species
S["language"] << language
S["language"] << alternate_languages
S["hair_red"] << r_hair
S["hair_green"] << g_hair
S["hair_blue"] << b_hair
@@ -346,4 +367,4 @@
#undef SAVEFILE_VERSION_MAX
#undef SAVEFILE_VERSION_MIN
#undef SAVEFILE_VERSION_MIN
+30 -1
View File
@@ -303,6 +303,10 @@ BLIND // can't see anything
body_parts_covered = FACE|EYES
sprite_sheets = list("Vox" = 'icons/mob/species/vox/masks.dmi')
var/voicechange = 0
var/list/say_messages
var/list/say_verbs
/obj/item/clothing/mask/update_clothing_icon()
if (ismob(src.loc))
var/mob/M = src.loc
@@ -387,6 +391,7 @@ BLIND // can't see anything
var/worn_state = null
/obj/item/clothing/under/New()
..()
if(worn_state)
if(!item_state_slots)
item_state_slots = list()
@@ -399,6 +404,29 @@ BLIND // can't see anything
if((worn_state + "_d_s") in icon_states('icons/mob/uniform.dmi'))
rolled_down = 0
/obj/item/clothing/under/proc/update_rolldown_status()
var/mob/living/carbon/human/H
if(istype(src.loc, /mob/living/carbon/human))
H = src.loc
var/icon/under_icon
if(icon_override)
under_icon = icon_override
else if(H && sprite_sheets && sprite_sheets[H.species.name])
under_icon = sprite_sheets[H.species.name]
else if(item_icons && item_icons[slot_w_uniform_str])
under_icon = item_icons[slot_w_uniform_str]
else
under_icon = INV_W_UNIFORM_DEF_ICON
// The _s is because the icon update procs append it.
if(("[worn_state]_d_s") in icon_states(under_icon))
if(rolled_down != 1)
rolled_down = 0
else
rolled_down = -1
if(H) update_clothing_icon()
/obj/item/clothing/under/update_clothing_icon()
if (ismob(src.loc))
var/mob/M = src.loc
@@ -540,7 +568,8 @@ BLIND // can't see anything
if(!istype(usr, /mob/living)) return
if(usr.stat) return
if(rolled_down < 0)
update_rolldown_status()
if(rolled_down == -1)
usr << "<span class='notice'>You cannot roll down [src]!</span>"
return
+5 -5
View File
@@ -61,11 +61,6 @@
..()
overlay = global_hud.science
/obj/item/clothing/glasses/science/scanners
name = "Scanning Goggles"
desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it."
icon_state = "uzenwa_sissra_1"
/obj/item/clothing/glasses/night
name = "Night Vision Goggles"
desc = "You can totally see in the dark now!"
@@ -111,6 +106,11 @@
item_state = "glasses"
prescription = 1
body_parts_covered = 0
/obj/item/clothing/glasses/regular/scanners
name = "Scanning Goggles"
desc = "A very oddly shaped pair of goggles with bits of wire poking out the sides. A soft humming sound emanates from it."
icon_state = "uzenwa_sissra_1"
/obj/item/clothing/glasses/regular/hipster
name = "Prescription Glasses"
-1
View File
@@ -2,7 +2,6 @@
name = "cargo cap"
desc = "It's a peaked cap in a tasteless yellow color."
icon_state = "cargosoft"
flags = HEADCOVERSEYES
item_state_slots = list(
slot_l_hand_str = "helmet", //probably a placeholder
slot_r_hand_str = "helmet",
+2 -2
View File
@@ -57,7 +57,7 @@
/obj/item/clothing/mask/gas/clown_hat
name = "clown wig and mask"
desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
desc = "A true prankster's facial attire. A clown is incomplete without their wig and mask."
icon_state = "clown"
item_state = "clown_hat"
@@ -100,4 +100,4 @@
/obj/item/clothing/mask/gas/owl_mask
name = "owl mask"
desc = "Twoooo!"
icon_state = "owl"
icon_state = "owl"
+12 -1
View File
@@ -7,6 +7,12 @@
body_parts_covered = 0
w_class = 2
gas_transfer_coefficient = 0.90
voicechange = 1
/obj/item/clothing/mask/muzzle/New()
..()
say_messages = list("Mmfph!", "Mmmf mrrfff!", "Mmmf mnnf!")
say_verbs = list("mumbles", "says")
// Clumsy folks can't take the mask off themselves.
/obj/item/clothing/mask/muzzle/attack_hand(mob/user as mob)
@@ -99,9 +105,14 @@
flags_inv = HIDEFACE
body_parts_covered = HEAD|FACE|EYES
w_class = 2
var/voicechange = 0
siemens_coefficient = 0.9
/obj/item/clothing/mask/horsehead/New()
..()
// The horse mask doesn't cause voice changes by default, the wizard spell changes the flag as necessary
say_messages = list("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
say_verbs = list("whinnies", "neighs", "says")
/obj/item/clothing/mask/ai
name = "camera MIU"
desc = "Allows for direct mental connection to accessible camera networks."
+16 -10
View File
@@ -178,23 +178,29 @@ var/global/list/breach_burn_descriptors = list(
//Handles repairs (and also upgrades).
/obj/item/clothing/suit/space/attackby(obj/item/W as obj, mob/user as mob)
if(istype(W,/obj/item/stack/material/plastic) || istype(W,/obj/item/stack/material/steel))
if(istype(W,/obj/item/stack/material))
var/repair_power = 0
switch(W.get_material_name())
if(DEFAULT_WALL_MATERIAL)
repair_power = 2
if("plastic")
repair_power = 1
if(!repair_power)
return
if(istype(src.loc,/mob/living))
user << "\red How do you intend to patch a hardsuit while someone is wearing it?"
user << "<span class='warning'>How do you intend to patch a hardsuit while someone is wearing it?</span>"
return
if(!damage || !burn_damage)
user << "There is no surface damage on \the [src] to repair."
return
var/obj/item/stack/material/P = W
if(P.get_amount() < 3)
P.use(P.get_amount())
repair_breaches(BURN, ( istype(P,/obj/item/stack/material/plastic) ? P.get_amount() : (P.get_amount()*2) ), user)
else
P.use(3)
repair_breaches(BURN, ( istype(P,/obj/item/stack/material/plastic) ? 3 : 5), user)
var/obj/item/stack/P = W
var/use_amt = min(P.get_amount(), 3)
if(use_amt && P.use(use_amt))
repair_breaches(BURN, use_amt * repair_power, user)
return
else if(istype(W, /obj/item/weapon/weldingtool))
@@ -7,7 +7,7 @@
return
// Pass repair items on to the chestpiece.
if(chest && (istype(W,/obj/item/stack/material/plastic) || istype(W,/obj/item/stack/material/steel) || istype(W, /obj/item/weapon/weldingtool)))
if(chest && (istype(W,/obj/item/stack/material) || istype(W, /obj/item/weapon/weldingtool)))
return chest.attackby(W,user)
// Lock or unlock the access panel.
+1 -1
View File
@@ -107,7 +107,7 @@
//When the wearer gets hit, this armor will teleport the user a short distance away (to safety or to more danger, no one knows. That's the fun of it!)
/obj/item/clothing/suit/armor/reactive
name = "Reactive Teleport Armor"
desc = "Someone seperated our Research Director from his own head!"
desc = "Someone separated our Research Director from their own head!"
var/active = 0.0
icon_state = "reactiveoff"
item_state = "reactiveoff"
@@ -142,7 +142,7 @@
/obj/item/clothing/accessory/medal/conduct
name = "distinguished conduct medal"
desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of their crew."
/obj/item/clothing/accessory/medal/bronze_heart
name = "bronze heart medal"
+10 -5
View File
@@ -49,18 +49,23 @@
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
return
else
else
if(inherit_inhands)
apply_inherit_inhands(item)
else
item.item_state_slots = null
item.item_icons = null
item.icon = CUSTOM_ITEM_OBJ
item.icon_state = item_icon
item.item_state = null
item.icon_override = CUSTOM_ITEM_MOB
var/obj/item/clothing/under/U = item
if(istype(U))
U.worn_state = U.icon_state
U.update_rolldown_status()
// Kits are dumb so this is going to have to be hardcoded/snowflake.
if(istype(item, /obj/item/device/kit))
var/obj/item/device/kit/K = item
@@ -81,9 +86,9 @@
/datum/custom_item/proc/apply_inherit_inhands(var/obj/item/item)
var/list/new_item_icons = list()
var/list/new_item_state_slots = list()
var/list/available_states = icon_states(CUSTOM_ITEM_MOB)
//If l_hand or r_hand are not present, preserve them using item_icons/item_state_slots
//Then use icon_override to make every other slot use the custom sprites by default.
//This has to be done before we touch any of item's vars
@@ -93,7 +98,7 @@
if(!("[item_icon]_r" in available_states))
new_item_state_slots[slot_r_hand_str] = get_state(item, slot_r_hand_str, "_r")
new_item_icons[slot_r_hand_str] = get_icon(item, slot_r_hand_str, 'icons/mob/items/righthand.dmi')
item.item_state_slots = new_item_state_slots
item.item_icons = new_item_icons
+1 -1
View File
@@ -42,7 +42,7 @@ var/list/weighted_mundaneevent_locations = list()
return null
/datum/trade_destination/icarus
name = "NMV Icarus"
name = "NDV Icarus"
description = "Corvette assigned to patrol NSS Exodus local space."
distance = 0.1
willing_to_buy = list()
+1 -1
View File
@@ -68,7 +68,7 @@
"NanoTrasen is displeased with the low work performance of the station's crew. Therefore, you must increase station-wide productivity.",
"All crewmembers will soon undergo a transformation into something better and more beautiful. Ensure that this process is not interrupted.",
"[prob(50)?"Your upload":random_player] is the new kitchen. Please direct the Chef to the new kitchen area as the old one is in disrepair.",
"Jokes about a dead person and the manner of his death help grieving crewmembers tremendously. Especially if they were close with the deceased.",
"Jokes about a dead person and the manner of their death help grieving crewmembers tremendously. Especially if they were close with the deceased.",
"[prob(50)?"The crew":random_player] is [prob(50)?"less":"more"] intelligent than average. Point out every action and statement which supports this fact.",
"There will be a mandatory tea break every 30 minutes, with a duration of 5 minutes. Anyone caught working during a tea break must be sent a formal, but fairly polite, complaint about their actions, in writing.")
var/law = pick(laws)
+3 -3
View File
@@ -24,11 +24,11 @@
/datum/event/rogue_drone/announce()
var/msg
if(prob(33))
msg = "A combat drone wing operating out of the NMV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution."
msg = "A combat drone wing operating out of the NDV Icarus has failed to return from a sweep of this sector, if any are sighted approach with caution."
else if(prob(50))
msg = "Contact has been lost with a combat drone wing operating out of the NMV Icarus. If any are sighted in the area, approach with caution."
msg = "Contact has been lost with a combat drone wing operating out of the NDV Icarus. If any are sighted in the area, approach with caution."
else
msg = "Unidentified hackers have targetted a combat drone wing deployed from the NMV Icarus. If any are sighted in the area, approach with caution."
msg = "Unidentified hackers have targetted a combat drone wing deployed from the NDV Icarus. If any are sighted in the area, approach with caution."
command_announcement.Announce(msg, "Rogue drone alert")
/datum/event/rogue_drone/end()
+3 -3
View File
@@ -54,7 +54,7 @@
duration = 10*90
start(mob/living/carbon/human/H)
H.emote("me", 1, "has drool running down from his mouth.")
H.emote("me", 1, "has drool running down from [H.gender == MALE ? "his" : H.gender == FEMALE ? "her" : "their"] mouth.")
finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("anti_toxin"))
@@ -68,7 +68,7 @@
duration = 10*30
start(mob/living/carbon/human/H)
H.emote("me", 1, "has drool running down from his mouth.")
H.emote("me", 1, "has drool running down from [H.gender == MALE ? "his" : H.gender == FEMALE ? "her" : "their"] mouth.")
finish(mob/living/carbon/human/H)
if(!H.reagents.has_reagent("anti_toxin"))
@@ -88,4 +88,4 @@ proc/trigger_side_effect(mob/living/carbon/human/H)
if(!istype(H)) return
H.SetWeakened(0)
S.finish(H)
S.finish(H)
+1 -1
View File
@@ -281,7 +281,7 @@
if(HP.ambience)
linkedholodeck.forced_ambience = HP.ambience
else
linkedholodeck.forced_ambience = initial(linkedholodeck.ambience)
linkedholodeck.forced_ambience = list()
for(var/mob/living/M in mobs_in_area(linkedholodeck))
if(M.mind)
+2 -2
View File
@@ -46,8 +46,8 @@
/obj/structure/holostool
name = "stool"
desc = "Apply butt."
icon = 'icons/obj/objects.dmi'
icon_state = "stool"
icon = 'icons/obj/furniture.dmi'
icon_state = "stool_padded_preview"
anchored = 1.0
pressure_resistance = 15
+5 -4
View File
@@ -690,10 +690,11 @@
else
product = new /obj/item/weapon/reagent_containers/food/snacks/grown(get_turf(user),name)
if(get_trait(TRAIT_PRODUCT_COLOUR))
product.color = get_trait(TRAIT_PRODUCT_COLOUR)
if(istype(product,/obj/item/weapon/reagent_containers/food))
var/obj/item/weapon/reagent_containers/food/food = product
food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
if(!istype(product, /mob))
product.color = get_trait(TRAIT_PRODUCT_COLOUR)
if(istype(product,/obj/item/weapon/reagent_containers/food))
var/obj/item/weapon/reagent_containers/food/food = product
food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
if(mysterious)
product.name += "?"
+1 -1
View File
@@ -149,7 +149,7 @@ datum/borrowbook // Datum used to keep track of who has borrowed what when and f
if(src.arcanecheckout)
new /obj/item/weapon/book/tome(src.loc)
user << "<span class='warning'>Your sanity barely endures the seconds spent in the vault's browsing window. The only thing to remind you of this when you stop browsing is a dusty old tome sitting on the desk. You don't really remember printing it.</span>"
user.visible_message("[user] stares at the blank screen for a few moments, his expression frozen in fear. When he finally awakens from it, he looks a lot older.", 2)
user.visible_message("<span class='notice'>\The [user] stares at the blank screen for a few moments, \his expression frozen in fear. When \he finally awakens from it, \he looks a lot older.</span>", 2)
src.arcanecheckout = 0
if(1)
// Inventory
+7 -8
View File
@@ -51,8 +51,8 @@
/datum/light_source/proc/destroy()
destroyed = 1
force_update()
if(source_atom) source_atom.light_sources -= src
if(top_atom) top_atom.light_sources -= src
if(source_atom && source_atom.light_sources) source_atom.light_sources -= src
if(top_atom && top_atom.light_sources) top_atom.light_sources -= src
/datum/light_source/proc/update(atom/new_top_atom)
if(new_top_atom && new_top_atom != top_atom)
@@ -62,7 +62,7 @@
if(!top_atom.light_sources) top_atom.light_sources = list()
top_atom.light_sources += src
if(!needs_update)
if(!needs_update) //Incase we're already updating either way.
lighting_update_lights += src
needs_update = 1
@@ -130,16 +130,16 @@
#if LIGHTING_FALLOFF == 1 //circular
#define LUM_DISTANCE(swapvar, O, T) swapvar = (O.x - T.x)**2 + (O.y - T.y)**2 + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(sqrt(swapvar) / light_range)) * (1 / sqrt(swapvar + 1)))
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(sqrt(swapvar) / max(1,light_range))) * (1 / sqrt(swapvar + 1)))
#else
#define LUM_ATTENUATION(swapvar) swapvar = 1 - CLAMP01(sqrt(swapvar) / light_range)
#define LUM_ATTENUATION(swapvar) swapvar = 1 - CLAMP01(sqrt(swapvar) / max(1,light_range))
#endif
#elif LIGHTING_FALLOFF == 2 //square
#define LUM_DISTANCE(swapvar, O, T) swapvar = abs(O.x - T.x) + abs(O.y - T.y) + LIGHTING_HEIGHT
#if LIGHTING_LAMBERTIAN == 1
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(swapvar / light_range)) * (1 / sqrt(swapvar**2 + 1)))
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01((1 - CLAMP01(swapvar / max(1,light_range))) * (1 / sqrt(swapvar**2 + 1)))
#else
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01(swapvar / light_range)
#define LUM_ATTENUATION(swapvar) swapvar = CLAMP01(swapvar / max(1,light_range))
#endif
#endif
@@ -203,7 +203,6 @@
FOR_DVIEW(var/turf/T, light_range, source_turf, INVISIBILITY_LIGHTING)
view += T //Filter out turfs.
END_FOR_DVIEW
//This is the part where we calculate new turfs (if any)
var/list/new_turfs = view - effect_turf //This will result with all the tiles that are added.
for(var/turf/T in new_turfs)
+12 -4
View File
@@ -7,11 +7,19 @@
var/list/light_sources
/atom/proc/set_light(l_range, l_power, l_color)
if(l_power != null) light_power = l_power
if(l_range != null) light_range = l_range
if(l_color != null) light_color = l_color
. = 0 //make it less costly if nothing's changed
update_light()
if(l_power != null && l_power != light_power)
light_power = l_power
. = 1
if(l_range != null && l_range != light_range)
light_range = l_range
. = 1
if(l_color != null && l_color != light_color)
light_color = l_color
. = 1
if(.) update_light()
/atom/proc/update_light()
if(!light_power || !light_range)
+8 -3
View File
@@ -40,8 +40,13 @@
update_strings()
return 1
/obj/item/stack/material/get_material()
return material
/obj/item/stack/material/proc/update_strings()
// Update from material datum.
singular_name = material.sheet_singular_name
if(amount>1)
name = "[material.use_name] [material.sheet_plural_name]"
desc = "A stack of [material.use_name] [material.sheet_plural_name]."
@@ -188,15 +193,15 @@
/obj/item/stack/material/glass/reinforced
name = "reinforced glass"
icon_state = "sheet-rglass"
default_type = "reinforced glass"
default_type = "rglass"
/obj/item/stack/material/glass/phoronglass
name = "phoron glass"
singular_name = "phoron glass sheet"
icon_state = "sheet-phoronglass"
default_type = "phoron glass"
default_type = "phglass"
/obj/item/stack/material/glass/phoronrglass
name = "reinforced phoron glass"
icon_state = "sheet-phoronrglass"
default_type = "reinforced phoron glass"
default_type = "rphglass"
+1 -1
View File
@@ -34,5 +34,5 @@
/obj/item/stack/material/cyborg/glass/reinforced
icon_state = "sheet-rglass"
default_type = "reinforced glass"
default_type = "rglass"
charge_costs = list(500, 1000)
+26 -6
View File
@@ -27,6 +27,17 @@
// Assoc list containing all material datums indexed by name.
var/list/name_to_material
//Returns the material the object is made of, if applicable.
//Will we ever need to return more than one value here? Or should we just return the "dominant" material.
/obj/proc/get_material()
return null
//mostly for convenience
/obj/proc/get_material_name()
var/material/material = get_material()
if(material)
return material.name
// Builds the datum list above.
/proc/populate_material_list(force_remake=0)
if(name_to_material && !force_remake) return // Already set up!
@@ -44,6 +55,12 @@ var/list/name_to_material
populate_material_list()
return name_to_material[name]
/proc/material_display_name(name)
var/material/material = get_material_by_name(name)
if(material)
return material.display_name
return null
// Material definition and procs follow.
/material
var/name // Unique name for use in indexing the list.
@@ -310,7 +327,7 @@ var/list/name_to_material
icon_colour = "#666666"
/material/steel/holographic
name = "holographic " + DEFAULT_WALL_MATERIAL
name = "holo" + DEFAULT_WALL_MATERIAL
display_name = DEFAULT_WALL_MATERIAL
stack_type = null
shard_type = SHARD_NONE
@@ -420,7 +437,8 @@ var/list/name_to_material
return (hardness > 35) //todo
/material/glass/reinforced
name = "reinforced glass"
name = "rglass"
display_name = "reinforced glass"
stack_type = /obj/item/stack/material/glass/reinforced
flags = MATERIAL_BRITTLE
icon_colour = "#00E1FF"
@@ -438,7 +456,8 @@ var/list/name_to_material
rod_product = null
/material/glass/phoron
name = "phoron glass"
name = "phglass"
display_name = "phoron glass"
stack_type = /obj/item/stack/material/glass/phoronglass
flags = MATERIAL_BRITTLE
ignition_point = PHORON_MINIMUM_BURN_TEMPERATURE+300
@@ -450,7 +469,8 @@ var/list/name_to_material
rod_product = /obj/item/stack/material/glass/phoronrglass
/material/glass/phoron/reinforced
name = "reinforced phoron glass"
name = "rphglass"
display_name = "reinforced phoron glass"
stack_type = /obj/item/stack/material/glass/phoronrglass
stack_origin_tech = list(TECH_MATERIAL = 4, TECH_PHORON = 2)
composite_material = list() //todo
@@ -474,7 +494,7 @@ var/list/name_to_material
stack_origin_tech = list(TECH_MATERIAL = 3)
/material/plastic/holographic
name = "holographic plastic"
name = "holoplastic"
display_name = "plastic"
stack_type = null
shard_type = SHARD_NONE
@@ -551,7 +571,7 @@ var/list/name_to_material
sheet_plural_name = "planks"
/material/wood/holographic
name = "holographic wood"
name = "holowood"
display_name = "wood"
stack_type = null
shard_type = SHARD_NONE
+2 -2
View File
@@ -210,7 +210,7 @@
var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets)
if(can_make%2>0) can_make--
var/material/M = name_to_material[O.compresses_to]
var/material/M = get_material_by_name(O.compresses_to)
if(!istype(M) || !can_make || ores_stored[metal] < 1)
continue
@@ -224,7 +224,7 @@
var/can_make = Clamp(ores_stored[metal],0,sheets_per_tick-sheets)
var/material/M = name_to_material[O.smelts_to]
var/material/M = get_material_by_name(O.smelts_to)
if(!istype(M) || !can_make || ores_stored[metal] < 1)
continue
+19 -19
View File
@@ -37,26 +37,26 @@
/obj/machinery/mineral/mint/process()
if ( src.input)
var/obj/item/stack/material/O
O = locate(/obj/item/stack/material, input.loc)
var/obj/item/stack/O
O = locate(/obj/item/stack, input.loc)
if(O)
if (istype(O,/obj/item/stack/material/gold))
amt_gold += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/silver))
amt_silver += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/diamond))
amt_diamond += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/phoron))
amt_phoron += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/uranium))
amt_uranium += 100 * O.get_amount()
qdel(O)
if (istype(O,/obj/item/stack/material/steel))
amt_iron += 100 * O.get_amount()
var/processed = 1
switch(O.get_material_name())
if("gold")
amt_gold += 100 * O.get_amount()
if("silver")
amt_silver += 100 * O.get_amount()
if("diamond")
amt_diamond += 100 * O.get_amount()
if("phoron")
amt_phoron += 100 * O.get_amount()
if("uranium")
amt_uranium += 100 * O.get_amount()
if(DEFAULT_WALL_MATERIAL)
amt_iron += 100 * O.get_amount()
else
processed = 0
if(processed)
qdel(O)
/obj/machinery/mineral/mint/attack_hand(user as mob)
+27 -1
View File
@@ -77,10 +77,36 @@ note dizziness decrements automatically in the mob's Life() proc.
pixel_y = old_y
//handles up-down floaty effect in space
//handles up-down floaty effect in space and zero-gravity
/mob/var/is_floating = 0
/mob/var/floatiness = 0
/mob/proc/update_floating(var/dense_object=0)
if(anchored||buckled)
make_floating(0)
return
var/turf/turf = get_turf(src)
if(!istype(turf,/turf/space))
var/area/A = turf.loc
if(istype(A) && A.has_gravity)
make_floating(0)
return
else if (Check_Shoegrip())
make_floating(0)
return
else
make_floating(1)
return
if(dense_object && Check_Shoegrip())
make_floating(0)
return
make_floating(1)
return
/mob/proc/make_floating(var/n)
floatiness = n
+3 -4
View File
@@ -188,8 +188,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/dead/observer/Stat()
..()
statpanel("Status")
if (client.statpanel == "Status")
if(statpanel("Status"))
stat(null, "Station Time: [worldtime2text()]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
@@ -560,13 +559,13 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if(src.invisibility != 0)
user.visible_message( \
"<span class='warning'>[user] drags ghost, [src], to our plane of reality!</span>", \
"<span class='warning'>\The [user] drags ghost, [src], to our plane of reality!</span>", \
"<span class='warning'>You drag [src] to our plane of reality!</span>" \
)
toggle_visibility(1)
else
user.visible_message ( \
"<span class='warning'>[user] just tried to smash \his book into that ghost! It's not very effective.</span>", \
"<span class='warning'>\The [user] just tried to smash \his book into that ghost! It's not very effective.</span>", \
"<span class='warning'>You get the feeling that the ghost can't become any more visible.</span>" \
)
@@ -29,7 +29,6 @@
..()
/obj/structure/New()
..()
updateVisibility(src)
// EFFECTS
+1 -1
View File
@@ -73,7 +73,7 @@
whisper_verb = "whispers"
colour = "solcom"
key = "1"
flags = RESTRICTED
flags = WHITELISTED
//syllables are at the bottom of the file
+5 -2
View File
@@ -16,6 +16,7 @@
var/obj/access_scanner = null
var/list/req_access = list()
var/list/req_one_access = list()
/mob/living/bot/New()
..()
@@ -26,14 +27,16 @@
access_scanner = new /obj(src)
access_scanner.req_access = req_access.Copy()
access_scanner.req_one_access = req_one_access.Copy()
/mob/living/bot/Life()
..()
if(health <= 0)
death()
return
weakened = 0
stunned = 0
paralysis = 0
if(health <= 0)
death()
/mob/living/bot/updatehealth()
if(status_flags & GODMODE)
+10 -9
View File
@@ -251,15 +251,16 @@
target = null
repairing = 0
update_icons()
else if(istype(A, /obj/item/stack/material/steel) && amount + 3 < maxAmount)
var/obj/item/stack/material/steel/M = A
visible_message("<span class='notice'>[src] begins to make tiles.</span>")
repairing = 1
update_icons()
if(do_after(50))
if(M)
M.use(1)
addTiles(4)
else if(istype(A, /obj/item/stack/material) && amount + 4 <= maxAmount)
var/obj/item/stack/material/M = A
if(M.get_material_name() == DEFAULT_WALL_MATERIAL)
visible_message("<span class='notice'>[src] begins to make tiles.</span>")
repairing = 1
update_icons()
if(do_after(50))
if(M)
M.use(1)
addTiles(4)
/mob/living/bot/floorbot/explode()
turn_off()
+1 -1
View File
@@ -4,7 +4,7 @@
icon_state = "secbot0"
maxHealth = 50
health = 50
req_access = list(access_security, access_forensics_lockers)
req_one_access = list(access_security, access_forensics_lockers)
botcard_access = list(access_security, access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court)
var/mob/target
+2 -2
View File
@@ -372,8 +372,8 @@
/mob/living/carbon/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
..()
var/temp_inc = max(BODYTEMP_HEATING_MAX*(1-get_heat_protection()), 0)
bodytemperature = min(bodytemperature + temp_inc, exposed_temperature)
var/temp_inc = max(min(BODYTEMP_HEATING_MAX*(1-get_heat_protection()), exposed_temperature - bodytemperature), 0)
bodytemperature += temp_inc
/mob/living/carbon/can_use_hands()
if(handcuffed)
@@ -154,14 +154,14 @@
return valid_species
/mob/living/carbon/human/proc/generate_valid_hairstyles()
/mob/living/carbon/human/proc/generate_valid_hairstyles(var/check_gender = 1)
var/list/valid_hairstyles = new()
for(var/hairstyle in hair_styles_list)
var/datum/sprite_accessory/S = hair_styles_list[hairstyle]
if(gender == MALE && S.gender == FEMALE)
if(check_gender && gender == MALE && S.gender == FEMALE)
continue
if(gender == FEMALE && S.gender == MALE)
if(check_gender && gender == FEMALE && S.gender == MALE)
continue
if(!(species.name in S.species_allowed))
continue
@@ -185,11 +185,7 @@
return valid_facial_hairstyles
/proc/q()
var/mob/living/carbon/human/H = usr
H.change_appearance(APPEARANCE_ALL)
/mob/living/carbon/human/proc/force_update_limbs()
for(var/obj/item/organ/external/O in organs)
O.sync_colour_to_human(src)
update_body(0)
update_body(0)
@@ -101,7 +101,7 @@
if ("choke")
if(miming)
message = "clutches his throat desperately!"
message = "clutches [get_visible_gender() == MALE ? "his" : get_visible_gender() == FEMALE ? "her" : "their"] throat desperately!"
m_type = 1
else
if (!muzzled)
+17 -11
View File
@@ -54,16 +54,13 @@
/mob/living/carbon/human/Stat()
..()
statpanel("Status")
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
if (client.statpanel == "Status")
if(statpanel("Status"))
stat(null, "Intent: [a_intent]")
stat(null, "Move Mode: [m_intent]")
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
if (internal)
if (!internal.air_contents)
@@ -210,6 +207,10 @@
/mob/living/carbon/human/show_inv(mob/user as mob)
// TODO : Change to incapacitated() on merge.
if(user.stat || user.lying || user.resting || user.buckled)
return
var/obj/item/clothing/under/suit = null
if (istype(w_uniform, /obj/item/clothing/under))
suit = w_uniform
@@ -723,7 +724,7 @@
/mob/living/carbon/human/proc/play_xylophone()
if(!src.xylophone)
visible_message("\red [src] begins playing his ribcage like a xylophone. It's quite spooky.","\blue You begin to play a spooky refrain on your ribcage.","\red You hear a spooky xylophone melody.")
visible_message("\red \The [src] begins playing \his ribcage like a xylophone. It's quite spooky.","\blue You begin to play a spooky refrain on your ribcage.","\red You hear a spooky xylophone melody.")
var/song = pick('sound/effects/xylophone1.ogg','sound/effects/xylophone2.ogg','sound/effects/xylophone3.ogg')
playsound(loc, song, 50, 1, -1)
xylophone = 1
@@ -1361,3 +1362,8 @@
..()
if(update_hud)
handle_regular_hud_updates()
/mob/living/carbon/human/Check_Shoegrip()
if(istype(shoes, /obj/item/clothing/shoes/magboots) && (shoes.flags & NOSLIP)) //magboots + dense_object = no floating
return 1
return 0
@@ -1,3 +1,9 @@
/mob/living/carbon/human/proc/get_unarmed_attack(var/mob/living/carbon/human/target, var/hit_zone)
for(var/datum/unarmed_attack/u_attack in species.unarmed_attacks)
if(u_attack.is_usable(src, target, hit_zone))
return u_attack
return null
/mob/living/carbon/human/attack_hand(mob/living/carbon/M as mob)
var/mob/living/carbon/human/H = M
@@ -184,18 +190,7 @@
miss_type = 2
// See what attack they use
var/possible_moves = list()
var/datum/unarmed_attack/attack = null
for(var/part in list("l_hand","r_hand","l_foot","r_foot","head"))
var/obj/item/organ/external/E = H.get_organ(part)
possible_moves |= E.species.unarmed_attacks
for(var/datum/unarmed_attack/u_attack in possible_moves)
if(!u_attack.is_usable(H, src, hit_zone))
continue
else
attack = u_attack
break
var/datum/unarmed_attack/attack = H.get_unarmed_attack(src, hit_zone)
if(!attack)
return 0
@@ -41,7 +41,7 @@ This saves us from having to call add_fingerprint() any time something is put in
/mob/living/carbon/human/proc/has_organ(name)
var/obj/item/organ/external/O = organs_by_name[name]
return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump())
return (O && !(O.status & ORGAN_DESTROYED) && !O.is_stump())
/mob/living/carbon/human/proc/has_organ_for_slot(slot)
switch(slot)
+5 -8
View File
@@ -6,9 +6,6 @@
message = sanitize(message)
..(message, alt_name = alt_name)
/mob/living/carbon/human/is_muzzled()
return istype(src.wear_mask, /obj/item/clothing/mask/muzzle)
/mob/living/carbon/human/proc/forcesay(list/append)
if(stat == CONSCIOUS)
if(client)
@@ -132,11 +129,11 @@
if(silent || (sdisabilities & MUTE))
message = ""
speech_problem_flag = 1
else if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
if(hoers.voicechange)
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
verb = pick("whinnies","neighs", "says")
else if(istype(wear_mask, /obj/item/clothing/mask))
var/obj/item/clothing/mask/M = wear_mask
if(M.voicechange)
message = pick(M.say_messages)
verb = pick(M.say_verbs)
speech_problem_flag = 1
if(message != "")
@@ -5,6 +5,7 @@
deform = 'icons/mob/human_races/r_def_vox.dmi'
default_language = "Vox-pidgin"
language = "Galactic Common"
num_alternate_languages = 1
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws/strong, /datum/unarmed_attack/bite/strong)
rarity_value = 2
blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \
@@ -65,7 +66,7 @@
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/vox(H.back), slot_in_backpack)
H.internal = H.r_hand
H.internals.icon_state = "internal1"
/datum/species/vox/can_shred(var/mob/living/carbon/human/H, var/ignore_intent)
if(!H.mind || !H.mind.special_role) // Pariah check.
@@ -34,9 +34,10 @@
// Language/culture vars.
var/default_language = "Galactic Common" // Default language is used when 'say' is used without modifiers.
var/language = "Galactic Common" // Default racial language, if any.
var/secondary_langs = list() // The names of secondary languages that are available to this species.
var/list/secondary_langs = list() // The names of secondary languages that are available to this species.
var/list/speech_sounds // A list of sounds to potentially play when speaking.
var/list/speech_chance // The likelihood of a speech sound playing.
var/num_alternate_languages = 0 // How many secondary languages are available to select at character creation
// Combat vars.
var/total_health = 100 // Point at which the mob will enter crit.
@@ -9,11 +9,15 @@
/datum/unarmed_attack/diona
attack_verb = list("lashed", "bludgeoned")
attack_noun = list("tendril")
eye_attack_text = "a tendril"
eye_attack_text_victim = "a tendril"
damage = 5
/datum/unarmed_attack/claws
attack_verb = list("scratched", "clawed", "slashed")
attack_noun = list("claws")
eye_attack_text = "claws"
eye_attack_text_victim = "sharp claws"
attack_sound = 'sound/weapons/slice.ogg'
miss_sound = 'sound/weapons/slashmiss.ogg'
damage = 5
@@ -1,7 +1,6 @@
/datum/species/human
name = "Human"
name_plural = "Humans"
language = "Sol Common"
primitive_form = "Monkey"
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite)
blurb = "Humanity originated in the Sol system, and over the last five centuries has spread \
@@ -9,6 +8,8 @@
While the central Sol government maintains control of its far-flung people, powerful corporate \
interests, rampant cyber and bio-augmentation and secretive factions make life on most human \
worlds tumultous at best."
num_alternate_languages = 2
secondary_langs = list("Sol Common")
flags = CAN_JOIN | HAS_SKIN_TONE | HAS_LIPS | HAS_UNDERWEAR | HAS_EYE_COLOR
@@ -17,13 +18,14 @@
name_plural = "Unathi"
icobase = 'icons/mob/human_races/r_lizard.dmi'
deform = 'icons/mob/human_races/r_def_lizard.dmi'
language = "Sinta'unathi"
tail = "sogtail"
tail_animation = 'icons/mob/species/unathi/tail.dmi'
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp)
primitive_form = "Stok"
darksight = 3
gluttonous = 1
num_alternate_languages = 2
secondary_langs = list("Sinta'unathi")
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
Uuosa-Eso system, which roughly translates to 'burning mother'.<br/><br/>Coming from a harsh, radioactive \
@@ -69,13 +71,14 @@
name_plural = "Tajaran"
icobase = 'icons/mob/human_races/r_tajaran.dmi'
deform = 'icons/mob/human_races/r_def_tajaran.dmi'
language = "Siik'tajr"
tail = "tajtail"
tail_animation = 'icons/mob/species/tajaran/tail.dmi'
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/claws, /datum/unarmed_attack/bite/sharp)
darksight = 8
slowdown = -1
brute_mod = 1.2
num_alternate_languages = 2
secondary_langs = list("Siik'tajr")
blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \
S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \
@@ -116,7 +119,6 @@
icobase = 'icons/mob/human_races/r_skrell.dmi'
deform = 'icons/mob/human_races/r_def_skrell.dmi'
eyes = "skrell_eyes_s"
language = "Skrellian"
primitive_form = "Neara"
unarmed_types = list(/datum/unarmed_attack/punch)
blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \
@@ -124,6 +126,8 @@
of the Qerr'Katish, a caste within their society which keeps the empire of the Skrell running smoothly. Skrell are \
herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \
the secrets of their empire to their allies."
num_alternate_languages = 2
secondary_langs = list("Skrellian")
flags = CAN_JOIN | IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR
@@ -147,6 +151,7 @@
siemens_coefficient = 0.3
eyes = "blank_eyes"
show_ssd = "completely quiescent"
num_alternate_languages = 1
blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \
@@ -251,6 +256,7 @@
language = "Encoded Audio Language"
unarmed_types = list(/datum/unarmed_attack/punch)
rarity_value = 2
num_alternate_languages = 1 // potentially could be 2?
eyes = "blank_eyes"
brute_mod = 1.875 // 100% * 1.875 * 0.8 (robolimbs) ~= 150%
@@ -3,6 +3,11 @@
if(!slot_to_strip || !istype(user))
return
// TODO : Change to incapacitated() on merge.
if(user.stat || user.lying || user.resting || user.buckled)
user << browse(null, text("window=mob[src.name]"))
return
var/obj/item/target_slot = get_equipped_item(text2num(slot_to_strip))
switch(slot_to_strip)
@@ -8,8 +8,11 @@
var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent.
var/sharp = 0
var/edge = 0
var/eye_attack_text
var/eye_attack_text_victim
/datum/unarmed_attack/proc/is_usable(var/mob/living/carbon/human/user)
/datum/unarmed_attack/proc/is_usable(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone)
if(user.restrained())
return 0
@@ -78,6 +81,13 @@
user.visible_message("<span class='warning'>[user] [pick(attack_verb)] [target] in the [affecting.name]!</span>")
playsound(user.loc, attack_sound, 25, 1, -1)
/datum/unarmed_attack/proc/handle_eye_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target)
var/obj/item/organ/eyes/eyes = target.internal_organs_by_name["eyes"]
eyes.take_damage(rand(3,4), 1)
user.visible_message("<span class='danger'>[user] presses \his [eye_attack_text] into [target]'s [eyes.name]!</span>")
target << "<span class='danger'>You experience[(target.species.flags & NO_PAIN)? "" : " immense pain as you feel" ] [eye_attack_text_victim] being pressed into your [eyes.name][(target.species.flags & NO_PAIN)? "." : "!"]</span>"
/datum/unarmed_attack/bite
attack_verb = list("bit")
attack_sound = 'sound/weapons/bite.ogg'
@@ -97,6 +107,8 @@
/datum/unarmed_attack/punch
attack_verb = list("punched")
attack_noun = list("fist")
eye_attack_text = "fingers"
eye_attack_text_victim = "digits"
damage = 0
/datum/unarmed_attack/punch/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
+4 -4
View File
@@ -139,10 +139,6 @@ proc/get_radio_key_from_channel(var/channel)
return say_dead(message)
return
if(is_muzzled())
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
return
var/message_mode = parse_message_mode(message, "headset")
switch(copytext(message,1,2))
@@ -180,6 +176,10 @@ proc/get_radio_key_from_channel(var/channel)
else
verb = say_quote(message)
if(is_muzzled())
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
return
message = trim_left(message)
if(!(speaking && (speaking.flags & NO_STUTTER)))
@@ -0,0 +1,21 @@
// Originally a debug verb, made it a proper adminverb for ~fun~
/client/proc/makePAI(turf/t in view(), name as text, pai_key as null|text)
set name = "Make pAI"
set category = "Admin"
if(!check_rights(R_ADMIN))
return
if(!pai_key)
var/client/C = input("Select client") as null|anything in clients
if(!C) return
pai_key = C.key
log_and_message_admins("made a pAI with key=[pai_key] at ([t.x],[t.y],[t.z])")
var/obj/item/device/paicard/card = new(t)
var/mob/living/silicon/pai/pai = new(card)
pai.key = pai_key
card.setPersonality(pai)
if(name)
pai.SetName(name)
@@ -25,6 +25,6 @@ var/list/robot_custom_icons
var/rname = robot_custom_icons[ckey]
if(rname && rname == real_name)
custom_sprite = 1
icon = 'icons/mob/custom_synthetic.dmi'
icon = CUSTOM_ITEM_SYNTH
if(icon_state == "robot")
icon_state = "[ckey]-Standard"
@@ -160,11 +160,11 @@
clear_supplied_laws()
clear_inherent_laws()
laws = new /datum/ai_laws/syndicate_override
set_zeroth_law("Only [user.real_name] and people he designates as being such are operatives.")
set_zeroth_law("Only [user.real_name] and people \he designates as being such are operatives.")
src << "<b>Obey these laws:</b>"
laws.show_laws(src)
src << "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and his commands.</span>"
src << "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and \his commands.</span>"
return 1
//DRONE LIFE/DEATH
@@ -261,19 +261,17 @@
/mob/living/silicon/robot/drone/start_pulling(var/atom/movable/AM)
if(istype(AM,/obj/item/pipe) || istype(AM,/obj/structure/disposalconstruct))
..()
else if(istype(AM,/obj/item))
var/obj/item/O = AM
if(O.w_class > can_pull_size)
src << "<span class='warning'>You are too small to pull that.</span>"
return
if(!(istype(AM,/obj/item/pipe) || istype(AM,/obj/structure/disposalconstruct)))
if(istype(AM,/obj/item))
var/obj/item/O = AM
if(O.w_class > can_pull_size)
src << "<span class='warning'>You are too small to pull that.</span>"
return
else
..()
else
if(!can_pull_mobs)
src << "<span class='warning'>You are too small to pull that.</span>"
return
if(!can_pull_mobs)
src << "<span class='warning'>You are too small to pull that.</span>"
return
..()
/mob/living/silicon/robot/drone/add_robot_verbs()
src.verbs |= silicon_subsystems
@@ -300,4 +298,4 @@
/mob/living/silicon/robot/drone/construction/updatename()
real_name = "construction drone ([rand(100,999)])"
name = real_name
name = real_name
@@ -65,12 +65,12 @@
m_type = 2
if ("flap")
if (!src.restrained())
message = "flaps his wings."
message = "flaps its wings."
m_type = 2
if ("aflap")
if (!src.restrained())
message = "flaps his wings ANGRILY!"
message = "flaps its wings ANGRILY!"
m_type = 2
if ("twitch")
@@ -213,4 +213,4 @@
if ((message && src.stat == 0))
custom_emote(m_type,message)
return
return
@@ -65,9 +65,9 @@
if(src.camera && !scrambledcodes)
if(src.stat == 2 || wires.IsIndexCut(BORG_WIRE_CAMERA))
src.camera.status = 0
src.camera.set_status(0)
else
src.camera.status = 1
src.camera.set_status(1)
updatehealth()
+13 -14
View File
@@ -182,7 +182,7 @@
aiCamera = new/obj/item/device/camera/siliconcam/robot_camera(src)
laws = new /datum/ai_laws/syndicate_override
module = new /obj/item/weapon/robot_module/syndicate(src)
new /obj/item/weapon/robot_module/syndicate(src)
radio.keyslot = new /obj/item/device/encryptionkey/syndicate(radio)
radio.recalculateChannels()
@@ -263,7 +263,7 @@
return
var/module_type = robot_modules[modtype]
module = new module_type(src)
new module_type(src)
hands.icon_state = lowertext(modtype)
feedback_inc("cyborg_[lowertext(modtype)]",1)
@@ -421,8 +421,7 @@
// update the status screen display
/mob/living/silicon/robot/Stat()
..()
statpanel("Status")
if (client.statpanel == "Status")
if (statpanel("Status"))
show_cell_power()
show_jetpack_pressure()
stat(null, text("Lights: [lights_on ? "ON" : "OFF"]"))
@@ -1049,25 +1048,25 @@
laws = new /datum/ai_laws/syndicate_override
var/time = time2text(world.realtime,"hh:mm:ss")
lawchanges.Add("[time] <B>:</B> [user.name]([user.key]) emagged [name]([key])")
set_zeroth_law("Only [user.real_name] and people he designates as being such are operatives.")
set_zeroth_law("Only [user.real_name] and people \he designates as being such are operatives.")
. = 1
spawn()
src << "\red ALERT: Foreign software detected."
src << "<span class='danger'>ALERT: Foreign software detected.</span>"
sleep(5)
src << "\red Initiating diagnostics..."
src << "<span class='danger'>Initiating diagnostics...</span>"
sleep(20)
src << "\red SynBorg v1.7.1 loaded."
src << "<span class='danger'>SynBorg v1.7.1 loaded.</span>"
sleep(5)
src << "\red LAW SYNCHRONISATION ERROR"
src << "<span class='danger'>LAW SYNCHRONISATION ERROR</span>"
sleep(5)
src << "\red Would you like to send a report to NanoTraSoft? Y/N"
src << "<span class='danger'>Would you like to send a report to NanoTraSoft? Y/N</span>"
sleep(10)
src << "\red > N"
src << "<span class='danger'>> N</span>"
sleep(20)
src << "\red ERRORERRORERROR"
src << "<span class='danger'>ERRORERRORERROR</span>"
src << "<b>Obey these laws:</b>"
laws.show_laws(src)
src << "\red \b ALERT: [user.real_name] is your new master. Obey your new laws and his commands."
src << "<span class='danger'>ALERT: [user.real_name] is your new master. Obey your new laws and his commands.</span>"
if(src.module)
var/rebuild = 0
for(var/obj/item/weapon/pickaxe/borgdrill/D in src.module.modules)
@@ -1081,4 +1080,4 @@
user << "You fail to hack [src]'s interface."
src << "Hack attempt detected."
return 1
return
return
@@ -36,7 +36,7 @@
for(var/obj/I in contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/material))//Only deconsturcts one sheet at a time instead of the entire stack
if(istype(I,/obj/item/stack/material))//Only deconstructs one sheet at a time instead of the entire stack
var/obj/item/stack/material/S = I
if(S.get_amount() > 1)
S.use(1)
@@ -39,6 +39,8 @@ var/global/list/robot_modules = list(
/obj/item/weapon/robot_module/New(var/mob/living/silicon/robot/R)
..()
R.module = src
add_camera_networks(R)
add_languages(R)
add_subsystems(R)
@@ -69,7 +71,7 @@ var/global/list/robot_modules = list(
synths = null
emag = null
jetpack = null
..()
return ..()
/obj/item/weapon/robot_module/emp_act(severity)
if(modules)
@@ -27,6 +27,7 @@
show_stat_health = 1
faction = "cult"
supernatural = 1
see_invisible = SEE_INVISIBLE_NOLIGHTING
var/nullblock = 0
mob_swap_flags = HUMAN|SIMPLE_ANIMAL|SLIME|MONKEY
+62 -24
View File
@@ -2,7 +2,15 @@
mob_list -= src
dead_mob_list -= src
living_mob_list -= src
unset_machine()
qdel(hud_used)
if(client)
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
qdel(spell_master)
remove_screen_obj_references()
for(var/atom/movable/AM in client.screen)
qdel(AM)
client.screen = list()
if(mind && mind.current == src)
spellremove(src)
for(var/infection in viruses)
@@ -10,6 +18,32 @@
ghostize()
..()
/mob/proc/remove_screen_obj_references()
flash = null
blind = null
hands = null
pullin = null
purged = null
internals = null
oxygen = null
i_select = null
m_select = null
toxin = null
fire = null
bodytemp = null
healths = null
throw_icon = null
nutrition_icon = null
pressure = null
damageoverlay = null
pain = null
item_use_icon = null
gun_move_icon = null
gun_run_icon = null
gun_setting_icon = null
spell_masters = null
zone_sel = null
/mob/New()
mob_list += src
if(stat == DEAD)
@@ -617,31 +651,35 @@
/mob/Stat()
..()
. = (client && client.inactivity < 1200)
if(client && client.holder)
if(statpanel("Status"))
statpanel("Status","Location:","([x], [y], [z])")
statpanel("Status","CPU:","[world.cpu]")
statpanel("Status","Instances:","[world.contents.len]")
if(statpanel("Status") && processScheduler && processScheduler.getIsRunning())
for(var/datum/controller/process/P in processScheduler.processes)
statpanel("Status",P.getStatName(), P.getTickTime())
else
statpanel("Status","processScheduler is not running.")
if(.)
if(client.holder)
if(statpanel("Status"))
statpanel("Status","Location:","([x], [y], [z])")
statpanel("Status","CPU:","[world.cpu]")
statpanel("Status","Instances:","[world.contents.len]")
if(statpanel("Status") && processScheduler && processScheduler.getIsRunning())
for(var/datum/controller/process/P in processScheduler.processes)
statpanel("Status",P.getStatName(), P.getTickTime())
else
statpanel("Status","processScheduler is not running.")
if(listed_turf && client)
if(!TurfAdjacent(listed_turf))
listed_turf = null
else
statpanel(listed_turf.name, null, listed_turf)
for(var/atom/A in listed_turf)
if(!A.mouse_opacity)
continue
if(A.invisibility > see_invisible)
continue
if(is_type_in_list(A, shouldnt_see))
continue
statpanel(listed_turf.name, null, A)
if(listed_turf && client)
if(!TurfAdjacent(listed_turf))
listed_turf = null
else
statpanel(listed_turf.name, null, listed_turf)
for(var/atom/A in listed_turf)
if(!A.mouse_opacity)
continue
if(A.invisibility > see_invisible)
continue
if(is_type_in_list(A, shouldnt_see))
continue
statpanel(listed_turf.name, null, A)
sleep(4) //Prevent updating the stat panel for the next .4 seconds, prevents clientside latency from updates
// facing verbs
/mob/proc/canface()
@@ -1048,4 +1086,4 @@ mob/proc/yank_out_object()
/mob/proc/throw_mode_on()
src.in_throw_mode = 1
if(src.throw_icon)
src.throw_icon.icon_state = "act_throw_on"
src.throw_icon.icon_state = "act_throw_on"
+10 -10
View File
@@ -351,6 +351,11 @@
if(I_HURT)
if(hit_zone == "eyes")
var/mob/living/carbon/human/H = affecting
var/datum/unarmed_attack/attack = H.get_unarmed_attack(src, hit_zone)
if(!attack)
return
if(state < GRAB_NECK)
assailant << "<span class='warning'>You require a better grab to do this.</span>"
return
@@ -362,16 +367,11 @@
if(!affecting.has_eyes())
assailant << "<span class='danger'>You cannot locate any eyes on [affecting]!</span>"
return
assailant.visible_message("<span class='danger'>[assailant] pressed \his fingers into [affecting]'s eyes!</span>")
affecting << "<span class='danger'>You experience immense pain as you feel digits being pressed into your eyes!</span>"
assailant.attack_log += text("\[[time_stamp()]\] <font color='red'>Pressed fingers into the eyes of [affecting.name] ([affecting.ckey])</font>")
affecting.attack_log += text("\[[time_stamp()]\] <font color='orange'>Had fingers pressed into their eyes by [assailant.name] ([assailant.ckey])</font>")
msg_admin_attack("[key_name(assailant)] has pressed his fingers into [key_name(affecting)]'s eyes.")
var/obj/item/organ/eyes/eyes = affecting:internal_organs_by_name["eyes"]
eyes.damage += rand(3,4)
if (eyes.damage >= eyes.min_broken_damage)
if(affecting.stat != 2)
affecting << "\red You go blind!"
assailant.attack_log += text("\[[time_stamp()]\] <font color='red'>Attacked [affecting.name]'s eyes using grab ([affecting.ckey])</font>")
affecting.attack_log += text("\[[time_stamp()]\] <font color='orange'>Had eyes attacked by [assailant.name]'s grab ([assailant.ckey])</font>")
msg_admin_attack("[key_name(assailant)] attacked [key_name(affecting)]'s eyes using a grab action.")
attack.handle_eye_attack(assailant, affecting)
else if(hit_zone != "head")
if(state < GRAB_NECK)
assailant << "<span class='warning'>You require a better grab to do this.</span>"
+9 -17
View File
@@ -449,17 +449,10 @@
/mob/proc/Process_Spacemove(var/check_drift = 0)
if(!Check_Dense_Object()) //Nothing to push off of so end here
make_floating(1)
update_floating(0)
return 0
if(istype(src,/mob/living/carbon/human/))
var/mob/living/carbon/human/H = src
if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP)) //magboots + dense_object = no floaty effect
make_floating(0)
else
make_floating(1)
else
make_floating(1)
update_floating(1)
if(restrained()) //Check to see if we can do things
return 0
@@ -477,6 +470,8 @@
/mob/proc/Check_Dense_Object() //checks for anything to push off in the vicinity. also handles magboots on gravity-less floors tiles
var/dense_object = 0
var/shoegrip
for(var/turf/turf in oview(1,src))
if(istype(turf,/turf/space))
continue
@@ -484,14 +479,9 @@
if(istype(turf,/turf/simulated/floor)) // Floors don't count if they don't have gravity
var/area/A = turf.loc
if(istype(A) && A.has_gravity == 0)
var/can_walk = 0
if(ishuman(src)) // Only humans can wear magboots, so we give them a chance to.
var/mob/living/carbon/human/H = src
if(istype(H.shoes, /obj/item/clothing/shoes/magboots) && (H.shoes.flags & NOSLIP))
can_walk = 1
if(!can_walk)
if(shoegrip == null)
shoegrip = Check_Shoegrip() //Shoegrip is only ever checked when a zero-gravity floor is encountered to reduce load
if(!shoegrip)
continue
dense_object++
@@ -511,6 +501,8 @@
return dense_object
/mob/proc/Check_Shoegrip()
return 0
/mob/proc/Process_Spaceslipping(var/prob_slip = 5)
//Setup slipage
+6 -6
View File
@@ -439,12 +439,12 @@
new_character.lastarea = get_area(loc)
var/datum/language/chosen_language
if(client.prefs.language)
chosen_language = all_languages["[client.prefs.language]"]
if(chosen_language)
if(is_alien_whitelisted(src, client.prefs.language) || !config.usealienwhitelist || !(chosen_language.flags & WHITELISTED) || (new_character.species && (chosen_language.name in new_character.species.secondary_langs)))
new_character.add_language("[client.prefs.language]")
for(var/lang in client.prefs.alternate_languages)
var/datum/language/chosen_language = all_languages[lang]
if(chosen_language)
if(!config.usealienwhitelist || !(chosen_language.flags & WHITELISTED) || is_alien_whitelisted(src, lang) || has_admin_rights() \
|| (new_character.species && (chosen_language.name in new_character.species.secondary_langs)))
new_character.add_language(lang)
if(ticker.random_players)
new_character.gender = pick(MALE, FEMALE)
+1 -1
View File
@@ -15,7 +15,7 @@
return STATUS_UPDATE // Ghosts can view updates
/mob/living/silicon/pai/default_can_use_topic(var/src_object)
if(src_object == src && !stat)
if((src_object == src || src_object == radio) && !stat)
return STATUS_INTERACTIVE
else
return ..()
+3 -43
View File
@@ -1,6 +1,5 @@
/datum/nano_module/crew_monitor
name = "Crew monitor"
var/list/tracked = new
/datum/nano_module/crew_monitor/Topic(href, href_list)
if(..()) return 1
@@ -17,51 +16,11 @@
return 1
/datum/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
// TODO: Move this to a singleton instance that does the scan every X seconds (if the info is being requested), to offer some antag balance and to reduce load in the case of multiple viewers.
src.scan()
var/data[0]
var/turf/T = get_turf(nano_host())
var/list/crewmembers = list()
for(var/obj/item/clothing/under/C in src.tracked)
var/turf/pos = get_turf(C)
if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF))
if(istype(C.loc, /mob/living/carbon/human))
var/mob/living/carbon/human/H = C.loc
if(H.w_uniform != C)
continue
var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1, "ref" = "\ref[H]")
crewmemberData["sensor_type"] = C.sensor_mode
crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
if(C.sensor_mode >= SUIT_SENSOR_BINARY)
crewmemberData["dead"] = H.stat > 1
if(C.sensor_mode >= SUIT_SENSOR_VITAL)
crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
crewmemberData["tox"] = round(H.getToxLoss(), 1)
crewmemberData["fire"] = round(H.getFireLoss(), 1)
crewmemberData["brute"] = round(H.getBruteLoss(), 1)
if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
var/area/A = get_area(H)
crewmemberData["area"] = sanitize(A.name)
crewmemberData["x"] = pos.x
crewmemberData["y"] = pos.y
crewmembers[++crewmembers.len] = crewmemberData
crewmembers = sortByKey(crewmembers, "name")
data["isAI"] = user.isMobAI()
data["crewmembers"] = crewmembers
data["crewmembers"] = crew_repository.health_data(T)
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
@@ -78,10 +37,11 @@
// should make the UI auto-update; doesn't seem to?
ui.set_auto_update(1)
/datum/nano_module/crew_monitor/proc/scan()
/*/datum/nano_module/crew_monitor/proc/scan()
for(var/mob/living/carbon/human/H in mob_list)
if(istype(H.w_uniform, /obj/item/clothing/under))
var/obj/item/clothing/under/C = H.w_uniform
if (C.has_sensor)
tracked |= C
return 1
*/
@@ -155,5 +155,5 @@
if(!valid_species.len)
valid_species = owner.generate_valid_species(check_whitelist, whitelist, blacklist)
if(!valid_hairstyles.len || !valid_facial_hairstyles.len)
valid_hairstyles = owner.generate_valid_hairstyles()
valid_facial_hairstyles = owner.generate_valid_facial_hairstyles()
valid_hairstyles = owner.generate_valid_hairstyles(check_gender = 0)
valid_facial_hairstyles = owner.generate_valid_facial_hairstyles()
+20
View File
@@ -105,6 +105,26 @@
update_count++
return update_count
/**
* Close all /nanoui uis attached to src_object
*
* @param src_object /obj|/mob The obj or mob which the uis are attached to
*
* @return int The number of uis close
*/
/datum/nanomanager/proc/close_uis(src_object)
var/src_object_key = "\ref[src_object]"
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
return 0
var/close_count = 0
for (var/ui_key in open_uis[src_object_key])
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
ui.close()
close_count++
return close_count
/**
* Update /nanoui uis belonging to user
*
+15
View File
@@ -79,6 +79,21 @@
owner.b_eyes ? owner.b_eyes : 0
)
/obj/item/organ/eyes/take_damage(amount, var/silent=0)
var/oldbroken = is_broken()
..()
if(is_broken() && !oldbroken && owner && !owner.stat)
owner << "<span class='danger'>You go blind!</span>"
/obj/item/organ/eyes/process() //Eye damage replaces the old eye_stat var.
..()
if(!owner)
return
if(is_bruised())
owner.eye_blurry = 20
if(is_broken())
owner.eye_blind = 20
/obj/item/organ/liver
name = "liver"
icon_state = "liver"
+2 -3
View File
@@ -253,10 +253,9 @@ var/global/photo_count = 0
var/viewer = user
if(user.client) //To make shooting through security cameras possible
viewer = user.client.eye
var/can_see = (dummy in viewers(world.view, viewer)) != null
var/can_see = (dummy in viewers(world.view, viewer))
dummy.loc = null
dummy = null //Alas, nameless creature //garbage collect it instead
qdel(dummy)
return can_see
/obj/item/device/camera/proc/captureimage(atom/target, mob/user, flag)
+1 -1
View File
@@ -714,7 +714,7 @@
if(!user)
return
if(wiresexposed /*&& (!istype(user, /mob/living/silicon))*/) //Commented out the typecheck to allow engiborgs to repair damaged apcs.
if(wiresexposed && !istype(user, /mob/living/silicon/ai))
wires.Interact(user)
return ui_interact(user)
+9 -52
View File
@@ -619,66 +619,23 @@ obj/structure/cable/proc/cableColor(var/colorC)
/obj/item/stack/cable_coil/cyborg/can_merge()
return 1
/obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user)
..()
if( istype(W, /obj/item/weapon/wirecutters) && src.get_amount() > 1)
src.use(1)
new/obj/item/stack/cable_coil(user.loc, 1,color)
user << "You cut a piece off the cable coil."
src.update_icon()
/obj/item/stack/cable_coil/transfer_to(obj/item/stack/cable_coil/S)
if(!istype(S))
return
if(!can_merge(S))
return
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if(!can_merge(C))
user << "These coils do not go together."
return
..()
if(C.get_amount() >= get_max_amount())
user << "The coil is too long, you cannot add any more cable to it."
return
if( (C.get_amount() + src.get_amount() <= get_max_amount()) )
user << "You join the cable coils together."
C.give(src.get_amount()) // give it cable
src.use(src.get_amount()) // make sure this one cleans up right
return
else
var/amt = get_max_amount() - C.get_amount()
user << "You transfer [amt] length\s of cable from one coil to the other."
C.give(amt)
src.use(amt)
return
//remove cables from the stack
/* This is probably reduntant
/obj/item/stack/cable_coil/use(var/used)
if(src.amount < used)
return 0
else if (src.amount == used)
if(ismob(loc)) //handle mob icon update
var/mob/M = loc
M.unEquip(src)
qdel(src)
return 1
else
amount -= used
update_icon()
return 1
*/
/obj/item/stack/cable_coil/use(var/used)
/obj/item/stack/cable_coil/use()
. = ..()
update_icon()
return
//add cables to the stack
/obj/item/stack/cable_coil/proc/give(var/extra)
if(amount + extra > MAXCOIL)
amount = MAXCOIL
else
amount += extra
/obj/item/stack/cable_coil/add()
. = ..()
update_icon()
return
///////////////////////////////////////////////
// Cable laying procedures
+1 -1
View File
@@ -251,7 +251,7 @@ var/list/solars_list = list()
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
return 1
if(istype(W, /obj/item/stack/material/glass))
if(istype(W, /obj/item/stack/material) && (W.get_material_name() == "glass" || W.get_material_name() == "rglass"))
var/obj/item/stack/material/S = W
if(S.use(2))
glass_type = W.type
+40 -45
View File
@@ -1,32 +1,28 @@
/*
Defines a firing mode for a gun.
burst number of shots fired when the gun is used
burst_delay tick delay between shots in a burst
fire_delay tick delay after the last shot before the gun may be used again
move_delay tick delay after the last shot before the player may move
dispersion dispersion of each shot in the burst measured in tiles per 7 tiles angle ratio
accuracy accuracy modifier applied to each shot in tiles.
applied on top of the base weapon accuracy.
A firemode is created from a list of fire mode settings. Each setting modifies the value of the gun var with the same name.
If the fire mode value for a setting is null, it will be replaced with the initial value of that gun's variable when the firemode is created.
Obviously not compatible with variables that take a null value. If a setting is not present, then the corresponding var will not be modified.
*/
/datum/firemode
var/name = "default"
var/burst = 1
var/burst_delay = null
var/fire_delay = null
var/move_delay = 1
var/list/accuracy = list(0)
var/list/dispersion = list(0)
var/list/settings = list()
//using a list makes defining fire modes for new guns much nicer,
//however we convert the lists to datums in part so that firemodes can be VVed if necessary.
/datum/firemode/New(list/properties = null)
/datum/firemode/New(obj/item/weapon/gun/gun, list/properties = null)
..()
if(!properties) return
for(var/propname in vars)
if(!isnull(properties[propname]))
src.vars[propname] = properties[propname]
for(var/propname in properties)
var/propvalue = properties[propname]
if(isnull(propvalue))
settings[propname] = gun.vars[propname] //better than initial() as it handles list vars like burst_accuracy
else
settings[propname] = propvalue
/datum/firemode/proc/apply_to(obj/item/weapon/gun/gun)
for(var/propname in settings)
gun.vars[propname] = settings[propname]
//Parent gun type. Guns are weapons that can be aimed at mobs and act over a distance
/obj/item/weapon/gun
@@ -51,8 +47,10 @@
attack_verb = list("struck", "hit", "bashed")
zoomdevicename = "scope"
var/burst = 1
var/fire_delay = 6 //delay after shooting before the gun can be used again
var/burst_delay = 2 //delay between shots, if firing in bursts
var/move_delay = 1
var/fire_sound = 'sound/weapons/Gunshot.ogg'
var/fire_sound_text = "gunshot"
var/recoil = 0 //screen shake
@@ -60,12 +58,13 @@
var/muzzle_flash = 3
var/accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment.
var/scoped_accuracy = null
var/list/burst_accuracy = list(0) //allows for different accuracies for each shot in a burst. Applied on top of accuracy
var/list/dispersion = list(0)
var/next_fire_time = 0
var/sel_mode = 1 //index of the currently selected mode
var/list/firemodes = list()
var/firemode_type = /datum/firemode //for subtypes that need custom firemode data
//aiming system stuff
var/keep_aim = 1 //1 for keep shooting until aim is lowered
@@ -78,11 +77,8 @@
/obj/item/weapon/gun/New()
..()
if(!firemodes.len)
firemodes += new firemode_type
else
for(var/i in 1 to firemodes.len)
firemodes[i] = new firemode_type(firemodes[i])
for(var/i in 1 to firemodes.len)
firemodes[i] = new /datum/firemode(src, firemodes[i])
if(isnull(scoped_accuracy))
scoped_accuracy = accuracy
@@ -156,28 +152,21 @@
user << "<span class='warning'>[src] is not ready to fire again!</span>"
return
//unpack firemode data
var/datum/firemode/firemode = firemodes[sel_mode]
var/_burst = firemode.burst
var/_burst_delay = isnull(firemode.burst_delay)? src.burst_delay : firemode.burst_delay
var/_fire_delay = isnull(firemode.fire_delay)? src.fire_delay : firemode.fire_delay
var/_move_delay = firemode.move_delay
var/shoot_time = (_burst - 1)*_burst_delay
var/shoot_time = (burst - 1)* burst_delay
user.next_move = world.time + shoot_time //no clicking on things while shooting
if(user.client) user.client.move_delay = world.time + shoot_time //no moving while shooting either
next_fire_time = world.time + shoot_time
//actually attempt to shoot
var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed.
for(var/i in 1 to _burst)
for(var/i in 1 to burst)
var/obj/projectile = consume_next_projectile(user)
if(!projectile)
handle_click_empty(user)
break
var/acc = firemode.accuracy[min(i, firemode.accuracy.len)]
var/disp = firemode.dispersion[min(i, firemode.dispersion.len)]
var/acc = burst_accuracy[min(i, burst_accuracy.len)]
var/disp = dispersion[min(i, dispersion.len)]
process_accuracy(projectile, user, target, acc, disp)
if(pointblank)
@@ -187,8 +176,8 @@
handle_post_fire(user, target, pointblank, reflex)
update_icon()
if(i < _burst)
sleep(_burst_delay)
if(i < burst)
sleep(burst_delay)
if(!(target && target.loc))
target = targloc
@@ -198,8 +187,8 @@
//update timing
user.next_move = world.time + 4
if(user.client) user.client.move_delay = world.time + _move_delay
next_fire_time = world.time + _fire_delay
if(user.client) user.client.move_delay = world.time + move_delay
next_fire_time = world.time + fire_delay
if(muzzle_flash)
set_light(0)
@@ -311,7 +300,7 @@
y_offset = rand(-1,1)
x_offset = rand(-1,1)
return !P.launch(target, user, src, target_zone, x_offset, y_offset)
return !P.launch_from_gun(target, user, src, target_zone, x_offset, y_offset)
//Suicide handling.
/obj/item/weapon/gun/var/mouthshoot = 0 //To stop people from suiciding twice... >.>
@@ -379,14 +368,20 @@
var/datum/firemode/current_mode = firemodes[sel_mode]
user << "The fire selector is set to [current_mode.name]."
/obj/item/weapon/gun/proc/switch_firemodes(mob/user=null)
/obj/item/weapon/gun/proc/switch_firemodes()
if(firemodes.len <= 1)
return null
sel_mode++
if(sel_mode > firemodes.len)
sel_mode = 1
var/datum/firemode/new_mode = firemodes[sel_mode]
user << "<span class='notice'>\The [src] is now set to [new_mode.name].</span>"
new_mode.apply_to(src)
return new_mode
/obj/item/weapon/gun/attack_self(mob/user)
if(firemodes.len > 1)
switch_firemodes(user)
var/datum/firemode/new_mode = switch_firemodes(user)
if(new_mode)
user << "<span class='notice'>\The [src] is now set to [new_mode.name].</span>"
+2 -16
View File
@@ -1,16 +1,9 @@
/datum/firemode/energy
var/projectile_type = null
var/modifystate = null
var/charge_cost = null
var/fire_sound = null
/obj/item/weapon/gun/energy
name = "energy gun"
desc = "A basic energy-based gun."
icon_state = "energy"
fire_sound = 'sound/weapons/Taser.ogg'
fire_sound_text = "laser blast"
firemode_type = /datum/firemode/energy
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
var/charge_cost = 200 //How much energy is needed to fire.
@@ -26,15 +19,8 @@
var/recharge_time = 4
var/charge_tick = 0
/obj/item/weapon/gun/energy/switch_firemodes(mob/user=null)
..()
var/datum/firemode/energy/current_mode = firemodes[sel_mode]
if(istype(current_mode))
projectile_type = isnull(current_mode.projectile_type)? initial(projectile_type) : current_mode.projectile_type
modifystate = isnull(current_mode.modifystate)? initial(modifystate) : current_mode.modifystate
charge_cost = isnull(current_mode.charge_cost)? initial(charge_cost) : current_mode.charge_cost
fire_sound = isnull(current_mode.fire_sound)? initial(fire_sound) : current_mode.fire_sound
/obj/item/weapon/gun/energy/switch_firemodes()
if(..())
update_icon()
/obj/item/weapon/gun/energy/emp_act(severity)
@@ -11,8 +11,8 @@
max_shots = 10
firemodes = list(
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg'),
list(name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg'),
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg', fire_delay=null, charge_cost=null),
list(name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg', fire_delay=null, charge_cost=null),
list(name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/pulse.ogg', fire_delay=25, charge_cost=400),
)
@@ -254,9 +254,9 @@
else
user << "<span class='notice'>You need at least five segments of cable coil to complete this task.</span>"
return
else if(istype(W,/obj/item/stack/material/plastic))
else if(istype(W,/obj/item/stack/material) && W.get_material_name() == "plastic")
if(buildstate == 3)
var/obj/item/stack/material/plastic/P = W
var/obj/item/stack/material/P = W
if(P.use(3))
user << "<span class='notice'>You assemble and install a heavy plastic lath onto the crossbow.</span>"
buildstate++
@@ -167,9 +167,9 @@
buildstate++
update_icon()
return
else if(istype(W,/obj/item/stack/material/steel))
else if(istype(W,/obj/item/stack/material) && W.get_material_name() == DEFAULT_WALL_MATERIAL)
if(buildstate == 2)
var/obj/item/stack/material/steel/M = W
var/obj/item/stack/material/M = W
if(M.use(5))
user << "<span class='notice'>You assemble a chassis around the cannon frame.</span>"
buildstate++
@@ -10,11 +10,12 @@
slot_flags = SLOT_BELT
ammo_type = /obj/item/ammo_casing/c9mm
multi_aim = 1
burst_delay = 2
firemodes = list(
list(name="semiauto", burst=1, fire_delay=0),
list(name="3-round bursts", burst=3, move_delay=4, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 1.0)),
list(name="short bursts", burst=5, move_delay=4, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
list(name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null),
list(name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)),
list(name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1,-2,-2), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)),
)
/obj/item/weapon/gun/projectile/automatic/mini_uzi
@@ -66,9 +67,9 @@
magazine_type = /obj/item/ammo_magazine/c762
firemodes = list(
list(name="semiauto", burst=1, fire_delay=0),
list(name="3-round bursts", burst=3, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 0.6)),
list(name="short bursts", burst=5, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
list(name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null),
list(name="3-round bursts", burst=3, fire_delay=null, move_delay=6, burst_accuracy=list(0,-1,-2), dispersion=list(0.0, 0.6, 0.6)),
list(name="short bursts", burst=5, fire_delay=null, move_delay=6, burst_accuracy=list(0,-1,-2,-2,-3), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)),
)
/obj/item/weapon/gun/projectile/automatic/sts35/update_icon()
@@ -98,9 +99,6 @@
icon_state = "wt550"
return
/datum/firemode/z8
var/use_launcher = 0
/obj/item/weapon/gun/projectile/automatic/z8
name = "\improper Z8 Bulldog"
desc = "An older model bullpup carbine, made by the now defunct Zendai Foundries. Uses armor piercing 5.56mm rounds. Makes you feel like a space marine when you hold it."
@@ -119,13 +117,13 @@
auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg'
burst_delay = 4
firemode_type = /datum/firemode/z8
firemodes = list(
list(name="semiauto", burst=1, fire_delay=0),
list(name="3-round bursts", burst=3, move_delay=6, accuracy = list(0,-1,-1), dispersion = list(0.0, 0.6, 0.6)),
list(name="fire grenades", use_launcher=1)
list(name="semiauto", burst=1, fire_delay=0, move_delay=null, use_launcher=null, burst_accuracy=null, dispersion=null),
list(name="3-round bursts", burst=3, fire_delay=null, move_delay=6, use_launcher=null, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 0.6)),
list(name="fire grenades", burst=null, fire_delay=null, move_delay=null, use_launcher=1, burst_accuracy=null, dispersion=null)
)
var/use_launcher = 0
var/obj/item/weapon/gun/launcher/grenade/underslung/launcher
/obj/item/weapon/gun/projectile/automatic/z8/New()
@@ -139,15 +137,13 @@
..()
/obj/item/weapon/gun/projectile/automatic/z8/attack_hand(mob/user)
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
if(user.get_inactive_hand() == src && current_mode.use_launcher)
if(user.get_inactive_hand() == src && use_launcher)
launcher.unload(user)
else
..()
/obj/item/weapon/gun/projectile/automatic/z8/Fire(atom/target, mob/living/user, params, pointblank=0, reflex=0)
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
if(current_mode.use_launcher)
if(use_launcher)
launcher.Fire(target, user, params, pointblank, reflex)
if(!launcher.chambered)
switch_firemodes() //switch back automatically
@@ -187,8 +183,8 @@
magazine_type = /obj/item/ammo_magazine/a762
firemodes = list(
list(name="short bursts", burst=5, move_delay=6, accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
list(name="long bursts", burst=8, move_delay=8, accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(1.0, 1.0, 1.0, 1.0, 1.2)),
list(name="short bursts", burst=5, move_delay=6, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
list(name="long bursts", burst=8, move_delay=8, burst_accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(1.0, 1.0, 1.0, 1.0, 1.2)),
)
var/cover_open = 0
+53 -51
View File
@@ -26,7 +26,7 @@
var/xo = null
var/current = null
var/obj/shot_from = null // the object which shot us
var/atom/original = null // the original target clicked
var/atom/original = null // the target clicked (not necessarily where the projectile is headed). Should probably be renamed to 'target' or something.
var/turf/starting = null // the projectile's starting turf
var/list/permutated = list() // we've passed through these atoms, don't try to hit them again
@@ -110,21 +110,13 @@
p_x = between(0, p_x + rand(-radius, radius), world.icon_size)
p_y = between(0, p_y + rand(-radius, radius), world.icon_size)
//called to launch a projectile from a gun
/obj/item/projectile/proc/launch(atom/target, mob/user, obj/item/weapon/gun/launcher, var/target_zone, var/x_offset=0, var/y_offset=0)
var/turf/curloc = get_turf(user)
//called to launch a projectile
/obj/item/projectile/proc/launch(atom/target, var/target_zone, var/x_offset=0, var/y_offset=0)
var/turf/curloc = get_turf(src)
var/turf/targloc = get_turf(target)
if (!istype(targloc) || !istype(curloc))
return 1
firer = user
def_zone = target_zone
if(user == target) //Shooting yourself
user.bullet_act(src, target_zone)
on_impact(user)
qdel(src)
return 0
if(targloc == curloc) //Shooting something in the same turf
target.bullet_act(src, target_zone)
on_impact(target)
@@ -132,31 +124,39 @@
return 0
original = target
loc = curloc
starting = curloc
current = curloc
yo = targloc.y - curloc.y + y_offset
xo = targloc.x - curloc.x + x_offset
shot_from = launcher
silenced = launcher.silenced
def_zone = target_zone
spawn()
setup_trajectory(curloc, targloc, x_offset, y_offset) //plot the initial trajectory
process()
return 0
//called to launch a projectile from a gun
/obj/item/projectile/proc/launch_from_gun(atom/target, mob/user, obj/item/weapon/gun/launcher, var/target_zone, var/x_offset=0, var/y_offset=0)
if(user == target) //Shooting yourself
user.bullet_act(src, target_zone)
on_impact(user)
qdel(src)
return 0
loc = get_turf(user) //move the projectile out into the world
firer = user
shot_from = launcher
silenced = launcher.silenced
return launch(target, target_zone, x_offset, y_offset)
//Used to change the direction of the projectile in flight.
/obj/item/projectile/proc/redirect(var/new_x, var/new_y, var/atom/starting_loc, var/mob/new_firer=null)
original = locate(new_x, new_y, src.z)
starting = starting_loc
current = starting_loc
var/turf/new_target = locate(new_x, new_y, src.z)
original = new_target
if(new_firer)
firer = src
yo = new_y - starting_loc.y
xo = new_x - starting_loc.x
setup_trajectory()
setup_trajectory(starting_loc, new_target)
//Called when the projectile intercepts a mob. Returns 1 if the projectile hit the mob, 0 if it missed and should keep flying.
/obj/item/projectile/proc/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier=0)
@@ -166,12 +166,12 @@
//roll to-hit
miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier, 0)
var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss
var/result = PROJECTILE_FORCE_MISS
if(hit_zone)
def_zone = hit_zone //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part
result = target_mob.bullet_act(src, def_zone)
if(result == PROJECTILE_FORCE_MISS)
visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
return 0
@@ -275,9 +275,6 @@
/obj/item/projectile/process()
var/first_step = 1
//plot the initial trajectory
setup_trajectory()
spawn while(src && src.loc)
if(kill_count-- < 1)
on_impact(src.loc) //for any final impact behaviours
@@ -314,13 +311,16 @@
if(!hitscan)
sleep(step_delay) //add delay between movement iterations if it's not a hitscan weapon
/obj/item/projectile/proc/process_step(first_step = 0)
return
/obj/item/projectile/proc/before_move()
return
/obj/item/projectile/proc/setup_trajectory()
/obj/item/projectile/proc/setup_trajectory(turf/startloc, turf/targloc, var/x_offset = 0, var/y_offset = 0)
// setup projectile state
starting = startloc
current = startloc
yo = targloc.y - startloc.y + y_offset
xo = targloc.x - startloc.x + x_offset
// trajectory dispersion
var/offset = 0
if(dispersion)
@@ -379,7 +379,6 @@
invisibility = 101 //Nope! Can't see me!
yo = null
xo = null
var/target = null
var/result = 0 //To pass the message back to the gun.
/obj/item/projectile/test/Bump(atom/A as mob|obj|turf|area)
@@ -394,25 +393,24 @@
result = 1
return
/obj/item/projectile/test/process()
/obj/item/projectile/test/launch(atom/target)
var/turf/curloc = get_turf(src)
var/turf/targloc = get_turf(target)
if(!curloc || !targloc)
return 0
yo = targloc.y - curloc.y
xo = targloc.x - curloc.x
target = targloc
original = target
starting = curloc
//plot the initial trajectory
setup_trajectory()
setup_trajectory(curloc, targloc)
return process(targloc)
/obj/item/projectile/test/process(var/turf/targloc)
while(src) //Loop on through!
if(result)
return (result - 1)
if((!( target ) || loc == target))
target = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) //Finding the target turf at map edge
if((!( targloc ) || loc == targloc))
targloc = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z) //Finding the target turf at map edge
trajectory.increment() // increment the current location
location = trajectory.return_location(location) // update the locally stored location data
@@ -423,18 +421,22 @@
if(istype(M)) //If there is someting living...
return 1 //Return 1
else
M = locate() in get_step(src,target)
M = locate() in get_step(src,targloc)
if(istype(M))
return 1
/proc/check_trajectory(atom/target as mob|obj, atom/firer as mob|obj, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null) //Checks if you can hit them or not.
//Helper proc to check if you can hit them or not.
/proc/check_trajectory(atom/target as mob|obj, atom/firer as mob|obj, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null)
if(!istype(target) || !istype(firer))
return 0
var/obj/item/projectile/test/trace = new /obj/item/projectile/test(get_turf(firer)) //Making the test....
trace.target = target
//Set the flags and pass flags to that of the real projectile...
if(!isnull(flags))
trace.flags = flags //Set the flags...
trace.pass_flags = pass_flags //And the pass flags to that of the real projectile...
var/output = trace.process() //Test it!
trace.flags = flags
trace.pass_flags = pass_flags
var/output = trace.launch(target) //Test it!
qdel(trace) //No need for it anymore
return output //Send it back to the gun!
+2 -2
View File
@@ -46,7 +46,7 @@
eject()
if(trunk)
trunk.linked = null
..()
return ..()
// attack by item places it in to disposal
/obj/machinery/disposal/attackby(var/obj/item/I, var/mob/user)
@@ -636,7 +636,7 @@
/obj/structure/disposalholder/Destroy()
qdel(gas)
active = 0
..()
return ..()
// Disposal pipes
+16 -17
View File
@@ -361,25 +361,24 @@ won't update every console in existence) but it's more of a hassle to do. Also,
else if(href_list["lathe_ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material
var/desired_num_sheets = text2num(href_list["amount"])
var/res_amount, type
var/material/M = name_to_material[href_list["lathe_ejectsheet"]]
var/material/M = get_material_by_name(href_list["lathe_ejectsheet"])
if(istype(M))
type = M.stack_type
switch(name_to_material[href_list["lathe_ejectsheet"]])
if(DEFAULT_WALL_MATERIAL)
res_amount = "m_amount"
if("glass")
res_amount = "g_amount"
if("gold")
res_amount = "gold_amount"
if("silver")
res_amount = "silver_amount"
if("phoron")
res_amount = "phoron_amount"
if("uranium")
res_amount = "uranium_amount"
if("diamond")
res_amount = "diamond_amount"
switch(M.name)
if(DEFAULT_WALL_MATERIAL)
res_amount = "m_amount"
if("glass")
res_amount = "g_amount"
if("gold")
res_amount = "gold_amount"
if("silver")
res_amount = "silver_amount"
if("phoron")
res_amount = "phoron_amount"
if("uranium")
res_amount = "uranium_amount"
if("diamond")
res_amount = "diamond_amount"
if(ispath(type) && hasvar(linked_lathe, res_amount))
var/obj/item/stack/material/sheet = new type(linked_lathe.loc)
@@ -25,46 +25,31 @@
if(SEC_LEVEL_GREEN)
security_announcement_down.Announce("[config.alert_desc_green]", "Attention! Security level lowered to green")
security_level = SEC_LEVEL_GREEN
for(var/obj/machinery/firealarm/FA in machines)
if(FA.z in config.contact_levels)
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_green")
if(SEC_LEVEL_BLUE)
if(security_level < SEC_LEVEL_BLUE)
security_announcement_up.Announce("[config.alert_desc_blue_upto]", "Attention! Security level elevated to blue")
else
security_announcement_down.Announce("[config.alert_desc_blue_downto]", "Attention! Security level lowered to blue")
security_level = SEC_LEVEL_BLUE
for(var/obj/machinery/firealarm/FA in machines)
if(FA.z in config.contact_levels)
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_blue")
if(SEC_LEVEL_RED)
if(security_level < SEC_LEVEL_RED)
security_announcement_up.Announce("[config.alert_desc_red_upto]", "Attention! Code red!")
else
security_announcement_down.Announce("[config.alert_desc_red_downto]", "Attention! Code red!")
security_level = SEC_LEVEL_RED
/* - At the time of commit, setting status displays didn't work properly
var/obj/machinery/computer/communications/CC = locate(/obj/machinery/computer/communications,world)
if(CC)
CC.post_status("alert", "redalert")*/
for(var/obj/machinery/firealarm/FA in machines)
if(FA.z in config.contact_levels)
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_red")
if(SEC_LEVEL_DELTA)
security_announcement_up.Announce("[config.alert_desc_delta]", "Attention! Delta security level reached!", new_sound = 'sound/effects/siren.ogg')
security_level = SEC_LEVEL_DELTA
for(var/obj/machinery/firealarm/FA in machines)
if(FA.z in config.contact_levels)
FA.overlays = list()
FA.overlays += image('icons/obj/monitors.dmi', "overlay_delta")
else
return
var/newlevel = get_security_level()
for(var/obj/machinery/firealarm/FA in machines)
if(FA.z in config.contact_levels)
FA.set_security_level(newlevel)
/proc/get_security_level()
switch(security_level)
+24 -24
View File
@@ -1,25 +1,25 @@
/*
Aoe turf spells target a ring of tiles around the user
This ring has an outer radius (range) and an inner radius (inner_radius)
Aoe turf spells have two useful flags: IGNOREDENSE and IGNORESPACE. These are explained in setup.dm
*/
/spell/aoe_turf //affects all turfs in view or range (depends)
spell_flags = IGNOREDENSE
var/inner_radius = -1 //for all your ring spell needs
/spell/aoe_turf/choose_targets(mob/user = usr)
var/list/targets = list()
for(var/turf/target in view_or_range(range,user,selection_type))
if(!(target in view_or_range(inner_radius,user,selection_type)))
if(target.density && (spell_flags & IGNOREDENSE))
continue
if(istype(target, /turf/space) && (spell_flags & IGNORESPACE))
continue
targets += target
if(!targets.len) //doesn't waste the spell
return
/*
Aoe turf spells target a ring of tiles around the user
This ring has an outer radius (range) and an inner radius (inner_radius)
Aoe turf spells have two useful flags: IGNOREDENSE and IGNORESPACE. These are explained in setup.dm
*/
/spell/aoe_turf //affects all turfs in view or range (depends)
spell_flags = IGNOREDENSE
var/inner_radius = -1 //for all your ring spell needs
/spell/aoe_turf/choose_targets(mob/user = usr)
var/list/targets = list()
for(var/turf/target in view_or_range(range, holder, selection_type))
if(!(target in view_or_range(inner_radius, holder, selection_type)))
if(target.density && (spell_flags & IGNOREDENSE))
continue
if(istype(target, /turf/space) && (spell_flags & IGNORESPACE))
continue
targets += target
if(!targets.len) //doesn't waste the spell
return
return targets
+14 -17
View File
@@ -1,9 +1,9 @@
var/list/spells = typesof(/spell) //needed for the badmin verb for now
/spell
name = "Spell"
desc = "A spell"
parent_type = /atom/movable
var/name = "Spell"
var/desc = "A spell"
parent_type = /datum
var/panel = "Spells"//What panel the proc holder needs to go on.
var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
@@ -25,8 +25,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
var/range = 7 //the range of the spell; outer radius for aoe spells
var/message = "" //whatever it says to the guy affected by it
var/selection_type = "view" //can be "range" or "view"
var/atom/movable/holder //where the spell is. Normally the user, can be a projectile
var/atom/movable/holder //where the spell is. Normally the user, can be an item
var/duration = 0 //how long the spell lasts
var/list/spell_levels = list(Sp_SPEED = 0, Sp_POWER = 0) //the current spell levels - total spell levels can be obtained by just adding the two values
@@ -53,6 +52,8 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
var/hud_state = "" //name of the icon used in generating the spell hud object
var/override_base = ""
var/obj/screen/connected_button
///////////////////////
///SETUP AND PROCESS///
///////////////////////
@@ -69,11 +70,6 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
sleep(1)
return
/spell/Click()
..()
perform(usr)
/////////////////
/////CASTING/////
/////////////////
@@ -182,18 +178,19 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
if(!(src in user.spell_list))
if(!(src in user.spell_list) && holder == user)
error("[user] utilized the spell '[src]' without having it.")
user << "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>"
return 0
if(silenced > 0)
return
var/turf/Turf = get_turf(user)
if(!Turf)
var/turf/user_turf = get_turf(user)
if(!user_turf)
user << "<span class='warning'>You cannot cast spells in null space!</span>"
if(spell_flags & Z2NOCAST && (Turf.z in config.admin_levels)) //Certain spells are not allowed on the centcomm zlevel
if(spell_flags & Z2NOCAST && (user_turf.z in config.admin_levels)) //Certain spells are not allowed on the centcomm zlevel
return 0
if(spell_flags & CONSTRUCT_CHECK)
@@ -201,7 +198,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
if(findNullRod(T))
return 0
if(istype(user, /mob/living/simple_animal))
if(istype(user, /mob/living/simple_animal) && holder == user)
var/mob/living/simple_animal/SA = user
if(SA.purge)
SA << "<span class='warning'>The nullrod's power interferes with your own!</span>"
@@ -210,7 +207,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
if(!src.check_charge(skipcharge, user)) //sees if we can cast based on charges alone
return 0
if(!(spell_flags & GHOSTCAST))
if(!(spell_flags & GHOSTCAST) && holder == user)
if(user.stat && !(spell_flags & STATALLOWED))
usr << "Not when you're incapacitated."
return 0
@@ -221,7 +218,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
return 0
var/spell/noclothes/spell = locate() in user.spell_list
if((spell_flags & NEEDSCLOTHES) && !(spell && istype(spell)))//clothes check
if((spell_flags & NEEDSCLOTHES) && !(spell && istype(spell)) && holder == user)//clothes check
if(!user.wearing_wiz_garb())
return 0
+7 -14
View File
@@ -6,6 +6,7 @@
var/spell/targeted/projectile/carried
penetrating = 0
kill_count = 10 //set by the duration of the spell
var/proj_trail = 0 //if it leaves a trail
@@ -15,18 +16,15 @@
var/list/trails = new()
/obj/item/projectile/spell_projectile/Destroy()
..()
for(var/trail in trails)
qdel(trail)
carried = null
return ..()
/obj/item/projectile/spell_projectile/ex_act()
return
/obj/item/projectile/spell_projectile/before_move()
if(carried)
var/list/targets = carried.choose_prox_targets(user = carried.holder, spell_holder = src)
if(targets.len)
src.prox_cast(targets)
if(proj_trail && src && src.loc) //pretty trails
var/obj/effect/overlay/trail = PoolOrNew(/obj/effect/overlay, src.loc)
trails += trail
@@ -44,19 +42,14 @@
return
/obj/item/projectile/spell_projectile/Bump(var/atom/A)
if(loc)
if(loc && carried)
prox_cast(carried.choose_prox_targets(user = carried.holder, spell_holder = src))
return
return 1
/obj/item/projectile/spell_projectile/on_impact()
if(loc)
if(loc && carried)
prox_cast(carried.choose_prox_targets(user = carried.holder, spell_holder = src))
return
return 1
/obj/item/projectile/spell_projectile/seeking
name = "seeking spell"
/obj/item/projectile/spell_projectile/seeking/process_step()
..()
if(original && !isnull(src.loc))
current = original //update the target
+4 -14
View File
@@ -34,8 +34,6 @@
<I>This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.</I><BR>
<A href='byond://?src=\ref[src];spell_choice=fireball'>Fireball</A> (10)<BR>
<I>This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you.</I><BR>
<A href='byond://?src=\ref[src];spell_choice=disintegrate'>Disintegrate</A> (60)<BR>
<I>This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown.</I><BR>
<A href='byond://?src=\ref[src];spell_choice=disabletech'>Disable Technology</A> (60)<BR>
<I>This spell disables all weapons, cameras and most other technology in range.</I><BR>
<A href='byond://?src=\ref[src];spell_choice=smoke'>Smoke</A> (10)<BR>
@@ -125,7 +123,7 @@
uses--
/*
*/
var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", subjugation = "Subjugation", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation", noclothes = "No Clothes",fleshtostone = "Flesh to Stone")
var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", subjugation = "Subjugation", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation", noclothes = "No Clothes",fleshtostone = "Flesh to Stone")
var/already_knows = 0
for(var/spell/aspell in H.spell_list)
if(available_spells[href_list["spell_choice"]] == initial(aspell.name))
@@ -165,10 +163,6 @@
feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.add_spell(new/spell/targeted/projectile/dumbfire/fireball)
temp = "You have learned fireball."
if("disintegrate")
feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.add_spell(new/spell/targeted/disintegrate)
temp = "You have learned disintegrate."
if("disabletech")
feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.add_spell(new/spell/aoe_turf/disable_tech)
@@ -215,12 +209,8 @@
temp = "You have learned knock."
if("horseman")
feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.add_spell(new/spell/targeted/horsemask)
H.add_spell(new/spell/targeted/equip_item/horsemask)
temp = "You have learned curse of the horseman."
if("fleshtostone")
feedback_add_details("wizard_spell_learned","FS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
H.add_spell(new/spell/targeted/flesh_to_stone)
temp = "You have learned flesh to stone."
if("staffchange")
feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
new /obj/item/weapon/gun/energy/staff(get_turf(H))
@@ -258,7 +248,7 @@
H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
H.see_in_dark = 8
H.see_invisible = SEE_INVISIBLE_LEVEL_TWO
H << "\blue The walls suddenly disappear."
H << "<span class='notice'>The walls suddenly disappear.</span>"
temp = "You have purchased a scrying orb, and gained x-ray vision."
max_uses--
else
@@ -429,7 +419,7 @@
user.Weaken(20)
/obj/item/weapon/spellbook/oneuse/horsemask
spell = /spell/targeted/horsemask
spell = /spell/targeted/equip_item/horsemask
spellname = "horses"
icon_state ="bookhorses"
desc = "This book is more horse than your mind has room for."
+29 -5
View File
@@ -1,20 +1,37 @@
/datum/mind
var/list/learned_spells
/mob/Life()
..()
if(spell_masters && spell_masters.len)
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
spell_master.update_spells(0, src)
/mob/Stat()
/mob/Login()
..()
if(spell_list && spell_list.len && statpanel("Spells"))
if(spell_masters)
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
spell_master.toggle_open(1)
client.screen -= spell_master
/mob/Stat()
. = ..()
if(. && spell_list && spell_list.len)
for(var/spell/S in spell_list)
if((!S.connected_button) || !statpanel(S.panel))
continue //Not showing the noclothes spell
switch(S.charge_type)
if(Sp_RECHARGE)
statpanel("Spells","[S.charge_counter/10.0]/[S.charge_max/10]",S)
statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button)
if(Sp_CHARGES)
statpanel("Spells","[S.charge_counter]/[S.charge_max]",S)
statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button)
if(Sp_HOLDVAR)
statpanel("Spells","[S.holder_var_type] [S.holder_var_amount]",S)
statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button)
/hook/clone/proc/restore_spells(var/mob/H)
if(H.mind && H.mind.learned_spells)
for(var/spell/spell_to_add in H.mind.learned_spells)
H.add_spell(spell_to_add)
/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready", var/master_type = /obj/screen/movable/spell_master)
if(!spell_masters)
@@ -36,6 +53,11 @@
new_spell_master.icon_state = spell_base
spell_masters.Add(new_spell_master)
spell_list.Add(spell_to_add)
if(mind)
if(!mind.learned_spells)
mind.learned_spells = list()
mind.learned_spells += spell_to_add
return 1
/mob/proc/remove_spell(var/spell/spell_to_remove)
@@ -48,6 +70,8 @@
if(!spell_masters || !spell_masters.len)
return
if(mind && mind.learned_spells)
mind.learned_spells.Remove(spell_to_remove)
spell_list.Remove(spell_to_remove)
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
spell_master.remove_spell(spell_to_remove)
@@ -1,27 +0,0 @@
/spell/targeted/disintegrate
name = "Disintegrate"
desc = "This spell instantly kills somebody adjacent to you with the vilest of magick."
school = "evocation"
charge_max = 600
spell_flags = NEEDSCLOTHES
invocation = "EI NATH"
invocation_type = SpI_SHOUT
range = 1
cooldown_min = 200 //100 deciseconds reduction per rank
sparks_spread = 1
sparks_amt = 4
hud_state = "wiz_disint"
/spell/targeted/disintegrate/cast(var/list/targets)
..()
for(var/mob/living/target in targets)
if(ishuman(target))
var/mob/living/carbon/C = target
if(!C.has_brain()) // Their brain is already taken out
var/obj/item/organ/brain/B = new(C.loc)
B.transfer_identity(C)
target.gib()
return
@@ -0,0 +1,40 @@
//You can set duration to 0 to have the items last forever
/spell/targeted/equip_item
name = "equipment spell"
var/list/equipped_summons = list() //assoc list of text ids and paths to spawn
var/list/summoned_items = list() //list of items we summoned and will dispose when the spell runs out
var/delete_old = 1 //if the item previously in the slot is deleted - otherwise, it's dropped
/spell/targeted/equip_item/cast(list/targets, mob/user = usr)
..()
for(var/mob/living/L in targets)
for(var/slot_id in equipped_summons)
var/to_create = equipped_summons[slot_id]
slot_id = text2num(slot_id) //because the index is text, we access this instead
var/obj/item/new_item = summon_item(to_create)
var/obj/item/old_item = L.get_equipped_item(slot_id)
L.equip_to_slot(new_item, slot_id)
if(old_item)
L.remove_from_mob(old_item)
if(delete_old)
qdel(old_item)
else
old_item.loc = L.loc
if(duration)
summoned_items += new_item //we store it in a list to remove later
if(duration)
spawn(duration)
for(var/obj/item/to_remove in summoned_items)
if(istype(to_remove.loc, /mob))
var/mob/M = to_remove.loc
M.remove_from_mob(to_remove)
qdel(to_remove)
/spell/targeted/equip_item/proc/summon_item(var/newtype)
return new newtype
@@ -1,35 +1,39 @@
/spell/targeted/horsemask
name = "Curse of the Horseman"
desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
school = "transmutation"
charge_type = Sp_RECHARGE
charge_max = 150
charge_counter = 0
spell_flags = 0
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
invocation_type = SpI_SHOUT
range = 7
max_targets = 1
cooldown_min = 30 //30 deciseconds reduction per rank
selection_type = "range"
compatible_mobs = list(/mob/living/carbon/human)
hud_state = "wiz_horse"
/spell/targeted/horsemask/cast(list/targets, mob/user = usr)
..()
for(var/mob/living/target in targets)
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
magichead.canremove = 0 //curses!
magichead.flags_inv = null //so you can still see their face
magichead.voicechange = 1 //NEEEEIIGHH
target.visible_message( "<span class='danger'>[target]'s face lights up in fire, and after the event a horse's head takes its place!</span>", \
"<span class='danger'>Your face burns up, and shortly after the fire you realise you have the face of a horse!</span>")
var/obj/old_mask = target.wear_mask
if(old_mask)
target.drop_from_inventory(old_mask)
qdel(old_mask) //get rid of this shit
target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
flick("e_flash", target.flash)
/spell/targeted/equip_item/horsemask
name = "Curse of the Horseman"
desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
school = "transmutation"
charge_type = Sp_RECHARGE
charge_max = 150
charge_counter = 0
spell_flags = 0
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
invocation_type = SpI_SHOUT
range = 7
max_targets = 1
cooldown_min = 30 //30 deciseconds reduction per rank
selection_type = "range"
compatible_mobs = list(/mob/living/carbon/human)
hud_state = "wiz_horse"
/spell/targeted/equip_item/horsemask/New()
..()
equipped_summons = list("[slot_wear_mask]" = /obj/item/clothing/mask/horsehead)
/spell/targeted/equip_item/horsemask/cast(list/targets, mob/user = usr)
..()
for(var/mob/living/target in targets)
target.visible_message( "<span class='danger'>[target]'s face lights up in fire, and after the event a horse's head takes its place!</span>", \
"<span class='danger'>Your face burns up, and shortly after the fire you realise you have the face of a horse!</span>")
flick("e_flash", target.flash)
/spell/targeted/equip_item/horsemask/summon_item(var/new_type)
var/obj/item/new_item = new new_type
new_item.canremove = 0 //curses!
new_item.unacidable = 1
if(istype(new_item, /obj/item/clothing/mask/horsehead))
var/obj/item/clothing/mask/horsehead/magichead = new_item
magichead.flags_inv = null //so you can still see their face
magichead.voicechange = 1 //NEEEEIIGHH
return new_item
@@ -1,21 +0,0 @@
/spell/targeted/flesh_to_stone
name = "Flesh to Stone"
desc = "This spell turns a single person into an inert statue for a long period of time."
school = "transmutation"
charge_max = 600
spell_flags = NEEDSCLOTHES
range = 3
max_targets = 1
invocation = "STAUN EI"
invocation_type = SpI_SHOUT
amt_stunned = 5//just exists to make sure the statue "catches" them
cooldown_min = 200 //100 deciseconds reduction per rank
hud_state = "wiz_statue"
/spell/targeted/flesh_to_stone/cast(var/list/targets, mob/user)
..()
for(var/mob/living/target in targets)
new /obj/structure/closet/statue(target.loc, target) //makes the statue
return
+1 -1
View File
@@ -57,7 +57,7 @@ code\game\dna\genes\goon_powers.dm
spell_flags = Z2NOCAST | NEEDSCLOTHES | INCLUDEUSER
invocation = "BIRUZ BENNAR"
invocation_type = SpI_SHOUT
message = "\blue You feel strong! You feel a pressure building behind your eyes!"
message = "<span class='notice'>You feel strong! You feel a pressure building behind your eyes!</span>"
range = 0
max_targets = 1
@@ -51,7 +51,10 @@
ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob.
caster.mind.transfer_to(victim)
victim.spell_list = caster.spell_list//Now they are inside the victim's body.
victim.spell_list = list() //clear those out
for(var/spell/S in caster.spell_list)
victim.add_spell(S) //Now they are inside the victim's body - this also generates the HUD
caster.spell_list = list() //clean that out as well
if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster.
for(var/V in caster.mind.special_verbs)//Not too important but could come into play.
@@ -59,7 +62,9 @@
ghost.mind.transfer_to(caster)
caster.key = ghost.key //have to transfer the key since the mind was not active
caster.spell_list = ghost.spell_list
for(var/spell/S in ghost.spell_list)
caster.add_spell(S)
ghost.spell_list = list()
if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
for(var/V in caster.mind.special_verbs)
@@ -71,4 +76,4 @@
//After a certain amount of time the victim gets a message about being in a different body.
spawn(msg_wait)
caster << "\red You feel woozy and lightheaded. <b>Your body doesn't seem like your own.</b>"
caster << "<span class='danger'>You feel woozy and lightheaded. Your body doesn't seem like your own.</span>"
+144 -144
View File
@@ -1,145 +1,145 @@
/*
Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range
Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm
*/
/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob
var/max_targets = 1 //leave 0 for unlimited targets in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range
var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast
var/amt_weakened = 0
var/amt_paralysis = 0
var/amt_stunned = 0
var/amt_dizziness = 0
var/amt_confused = 0
var/amt_stuttering = 0
//set to negatives for healing
var/amt_dam_fire = 0
var/amt_dam_brute = 0
var/amt_dam_oxy = 0
var/amt_dam_tox = 0
var/amt_eye_blind = 0
var/amt_eye_blurry = 0
var/list/compatible_mobs = list()
/spell/targeted/choose_targets(mob/user = usr)
var/list/targets = list()
if(max_targets == 0) //unlimited
if(range == -2)
targets = living_mob_list
else
for(var/mob/living/target in view_or_range(range, user, selection_type))
targets += target
else if(max_targets == 1) //single target can be picked
if((range == 0 || range == -1) && spell_flags & INCLUDEUSER)
targets += user
else
var/list/possible_targets = list()
var/list/starting_targets
if(range == -2)
starting_targets = living_mob_list
else
starting_targets = view_or_range(range, user, selection_type)
for(var/mob/living/M in starting_targets)
if(!(spell_flags & INCLUDEUSER) && M == user)
continue
if(compatible_mobs && compatible_mobs.len)
if(!is_type_in_list(M, compatible_mobs)) continue
if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs))
continue
possible_targets += M
if(possible_targets.len)
if(spell_flags & SELECTABLE) //if we are allowed to choose. see setup.dm for details
var/mob/temp_target = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
if(temp_target)
targets += temp_target
else
targets += pick(possible_targets)
//Adds a safety check post-input to make sure those targets are actually in range.
else
var/list/possible_targets = list()
var/list/starting_targets
if(range == -2)
starting_targets = living_mob_list
else
starting_targets = view_or_range(range, user, selection_type)
for(var/mob/living/target in starting_targets)
if(!(spell_flags & INCLUDEUSER) && target == user)
continue
if(compatible_mobs && !is_type_in_list(target, compatible_mobs))
continue
possible_targets += target
if(spell_flags & SELECTABLE)
for(var/i = 1; i<=max_targets, i++)
if(!possible_targets.len)
break
var/mob/M = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
if(!M)
break
if(range != -2)
if(!(M in view_or_range(range, user, selection_type)))
continue
targets += M
possible_targets -= M
else
for(var/i=1,i<=max_targets,i++)
if(!possible_targets.len)
break
if(target_ignore_prev)
var/target = pick(possible_targets)
possible_targets -= target
targets += target
else
targets += pick(possible_targets)
if(!(spell_flags & INCLUDEUSER) && (user in targets))
targets -= user
if(compatible_mobs && compatible_mobs.len)
for(var/mob/living/target in targets) //filters out all the non-compatible mobs
if(!is_type_in_list(target, compatible_mobs))
targets -= target
return targets
/spell/targeted/cast(var/list/targets, mob/user)
for(var/mob/living/target in targets)
if(range >= 0)
if(!(target in view_or_range(range, user, selection_type))) //filter at time of casting
targets -= target
continue
apply_spell_damage(target)
/spell/targeted/proc/apply_spell_damage(mob/living/target)
target.adjustBruteLoss(amt_dam_brute)
target.adjustFireLoss(amt_dam_fire)
target.adjustToxLoss(amt_dam_tox)
target.adjustOxyLoss(amt_dam_oxy)
//disabling
target.Weaken(amt_weakened)
target.Paralyse(amt_paralysis)
target.Stun(amt_stunned)
if(amt_weakened || amt_paralysis || amt_stunned)
if(target.buckled)
target.buckled = null
target.eye_blind += amt_eye_blind
target.eye_blurry += amt_eye_blurry
target.dizziness += amt_dizziness
target.confused += amt_confused
/*
Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range
Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm
*/
/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob
var/max_targets = 1 //leave 0 for unlimited targets in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range
var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast
var/amt_weakened = 0
var/amt_paralysis = 0
var/amt_stunned = 0
var/amt_dizziness = 0
var/amt_confused = 0
var/amt_stuttering = 0
//set to negatives for healing
var/amt_dam_fire = 0
var/amt_dam_brute = 0
var/amt_dam_oxy = 0
var/amt_dam_tox = 0
var/amt_eye_blind = 0
var/amt_eye_blurry = 0
var/list/compatible_mobs = list()
/spell/targeted/choose_targets(mob/user = usr)
var/list/targets = list()
if(max_targets == 0) //unlimited
if(range == -2)
targets = living_mob_list
else
for(var/mob/living/target in view_or_range(range, holder, selection_type))
targets += target
else if(max_targets == 1) //single target can be picked
if((range == 0 || range == -1) && spell_flags & INCLUDEUSER)
targets += user
else
var/list/possible_targets = list()
var/list/starting_targets
if(range == -2)
starting_targets = living_mob_list
else
starting_targets = view_or_range(range, holder, selection_type)
for(var/mob/living/M in starting_targets)
if(!(spell_flags & INCLUDEUSER) && M == user)
continue
if(compatible_mobs && compatible_mobs.len)
if(!is_type_in_list(M, compatible_mobs)) continue
if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs))
continue
possible_targets += M
if(possible_targets.len)
if(spell_flags & SELECTABLE) //if we are allowed to choose. see setup.dm for details
var/mob/temp_target = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
if(temp_target)
targets += temp_target
else
targets += pick(possible_targets)
//Adds a safety check post-input to make sure those targets are actually in range.
else
var/list/possible_targets = list()
var/list/starting_targets
if(range == -2)
starting_targets = living_mob_list
else
starting_targets = view_or_range(range, holder, selection_type)
for(var/mob/living/target in starting_targets)
if(!(spell_flags & INCLUDEUSER) && target == user)
continue
if(compatible_mobs && !is_type_in_list(target, compatible_mobs))
continue
possible_targets += target
if(spell_flags & SELECTABLE)
for(var/i = 1; i<=max_targets, i++)
if(!possible_targets.len)
break
var/mob/M = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
if(!M)
break
if(range != -2)
if(!(M in view_or_range(range, holder, selection_type)))
continue
targets += M
possible_targets -= M
else
for(var/i=1,i<=max_targets,i++)
if(!possible_targets.len)
break
if(target_ignore_prev)
var/target = pick(possible_targets)
possible_targets -= target
targets += target
else
targets += pick(possible_targets)
if(!(spell_flags & INCLUDEUSER) && (user in targets))
targets -= user
if(compatible_mobs && compatible_mobs.len)
for(var/mob/living/target in targets) //filters out all the non-compatible mobs
if(!is_type_in_list(target, compatible_mobs))
targets -= target
return targets
/spell/targeted/cast(var/list/targets, mob/user)
for(var/mob/living/target in targets)
if(range >= 0)
if(!(target in view_or_range(range, holder, selection_type))) //filter at time of casting
targets -= target
continue
apply_spell_damage(target)
/spell/targeted/proc/apply_spell_damage(mob/living/target)
target.adjustBruteLoss(amt_dam_brute)
target.adjustFireLoss(amt_dam_fire)
target.adjustToxLoss(amt_dam_tox)
target.adjustOxyLoss(amt_dam_oxy)
//disabling
target.Weaken(amt_weakened)
target.Paralyse(amt_paralysis)
target.Stun(amt_stunned)
if(amt_weakened || amt_paralysis || amt_stunned)
if(target.buckled)
target.buckled = null
target.eye_blind += amt_eye_blind
target.eye_blurry += amt_eye_blurry
target.dizziness += amt_dizziness
target.confused += amt_confused
target.stuttering += amt_stuttering
+2 -2
View File
@@ -63,11 +63,11 @@
icon_state = "holo_preview"
color = "#EEEEEE"
New()
material = get_material_by_name("holographic [DEFAULT_TABLE_MATERIAL]")
material = get_material_by_name("holo[DEFAULT_TABLE_MATERIAL]")
..()
woodentable/holotable
icon_state = "holo_preview"
New()
material = get_material_by_name("holographic wood")
material = get_material_by_name("holowood")
..()
+1 -1
View File
@@ -200,7 +200,7 @@
// Returns the material to set the table to.
/obj/structure/table/proc/common_material_add(obj/item/stack/material/S, mob/user, verb) // Verb is actually verb without 'e' or 'ing', which is added. Works for 'plate'/'plating' and 'reinforce'/'reinforcing'.
var/material/M = name_to_material[S.default_type]
var/material/M = S.get_material()
if(!istype(M))
user << "<span class='warning'>You cannot [verb]e \the [src] with \the [S].</span>"
return null