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

This commit is contained in:
PsiOmega
2015-02-23 10:32:32 +01:00
170 changed files with 3881 additions and 2166 deletions

View File

@@ -292,7 +292,7 @@
if("monkey") M.change_mob_type( /mob/living/carbon/monkey , null, null, delmob )
if("robot") M.change_mob_type( /mob/living/silicon/robot , null, null, delmob )
if("cat") M.change_mob_type( /mob/living/simple_animal/cat , null, null, delmob )
if("runtime") M.change_mob_type( /mob/living/simple_animal/cat/Runtime , null, null, delmob )
if("runtime") M.change_mob_type( /mob/living/simple_animal/cat/fluff/Runtime , null, null, delmob )
if("corgi") M.change_mob_type( /mob/living/simple_animal/corgi , null, null, delmob )
if("ian") M.change_mob_type( /mob/living/simple_animal/corgi/Ian , null, null, delmob )
if("crab") M.change_mob_type( /mob/living/simple_animal/crab , null, null, delmob )

View File

@@ -3,11 +3,13 @@
set desc = "Fires a laser bolt at your position. You should only do this as a(n) (a)ghost"
set category = "Fun"
var/turf/target = get_turf(src.mob)
admin_log_and_message_admins("has fired the Icarus point defense laser at [target.x]-[target.y]-[target.z]")
if(!src.holder)
src << "Only administrators may use this command."
return
Icarus_FireLaser(get_turf(src.mob))
Icarus_FireLaser(target)
/client/proc/FireCannons()
@@ -15,11 +17,13 @@
set desc = "Fires an explosive missile at your position. You should only do this as a(n) (a)ghost."
set category = "Fun"
var/turf/target = get_turf(src.mob)
admin_log_and_message_admins("has fired the Icarus main gun projectile at [target.x]-[target.y]-[target.z]")
if(!src.holder)
src << "Only administrators may use this command."
return
Icarus_FireCannon(get_turf(src.mob))
Icarus_FireCannon(target)
/client/proc/ChangeIcarusPosition()
@@ -27,6 +31,7 @@
set desc = "Lets you chose the position of the Icarus in regards to the map."
set category = "Fun"
admin_log_and_message_admins("is changing the Icarus position.")
if(!src.holder)
src << "Only administrators may use this command."
return
@@ -122,4 +127,4 @@ proc/Icarus_SetPosition(var/user)
if(!direction)
return
icarus_position = directions[direction]
icarus_position = directions[direction]

View File

@@ -40,7 +40,7 @@
return
/obj/item/assembly/shock_kit/receive_signal()
if(istype(loc, /obj/structure/stool/bed/chair/e_chair))
var/obj/structure/stool/bed/chair/e_chair/C = loc
if(istype(loc, /obj/structure/bed/chair/e_chair))
var/obj/structure/bed/chair/e_chair/C = loc
C.shock()
return

View File

@@ -416,11 +416,25 @@ var/global/list/gear_datums = list()
cost = 1
/datum/gear/armpit
display_name = "shoulder holster"
display_name = "holster, armpit"
path = /obj/item/clothing/accessory/holster/armpit
slot = slot_tie
cost = 2
allowed_roles = list("Captain", "Head of Personnel", "Security Officer", "Warden", "Head of Security")
allowed_roles = list("Captain", "Head of Personnel", "Security Officer", "Warden", "Head of Security","Detective")
/datum/gear/hip
display_name = "holster, hip"
path = /obj/item/clothing/accessory/holster/hip
slot = slot_tie
cost = 2
allowed_roles = list("Captain", "Head of Personnel", "Security Officer", "Warden", "Head of Security", "Detective")
/datum/gear/waist
display_name = "holster, waist"
path = /obj/item/clothing/accessory/holster/waist
slot = slot_tie
cost = 2
allowed_roles = list("Captain", "Head of Personnel", "Security Officer", "Warden", "Head of Security", "Detective")
/datum/gear/tie_blue
display_name = "tie, blue"

View File

@@ -191,9 +191,11 @@
if(isnull(species) || !(species in playable_species))
species = "Human"
if(isnum(underwear))
var/list/undies = gender == MALE ? underwear_m : underwear_f
underwear = undies[undies[underwear]]
if(isnum(undershirt))
undershirt = undershirt_t[undershirt_t[undershirt]]
@@ -219,8 +221,6 @@
r_eyes = sanitize_integer(r_eyes, 0, 255, initial(r_eyes))
g_eyes = sanitize_integer(g_eyes, 0, 255, initial(g_eyes))
b_eyes = sanitize_integer(b_eyes, 0, 255, initial(b_eyes))
underwear = sanitize_integer(underwear, 1, underwear_m.len, initial(underwear))
undershirt = sanitize_integer(undershirt, 1, undershirt_t.len, initial(undershirt))
backbag = sanitize_integer(backbag, 1, backbaglist.len, initial(backbag))
b_type = sanitize_text(b_type, initial(b_type))

View File

@@ -84,3 +84,18 @@
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
siemens_coefficient = 0.9
body_parts_covered = UPPER_TORSO|ARMS
//Orange emergency space suit
/obj/item/clothing/head/helmet/space/emergency
name = "Emergency Space Helmet"
icon_state = "emergencyhelm"
item_state = "emergencyhelm"
desc = "A simple helmet with a built in light, smells like mothballs."
/obj/item/clothing/suit/space/emergency
name = "Emergency Softsuit"
icon_state = "syndicate-orange"
item_state = "syndicate-orange"
desc = "A thin, ungainly softsuit colored in blaze orange for rescuers to easily locate, looks pretty fragile."
slowdown = 4

View File

@@ -197,7 +197,7 @@
armor = list(melee = 60, bullet = 60, laser = 60, energy = 40, bomb = 20, bio = 0, rad = 0)
siemens_coefficient = 0.7
var/obj/item/clothing/accessory/holster/holster
/obj/item/clothing/suit/armor/tactical/New()
..()
holster = new(src)
@@ -212,7 +212,7 @@
set src in usr
if(!istype(usr, /mob/living)) return
if(usr.stat) return
if(!holster.holstered)
var/obj/item/W = usr.get_active_hand()
if(!istype(W, /obj/item))
@@ -220,7 +220,7 @@
return
holster.holster(W, usr)
else
holster.unholster(usr)
holster.unholster(usr)
//Non-hardsuit ERT armor.
/obj/item/clothing/suit/armor/vest/ert
@@ -252,3 +252,101 @@
name = "emergency response team medical armor"
desc = "A set of armor worn by medical members of the NanoTrasen Emergency Response Team. Has red and white highlights."
icon_state = "ertarmor_med"
//New Vests
/obj/item/clothing/suit/storage/vest
name = "armor vest"
desc = "A simple kevlar plate carrier."
icon_state = "kvest"
item_state = "kvest"
armor = list(melee = 50, bullet = 15, laser = 50, energy = 10, bomb = 25, bio = 0, rad = 0)
allowed = list(/obj/item/weapon/gun,/obj/item/weapon/reagent_containers/spray/pepper,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/handcuffs)
/obj/item/clothing/suit/storage/vest/officer
name = "officer armor vest"
desc = "A simple kevlar plate carrier beloning to Nanotrasen. This one has a security holobadge clipped to the chest."
icon_state = "officervest_nobadge"
item_state = "officervest_nobadge"
icon_badge = "officervest_badge"
icon_nobadge = "officervest_nobadge"
/obj/item/clothing/suit/storage/vest/warden
name = "warden armor vest"
desc = "A simple kevlar plate carrier belonging to Nanotrasen. This one has a silver badge clipped to the chest."
icon_state = "wardenvest_nobadge"
item_state = "wardenvest_nobadge"
icon_badge = "wardenvest_badge"
icon_nobadge = "wardenvest_nobadge"
/obj/item/clothing/suit/storage/vest/hos
name = "commander armor vest"
desc = "A simple kevlar plate carrier belonging to Nanotrasen. This one has a gold badge clipped to the chest."
icon_state = "hosvest_nobadge"
item_state = "hosvest_nobadge"
icon_badge = "hosvest_badge"
icon_nobadge = "hosvest_nobadge"
/obj/item/clothing/suit/storage/vest/pcrc
name = "PCRC armor vest"
desc = "A simple kevlar plate carrier belonging to Proxima Centauri Risk Control. This one has a PCRC crest clipped to the chest."
icon_state = "pcrcvest_nobadge"
item_state = "pcrcvest_nobadge"
icon_badge = "pcrcvest_badge"
icon_nobadge = "pcrcvest_nobadge"
/obj/item/clothing/suit/storage/vest/detective
name = "detective armor vest"
desc = "A simple kevlar plate carrier in a vintage brown, it has a badge clipped to the chest that reads, 'Private investigator'."
icon_state = "detectivevest_nobadge"
item_state = "detectivevest_nobadge"
icon_badge = "detectivevest_badge"
icon_nobadge = "detectivevest_nobadge"
/obj/item/clothing/suit/storage/vest/heavy
name = "heavy armor vest"
desc = "A heavy kevlar plate carrier with webbing attached."
icon_state = "webvest"
item_state = "webvest"
armor = list(melee = 50, bullet = 40, laser = 50, energy = 25, bomb = 30, bio = 0, rad = 0)
slowdown = 1
/obj/item/clothing/suit/storage/vest/heavy/officer
name = "officer heavy armor vest"
desc = "A heavy kevlar plate carrier belonging to Nanotrasen with webbing attached. This one has a security holobadge clipped to the chest."
icon_state = "officerwebvest_nobadge"
item_state = "officerwebvest_nobadge"
icon_badge = "officerwebvest_badge"
icon_nobadge = "officerwebvest_nobadge"
/obj/item/clothing/suit/storage/vest/heavy/warden
name = "warden heavy armor vest"
desc = "A heavy kevlar plate carrier belonging to Nanotrasen with webbing attached. This one has a silver badge clipped to the chest."
icon_state = "wardenwebvest_nobadge"
item_state = "wardenwebvest_nobadge"
icon_badge = "wardenwebvest_badge"
icon_nobadge = "wardenwebvest_nobadge"
/obj/item/clothing/suit/storage/vest/heavy/hos
name = "commander heavy armor vest"
desc = "A heavy kevlar plate carrier belonging to Nanotrasen with webbing attached. This one has a gold badge clipped to the chest."
icon_state = "hoswebvest_nobadge"
item_state = "hoswebvest_nobadge"
icon_badge = "hoswebvest_badge"
icon_nobadge = "hoswebvest_nobadge"
/obj/item/clothing/suit/storage/vest/heavy/pcrc
name = "PCRC heavy armor vest"
desc = "A heavy kevlar plate carrier belonging to Proxima Centauri Risk Control with webbing attached. This one has a PCRC crest clipped to the chest."
icon_state = "pcrcwebvest_nobadge"
item_state = "pcrcwebvest_nobadge"
icon_badge = "pcrcwebvest_badge"
icon_nobadge = "pcrcwebvest_nobadge"
/obj/item/clothing/suit/storage/vest/heavy/merc
name = "comfortable heavy armor vest"
desc = "A heavy kevlar plate carrier in a fetching tan. Fits pretty well."
icon_state = "mercwebvest"
item_state = "mercwebvest"
armor = list(melee = 60, bullet = 60, laser = 60, energy = 40, bomb = 40, bio = 0, rad = 0)
slowdown = 0

View File

@@ -48,4 +48,36 @@
else //in case some goofy admin switches icon states around without switching the icon_open or icon_closed
usr << "You attempt to button-up the velcro on your [src], before promptly realising how silly you are."
return
update_clothing_icon() //so our overlays update
update_clothing_icon() //so our overlays update
//New Vest 4 pocket storage and badge toggles, until suit accessories are a thing.
/obj/item/clothing/suit/storage/vest/heavy/New()
..()
pockets = new/obj/item/weapon/storage/internal(src)
pockets.storage_slots = 4
pockets.max_w_class = 2
pockets.max_combined_w_class = 8
/obj/item/clothing/suit/storage/vest
var/icon_badge
var/icon_nobadge
verb/toggle()
set name ="Adjust Badge"
set category = "Object"
set src in usr
if(!usr.canmove || usr.stat || usr.restrained())
return 0
if(icon_state == icon_badge)
icon_state = icon_nobadge
usr << "You unclip the badge from the vest."
else if(icon_state == icon_nobadge)
icon_state = icon_badge
usr << "You clip the badge to the vest."
else
usr << "You can't find a badge for [src]."
return
update_clothing_icon()

View File

@@ -30,12 +30,12 @@
else
if(user.a_intent == "hurt")
usr.visible_message(
"\red [user] draws \the [holstered], ready to shoot!</span>",
"\red [user] draws \the [holstered], ready to shoot!</span>",
"<span class='warning'>You draw \the [holstered], ready to shoot!</span>"
)
else
user.visible_message(
"<span class='notice'>[user] draws \the [holstered], pointing it at the ground.</span>",
"<span class='notice'>[user] draws \the [holstered], pointing it at the ground.</span>",
"<span class='notice'>You draw \the [holstered], pointing it at the ground.</span>"
)
user.put_in_hands(holstered)
@@ -103,13 +103,19 @@
H.unholster(usr)
/obj/item/clothing/accessory/holster/armpit
name = "shoulder holster"
name = "armpit holster"
desc = "A worn-out handgun holster. Perfect for concealed carry"
icon_state = "holster"
item_color = "holster"
/obj/item/clothing/accessory/holster/waist
name = "shoulder holster"
name = "waist holster"
desc = "A handgun holster. Made of expensive leather."
icon_state = "holster"
item_color = "holster_low"
item_color = "holster_low"
/obj/item/clothing/accessory/holster/hip
name = "hip holster"
desc = "A handgun holster slung low on the hip, draw pardner!"
icon_state = "holster_hip"
item_color = "holster_hip"

View File

@@ -1412,12 +1412,6 @@
////////////////////////////// Foxler - Erstatz Vryroxes /////////////////////////////////////////////////
/obj/item/weapon/holder/cat/fluff/bones
name = "Bones"
desc = "It's Bones! Meow."
gender = MALE
icon_state = "cat3"
//Use this subtype for spawning in the custom item.
/obj/item/weapon/holder/cat/fluff/bones/custom_item
@@ -1426,6 +1420,12 @@
new/mob/living/simple_animal/cat/fluff/bones (src)
..()
/obj/item/weapon/holder/cat/fluff/bones
name = "Bones"
desc = "It's Bones! Meow."
gender = MALE
icon_state = "cat3"
/mob/living/simple_animal/cat/fluff/bones
name = "Bones"
desc = "That's Bones the cat. He's a laid back, black cat. Meow."
@@ -1434,61 +1434,12 @@
icon_living = "cat3"
icon_dead = "cat3_dead"
holder_type = /obj/item/weapon/holder/cat/fluff/bones
bff_name = "Erstatz Vryroxes"
var/friend_name = "Erstatz Vryroxes"
/mob/living/simple_animal/cat/fluff
var/bff_name
var/mob/living/carbon/human/bff
/mob/living/simple_animal/cat/fluff/handle_movement_target()
if (!bff)
/mob/living/simple_animal/cat/fluff/bones/handle_movement_target()
if (!friend)
for (var/mob/living/carbon/human/M in player_list)
if (M.real_name == bff_name)
bff = M
if (M.real_name == friend_name)
friend = M
break
if (bff)
var/follow_dist = 5
if (bff.stat >= DEAD || bff.health <= config.health_threshold_softcrit) //danger
follow_dist = 1
else if (bff.stat || bff.health <= 50) //danger or just sleeping
follow_dist = 2
var/near_dist = max(follow_dist - 3, 1)
var/current_dist = get_dist(src, bff)
if (movement_target != bff)
if (current_dist > follow_dist && !istype(movement_target, /mob/living/simple_animal/mouse) && (bff in oview(src)))
//stop existing movement
walk_to(src,0)
turns_since_scan = 0
//walk to bff
stop_automated_movement = 1
movement_target = bff
walk_to(src, movement_target, near_dist, 4)
//already following and close enough, stop
else if (current_dist <= near_dist)
walk_to(src,0)
movement_target = null
stop_automated_movement = 0
if (!(bff && movement_target == bff))
..()
/mob/living/simple_animal/cat/fluff/Life()
..()
if (stat || !bff)
return
if (get_dist(src, bff) <= 1)
if (bff.stat >= DEAD || bff.health <= config.health_threshold_softcrit)
if (prob((bff.stat < DEAD)? 50 : 15))
audible_emote(pick("meows in distress.", "meows anxiously."))
else
if (prob(5))
visible_emote(pick("nuzzles [bff].",
"brushes against [bff].",
"rubs against [bff].",
"purrs."))
else if (bff.health <= 50)
if (prob(10)) audible_emote("meows anxiously.")

View File

@@ -0,0 +1,166 @@
/obj/machinery/atmospherics/pipe
description_info = "This pipe, and all other pipes, can be connected or disconnected by a wrench. The internal pressure of the pipe must \
be below 300 kPa to do this. More pipes can be obtained from the pipe dispenser."
/obj/machinery/atmospherics/pipe/New() //This is needed or else 20+ lines of copypasta to dance around inheritence.
..()
description_info += "<br>Most pipes and atmospheric devices can be connected or disconnected with a wrench. The pipe's pressure must not be too high, \
or if it is a device, it must be turned off first."
//HE pipes
/obj/machinery/atmospherics/pipe/simple/heat_exchanging
description_info = "This radiates heat from the pipe's gas to space, cooling it down."
//Supply/Scrubber pipes
/obj/machinery/atmospherics/pipe/simple/visible/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/visible/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/hidden/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
//Universal adapters
/obj/machinery/atmospherics/pipe/simple/visible/universal
description_info = "This allows you to connect 'normal' pipes, red 'scrubber' pipes, and blue 'supply' pipes."
/obj/machinery/atmospherics/pipe/simple/hidden/universal
description_info = "This allows you to connect 'normal' pipes, red 'scrubber' pipes, and blue 'supply' pipes."
//Three way manifolds
/obj/machinery/atmospherics/pipe/manifold
description_info = "A normal pipe with three ends to connect to."
/obj/machinery/atmospherics/pipe/manifold/visible/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/visible/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold/hidden/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
//Insulated pipes
/obj/machinery/atmospherics/pipe/simple/insulated
description_info = "This is completely useless, use a normal pipe." //Sorry, but it's true.
//Four way manifolds
/obj/machinery/atmospherics/pipe/manifold4w
description_info = "This is a four-way pipe."
/obj/machinery/atmospherics/pipe/manifold4w/visible/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/hidden/supply
description_info = "This is a special 'supply' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
/obj/machinery/atmospherics/pipe/manifold4w/hidden/scrubbers
description_info = "This is a special 'scrubber' pipe, which does not connect to 'normal' pipes. If you want to connect it, use \
a Universal Adapter pipe."
//Endcaps
/obj/machinery/atmospherics/pipe/cap
description_info = "This is a cosmetic attachment, as pipes currently do not spill their contents into the air."
//T-shaped valves
/obj/machinery/atmospherics/tvalve
description_info = "Click this to toggle the mode. The direction with the green light is where the gas will flow."
//Normal valves
/obj/machinery/atmospherics/valve
description_info = "Click this to turn the valve. If red, the pipes on each end are seperated. Otherwise, they are connected."
//TEG ports
/obj/machinery/atmospherics/binary/circulator
description_info = "This generates electricity, depending on the difference in temperature between each side of the machine. The meter in \
the center of the machine gives an indicator of how much elecrtricity is being generated."
//Passive gates
/obj/machinery/atmospherics/binary/passive_gate
description_info = "This is a one-way regulator, allowing gas to flow only at a specific pressure and flow rate. If the light is green, it is flowing."
//Normal pumps (high power one inherits from this)
/obj/machinery/atmospherics/binary/pump
description_info = "This moves gas from one pipe to another. A higher target pressure demands more energy. The side with the red end is the output."
//Vents
/obj/machinery/atmospherics/unary/vent_pump
description_info = "This pumps the contents of the attached pipe out into the atmosphere, if needed. It can be controlled from an Air Alarm."
//Freezers
/obj/machinery/atmospherics/unary/freezer
description_info = "Cools down the gas of the pipe it is connected to. It uses massive amounts of electricity while on. \
It can be upgraded by replacing the capacitors, manipulators, and matter bins. It can be deconstructed by screwing the maintenance panel open with a \
screwdriver, and then using a crowbar."
//Heaters
/obj/machinery/atmospherics/unary/heater
description_info = "Heats up the gas of the pipe it is connected to. It uses massive amounts of electricity while on. \
It can be upgraded by replacing the capacitors, manipulators, and matter bins. It can be deconstructed by screwing the maintenance panel open with a \
screwdriver, and then using a crowbar."
//Gas injectors
/obj/machinery/atmospherics/unary/outlet_injector
description_info = "Outputs the pipe's gas into the atmosphere, similar to an airvent. It can be controlled by a nearby atmospherics computer. \
A green light on it means it is on."
//Scrubbers
/obj/machinery/atmospherics/unary/vent_scrubber
description_info = "This filters the atmosphere of harmful gas. Filtered gas goes to the pipes connected to it, typically a scrubber pipe. \
It can be controlled from an Air Alarm. It can be configured to drain all air rapidly with a 'panic syphon' from an air alarm."
//Omni filters
/obj/machinery/atmospherics/omni/filter
description_info = "Filters gas from a custom input direction, with up to two filtered outputs and a 'everything else' \
output. The filtered output's arrows glow orange."
//Omni mixers
/obj/machinery/atmospherics/omni/mixer
description_info = "Combines gas from custom input and output directions. The percentage of combined gas can be defined."
//Canisters
/obj/machinery/portable_atmospherics/canister
description_info = "The canister can be connected to a connector port with a wrench. Tanks of gas (the kind you can hold in your hand) \
can be filled by the canister, by using the tank on the canister, increasing the release pressure, then opening the valve until it is full, and then close it. \
*DO NOT* remove the tank until the valve is closed. A gas analyzer can be used to check the contents of the canister."
description_antag = "Canisters can be damaged, spilling their contents into the air, or you can just leave the release valve open."
//Portable pumps
/obj/machinery/portable_atmospherics/powered/pump
description_info = "Invaluable for filling air in a room rapidly after a breach repair. The internal gas container can be filled by \
connecting it to a connector port. The pump can pump the air in (sucking) or out (blowing), at a specific target pressure. The powercell inside can be \
replaced by using a screwdriver, and then adding a new cell. A tank of gas can also be attached to the air pump."
//Portable scrubbers
/obj/machinery/portable_atmospherics/powered/scrubber
description_info = "Filters the air, placing harmful gases into the internal gas container. The container can be emptied by \
connecting it to a connector port. The pump can pump the air in (sucking) or out (blowing), at a specific target pressure. The powercell inside can be \
replaced by using a screwdriver, and then adding a new cell. A tank of gas can also be attached to the scrubber. "
//Meters
/obj/machinery/meter
description_info = "Measures the volume and temperature of the pipe under the meter."
//Pipe dispensers
/obj/machinery/pipedispenser
description_info = "This can be moved by using a wrench. You will need to wrench it again when you want to use it. You can put \
excess (atmospheric) pipes into the dispenser, as well. The dispenser requires electricity to function."

View File

@@ -0,0 +1,35 @@
/obj/machinery/power/supermatter
description_info = "When energized by a laser (or something hitting it), it emits radiation and heat. If the heat reaches above 7000 kelvin, it will send an alert and start taking damage. \
After integrity falls to zero percent, it will delaminate, causing a massive explosion, station-wide radiation spikes, and hallucinations. \
Supermatter reacts badly to oxygen in the atmosphere. It'll also heat up really quick if it is in vacuum.<br>\
<br>\
Supermatter cores are extremely dangerous to be close to, and requires protection to handle properly. The protection you will need is:<br>\
Optical meson scanners on your eyes, to prevent hallucinations when looking at the supermatter.<br>\
Radiation helmet and suit, as the supermatter is radioactive.<br>\
<br>\
Touching the supermatter will result in *instant death*, with no corpse left behind! You can drag the supermatter, but anything else will kill you. \
It is advised to obtain a genetic backup before trying to drag it."
description_antag = "Exposing the supermatter to oxygen or vaccum will cause it to start rapidly heating up. Sabotaging the supermatter and making it explode will \
cause a period of lag as the explosion is processed by the server, as well as irradiating the entire station and causing hallucinations to happen. \
Wearing radiation equipment will protect you from most of the delamination effects sans explosion."
/obj/machinery/power/apc
description_info = "An APC (Area Power Controller) regulates and supplies backup power for the area they are in. Their power channels are divided \
out into 'environmental' (Items that manipulate airflow and temperature), 'lighting' (the lights), and 'equipment' (Everything else that consumes power). \
Power consumption and backup power cell charge can be seen from the interface, further controls (turning a specific channel on, off or automatic, \
toggling the APC's ability to charge the backup cell, or toggling power for the entire area via master breaker) first requires the interface to be unlocked \
with an ID with Engineering access or by one of the station's robots or the artificial intelligence."
description_antag = "This can be emagged to unlock it. It will cause the APC to have a blue error screen. \
Wires can be pulsed remotely with a signaler attached to it. A powersink will also drain any APCs connected to the same wire the powersink is on."
/obj/item/inflatable
description_info = "Inflate by using it in your hand. The inflatable barrier will inflate on your tile. To deflate it, use the 'deflate' verb."
/obj/structure/inflatable
description_info = "To remove these safely, use the 'deflate' verb. Hitting these with any objects will probably puncture and break it forever."
/obj/structure/inflatable/door
description_info = "Click the door to open or close it. It only stops air while closed.<br>\
To remove these safely, use the 'deflate' verb. Hitting these with any objects will probably puncture and break it forever."

View File

@@ -0,0 +1,8 @@
/mob/living/silicon/robot/drone
description_info = "Drones are player-controlled synthetics which are lawed to maintain the station and not \
interact with anyone else, except for other drones. They hold a wide array of tools to build, repair, maintain, and clean. \
They fuction similarly to other synthetics, in that they require recharging regularly, have laws, and are resilient to many hazards, \
such as fire, radiation, vacuum, and more. Ghosts can join the round as a maintenance drone by using the appropriate verb in the 'ghost' tab. \
An inactive drone can be rebooted by swiping an ID card on it with engineering or robotics access."
description_antag = "An Electromagnetic Sequencer can be used to subvert the drone to your cause."

View File

@@ -0,0 +1,24 @@
/obj/item/stack/rods
description_info = "Made from metal sheets. You can build a grille by using it in your hand. \
Clicking on a floor without any tiles will reinforce the floor. You can make reinforced glass by combining rods and normal glass sheets."
/obj/item/stack/sheet/glass
description_info = "Use in your hand to build a window. Can be upgraded to reinforced glass by adding metal rods, which are made from metal sheets."
/obj/item/stack/sheet/glass/cyborg
description_info = "Use in your hand to build a window. Can be upgraded to reinforced glass by adding metal rods, which are made from metal sheets.<br>\
As a synthetic, you can acquire more sheets of glass by recharging."
/obj/item/stack/sheet/glass/reinforced
description_info = "Use in your hand to build a window. Reinforced glass is much stronger against damage."
/obj/item/stack/sheet/glass/reinforced/cyborg
description_info = "Use in your hand to build a window. Reinforced glass is much stronger against damage.<br>\
As a synthetic, you can gain more reinforced glass by recharging."
/obj/item/stack/sheet/metal/cyborg
description_info = "Use in your hand to bring up the recipe menu. If you have enough sheets, click on something on the list to build it.<br>\
You can replenish your supply of metal as a synthetic by recharging."
/obj/item/stack/sheet
description_info = "Use in your hand to bring up the recipe menu. If you have enough sheets, click on something on the list to build it."

View File

@@ -0,0 +1,15 @@
/obj/structure/girder
description_info = "Use metal sheets on this to build a normal wall. Adding plasteel instead will make a reinforced wall.<br>\
A false wall can be made by using a crowbar on this girder, and then adding metal or plasteel.<br>\
You can dismantle the grider with a wrench."
/obj/structure/girder/reinforced
description_info = "Add another sheet of plasteel to finish."
/obj/structure/grille
description_info = "A powered and knotted wire underneath this will cause the grille to shock anyone not wearing insulated gloves.<br>\
Wirecutters will turn the grille into metal rods instantly. Grilles are made with metal rods."
/obj/structure/lattice
description_info = "Add a metal floor tile to build a floor on top of the lattice.<br>\
Lattices can be made by applying metal rods to a space tile."

View File

@@ -0,0 +1,3 @@
/turf/simulated/wall
description_info = "You can deconstruct this by welding it, and then wrenching the girder.<br>\
You can build a wall by using metal sheets and making a girder, then adding more metal or plasteel."

View File

@@ -0,0 +1,71 @@
/* This code is responsible for the examine tab. When someone examines something, it copies the examined object's description_info,
description_fluff, and description_antag, and shows it in a new tab.
In this file, some atom and mob stuff is defined here. It is defined here instead of in the normal files, to keep the whole system self-contained.
This means that this file can be unchecked, along with the other examine files, and can be removed entirely with no effort.
*/
/atom/
var/description_info = null //Helpful blue text.
var/description_fluff = null //Green text about the atom's fluff, if any exists.
var/description_antag = null //Malicious red text, for the antags.
/atom/examine(mob/user)
..()
user.description_holders["info"] = get_description_info()
user.description_holders["fluff"] = get_description_fluff()
if(user.mind && user.mind.special_role || isobserver(user)) //Runtime prevention, as ghosts don't have minds.
user.description_holders["antag"] = get_description_antag()
if(name) //This shouldn't be needed but I'm paranoid.
user.description_holders["name"] = "[src.name]" //\icon[src]
user.description_holders["icon"] = "\icon[src]"
if(desc)
user << desc
user.description_holders["desc"] = src.desc
else
user.description_holders["desc"] = null //This is needed, or else if you examine one thing with a desc, then another without, the panel will retain the first examined's desc.
//Override these if you need special behaviour for a specific type.
/atom/proc/get_description_info()
if(description_info)
return description_info
return
/atom/proc/get_description_fluff()
if(description_fluff)
return description_fluff
return
/atom/proc/get_description_antag()
if(description_antag)
return description_antag
return
/mob/
var/description_holders[0]
/mob/Stat()
..()
if(statpanel("Examine"))
stat(null,"[description_holders["icon"]] <font size='5'>[description_holders["name"]]</font>") //The name, written in big letters.
stat(null,"[description_holders["desc"]]") //the default examine text.
if(description_holders["info"])
stat(null,"<font color='#084B8A'><b>[description_holders["info"]]</b></font>") //Blue, informative text.
if(description_holders["fluff"])
stat(null,"<font color='#298A08'><b>[description_holders["fluff"]]</b></font>") //Yellow, fluff-related text.
if(description_holders["antag"])
stat(null,"<font color='#8A0808'><b>[description_holders["antag"]]</b></font>") //Red, malicious antag-related text
/mob/living/get_description_fluff()
if(flavor_text) //Get flavor text for the green text.
return flavor_text
else //No flavor text? Try for hardcoded fluff instead.
return ..()
/mob/living/carbon/human/get_description_fluff()
return print_flavor_text(0)

View File

@@ -182,10 +182,10 @@
visible_message("[src] fades away as it shatters!")
del(src)
/obj/structure/stool/bed/chair/holochair/Del()
/obj/structure/bed/chair/holochair/Del()
..()
/obj/structure/stool/bed/chair/holochair/attackby(obj/item/weapon/W as obj, mob/user as mob)
/obj/structure/bed/chair/holochair/attackby(obj/item/weapon/W as obj, mob/user as mob)
if(istype(W, /obj/item/weapon/wrench))
user << ("<span class='notice'>It's a holochair, you can't dismantle it!</span>")
return

View File

@@ -335,6 +335,14 @@
icon_state = "unathiknife"
attack_verb = list("ripped", "torn", "cut")
/obj/item/weapon/hatchet/tacknife
name = "tactical knife"
desc = "You'd be killing loads of people if this was Medal of Valor: Heroes of Nyx."
icon = 'icons/obj/weapons.dmi'
icon_state = "tacknife"
item_state = "knife"
attack_verb = list("stabbed", "chopped", "cut")
/obj/item/weapon/scythe
icon_state = "scythe0"
name = "scythe"

View File

@@ -1635,7 +1635,7 @@ proc/populate_seed_list()
seed_noun = "data"
display_name = "runtimes"
packet_icon = "seed-replicapod"
products = list(/mob/living/simple_animal/cat/Runtime)
products = list(/mob/living/simple_animal/cat/fluff/Runtime)
plant_icon = "replicapod"
requires_nutrients = 0

View File

@@ -208,6 +208,7 @@
return 1
//Attemps to remove an object on a mob. Will not move it to another area or such, just removes from the mob.
//It does call u_equip() though. So it can drop items to the floor but only if src is human.
/mob/proc/remove_from_mob(var/obj/O)
src.u_equip(O)
if (src.client)
@@ -242,16 +243,7 @@
/** BS12's proc to get the item in the active hand. Couldn't find the /tg/ equivalent. **/
/mob/proc/equipped()
if(issilicon(src))
if(isrobot(src))
if(src:module_active)
return src:module_active
else
if (hand)
return l_hand
else
return r_hand
return
return get_active_hand() //TODO: get rid of this proc
/mob/living/carbon/human/proc/equip_if_possible(obj/item/W, slot, del_on_fail = 1) // since byond doesn't seem to have pointers, this seems like the best way to do this :/
//warning: icky code

View File

@@ -341,7 +341,7 @@
/mob/living/carbon/can_use_hands()
if(handcuffed)
return 0
if(buckled && ! istype(buckled, /obj/structure/stool/bed/chair)) // buckling does not restrict hands
if(buckled && ! istype(buckled, /obj/structure/bed/chair)) // buckling does not restrict hands
return 0
return 1

View File

@@ -213,7 +213,7 @@
distance = 1
if (src.stat)
msg += "<span class='warning'>[t_He] [t_is]n't responding to anything around [t_him] and seems to be asleep.</span>\n"
if((stat == 2 || src.health < config.health_threshold_crit) && distance <= 3)
if((stat == 2 || src.losebreath) && distance <= 3)
msg += "<span class='warning'>[t_He] does not appear to be breathing.</span>\n"
if(istype(usr, /mob/living/carbon/human) && !usr.stat && Adjacent(usr))
usr.visible_message("<b>[usr]</b> checks [src]'s pulse.", "You check [src]'s pulse.")
@@ -451,6 +451,7 @@
msg += "\n[t_He] is [pose]"
user << msg
..()
//Helper procedure. Called by /mob/living/carbon/human/examine() and /mob/living/carbon/human/Topic() to determine HUD access to security and medical records.
/proc/hasHUD(mob/M as mob, hudtype)

View File

@@ -696,6 +696,8 @@
number += 2
if(istype(src.head, /obj/item/clothing/head/helmet/space))
number += 2
if(istype(src.head, /obj/item/clothing/head/helmet/space/emergency))
number -= 2
if(istype(src.glasses, /obj/item/clothing/glasses/thermal))
number -= 1
if(istype(src.glasses, /obj/item/clothing/glasses/sunglasses))
@@ -1237,7 +1239,7 @@
// Might need re-wording.
user << "<span class='alert'>There is no exposed flesh or thin material [target_zone == "head" ? "on their head" : "on their body"] to inject into.</span>"
/mob/living/carbon/human/print_flavor_text()
/mob/living/carbon/human/print_flavor_text(var/shrink = 1)
var/list/equipment = list(src.head,src.wear_mask,src.glasses,src.w_uniform,src.wear_suit,src.gloves,src.shoes)
var/head_exposed = 1
var/face_exposed = 1
@@ -1273,7 +1275,10 @@
if((T == "head" && head_exposed) || (T == "face" && face_exposed) || (T == "eyes" && eyes_exposed) || (T == "torso" && torso_exposed) || (T == "arms" && arms_exposed) || (T == "hands" && hands_exposed) || (T == "legs" && legs_exposed) || (T == "feet" && feet_exposed))
flavor_text += flavor_texts[T]
flavor_text += "\n\n"
return ..()
if(!shrink)
return flavor_text
else
return ..()
/mob/living/carbon/human/getDNA()
if(species.flags & NO_SCAN)

View File

@@ -116,6 +116,7 @@
if(src.grabbed_by.len || src.buckled || !src.canmove || src==H)
accurate = 1 // certain circumstances make it impossible for us to evade punches
rand_damage = 5
// Process evasion and blocking
var/miss_type = 0
@@ -209,7 +210,7 @@
w_uniform.add_fingerprint(M)
var/datum/organ/external/affecting = get_organ(ran_zone(M.zone_sel.selecting))
if (istype(r_hand,/obj/item/weapon/gun) || istype(l_hand,/obj/item/weapon/gun))
if(istype(r_hand,/obj/item/weapon/gun) || istype(l_hand,/obj/item/weapon/gun))
var/obj/item/weapon/gun/W = null
var/chance = 0
@@ -231,9 +232,13 @@
var/randn = rand(1, 100)
if(!(species.flags & NO_SLIP) && randn <= 25)
apply_effect(3, WEAKEN, run_armor_check(affecting, "melee"))
var/armor_check = run_armor_check(affecting, "melee")
apply_effect(3, WEAKEN, armor_check)
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
visible_message("\red <B>[M] has pushed [src]!</B>")
if(armor_check < 2)
visible_message("<span class='danger'>[M] has pushed [src]!</span>")
else
visible_message("<span class='warning'>[M] attempted to push [src]!</span>")
return
var/talked = 0 // BubbleWrap

View File

@@ -38,9 +38,9 @@ emp_act
return -1 // complete projectile permutation
//Shrapnel
if (P.damage_type == BRUTE)
if(P.can_embed())
var/armor = getarmor_organ(organ, "bullet")
if((P.embed && prob(20 + max(P.damage - armor, -10))))
if(prob(20 + max(P.damage - armor, -10)))
var/obj/item/weapon/shard/shrapnel/SP = new()
SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel"
SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]."

View File

@@ -26,7 +26,7 @@
if(wear_suit)
tally += wear_suit.slowdown
if(istype(buckled, /obj/structure/stool/bed/chair/wheelchair))
if(istype(buckled, /obj/structure/bed/chair/wheelchair))
for(var/organ_name in list("l_hand","r_hand","l_arm","r_arm"))
var/datum/organ/external/E = get_organ(organ_name)
if(!E || (E.status & ORGAN_DESTROYED))

View File

@@ -771,13 +771,7 @@ It can still be worn/put on as normal.
if(slot_to_process)
if(strip_item) //Stripping an item from the mob
var/obj/item/W = strip_item
target.u_equip(W)
if (target.client)
target.client.screen -= W
if (W)
W.loc = target.loc
W.layer = initial(W.layer)
W.dropped(target)
target.remove_from_mob(W)
W.add_fingerprint(source)
if(slot_to_process == slot_l_store) //pockets! Needs to process the other one too. Snowflake code, wooo! It's not like anyone will rewrite this anytime soon. If I'm wrong then... CONGRATULATIONS! ;)
if(target.r_store)

View File

@@ -326,7 +326,6 @@
if(istype(O)) O.add_autopsy_data("Radiation Poisoning", damage)
proc/breathe()
if(reagents.has_reagent("lexorin")) return
if(istype(loc, /obj/machinery/atmospherics/unary/cryo_cell)) return
if(species && (species.flags & NO_BREATHE || species.flags & IS_SYNTHETIC)) return
@@ -439,17 +438,15 @@
return
if(!breath || (breath.total_moles == 0) || suiciding)
failed_last_breath = 1
if(suiciding)
adjustOxyLoss(2)//If you are suiciding, you should die a little bit faster
failed_last_breath = 1
oxygen_alert = max(oxygen_alert, 1)
return 0
if(health > config.health_threshold_crit)
adjustOxyLoss(HUMAN_MAX_OXYLOSS)
failed_last_breath = 1
else
adjustOxyLoss(HUMAN_CRIT_MAX_OXYLOSS)
failed_last_breath = 1
oxygen_alert = max(oxygen_alert, 1)

View File

@@ -209,5 +209,5 @@
if("resin membrane")
new /obj/effect/alien/resin/membrane(loc)
if("resin nest")
new /obj/structure/stool/bed/nest(loc)
new /obj/structure/bed/nest(loc)
return

View File

@@ -64,7 +64,7 @@
target.apply_effects(stutter = attack_damage * 2, agony = attack_damage* 3, blocked = armour)
if("l_leg", "l_foot", "r_leg", "r_foot")
if(!target.lying)
target.visible_message("<span class='warning'>[src] gives way slightly.</span>")
target.visible_message("<span class='warning'>[target] gives way slightly.</span>")
target.apply_effect(attack_damage*3, AGONY, armour)
else if(attack_damage >= 5 && !(target == user) && (stun_chance + attack_damage * 5 >= 100) && armour < 2) // Chance to get the usual throwdown as well (25% standard chance)
if(!target.lying)
@@ -118,22 +118,28 @@
user.visible_message("<span class='danger'>[user] slapped [target] across \his cheek!</span>")
if(3 to 4)
user.visible_message(pick(
80; "<span class='danger'>[user] [pick(attack_verb)] [target] in the head!</span>", //striking someone with a 'closed fist' is called punching them.
20; "<span class='danger'>[user] struck [target] in the head[pick("", " with a closed fist")]!</span>"
40; "<span class='danger'>[user] [pick(attack_verb)] [target] in the head!</span>",
30; "<span class='danger'>[user] struck [target] in the head[pick("", " with a closed fist")]!</span>",
30; "<span class='danger'>[user] threw a hook against [target]'s head!</span>"
))
if(5)
user.visible_message(pick(
10; "<span class='danger'>[user] gave [target] a resounding slap to the face!</span>",
90; "<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s [organ]!</span>"
30; "<span class='danger'>[user] gave [target] a resounding [pick("slap", "punch")] to the face!</span>",
40; "<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s face!</span>",
30; "<span class='danger'>[user] gave a strong blow against [target]'s jaw!</span>"
))
else
// ----- BODY ----- //
switch(attack_damage)
if(1 to 2) user.visible_message("<span class='danger'>[user] slapped [target]'s [organ]!</span>")
if(3 to 4) user.visible_message("<span class='danger'>[user] [pick(attack_verb)] [target] in \his [organ]!</span>")
if(5) user.visible_message("<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s [organ]!</span>")
if(1 to 2) user.visible_message("<span class='danger'>[user] threw a glancing punch at [target]'s [organ]!</span>")
if(1 to 4) user.visible_message("<span class='danger'>[user] [pick(attack_verb)] [target] in \his [organ]!</span>")
if(5)
user.visible_message(pick(
50; "<span class='danger'>[user] smashed \his [pick(attack_noun)] into [target]'s [organ]!</span>",
50; "<span class='danger'>[user] landed a striking [pick(attack_noun)] on [target]'s [organ]!</span>"
))
else
user.visible_message("<span class='danger'>[user] [pick("punched", "threw a punch", "struck", "slapped", "slammed their [pick(attack_noun)] into")] [target]'s [organ]!</span>") //why do we have a separate set of verbs for lying targets?
user.visible_message("<span class='danger'>[user] [pick("punched", "threw a punch against", "struck", "slammed their [pick(attack_noun)] into")] [target]'s [organ]!</span>") //why do we have a separate set of verbs for lying targets?
/datum/unarmed_attack/kick
attack_verb = list("kicked", "kicked", "kicked", "kneed")
@@ -177,7 +183,7 @@
/datum/unarmed_attack/stomp
attack_verb = null
attack_noun = list("kick")
attack_noun = list("stomp")
attack_sound = "swing_hit"
damage = 0
@@ -189,7 +195,7 @@
if(!istype(target))
return 0
if (!user.lying && (target.lying || zone in list("l_foot", "r_foot")))
if (!user.lying && (target.lying || (zone in list("l_foot", "r_foot"))))
if(target.grabbed_by == user && target.lying)
return 0
var/datum/organ/external/E = user.organs_by_name["l_foot"]
@@ -214,6 +220,5 @@
attack_damage = Clamp(attack_damage, 1, 5)
switch(attack_damage)
if(1 to 2) user.visible_message("<span class='danger'>[user] [pick("stepped on", "treaded on")] [target]'s [organ]!</span>") //stepped on conveys the same meaning and is more recognizable as an actual word than "clomped"
if(3 to 4) user.visible_message("<span class='danger'>[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")
if(1 to 4) user.visible_message("<span class='danger'>[pick("[user] stomped on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down onto")] [target]'s [organ]!</span>")
if(5) user.visible_message("<span class='danger'>[pick("[user] landed a powerful stomp on", "[user] stomped down hard on", "[user] slammed \his [shoes ? copytext(shoes.name, 1, -1) : "foot"] down hard onto")] [target]'s [organ]!</span>") //Devastated lol. No. We want to say that the stomp was powerful or forceful, not that it /wrought devastation/

View File

@@ -107,28 +107,29 @@ Please contact me on #coderbus IRC. ~Carn x
//Human Overlays Indexes/////////
#define MUTATIONS_LAYER 1
#define DAMAGE_LAYER 2
#define UNIFORM_LAYER 3
#define TAIL_LAYER 4 //bs12 specific. this hack is probably gonna come back to haunt me
#define ID_LAYER 5
#define SHOES_LAYER 6
#define GLOVES_LAYER 7
#define SUIT_LAYER 8
#define GLASSES_LAYER 9
#define BELT_LAYER 10 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 11
#define BACK_LAYER 12
#define HAIR_LAYER 13 //TODO: make part of head layer?
#define EARS_LAYER 14
#define FACEMASK_LAYER 15
#define HEAD_LAYER 16
#define COLLAR_LAYER 17
#define HANDCUFF_LAYER 18
#define LEGCUFF_LAYER 19
#define L_HAND_LAYER 20
#define R_HAND_LAYER 21
#define FIRE_LAYER 22 //If you're on fire
#define TARGETED_LAYER 23 //BS12: Layer for the target overlay from weapon targeting system
#define TOTAL_LAYERS 23
#define SURGERY_LEVEL 3 //bs12 specific.
#define UNIFORM_LAYER 4
#define TAIL_LAYER 5 //bs12 specific. this hack is probably gonna come back to haunt me
#define ID_LAYER 6
#define SHOES_LAYER 7
#define GLOVES_LAYER 8
#define SUIT_LAYER 9
#define GLASSES_LAYER 10
#define BELT_LAYER 11 //Possible make this an overlay of somethign required to wear a belt?
#define SUIT_STORE_LAYER 12
#define BACK_LAYER 13
#define HAIR_LAYER 14 //TODO: make part of head layer?
#define EARS_LAYER 15
#define FACEMASK_LAYER 16
#define HEAD_LAYER 17
#define COLLAR_LAYER 18
#define HANDCUFF_LAYER 19
#define LEGCUFF_LAYER 20
#define L_HAND_LAYER 21
#define R_HAND_LAYER 22
#define FIRE_LAYER 23 //If you're on fire
#define TARGETED_LAYER 24 //BS12: Layer for the target overlay from weapon targeting system
#define TOTAL_LAYERS 24
//////////////////////////////////
/mob/living/carbon/human
@@ -509,6 +510,7 @@ proc/get_damage_icon_part(damage_state, body_part)
update_inv_legcuffed(0)
update_inv_pockets(0)
update_fire(0)
update_surgery(0)
UpdateDamageIcon()
update_icons()
//Hud Stuff
@@ -547,16 +549,9 @@ proc/get_damage_icon_part(damage_state, body_part)
overlays_standing[UNIFORM_LAYER] = null
// This really, really seems like it should not be mixed in the middle of display code...
// Automatically drop anything in store / id / belt if you're not wearing a uniform. //CHECK IF NECESARRY
for( var/obj/item/thing in list(r_store, l_store, wear_id, belt) ) //
if(thing) //
u_equip(thing) //
if (client) //
client.screen -= thing //
//
if (thing) //
thing.loc = loc //
thing.dropped(src) //
thing.layer = initial(thing.layer)
for( var/obj/item/thing in list(r_store, l_store, wear_id, belt) )
if(thing)
remove_from_mob(thing)
if(update_icons) update_icons()
/mob/living/carbon/human/update_inv_wear_id(var/update_icons=1)
@@ -723,13 +718,22 @@ proc/get_damage_icon_part(damage_state, body_part)
belt.screen_loc = ui_belt //TODO
var/t_state = belt.item_state
if(!t_state) t_state = belt.icon_state
var/image/standing = image("icon_state" = "[t_state]")
if(belt.icon_override)
overlays_standing[BELT_LAYER] = image("icon" = belt.icon_override, "icon_state" = "[t_state]")
standing.icon = belt.icon_override
else if(belt.sprite_sheets && belt.sprite_sheets[species.name])
overlays_standing[BELT_LAYER] = image("icon" = belt.sprite_sheets[species.name], "icon_state" = "[t_state]")
standing.icon = belt.sprite_sheets[species.name]
else
overlays_standing[BELT_LAYER] = image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[t_state]")
standing.icon = 'icons/mob/belt.dmi'
if(belt.contents.len && istype(belt, /obj/item/weapon/storage/belt))
for(var/obj/item/i in belt.contents)
var/i_state = i.item_state
if(!i_state) i_state = i.icon_state
standing.overlays += image("icon" = 'icons/mob/belt.dmi', "icon_state" = "[i_state]")
overlays_standing[BELT_LAYER] = standing
else
overlays_standing[BELT_LAYER] = null
if(update_icons) update_icons()
@@ -920,6 +924,16 @@ proc/get_damage_icon_part(damage_state, body_part)
if(update_icons) update_icons()
/mob/living/carbon/human/proc/update_surgery(var/update_icons=1)
overlays_standing[SURGERY_LEVEL] = null
var/image/total = new
for(var/datum/organ/external/E in organs)
if(E.open)
var/image/I = image("icon"='icons/mob/surgery.dmi', "icon_state"="[E.name][round(E.open)]", "layer"=-SURGERY_LEVEL)
total.overlays += I
overlays_standing[SURGERY_LEVEL] = total
if(update_icons) update_icons()
// Used mostly for creating head items
/mob/living/carbon/human/proc/generate_head_icon()
//gender no longer matters for the mouth, although there should probably be seperate base head icons.
@@ -958,6 +972,7 @@ proc/get_damage_icon_part(damage_state, body_part)
//Human Overlays Indexes/////////
#undef MUTATIONS_LAYER
#undef DAMAGE_LAYER
#undef SURGERY_LEVEL
#undef UNIFORM_LAYER
#undef TAIL_LAYER
#undef ID_LAYER

View File

@@ -171,7 +171,6 @@
// ++++ROCKDTBEN++++ MOB PROCS //END
/mob/proc/get_contents()
@@ -514,7 +513,7 @@
return
//resisting grabs (as if it helps anyone...)
if ((!( L.stat ) && L.canmove && !( L.restrained() )))
if ((!( L.stat ) && !( L.restrained() )))
var/resisting = 0
for(var/obj/O in L.requests)
L.requests.Remove(O)
@@ -522,23 +521,20 @@
resisting++
for(var/obj/item/weapon/grab/G in usr.grabbed_by)
resisting++
if (G.state == 1)
del(G)
else
if (G.state == 2)
if (prob(25))
for(var/mob/O in viewers(L, null))
O.show_message(text("\red [] has broken free of []'s grip!", L, G.assailant), 1)
switch(G.state)
if(GRAB_PASSIVE)
del(G)
if(GRAB_AGGRESSIVE)
if(prob(60)) //same chance of breaking the grab as disarm
L.visible_message("<span class='warning'>[L] has broken free of [G.assailant]'s grip!</span>")
del(G)
if(GRAB_NECK)
//If the you move when grabbing someone then it's easier for them to break free. Same if the affected mob is immune to stun.
if (((world.time - G.assailant.l_move_time < 20 || !L.stunned) && prob(15)) || prob(3))
L.visible_message("<span class='warning'>[L] has broken free of [G.assailant]'s headlock!</span>")
del(G)
else
if (G.state == 3)
if (prob(5))
for(var/mob/O in viewers(usr, null))
O.show_message(text("\red [] has broken free of []'s headlock!", L, G.assailant), 1)
del(G)
if(resisting)
for(var/mob/O in viewers(usr, null))
O.show_message(text("\red <B>[] resists!</B>", L), 1)
L.visible_message("<span class='danger'>[L] resists!</span>")
//unbuckling yourself

View File

@@ -16,8 +16,8 @@
if(stat == DEAD || paralysis || weakened || stunned || restrained())
return
if (layer != TURF_LAYER+0.2)
layer = TURF_LAYER+0.2
if (layer != 2.45)
layer = 2.45 //Just above cables with their 2.44
src << text("\blue You are now hiding.")
else
layer = MOB_LAYER

View File

@@ -16,14 +16,6 @@
integrated_light_power = 2
local_transmit = 1
// We need to keep track of a few module items so we don't need to do list operations
// every time we need them. These get set in New() after the module is chosen.
var/obj/item/stack/sheet/metal/cyborg/stack_metal = null
var/obj/item/stack/sheet/wood/cyborg/stack_wood = null
var/obj/item/stack/sheet/glass/cyborg/stack_glass = null
var/obj/item/stack/sheet/mineral/plastic/cyborg/stack_plastic = null
var/obj/item/weapon/matter_decompiler/decompiler = null
//Used for self-mailing.
var/mail_destination = ""
@@ -56,15 +48,6 @@
verbs -= /mob/living/silicon/robot/verb/Namepick
module = new /obj/item/weapon/robot_module/drone(src)
//Grab stacks.
stack_metal = locate(/obj/item/stack/sheet/metal/cyborg) in src.module
stack_wood = locate(/obj/item/stack/sheet/wood/cyborg) in src.module
stack_glass = locate(/obj/item/stack/sheet/glass/cyborg) in src.module
stack_plastic = locate(/obj/item/stack/sheet/mineral/plastic/cyborg) in src.module
//Grab decompiler.
decompiler = locate(/obj/item/weapon/matter_decompiler) in src.module
//Some tidying-up.
flavor_text = "It's a tiny little repair drone. The casing is stamped with an NT logo and the subscript: 'NanoTrasen Recursive Repair Systems: Fixing Tomorrow's Problem, Today!'"
updateicon()

View File

@@ -2,7 +2,7 @@
/mob/living/silicon/robot/drone/verb/set_mail_tag()
set name = "Set Mail Tag"
set desc = "Tag yourself for delivery through the disposals system."
set category = "Drone"
set category = "Robot Commands"
var/new_tag = input("Select the desired destination.", "Set Mail Tag", null) as null|anything in tagger_locations

View File

@@ -57,7 +57,7 @@
set name = "Drop Item"
set desc = "Release an item from your magnetic gripper."
set category = "Drone"
set category = "Robot Commands"
if(!wrapped)
//There's some weirdness with items being lost inside the arm. Trying to fix all cases. ~Z
@@ -151,12 +151,10 @@
icon_state = "decompiler"
//Metal, glass, wood, plastic.
var/list/stored_comms = list(
"metal" = 0,
"glass" = 0,
"wood" = 0,
"plastic" = 0
)
var/datum/matter_synth/metal = null
var/datum/matter_synth/glass = null
var/datum/matter_synth/wood = null
var/datum/matter_synth/plastic = null
/obj/item/weapon/matter_decompiler/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob)
return
@@ -178,10 +176,10 @@
src.loc.visible_message("\red [src.loc] sucks [M] into its decompiler. There's a horrible crunching noise.","\red It's a bit of a struggle, but you manage to suck [M] into your decompiler. It makes a series of visceral crunching noises.")
new/obj/effect/decal/cleanable/blood/splatter(get_turf(src))
del(M)
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(2000)
return
else if(istype(M,/mob/living/silicon/robot/drone) && !M.client)
@@ -203,61 +201,66 @@
del(M)
new/obj/effect/decal/cleanable/blood/oil(get_turf(src))
stored_comms["metal"] += 15
stored_comms["glass"] += 15
stored_comms["wood"] += 5
stored_comms["plastic"] += 5
if(metal)
metal.add_charge(15000)
if(glass)
glass.add_charge(15000)
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(1000)
return
else
continue
for(var/obj/W in T)
//Different classes of items give different commodities.
if (istype(W,/obj/item/weapon/cigbutt))
stored_comms["plastic"]++
if(istype(W,/obj/item/weapon/cigbutt))
if(plastic)
plastic.add_charge(500)
else if(istype(W,/obj/effect/spider/spiderling))
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
if(wood)
wood.add_charge(2000)
if(plastic)
plastic.add_charge(2000)
else if(istype(W,/obj/item/weapon/light))
var/obj/item/weapon/light/L = W
if(L.status >= 2) //In before someone changes the inexplicably local defines. ~ Z
stored_comms["metal"]++
stored_comms["glass"]++
if(metal)
metal.add_charge(250)
if(glass)
glass.add_charge(250)
else
continue
else if(istype(W,/obj/effect/decal/remains/robot))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
stored_comms["glass"]++
if(metal)
metal.add_charge(2000)
if(plastic)
plastic.add_charge(2000)
if(glass)
glass.add_charge(1000)
else if(istype(W,/obj/item/trash))
stored_comms["metal"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
stored_comms["plastic"]++
if(metal)
metal.add_charge(1000)
if(plastic)
plastic.add_charge(3000)
else if(istype(W,/obj/effect/decal/cleanable/blood/gibs/robot))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["glass"]++
stored_comms["glass"]++
if(metal)
metal.add_charge(2000)
if(glass)
glass.add_charge(2000)
else if(istype(W,/obj/item/ammo_casing))
stored_comms["metal"]++
if(metal)
metal.add_charge(1000)
else if(istype(W,/obj/item/weapon/shard/shrapnel))
stored_comms["metal"]++
stored_comms["metal"]++
stored_comms["metal"]++
if(metal)
metal.add_charge(1000)
else if(istype(W,/obj/item/weapon/shard))
stored_comms["glass"]++
stored_comms["glass"]++
stored_comms["glass"]++
if(glass)
glass.add_charge(1000)
else if(istype(W,/obj/item/weapon/reagent_containers/food/snacks/grown))
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["wood"]++
stored_comms["wood"]++
if(wood)
wood.add_charge(4000)
else if(istype(W,/obj/item/pipe))
// This allows drones and engiborgs to clear pipe assemblies from floors.
else
@@ -325,39 +328,3 @@
dat += resources
src << browse(dat, "window=robotmod")
//Putting the decompiler here to avoid doing list checks every tick.
/mob/living/silicon/robot/drone/use_power()
..()
if(!src.has_power || !decompiler)
return
//The decompiler replenishes drone stores from hoovered-up junk each tick.
for(var/type in decompiler.stored_comms)
if(decompiler.stored_comms[type] > 0)
var/obj/item/stack/sheet/stack
switch(type)
if("metal")
if(!stack_metal)
stack_metal = new /obj/item/stack/sheet/metal/cyborg(src.module)
stack_metal.amount = 1
stack = stack_metal
if("glass")
if(!stack_glass)
stack_glass = new /obj/item/stack/sheet/glass/cyborg(src.module)
stack_glass.amount = 1
stack = stack_glass
if("wood")
if(!stack_wood)
stack_wood = new /obj/item/stack/sheet/wood/cyborg(src.module)
stack_wood.amount = 1
stack = stack_wood
if("plastic")
if(!stack_plastic)
stack_plastic = new /obj/item/stack/sheet/mineral/plastic/cyborg(src.module)
stack_plastic.amount = 1
stack = stack_plastic
stack.amount++
decompiler.stored_comms[type]--;

View File

@@ -552,6 +552,9 @@ var/list/robot_verbs_default = list(
show_cell_power()
show_jetpack_pressure()
stat(null, text("Lights: [lights_on ? "ON" : "OFF"]"))
if(module)
for(var/datum/matter_synth/ms in module.synths)
stat("[ms.name]: [ms.energy]/[ms.max_energy]")
/mob/living/silicon/robot/restrained()
return 0

View File

@@ -7,9 +7,9 @@
flags = CONDUCT
var/channels = list()
var/list/modules = list()
var/list/datum/matter_synth/synths = list()
var/obj/item/emag = null
var/obj/item/borg/upgrade/jetpack = null
var/list/stacktypes
/obj/item/weapon/robot_module/emp_act(severity)
if(modules)
@@ -17,40 +17,19 @@
O.emp_act(severity)
if(emag)
emag.emp_act(severity)
if(synths)
for(var/datum/matter_synth/S in synths)
S.emp_act(severity)
..()
return
/obj/item/weapon/robot_module/New()
..()
// Build initial inventory.
if(stacktypes && stacktypes.len)
for(var/stack_type in stacktypes)
var/obj/item/stack/new_stack = new stack_type (src)
new_stack.amount = stacktypes[stack_type]
modules |= new_stack
/obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R, var/rate)
/obj/item/weapon/robot_module/proc/respawn_consumable(var/mob/living/silicon/robot/R)
if(!synths || !synths.len)
return
if(!stacktypes || !stacktypes.len) return
for(var/T in stacktypes)
var/obj/item/stack/S
for(var/obj/O in src.modules)
if(O.type == T)
S = O
break
if(!S)
src.modules -= null
S = new T(src)
src.modules |= S
S.amount = 1
if(!istype(S))
continue
if(S && S.amount < stacktypes[T])
S.amount++
for(var/datum/matter_synth/T in synths)
T.add_charge(T.recharge_rate * rate)
/obj/item/weapon/robot_module/proc/rebuild()//Rebuilds the list so it's possible to add/remove items from the module
var/list/temp_list = modules
@@ -84,10 +63,6 @@
/obj/item/weapon/robot_module/surgeon
name = "surgeon robot module"
stacktypes = list(
/obj/item/stack/medical/advanced/bruise_pack = 5,
/obj/item/stack/nanopaste = 5
)
/obj/item/weapon/robot_module/surgeon/New()
..()
@@ -104,26 +79,34 @@
src.modules += new /obj/item/weapon/circular_saw(src)
src.modules += new /obj/item/weapon/surgicaldrill(src)
src.modules += new /obj/item/weapon/extinguisher/mini(src)
src.modules += new /obj/item/stack/medical/advanced/bruise_pack(src)
src.modules += new /obj/item/stack/nanopaste(src)
src.emag = new /obj/item/weapon/reagent_containers/spray(src)
src.emag.reagents.add_reagent("pacid", 250)
src.emag.name = "Polyacid spray"
var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(10000)
synths += medicine
var/obj/item/stack/nanopaste/N = new /obj/item/stack/nanopaste(src)
var/obj/item/stack/medical/advanced/bruise_pack/B = new /obj/item/stack/medical/advanced/bruise_pack(src)
N.uses_charge = 1
N.charge_costs = list(1000)
N.synths = list(medicine)
B.uses_charge = 1
B.charge_costs = list(1000)
B.synths = list(medicine)
src.modules += N
src.modules += B
return
/obj/item/weapon/robot_module/surgeon/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/surgeon/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/PS = src.emag
PS.reagents.add_reagent("pacid", 2)
PS.reagents.add_reagent("pacid", 2 * amount)
..()
/obj/item/weapon/robot_module/crisis
name = "crisis robot module"
stacktypes = list(
/obj/item/stack/medical/ointment = 5,
/obj/item/stack/medical/bruise_pack = 5,
/obj/item/stack/medical/splint = 5
)
/obj/item/weapon/robot_module/crisis/New()
..()
@@ -132,9 +115,6 @@
src.modules += new /obj/item/device/healthanalyzer(src)
src.modules += new /obj/item/device/reagent_scanner/adv(src)
src.modules += new /obj/item/roller_holder(src)
src.modules += new /obj/item/stack/medical/ointment(src)
src.modules += new /obj/item/stack/medical/bruise_pack(src)
src.modules += new /obj/item/stack/medical/splint(src)
src.modules += new /obj/item/weapon/reagent_containers/borghypo/crisis(src)
src.modules += new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
src.modules += new /obj/item/weapon/reagent_containers/robodropper(src)
@@ -143,9 +123,29 @@
src.emag = new /obj/item/weapon/reagent_containers/spray(src)
src.emag.reagents.add_reagent("pacid", 250)
src.emag.name = "Polyacid spray"
var/datum/matter_synth/medicine = new /datum/matter_synth/medicine(15000)
synths += medicine
var/obj/item/stack/medical/ointment/O = new /obj/item/stack/medical/ointment(src)
var/obj/item/stack/medical/bruise_pack/B = new /obj/item/stack/medical/bruise_pack(src)
var/obj/item/stack/medical/splint/S = new /obj/item/stack/medical/splint(src)
O.uses_charge = 1
O.charge_costs = list(1000)
O.synths = list(medicine)
B.uses_charge = 1
B.charge_costs = list(1000)
B.synths = list(medicine)
S.uses_charge = 1
S.charge_costs = list(1000)
S.synths = list(medicine)
src.modules += O
src.modules += B
src.modules += S
return
/obj/item/weapon/robot_module/crisis/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/crisis/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/weapon/reagent_containers/syringe/S = locate() in src.modules
if(S.mode == 2)
@@ -156,20 +156,13 @@
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/PS = src.emag
PS.reagents.add_reagent("pacid", 2)
PS.reagents.add_reagent("pacid", 2 * amount)
..()
/obj/item/weapon/robot_module/construction
name = "construction robot module"
stacktypes = list(
/obj/item/stack/sheet/metal = 50,
/obj/item/stack/sheet/plasteel = 10,
/obj/item/stack/sheet/glass/reinforced = 50,
/obj/item/stack/rods = 50
)
/obj/item/weapon/robot_module/construction/New()
..()
src.modules += new /obj/item/device/flash(src)
@@ -182,18 +175,32 @@
src.modules += new /obj/item/weapon/pickaxe/plasmacutter(src)
src.modules += new /obj/item/device/pipe_painter(src)
var/datum/matter_synth/metal = new /datum/matter_synth/metal()
var/datum/matter_synth/plasteel = new /datum/matter_synth/plasteel()
var/datum/matter_synth/glass = new /datum/matter_synth/glass()
synths += metal
synths += plasteel
synths += glass
var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src)
M.synths = list(metal)
src.modules += M
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/sheet/plasteel/cyborg/S = new /obj/item/stack/sheet/plasteel/cyborg(src)
S.synths = list(metal)
src.modules += S
var/obj/item/stack/sheet/glass/reinforced/cyborg/RG = new /obj/item/stack/sheet/glass/reinforced/cyborg(src)
RG.synths = list(metal, glass)
src.modules += R
/obj/item/weapon/robot_module/engineering
name = "engineering robot module"
stacktypes = list(
/obj/item/stack/sheet/metal = 50,
/obj/item/stack/sheet/glass = 50,
/obj/item/stack/sheet/glass/reinforced = 50,
/obj/item/stack/cable_coil/robot = 50,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15
)
/obj/item/weapon/robot_module/engineering/New()
..()
src.modules += new /obj/item/device/flash(src)
@@ -209,9 +216,45 @@
src.modules += new /obj/item/device/analyzer(src)
src.modules += new /obj/item/taperoll/engineering(src)
src.modules += new /obj/item/weapon/gripper(src)
src.modules += new /obj/item/weapon/matter_decompiler(src)
src.modules += new /obj/item/device/pipe_painter(src)
src.emag = new /obj/item/borg/stun(src)
var/datum/matter_synth/metal = new /datum/matter_synth/metal(40000)
var/datum/matter_synth/glass = new /datum/matter_synth/glass(40000)
var/datum/matter_synth/wire = new /datum/matter_synth/wire()
synths += metal
synths += glass
synths += wire
var/obj/item/weapon/matter_decompiler/MD = new /obj/item/weapon/matter_decompiler(src)
MD.metal = metal
MD.glass = glass
src.modules += MD
var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src)
M.synths = list(metal)
src.modules += M
var/obj/item/stack/sheet/glass/cyborg/G = new /obj/item/stack/sheet/glass/cyborg(src)
G.synths = list(glass)
src.modules += G
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
C.synths = list(wire)
src.modules += C
var/obj/item/stack/tile/plasteel/cyborg/S = new /obj/item/stack/tile/plasteel/cyborg(src)
S.synths = list(metal)
src.modules += S
var/obj/item/stack/sheet/glass/reinforced/cyborg/RG = new /obj/item/stack/sheet/glass/reinforced/cyborg(src)
RG.synths = list(metal, glass)
src.modules += RG
return
/obj/item/weapon/robot_module/security
@@ -228,7 +271,7 @@
src.emag = new /obj/item/weapon/gun/energy/laser/mounted(src)
return
/obj/item/weapon/robot_module/security/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/security/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/device/flash/F = locate() in src.modules
if(F.broken)
F.broken = 0
@@ -238,7 +281,7 @@
F.times_used--
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in src.modules
if(T.power_supply.charge < T.power_supply.maxcharge)
T.power_supply.give(T.charge_cost)
T.power_supply.give(T.charge_cost * amount)
T.update_icon()
else
T.charge_tick = 0
@@ -258,12 +301,12 @@
src.emag.name = "Lube spray"
return
/obj/item/weapon/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/janitor/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/device/lightreplacer/LR = locate() in src.modules
LR.Charge(R)
LR.Charge(R, amount)
if(src.emag)
var/obj/item/weapon/reagent_containers/spray/S = src.emag
S.reagents.add_reagent("lube", 2)
S.reagents.add_reagent("lube", 2 * amount)
/obj/item/weapon/robot_module/butler
name = "service robot module"
@@ -327,12 +370,12 @@
R.add_language("Tradeband", 1)
R.add_language("Gutter", 1)
/obj/item/weapon/robot_module/butler/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/butler/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/weapon/reagent_containers/food/condiment/enzyme/E = locate() in src.modules
E.reagents.add_reagent("enzyme", 2)
E.reagents.add_reagent("enzyme", 2 * amount)
if(src.emag)
var/obj/item/weapon/reagent_containers/food/drinks/cans/beer/B = src.emag
B.reagents.add_reagent("beer2", 2)
B.reagents.add_reagent("beer2", 2 * amount)
/obj/item/weapon/robot_module/miner
name = "miner robot module"
@@ -392,17 +435,6 @@
/obj/item/weapon/robot_module/drone
name = "drone module"
stacktypes = list(
/obj/item/stack/sheet/wood = 1,
/obj/item/stack/sheet/mineral/plastic = 1,
/obj/item/stack/sheet/glass/reinforced = 5,
/obj/item/stack/tile/wood = 5,
/obj/item/stack/rods = 15,
/obj/item/stack/tile/plasteel = 15,
/obj/item/stack/sheet/metal = 20,
/obj/item/stack/sheet/glass = 20,
/obj/item/stack/cable_coil/robot = 30
)
/obj/item/weapon/robot_module/drone/New()
..()
@@ -414,20 +446,73 @@
src.modules += new /obj/item/device/multitool(src)
src.modules += new /obj/item/device/lightreplacer(src)
src.modules += new /obj/item/weapon/gripper(src)
src.modules += new /obj/item/weapon/matter_decompiler(src)
src.modules += new /obj/item/weapon/reagent_containers/spray/cleaner/drone(src)
src.emag = new /obj/item/weapon/pickaxe/plasmacutter(src)
src.emag.name = "Plasma Cutter"
var/datum/matter_synth/metal = new /datum/matter_synth/metal(25000)
var/datum/matter_synth/glass = new /datum/matter_synth/glass(25000)
var/datum/matter_synth/wood = new /datum/matter_synth/wood(2000)
var/datum/matter_synth/plastic = new /datum/matter_synth/plastic(1000)
var/datum/matter_synth/wire = new /datum/matter_synth/wire(30)
synths += metal
synths += glass
synths += wood
synths += plastic
synths += wire
var/obj/item/weapon/matter_decompiler/MD = new /obj/item/weapon/matter_decompiler(src)
MD.metal = metal
MD.glass = glass
MD.wood = wood
MD.plastic = plastic
src.modules += MD
var/obj/item/stack/sheet/metal/cyborg/M = new /obj/item/stack/sheet/metal/cyborg(src)
M.synths = list(metal)
src.modules += M
var/obj/item/stack/sheet/glass/cyborg/G = new /obj/item/stack/sheet/glass/cyborg(src)
G.synths = list(glass)
src.modules += G
var/obj/item/stack/rods/cyborg/R = new /obj/item/stack/rods/cyborg(src)
R.synths = list(metal)
src.modules += R
var/obj/item/stack/cable_coil/cyborg/C = new /obj/item/stack/cable_coil/cyborg(src)
C.synths = list(wire)
src.modules += C
var/obj/item/stack/tile/plasteel/cyborg/S = new /obj/item/stack/tile/plasteel/cyborg(src)
S.synths = list(metal)
src.modules += S
var/obj/item/stack/sheet/glass/reinforced/cyborg/RG = new /obj/item/stack/sheet/glass/reinforced/cyborg(src)
RG.synths = list(metal, glass)
src.modules += RG
var/obj/item/stack/tile/wood/cyborg/WT = new /obj/item/stack/tile/wood/cyborg(src)
WT.synths = list(wood)
src.modules += WT
var/obj/item/stack/sheet/wood/cyborg/W = new /obj/item/stack/sheet/wood/cyborg(src)
W.synths = list(wood)
src.modules += W
var/obj/item/stack/sheet/mineral/plastic/cyborg/P = new /obj/item/stack/sheet/mineral/plastic/cyborg(src)
P.synths = list(plastic)
src.modules += P
/obj/item/weapon/robot_module/drone/add_languages(var/mob/living/silicon/robot/R)
return //not much ROM to spare in that tiny microprocessor!
/obj/item/weapon/robot_module/drone/respawn_consumable(var/mob/living/silicon/robot/R)
/obj/item/weapon/robot_module/drone/respawn_consumable(var/mob/living/silicon/robot/R, var/amount)
var/obj/item/weapon/reagent_containers/spray/cleaner/C = locate() in src.modules
C.reagents.add_reagent("cleaner", 3)
C.reagents.add_reagent("cleaner", 3 * amount)
var/obj/item/device/lightreplacer/LR = locate() in src.modules
LR.Charge(R)
LR.Charge(R, amount)
..()
return

View File

@@ -18,6 +18,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/mob/living/simple_animal/mouse/movement_target
var/mob/flee_target
min_oxy = 16 //Require atleast 16kPA oxygen
minbodytemp = 223 //Below -50 Degrees Celcius
maxbodytemp = 323 //Above 50 Degrees Celcius
@@ -44,27 +45,71 @@
break
if(!stat && !resting && !buckled)
handle_movement_target()
turns_since_scan++
if (turns_since_scan > 5)
walk_to(src,0)
turns_since_scan = 0
if (flee_target) //fleeing takes precendence
handle_flee_target()
else
handle_movement_target()
/mob/living/simple_animal/cat/proc/handle_movement_target()
turns_since_scan++
if(turns_since_scan > 5)
walk_to(src,0)
turns_since_scan = 0
/mob/living/simple_animal/cat/proc/handle_movement_target()
//if our target is neither inside a turf or inside a human(???), stop
if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) ))
movement_target = null
stop_automated_movement = 0
//if we have no target or our current one is out of sight/too far away
if( !movement_target || !(movement_target.loc in oview(src, 4)) )
movement_target = null
stop_automated_movement = 0
for(var/mob/living/simple_animal/mouse/snack in oview(src)) //search for a new target
if(isturf(snack.loc) && !snack.stat)
movement_target = snack
break
if(movement_target)
stop_automated_movement = 1
walk_to(src,movement_target,0,3)
if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) ))
movement_target = null
stop_automated_movement = 0
if( !movement_target || !(movement_target.loc in oview(src, 4)) )
movement_target = null
stop_automated_movement = 0
for(var/mob/living/simple_animal/mouse/snack in oview(src))
if(isturf(snack.loc) && !snack.stat)
movement_target = snack
break
if(movement_target)
stop_automated_movement = 1
walk_to(src,movement_target,0,3)
/mob/living/simple_animal/cat/proc/handle_flee_target()
//see if we should stop fleeing
if (flee_target && !(flee_target.loc in view(src)))
flee_target = null
stop_automated_movement = 0
if (flee_target)
if(prob(25)) say("HSSSSS")
stop_automated_movement = 1
walk_away(src, flee_target, 7, 2)
/mob/living/simple_animal/cat/proc/set_flee_target(atom/A)
if(A)
flee_target = A
turns_since_scan = 5
/mob/living/simple_animal/cat/attackby(var/obj/item/O, var/mob/user)
. = ..()
if(O.force)
set_flee_target(user? user : src.loc)
/mob/living/simple_animal/cat/attack_hand(mob/living/carbon/human/M as mob)
. = ..()
if(M.a_intent == "hurt")
set_flee_target(M)
/mob/living/simple_animal/cat/ex_act()
. = ..()
set_flee_target(src.loc)
/mob/living/simple_animal/cat/bullet_act(var/obj/item/projectile/proj)
. = ..()
set_flee_target(proj.firer? proj.firer : src.loc)
/mob/living/simple_animal/cat/hitby(atom/movable/AM)
. = ..()
set_flee_target(AM.thrower? AM.thrower : src.loc)
/mob/living/simple_animal/cat/MouseDrop(atom/over_object)
@@ -82,14 +127,91 @@
return //since the holder icon looks like a living cat
..()
//Basic friend AI
/mob/living/simple_animal/cat/fluff
var/mob/living/carbon/human/friend
var/befriend_job = null
/mob/living/simple_animal/cat/fluff/handle_movement_target()
if (friend)
var/follow_dist = 5
if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit) //danger
follow_dist = 1
else if (friend.stat || friend.health <= 50) //danger or just sleeping
follow_dist = 2
var/near_dist = max(follow_dist - 2, 1)
var/current_dist = get_dist(src, friend)
if (movement_target != friend)
if (current_dist > follow_dist && !istype(movement_target, /mob/living/simple_animal/mouse) && (friend in oview(src)))
//stop existing movement
walk_to(src,0)
turns_since_scan = 0
//walk to friend
stop_automated_movement = 1
movement_target = friend
walk_to(src, movement_target, near_dist, 4)
//already following and close enough, stop
else if (current_dist <= near_dist)
walk_to(src,0)
movement_target = null
stop_automated_movement = 0
if (prob(10))
say("Meow!")
if (!friend || movement_target != friend)
..()
/mob/living/simple_animal/cat/fluff/Life()
..()
if (stat || !friend)
return
if (get_dist(src, friend) <= 1)
if (friend.stat >= DEAD || friend.health <= config.health_threshold_softcrit)
if (prob((friend.stat < DEAD)? 50 : 15))
var/verb = pick("meows", "mews", "mrowls")
audible_emote(pick("[verb] in distress.", "[verb] anxiously."))
else
if (prob(5))
visible_emote(pick("nuzzles [friend].",
"brushes against [friend].",
"rubs against [friend].",
"purrs."))
else if (friend.health <= 50)
if (prob(10))
var/verb = pick("meows", "mews", "mrowls")
audible_emote("[verb] anxiously.")
/mob/living/simple_animal/cat/fluff/verb/friend()
set name = "Become Friends"
set category = "IC"
set src in view(1)
if(friend && usr == friend)
set_dir(get_dir(src, friend))
say("Meow!")
return
if (!(ishuman(usr) && befriend_job && usr.job == befriend_job))
usr << "<span class='notice'>[src] ignores you.</span>"
return
friend = usr
set_dir(get_dir(src, friend))
say("Meow!")
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/cat/Runtime
/mob/living/simple_animal/cat/fluff/Runtime
name = "Runtime"
desc = "Her fur has the look and feel of velvet, and her tail quivers occasionally."
gender = FEMALE
icon_state = "cat"
icon_living = "cat"
icon_dead = "cat_dead"
befriend_job = "Chief Medical Officer"
/mob/living/simple_animal/cat/kitten
name = "kitten"
@@ -97,4 +219,8 @@
icon_state = "kitten"
icon_living = "kitten"
icon_dead = "kitten_dead"
gender = NEUTER
gender = NEUTER
/mob/living/simple_animal/cat/kitten/New()
gender = pick(MALE, FEMALE)
..()

View File

@@ -265,7 +265,7 @@
adjustBruteLoss(-medical_pack.heal_brute)
visible_message("<span class='warning'>\The [user] applies the [medical_pack] to \the [src].</span>")
else
user << "<span class='warning'>\The [src] cannot benefit from medical items in its current state.</span>"
user << "<span class='warning'>\The [src] cannot benefit from medical items in \his current state.</span>"
return
else if(istype(O, /obj/item/weapon/kitchenknife) || istype(O, /obj/item/weapon/butch))

View File

@@ -183,7 +183,7 @@ var/list/slot_equipment_priority = list( \
if(!istype(W)) return 0
for(var/slot in slot_equipment_priority)
if(equip_to_slot_if_possible(W, slot, 0, 1, 1)) //del_on_fail = 0; disable_warning = 0; redraw_mob = 1
if(equip_to_slot_if_possible(W, slot, del_on_fail=0, disable_warning=1, redraw_mob=1))
return 1
return 0
@@ -836,6 +836,7 @@ note dizziness decrements automatically in the mob's Life() proc.
// facing verbs
/mob/proc/canface()
if(!canmove) return 0
@@ -867,7 +868,7 @@ note dizziness decrements automatically in the mob's Life() proc.
else if( stat || weakened || paralysis || resting || sleeping || (status_flags & FAKEDEATH))
lying = 1
canmove = 0
else if( stunned )
else if(stunned)
canmove = 0
else if(captured)
anchored = 1
@@ -884,6 +885,11 @@ note dizziness decrements automatically in the mob's Life() proc.
else
density = 1
for(var/obj/item/weapon/grab/G in grabbed_by)
if(G.state >= GRAB_AGGRESSIVE)
canmove = 0
break
//Temporarily moved here from the various life() procs
//I'm fixing stuff incrementally so this will likely find a better home.
//It just makes sense for now. ~Carn

View File

@@ -121,7 +121,7 @@
var/m_int = null//Living
var/m_intent = "run"//Living
var/lastKnownIP = null
var/obj/structure/stool/bed/buckled = null//Living
var/obj/structure/bed/buckled = null//Living
var/obj/item/l_hand = null//Living
var/obj/item/r_hand = null//Living
var/obj/item/weapon/back = null//Human/Monkey
@@ -223,3 +223,5 @@
var/list/shouldnt_see = list() //list of objects that this mob shouldn't see in the stat panel. this silliness is needed because of AI alt+click and cult blood runes
var/list/active_genes=list()

View File

@@ -35,6 +35,10 @@
hud.name = "reinforce grab"
hud.master = src
/obj/item/weapon/grab/Del()
//make sure the grabbed_by list doesn't fill up with nulls
if(affecting) affecting.grabbed_by -= src
..()
//Used by throw code to hand over the mob, instead of throwing the grab. The grab is then deleted by the throw code.
/obj/item/weapon/grab/proc/throw()
@@ -67,6 +71,7 @@
if(state <= GRAB_AGGRESSIVE)
allow_upgrade = 1
//disallow upgrading if we're grabbing more than one person
if((assailant.l_hand && assailant.l_hand != src && istype(assailant.l_hand, /obj/item/weapon/grab)))
var/obj/item/weapon/grab/G = assailant.l_hand
if(G.affecting != affecting)
@@ -76,31 +81,29 @@
if(G.affecting != affecting)
allow_upgrade = 0
if(state == GRAB_AGGRESSIVE)
var/h = affecting.hand
affecting.hand = 0
affecting.drop_item()
affecting.hand = 1
affecting.drop_item()
affecting.hand = h
affecting.drop_l_hand()
affecting.drop_r_hand()
//disallow upgrading past aggressive if we're being grabbed aggressively
for(var/obj/item/weapon/grab/G in affecting.grabbed_by)
if(G == src) continue
if(G.state == GRAB_AGGRESSIVE)
if(G.state >= GRAB_AGGRESSIVE)
allow_upgrade = 0
if(allow_upgrade)
hud.icon_state = "reinforce"
else
hud.icon_state = "!reinforce"
else
if(!affecting.buckled)
affecting.loc = assailant.loc
else if(!affecting.buckled)
affecting.loc = assailant.loc
if(state >= GRAB_NECK)
affecting.Stun(5) //It will hamper your voice, being choked and all.
affecting.Stun(1)
if(isliving(affecting))
var/mob/living/L = affecting
L.adjustOxyLoss(1)
if(state >= GRAB_KILL)
//affecting.apply_effect(STUTTER, 5) //would do this, but affecting isn't declared as mob/living for some stupid reason.
affecting.stuttering = max(affecting.stuttering, 5) //It will hamper your voice, being choked and all.
affecting.Weaken(5) //Should keep you down unless you get help.
affecting.losebreath = min(affecting.losebreath + 2, 3)
@@ -126,48 +129,46 @@
assailant.visible_message("<span class='warning'>[assailant] has grabbed [affecting] aggressively (now hands)!</span>")
state = GRAB_AGGRESSIVE
icon_state = "grabbed1"
else
if(state < GRAB_NECK)
if(isslime(affecting))
assailant << "<span class='notice'>You squeeze [affecting], but nothing interesting happens.</span>"
else if(state < GRAB_NECK)
if(isslime(affecting))
assailant << "<span class='notice'>You squeeze [affecting], but nothing interesting happens.</span>"
return
assailant.visible_message("<span class='warning'>[assailant] has reinforced \his grip on [affecting] (now neck)!</span>")
state = GRAB_NECK
icon_state = "grabbed+1"
if(!affecting.buckled)
affecting.loc = assailant.loc
affecting.attack_log += "\[[time_stamp()]\] <font color='orange'>Has had their neck grabbed by [assailant.name] ([assailant.ckey])</font>"
assailant.attack_log += "\[[time_stamp()]\] <font color='red'>Grabbed the neck of [affecting.name] ([affecting.ckey])</font>"
msg_admin_attack("[key_name(assailant)] grabbed the neck of [key_name(affecting)]")
hud.icon_state = "disarm/kill"
hud.name = "disarm/kill"
else if(state < GRAB_UPGRADING)
assailant.visible_message("<span class='danger'>[assailant] starts to tighten \his grip on [affecting]'s neck!</span>")
hud.icon_state = "disarm/kill1"
state = GRAB_UPGRADING
if(do_after(assailant, UPGRADE_KILL_TIMER))
if(state == GRAB_KILL)
return
if(!affecting)
del(src)
return
if(!assailant.canmove || assailant.lying)
del(src)
return
state = GRAB_KILL
assailant.visible_message("<span class='danger'>[assailant] has tightened \his grip on [affecting]'s neck!</span>")
affecting.attack_log += "\[[time_stamp()]\] <font color='orange'>Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])</font>"
assailant.attack_log += "\[[time_stamp()]\] <font color='red'>Strangled (kill intent) [affecting.name] ([affecting.ckey])</font>"
msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]")
assailant.visible_message("<span class='warning'>[assailant] has reinforced \his grip on [affecting] (now neck)!</span>")
state = GRAB_NECK
icon_state = "grabbed+1"
if(!affecting.buckled)
affecting.loc = assailant.loc
affecting.attack_log += "\[[time_stamp()]\] <font color='orange'>Has had their neck grabbed by [assailant.name] ([assailant.ckey])</font>"
assailant.attack_log += "\[[time_stamp()]\] <font color='red'>Grabbed the neck of [affecting.name] ([affecting.ckey])</font>"
msg_admin_attack("[key_name(assailant)] grabbed the neck of [key_name(affecting)]")
hud.icon_state = "disarm/kill"
hud.name = "disarm/kill"
assailant.next_move = world.time + 10
affecting.losebreath += 1
else
if(state < GRAB_UPGRADING)
assailant.visible_message("<span class='danger'>[assailant] starts to tighten \his grip on [affecting]'s neck!</span>")
hud.icon_state = "disarm/kill1"
state = GRAB_UPGRADING
if(do_after(assailant, UPGRADE_KILL_TIMER))
if(state == GRAB_KILL)
return
if(!affecting)
del(src)
return
if(!assailant.canmove || assailant.lying)
del(src)
return
state = GRAB_KILL
assailant.visible_message("<span class='danger'>[assailant] has tightened \his grip on [affecting]'s neck!</span>")
affecting.attack_log += "\[[time_stamp()]\] <font color='orange'>Has been strangled (kill intent) by [assailant.name] ([assailant.ckey])</font>"
assailant.attack_log += "\[[time_stamp()]\] <font color='red'>Strangled (kill intent) [affecting.name] ([affecting.ckey])</font>"
msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]")
assailant.next_move = world.time + 10
affecting.losebreath += 1
else
assailant.visible_message("<span class='warning'>[assailant] was unable to tighten \his grip on [affecting]'s neck!</span>")
hud.icon_state = "disarm/kill"
state = GRAB_NECK
assailant.visible_message("<span class='warning'>[assailant] was unable to tighten \his grip on [affecting]'s neck!</span>")
hud.icon_state = "disarm/kill"
state = GRAB_NECK
//This is used to make sure the victim hasn't managed to yackety sax away before using the grab.

View File

@@ -80,6 +80,18 @@
return 1
return 0
/mob/proc/isSilicon()
return 0
/mob/living/silicon/isSilicon()
return 1
/mob/proc/isAI()
return 0
/mob/living/silicon/ai/isAI()
return 1
/proc/ispAI(A)
if(istype(A, /mob/living/silicon/pai))
return 1

View File

@@ -284,9 +284,9 @@
if(mob.pulledby || mob.buckled) // Wheelchair driving!
if(istype(mob.loc, /turf/space))
return // No wheelchair driving in space
if(istype(mob.pulledby, /obj/structure/stool/bed/chair/wheelchair))
if(istype(mob.pulledby, /obj/structure/bed/chair/wheelchair))
return mob.pulledby.relaymove(mob, direct)
else if(istype(mob.buckled, /obj/structure/stool/bed/chair/wheelchair))
else if(istype(mob.buckled, /obj/structure/bed/chair/wheelchair))
if(ishuman(mob.buckled))
var/mob/living/carbon/human/driver = mob.buckled
var/datum/organ/external/l_hand = driver.get_organ("l_hand")
@@ -351,30 +351,13 @@
///Process_Grab()
///Called by client/Move()
///Checks to see if you are being grabbed and if so attemps to break it
///Checks to see if you are grabbing anything and if moving will affect your grab.
/client/proc/Process_Grab()
if(locate(/obj/item/weapon/grab, locate(/obj/item/weapon/grab, mob.grabbed_by.len)))
var/list/grabbing = list()
if(istype(mob.l_hand, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = mob.l_hand
grabbing += G.affecting
if(istype(mob.r_hand, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = mob.r_hand
grabbing += G.affecting
for(var/obj/item/weapon/grab/G in mob.grabbed_by)
if((G.state == 1)&&(!grabbing.Find(G.assailant))) del(G)
if(G.state == 2)
move_delay = world.time + 10
if(!prob(25)) return 1
mob.visible_message("\red [mob] has broken free of [G.assailant]'s grip!")
del(G)
if(G.state == 3)
move_delay = world.time + 10
if(!prob(5)) return 1
mob.visible_message("\red [mob] has broken free of [G.assailant]'s headlock!")
del(G)
return 0
for(var/obj/item/weapon/grab/G in list(mob.l_hand, mob.r_hand))
if(G.state == GRAB_KILL) //no wandering across the station/asteroid while choking someone
mob.visible_message("<span class='warning'>[mob] lost \his tight grip on [G.affecting]'s neck!</span>")
G.hud.icon_state = "disarm/kill"
G.state = GRAB_NECK
///Process_Incorpmove
///Called by client/Move()

View File

@@ -352,7 +352,7 @@
character.lastarea = get_area(loc)
// Moving wheelchair if they have one
if(character.buckled && istype(character.buckled, /obj/structure/stool/bed/chair/wheelchair))
if(character.buckled && istype(character.buckled, /obj/structure/bed/chair/wheelchair))
character.buckled.loc = character.loc
character.buckled.set_dir(character.dir)

View File

@@ -1,5 +1,5 @@
// This file contains all Nano procs/definitions for external classes/objects
// This file contains all Nano procs/definitions for external classes/objects
/**
* Called when a Nano UI window is closed
* This is how Nano handles closed windows
@@ -15,7 +15,7 @@
if (istype(ui))
ui.close()
if(ui.ref)
var/href = "close=1"
src.Topic(href, params2list(href), ui.ref) // this will direct to the atom's Topic() proc via client.Topic()
@@ -31,14 +31,14 @@
* ui_interact is currently defined for /atom/movable
*
* @param user /mob The mob who is interacting with this ui
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
* @param ui_key string A string key to use for this ui. Allows for multiple unique uis on one obj/mob (defaut value "main")
* @param ui /datum/nanoui This parameter is passed by the nanoui process() proc when updating an open ui
* @param force_open boolean Force the UI to (re)open, even if it's already open
*
* @return nothing
*/
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/atom/movable/proc/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/nano_ui/master_ui = null, var/datum/topic_state/custom_state = null)
return
// Used by the Nano UI Manager (/datum/nanomanager) to track UIs opened by this mob
/mob/var/list/open_uis = list()

View File

@@ -0,0 +1,127 @@
/atom/movable/proc/nano_host()
return src
/obj/nano_module/nano_host()
return loc
/atom/movable/proc/CanUseTopic(var/mob/user, href_list, var/datum/topic_state/custom_state)
return user.can_use_topic(nano_host(), custom_state)
/mob/proc/can_use_topic(var/mob/user, var/datum/topic_state/custom_state)
return STATUS_CLOSE // By default no mob can do anything with NanoUI
/mob/dead/observer/can_use_topic()
if(check_rights(R_ADMIN, 0))
return STATUS_INTERACTIVE // Admins are more equal
return STATUS_UPDATE // Ghosts can view updates
/mob/living/silicon/pai/can_use_topic(var/src_object)
if(src_object == src && !stat)
return STATUS_INTERACTIVE
else
return ..()
/mob/living/silicon/robot/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
if(stat || !client)
return STATUS_CLOSE
if(lockcharge || stunned || weakened)
return STATUS_DISABLED
// robots can interact with things they can see within their view range
if(!(custom_state.flags & NANO_IGNORE_DISTANCE) && (src_object in view(src)))
return STATUS_INTERACTIVE // interactive (green visibility)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
/mob/living/silicon/robot/syndicate/can_use_topic(var/src_object)
. = ..()
if(. != STATUS_INTERACTIVE)
return
if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level
return STATUS_INTERACTIVE
if(istype(get_area(src), /area/syndicate_station)) // If elsewhere, they can interact with everything on the syndicate shuttle
return STATUS_INTERACTIVE
if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery
var/obj/machinery/Machine = src_object
if(Machine.emagged)
return STATUS_INTERACTIVE
return STATUS_UPDATE
/mob/living/silicon/ai/can_use_topic(var/src_object)
if(!client || check_unable(1))
return STATUS_CLOSE
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
if(!T || !(z == T.z || (T.z in config.player_levels)))
return STATUS_CLOSE
// If an object is in view then we can interact with it
if(src_object in view(client.view, src))
return STATUS_INTERACTIVE
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
if(is_in_chassis())
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
return STATUS_INTERACTIVE
return STATUS_CLOSE
/mob/living/proc/shared_living_nano_interaction(var/src_object)
if (src.stat != CONSCIOUS)
return STATUS_CLOSE // no updates, close the interface
else if (restrained() || lying || stat || stunned || weakened)
return STATUS_UPDATE // update only (orange visibility)
return STATUS_INTERACTIVE
//Some atoms such as vehicles might have special rules for how mobs inside them interact with NanoUI.
/atom/proc/contents_nano_distance(var/src_object, var/mob/living/user)
return user.shared_living_nano_distance(src_object)
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
if(!isturf(src_object.loc))
if(src_object.loc == src) // Item in the inventory
return STATUS_INTERACTIVE
if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item
return STATUS_INTERACTIVE
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
return STATUS_CLOSE
var/dist = get_dist(src_object, src)
if (dist <= 1)
return STATUS_INTERACTIVE // interactive (green visibility)
else if (dist <= 2)
return STATUS_UPDATE // update only (orange visibility)
else if (dist <= 4)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
return STATUS_CLOSE
/mob/living/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE))
if(loc)
. = loc.contents_nano_distance(src_object, src)
else
. = shared_living_nano_distance(src_object)
if(STATUS_INTERACTIVE)
return STATUS_UPDATE
/mob/living/carbon/human/can_use_topic(var/src_object, var/datum/topic_state/custom_state)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && !(custom_state.flags & NANO_IGNORE_DISTANCE))
. = shared_living_nano_distance(src_object)
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
return STATUS_INTERACTIVE
/var/global/datum/topic_state/default_state = new()
/datum/topic_state
var/flags = 0
/datum/topic_state/proc/href_list(var/mob/user)
return list()

View File

@@ -186,7 +186,8 @@
return 0 // wasn't open
processing_uis.Remove(ui)
ui.user.open_uis.Remove(ui)
if(ui.user) // Sanity check in case a user has been deleted (say a blown up borg watching the alarm interface)
ui.user.open_uis.Remove(ui)
var/list/uis = open_uis[src_object_key][ui.ui_key]
uis.Remove(ui)

View File

@@ -1,11 +0,0 @@
/atom/movable/proc/nano_host()
return src
/obj/nano_module/nano_host()
return loc
/atom/movable/proc/nano_can_update()
return 1
/obj/machinery/nano_can_update()
return !(stat & (NOPOWER|BROKEN))

View File

@@ -52,6 +52,11 @@ nanoui is used to open and update nano browser uis
// the current status/visibility of the ui
var/status = STATUS_INTERACTIVE
// Relationship between a master interface and its children. Used in update_status
var/datum/nanoui/master_ui
var/list/datum/nanoui/children = list()
var/datum/topic_state/custom_state = null
var/cached_data = null
/**
@@ -68,17 +73,22 @@ nanoui is used to open and update nano browser uis
*
* @return /nanoui new nanoui object
*/
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
/datum/nanoui/New(nuser, nsrc_object, nui_key, ntemplate_filename, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null, var/datum/nanoui/master_ui = null, var/datum/topic_state/custom_state = null)
user = nuser
src_object = nsrc_object
ui_key = nui_key
window_id = "[ui_key]\ref[src_object]"
src.master_ui = master_ui
if(master_ui)
master_ui.children += src
src.custom_state = custom_state ? custom_state : new/datum/topic_state()
// add the passed template filename as the "main" template, this is required
add_template("main", ntemplate_filename)
if (ntitle)
title = ntitle
title = sanitize(ntitle)
if (nwidth)
width = nwidth
if (nheight)
@@ -133,120 +143,13 @@ nanoui is used to open and update nano browser uis
*/
/datum/nanoui/proc/update_status(var/push_update = 0)
var/atom/movable/host = src_object.nano_host()
if(!host.nano_can_update())
close()
return
var/status = user.can_interact_with_interface(host.nano_host())
if(status == STATUS_CLOSE)
var/new_status = host.CanUseTopic(user, list(), custom_state)
if(master_ui)
new_status = min(new_status, master_ui.status)
if(new_status == STATUS_CLOSE)
close()
else
set_status(status, push_update)
/*
Procs called by update_status()
*/
/mob/living/silicon/pai/can_interact_with_interface(src_object)
if(src_object == src && !stat)
return STATUS_INTERACTIVE
else
return ..()
/mob/proc/can_interact_with_interface(var/src_object)
return STATUS_CLOSE // By default no mob can do anything with NanoUI
/mob/dead/observer/can_interact_with_interface()
if(check_rights(R_ADMIN, 0))
return STATUS_INTERACTIVE // Admins are more equal
return STATUS_UPDATE // Ghosts can view updates
/mob/living/silicon/robot/can_interact_with_interface(var/src_object)
if(stat || !client)
return STATUS_CLOSE
if(lockcharge || stunned || weakened)
return STATUS_DISABLED
if (src_object in view(client.view, src)) // robots can see and interact with things they can see within their view range
return STATUS_INTERACTIVE // interactive (green visibility)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
/mob/living/silicon/robot/syndicate/can_interact_with_interface(var/src_object)
. = ..()
if(. != STATUS_INTERACTIVE)
return
if(z in config.admin_levels) // Syndicate borgs can interact with everything on the admin level
return STATUS_INTERACTIVE
if(istype(get_area(src), /area/syndicate_station)) // If elsewhere, they can interact with everything on the syndicate shuttle
return STATUS_INTERACTIVE
if(istype(src_object, /obj/machinery)) // Otherwise they can only interact with emagged machinery
var/obj/machinery/Machine = src_object
if(Machine.emagged)
return STATUS_INTERACTIVE
return STATUS_UPDATE
/mob/living/silicon/ai/can_interact_with_interface(var/src_object)
if(!client || check_unable(1))
return STATUS_CLOSE
// Prevents the AI from using Topic on admin levels (by for example viewing through the court/thunderdome cameras)
// unless it's on the same level as the object it's interacting with.
var/turf/T = get_turf(src_object)
if(!T || !(z == T.z || (T.z in config.player_levels)))
return STATUS_CLOSE
// If an object is in view then we can interact with it
if(src_object in view(client.view, src))
return STATUS_INTERACTIVE
// If we're installed in a chassi, rather than transfered to an inteliCard or other container, then check if we have camera view
if(is_in_chassis())
//stop AIs from leaving windows open and using then after they lose vision
//apc_override is needed here because AIs use their own APC when powerless
if(cameranet && !cameranet.checkTurfVis(get_turf(src_object)))
return apc_override ? STATUS_INTERACTIVE : STATUS_CLOSE
return STATUS_INTERACTIVE
return STATUS_CLOSE
/mob/living/proc/shared_living_nano_interaction(var/src_object)
if (src.stat != CONSCIOUS)
return STATUS_CLOSE // no updates, close the interface
else if (restrained() || lying || stat || stunned || weakened)
return STATUS_UPDATE // update only (orange visibility)
return STATUS_INTERACTIVE
/mob/living/proc/shared_living_nano_distance(var/atom/movable/src_object)
if(!isturf(src_object.loc))
if(src_object.loc == src) // Item in the inventory
return STATUS_INTERACTIVE
if(src.contents.Find(src_object.loc)) // A hidden uplink inside an item
return STATUS_INTERACTIVE
if (!(src_object in view(4, src))) // If the src object is not in visable, disable updates
return STATUS_CLOSE
var/dist = get_dist(src_object, src)
if (dist <= 1)
return STATUS_INTERACTIVE // interactive (green visibility)
else if (dist <= 2)
return STATUS_UPDATE // update only (orange visibility)
else if (dist <= 4)
return STATUS_DISABLED // no updates, completely disabled (red visibility)
return STATUS_CLOSE
/mob/living/can_interact_with_interface(var/src_object, var/be_close = 1)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && be_close)
. = shared_living_nano_distance(src_object)
if(STATUS_INTERACTIVE)
return STATUS_UPDATE
/mob/living/carbon/human/can_interact_with_interface(var/src_object, var/be_close = 1)
. = shared_living_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE && be_close)
. = shared_living_nano_distance(src_object)
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
return STATUS_INTERACTIVE
set_status(new_status, push_update)
/**
* Set the ui to auto update (every master_controller tick)
@@ -489,7 +392,6 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/open()
var/window_size = ""
if (width && height)
window_size = "size=[width]x[height];"
@@ -509,6 +411,8 @@ nanoui is used to open and update nano browser uis
is_auto_updating = 0
nanomanager.ui_closed(src)
user << browse(null, "window=[window_id]")
for(var/datum/nanoui/child in children)
child.close()
/**
* Set the UI window to call the nanoclose verb when the window is closed
@@ -573,7 +477,7 @@ nanoui is used to open and update nano browser uis
set_map_z_level(text2num(href_list["mapZLevel"]))
map_update = 1
if ((src_object && src_object.Topic(href, href_list)) || map_update)
if ((src_object && src_object.Topic(href, href_list, 0, custom_state)) || map_update)
nanomanager.update_uis(src_object) // update all UIs attached to src_object
/**
@@ -600,5 +504,4 @@ nanoui is used to open and update nano browser uis
* @return nothing
*/
/datum/nanoui/proc/update(var/force_open = 0)
src_object.ui_interact(user, ui_key, src, force_open)
src_object.ui_interact(user, ui_key, src, force_open, master_ui, custom_state)

View File

@@ -112,7 +112,7 @@
stance_damage = 0
// Buckled to a bed/chair. Stance damage is forced to 0 since they're sitting on something solid
if (istype(buckled, /obj/structure/stool/bed))
if (istype(buckled, /obj/structure/bed))
return
for (var/organ in list("l_leg","l_foot","r_leg","r_foot"))

View File

@@ -596,14 +596,11 @@ Note that amputating the affected organ does in fact remove the infection from t
update_damages()
var/obj/organ //Dropped limb object
var/list/dropped_items
switch(body_part)
if(HEAD)
organ= new /obj/item/weapon/organ/head(owner.loc, owner)
owner.u_equip(owner.glasses)
owner.u_equip(owner.head)
owner.u_equip(owner.l_ear)
owner.u_equip(owner.r_ear)
owner.u_equip(owner.wear_mask)
organ = new /obj/item/weapon/organ/head(owner.loc, owner)
dropped_items = list(owner.glasses, owner.head, owner.l_ear, owner.r_ear, owner.wear_mask)
if(ARM_RIGHT)
if(status & ORGAN_ROBOT)
organ = new /obj/item/robot_parts/r_arm(owner.loc)
@@ -627,19 +624,22 @@ Note that amputating the affected organ does in fact remove the infection from t
if(HAND_RIGHT)
if(!(status & ORGAN_ROBOT))
organ= new /obj/item/weapon/organ/r_hand(owner.loc, owner)
owner.u_equip(owner.gloves)
dropped_items = list(owner.gloves) //should probably make it so that you can still wear gloves if you have one hand
if(HAND_LEFT)
if(!(status & ORGAN_ROBOT))
organ= new /obj/item/weapon/organ/l_hand(owner.loc, owner)
owner.u_equip(owner.gloves)
dropped_items = list(owner.gloves)
if(FOOT_RIGHT)
if(!(status & ORGAN_ROBOT))
organ= new /obj/item/weapon/organ/r_foot/(owner.loc, owner)
owner.u_equip(owner.shoes)
dropped_items = list(owner.shoes)
if(FOOT_LEFT)
if(!(status & ORGAN_ROBOT))
organ = new /obj/item/weapon/organ/l_foot(owner.loc, owner)
owner.u_equip(owner.shoes)
dropped_items = list(owner.shoes)
if(dropped_items)
for(var/obj/O in dropped_items)
owner.remove_from_mob(O)
destspawn = 1
//Robotic limbs explode if sabotaged.

View File

@@ -482,8 +482,17 @@ obj/structure/cable/proc/cableColor(var/colorC)
item_state = "coil"
attack_verb = list("whipped", "lashed", "disciplined", "flogged")
/obj/item/stack/cable_coil/cyborg
name = "cable coil synthesizer"
desc = "A device that makes cable."
gender = NEUTER
matter = null
uses_charge = 1
charge_costs = list(1)
stacktype = /obj/item/stack/cable_coil
/obj/item/stack/cable_coil/suicide_act(mob/user)
if(locate(/obj/structure/stool) in user.loc)
if(locate(/obj/item/weapon/stool) in user.loc)
user.visible_message("<span class='suicide'>[user] is making a noose with the [src.name]! It looks like \he's trying to commit suicide.</span>")
else
user.visible_message("<span class='suicide'>[user] is strangling \himself with the [src.name]! It looks like \he's trying to commit suicide.</span>")
@@ -576,7 +585,7 @@ obj/structure/cable/proc/cableColor(var/colorC)
usr << "\blue You cannot do that."
..()
/obj/item/stack/cable_coil/robot/verb/set_colour()
/obj/item/stack/cable_coil/cyborg/verb/set_colour()
set name = "Change Colour"
set category = "Object"
@@ -606,26 +615,26 @@ obj/structure/cable/proc/cableColor(var/colorC)
// - Cable coil : merge cables
/obj/item/stack/cable_coil/attackby(obj/item/weapon/W, mob/user)
..()
if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1)
src.amount--
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()
return
else if(istype(W, /obj/item/stack/cable_coil))
var/obj/item/stack/cable_coil/C = W
if(C.amount >= MAXCOIL)
if(C.get_amount() >= get_max_amount())
user << "The coil is too long, you cannot add any more cable to it."
return
if( (C.amount + src.amount <= MAXCOIL) )
if( (C.get_amount() + src.get_amount() <= get_max_amount()) )
user << "You join the cable coils together."
C.give(src.amount) // give it cable
src.use(src.amount) // make sure this one cleans up right
C.give(src.get_amount()) // give it cable
src.use(src.get_amount()) // make sure this one cleans up right
return
else
var/amt = MAXCOIL - C.amount
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)

View File

@@ -55,7 +55,7 @@
initial_ammo = 0
/obj/item/ammo_magazine/mc9mm/flash
ammo_type = /obj/item/ammo_casing/c9mmf
ammo_type = /obj/item/ammo_casing/c9mmf
/obj/item/ammo_magazine/c9mm
name = "ammunition Box (9mm)"
@@ -68,6 +68,22 @@
/obj/item/ammo_magazine/c9mm/empty
initial_ammo = 0
/obj/item/ammo_magazine/mc9mmt
name = "top mounted magazine (9mm)"
icon_state = "9mmt"
mag_type = MAGAZINE
ammo_type = /obj/item/ammo_casing/c9mm
caliber = "9mm"
max_ammo = 20
multiple_sprites = 1
/obj/item/ammo_magazine/mc9mmt/empty
initial_ammo = 0
/obj/item/ammo_magazine/mc9mmt/rubber
name = "top mounted magazine (9mm rubber)"
ammo_type = /obj/item/ammo_casing/c9mmr
/obj/item/ammo_magazine/c45
name = "ammunition Box (.45)"
icon_state = "9mm"
@@ -92,6 +108,19 @@
/obj/item/ammo_magazine/a12mm/empty
initial_ammo = 0
/obj/item/ammo_magazine/a556
name = "magazine (5.56)"
icon_state = "5.56"
origin_tech = "combat=2"
mag_type = MAGAZINE
caliber = "a556"
ammo_type = /obj/item/ammo_casing/a556
max_ammo = 10
multiple_sprites = 1
/obj/item/ammo_magazine/a556/empty
initial_ammo = 0
/obj/item/ammo_magazine/a50
name = "magazine (.50)"
icon_state = "50ae"
@@ -168,4 +197,4 @@
ammo_type = "/obj/item/ammo_casing/a666"
max_ammo = 4
multiple_sprites = 1
*/
*/

View File

@@ -33,6 +33,11 @@
caliber = "9mm"
projectile_type = /obj/item/projectile/energy/flash
/obj/item/ammo_casing/c9mmr
desc = "A 9mm rubber bullet casing."
caliber = "9mm"
projectile_type = /obj/item/projectile/bullet/pistol/rubber
/obj/item/ammo_casing/c45
desc = "A .45 bullet casing."
@@ -84,7 +89,7 @@
projectile_type = /obj/item/projectile/bullet/shotgun/beanbag
matter = list("metal" = 500)
//Can stun in one hit if aimed at the head, but
//Can stun in one hit if aimed at the head, but
//is blocked by clothing that stops tasers and is vulnerable to EMP
/obj/item/ammo_casing/shotgun/stunshell
name = "stun shell"
@@ -113,12 +118,17 @@
/obj/item/ammo_casing/a145
name = "shell casing"
desc = "A 14.5mm AP shell."
desc = "A 14.5mm shell."
icon_state = "lcasing"
spent_icon = "lcasing-spent"
caliber = "14.5mm"
projectile_type = /obj/item/projectile/bullet/rifle/a145
/obj/item/ammo_casing/a556
desc = "A 5.56mm bullet casing."
caliber = "a556"
projectile_type = /obj/item/projectile/bullet/rifle/a556
/obj/item/ammo_casing/rocket
name = "rocket shell"
desc = "A high explosive designed to be fired from a launcher."

View File

@@ -258,6 +258,10 @@
accuracy = scoped_accuracy + scoped_accuracy_mod
if(recoil)
recoil = round(recoil*zoom_amount+1) //recoil is worse when looking through a scope
else
accuracy = (accuracy)
//make sure accuracy and recoil are reset regardless of how the item is unzoomed.
/obj/item/weapon/gun/zoom()
..()
if(!zoom)
accuracy = initial(accuracy)
recoil = initial(recoil)

View File

@@ -1,6 +1,6 @@
/obj/item/weapon/gun/energy/laser
name = "laser carbine"
desc = "A basic weapon designed to kill with concentrated energy bolts."
desc = "A common laser weapon, designed to kill with concentrated energy blasts."
icon_state = "laser"
item_state = "laser"
fire_sound = 'sound/weapons/Laser.ogg'
@@ -10,6 +10,8 @@
matter = list("metal" = 2000)
origin_tech = "combat=3;magnets=2"
projectile_type = /obj/item/projectile/beam
charge_cost = 75
fire_delay = 1
/obj/item/weapon/gun/energy/laser/mounted
self_recharge = 1
@@ -42,7 +44,7 @@ obj/item/weapon/gun/energy/laser/retro
item_state = "laser"
fire_sound = 'sound/weapons/lasercannonfire.ogg'
origin_tech = "combat=4;materials=3;powerstorage=3"
slot_flags = SLOT_BELT|SLOT_BACK
slot_flags = SLOT_BELT|SLOT_BACK
projectile_type = /obj/item/projectile/beam/heavylaser
charge_cost = 250
fire_delay = 20
@@ -50,7 +52,7 @@ obj/item/weapon/gun/energy/laser/retro
/obj/item/weapon/gun/energy/lasercannon/mounted
self_recharge = 1
use_external_power = 1
recharge_time = 25
recharge_time = 25
/obj/item/weapon/gun/energy/xray
name = "xray laser gun"
@@ -90,12 +92,12 @@ obj/item/weapon/gun/energy/laser/retro
name = "laser tag gun"
item_state = "laser"
desc = "Standard issue weapon of the Imperial Guard"
origin_tech = "combat=1;magnets=2"
origin_tech = "combat=1;magnets=2"
self_recharge = 1
matter = list("metal" = 2000)
fire_sound = 'sound/weapons/Laser.ogg'
projectile_type = /obj/item/projectile/beam/lastertag/blue
var/required_vest
var/required_vest
/obj/item/weapon/gun/energy/lasertag/special_check(var/mob/living/carbon/human/M)
if(ishuman(M))
@@ -112,4 +114,4 @@ obj/item/weapon/gun/energy/laser/retro
/obj/item/weapon/gun/energy/lasertag/red
icon_state = "redtag"
projectile_type = /obj/item/projectile/beam/lastertag/red
required_vest = /obj/item/clothing/suit/redtag
required_vest = /obj/item/clothing/suit/redtag

View File

@@ -21,10 +21,10 @@
name = "stun revolver"
desc = "A high-tech revolver that fires stun cartridges. The stun cartridges can be recharged using a conventional energy weapon recharger."
icon_state = "stunrevolver"
fire_sound = 'sound/weapons/Taser.ogg'
fire_sound = 'sound/weapons/Gunshot.ogg'
origin_tech = "combat=3;materials=3;powerstorage=2"
charge_cost = 125
projectile_type = /obj/item/projectile/beam/stun
projectile_type = /obj/item/projectile/energy/electrode/stunshot
cell_type = /obj/item/weapon/cell

View File

@@ -1,7 +1,6 @@
/obj/item/weapon/gun/launcher
name = "launcher"
desc = "A device that launches things."
icon = 'icons/obj/weapons.dmi'
w_class = 5.0
flags = CONDUCT
slot_flags = SLOT_BACK

View File

@@ -48,6 +48,7 @@
/obj/item/weapon/gun/launcher/crossbow
name = "powered crossbow"
desc = "A 2557AD twist on an old classic. Pick up that can."
icon = 'icons/obj/weapons.dmi'
icon_state = "crossbow"
item_state = "crossbow-solid"
fire_sound = 'sound/weapons/punchmiss.ogg' // TODO: Decent THWOK noise.

View File

@@ -1,7 +1,6 @@
/obj/item/weapon/gun/launcher/grenade
name = "grenade launcher"
desc = "A bulky pump-action grenade launcher. Holds up to 5 grenades in a revolving magazine."
icon = 'icons/obj/gun.dmi'
icon_state = "riotgun"
item_state = "riotgun"
w_class = 4

View File

@@ -1,7 +1,6 @@
/obj/item/weapon/gun/launcher/pneumatic
name = "pneumatic cannon"
desc = "A large gas-powered cannon."
icon = 'icons/obj/gun.dmi'
icon_state = "pneumatic"
item_state = "pneumatic"
slot_flags = SLOT_BELT

View File

@@ -1,6 +1,6 @@
/obj/item/weapon/syringe_cartridge
name = "syringe gun cartridge"
desc = "An impact-triggered compressed gas cartridge that can fitted to a syringe for rapid injection."
desc = "An impact-triggered compressed gas cartridge that can be fitted to a syringe for rapid injection."
icon = 'icons/obj/ammo.dmi'
icon_state = "syringe-cartridge"
var/icon_flight = "syringe-cartridge-flight" //so it doesn't look so weird when shot
@@ -25,6 +25,7 @@
user.remove_from_mob(syringe)
syringe.loc = src
sharp = 1
name = "syringe dart"
update_icon()
/obj/item/weapon/syringe_cartridge/attack_self(mob/user)
@@ -33,6 +34,7 @@
user.put_in_hands(syringe)
syringe = null
sharp = initial(sharp)
name = initial(name)
update_icon()
/obj/item/weapon/syringe_cartridge/proc/prime()
@@ -61,7 +63,6 @@
/obj/item/weapon/gun/launcher/syringe
name = "syringe gun"
desc = "A spring loaded rifle designed to fit syringes, designed to incapacitate unruly patients from a distance."
icon = 'icons/obj/gun.dmi'
icon_state = "syringegun"
item_state = "syringegun"
w_class = 3

View File

@@ -26,6 +26,10 @@
var/obj/item/ammo_magazine/ammo_magazine = null //stored magazine
var/auto_eject = 0 //if the magazine should automatically eject itself when empty.
var/auto_eject_sound = null
//TODO generalize ammo icon states for guns
//var/magazine_states = 0
//var/list/icon_keys = list() //keys
//var/list/ammo_states = list() //values
/obj/item/weapon/gun/projectile/New()
..()
@@ -37,8 +41,7 @@
update_icon()
/obj/item/weapon/gun/projectile/consume_next_projectile()
//store the next ammo_casing in a var so that handle_post_fire() knows which one to eject
//also we might as well remove chambered here, so that we don't have to figure out where it came from later
//get the next casing
if(loaded.len)
chambered = loaded[1] //load next casing.
if(handle_casings != HOLD_CASINGS)
@@ -47,25 +50,36 @@
chambered = ammo_magazine.stored_ammo[1]
if(handle_casings != HOLD_CASINGS)
ammo_magazine.stored_ammo -= chambered
return chambered.BB
if (chambered)
return chambered.BB
return null
/obj/item/weapon/gun/projectile/handle_post_fire()
..()
if(chambered)
chambered.expend()
//check chambered again in case it deleted itself
if(chambered && handle_casings != HOLD_CASINGS)
switch(handle_casings)
if(EJECT_CASINGS) //eject casing onto ground.
chambered.loc = get_turf(src)
if(CYCLE_CASINGS) //cycle the casing back to the end.
if(ammo_magazine)
ammo_magazine.stored_ammo += chambered
else
loaded += chambered
process_chambered()
/obj/item/weapon/gun/projectile/handle_click_empty()
..()
process_chambered()
/obj/item/weapon/gun/projectile/proc/process_chambered()
if (!chambered) return
switch(handle_casings)
if(EJECT_CASINGS) //eject casing onto ground.
chambered.loc = get_turf(src)
if(CYCLE_CASINGS) //cycle the casing back to the end.
if(ammo_magazine)
ammo_magazine.stored_ammo += chambered
else
loaded += chambered
if(handle_casings != HOLD_CASINGS)
chambered = null
//Attempts to load A into src, depending on the type of thing being loaded and the load_method
//Maybe this should be broken up into separate procs for each load method?
@@ -118,7 +132,6 @@
update_icon()
//attempts to unload src. If allow_dump is set to 0, the speedloader unloading method will be disabled
/obj/item/weapon/gun/projectile/proc/unload_ammo(mob/user, var/allow_dump=1)
if(ammo_magazine)
@@ -170,8 +183,9 @@
)
if(auto_eject_sound)
playsound(user, auto_eject_sound, 40, 1)
ammo_magazine.update_icon()
ammo_magazine = null
update_icon()
update_icon() //make sure to do this after unsetting ammo_magazine
/obj/item/weapon/gun/projectile/examine(mob/user)
..(user)

View File

@@ -6,12 +6,12 @@
load_method = SPEEDLOADER //yup. until someone sprites a magazine for it.
max_shells = 22
caliber = "9mm"
origin_tech = "combat=4;materials=2"
origin_tech = "combat=4;materials=2"
slot_flags = SLOT_BELT
ammo_type = /obj/item/ammo_casing/c9mm
multi_aim = 1
fire_delay = 0
/obj/item/weapon/gun/projectile/automatic/mini_uzi
name = "\improper Uzi"
desc = "A lightweight, fast firing gun, for when you want someone dead. Uses .45 rounds."
@@ -42,20 +42,64 @@
/obj/item/weapon/gun/projectile/automatic/c20r/update_icon()
..()
if(ammo_magazine)
icon_state = "c20r-[round(loaded.len,4)]"
icon_state = "c20r-[round(ammo_magazine.stored_ammo.len,4)]"
else
icon_state = "c20r"
return
/obj/item/weapon/gun/projectile/automatic/wt550
name = "\improper W-T 550 Saber"
desc = "A cheap, mass produced Ward-Takahashi PDW. Uses 9mm rounds."
icon_state = "wt550"
w_class = 3.0
caliber = "9mm"
origin_tech = "combat=5;materials=2"
slot_flags = SLOT_BELT
ammo_type = "/obj/item/ammo_casing/c9mmr"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/mc9mmt/rubber
/obj/item/weapon/gun/projectile/automatic/wt550/update_icon()
..()
if(ammo_magazine)
icon_state = "wt550-[round(ammo_magazine.stored_ammo.len,4)]"
else
icon_state = "wt550"
return
/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."
icon_state = "carbine"
item_state = "shotgun"
w_class = 4
force = 10
caliber = "a556"
origin_tech = "combat=8;materials=3"
ammo_type = "/obj/item/ammo_casing/a556"
fire_sound = 'sound/weapons/Gunshot.ogg'
slot_flags = SLOT_BACK
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/a556
/obj/item/weapon/gun/projectile/automatic/z8/update_icon()
..()
if(ammo_magazine)
icon_state = "carbine-[round(ammo_magazine.stored_ammo.len,2)]"
else
icon_state = "carbine"
return
/obj/item/weapon/gun/projectile/automatic/sts35
name = "\improper STS-35 Automatic Rifle"
desc = "A durable, rugged looking automatic weapon of make popular on the frontier, despite it's bulk. Uses 7.62mm rounds. It is unmarked."
name = "\improper STS-35 automatic rifle"
desc = "A durable, rugged looking automatic weapon of a make popular on the frontier. Uses 7.62mm rounds. It is unmarked."
icon_state = "assltrifle"
item_state = "shotgun"
w_class = 4
force = 10
caliber = "a762"
origin_tech = "combat=5;materials=1;syndicate=8"
origin_tech = "combat=6;materials=1;syndicate=4"
slot_flags = SLOT_BACK
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/c762
@@ -74,7 +118,7 @@
slot_flags = 0
max_shells = 50
caliber = "a762"
origin_tech = "combat=5;materials=1;syndicate=2"
origin_tech = "combat=6;materials=1;syndicate=2"
slot_flags = SLOT_BACK
ammo_type = "/obj/item/ammo_casing/a762"
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
@@ -88,7 +132,7 @@
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(loaded.len, 25) : "-empty"]"
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(ammo_magazine.stored_ammo.len, 25) : "-empty"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/special_check(mob/user)
if(cover_open)
@@ -102,7 +146,7 @@
return
..()
/obj/item/weapon/gun/projectile/automatic/l6_saw/unload_ammo(mob/user)
/obj/item/weapon/gun/projectile/automatic/l6_saw/unload_ammo(mob/user, var/allow_dump=1)
if(!cover_open)
return
..()
..()

View File

@@ -34,6 +34,21 @@
M << "You name the gun [input]. Say hello to your new friend."
return 1
/obj/item/weapon/gun/projectile/sec
desc = "A Nanotrasen designed sidearm, found pretty much everywhere humans are. Uses less-than-lethal .45 rounds."
name = "\improper NT Mk58"
icon_state = "secguncomp"
magazine_type = /obj/item/ammo_magazine/c45m/rubber
caliber = ".45"
origin_tech = "combat=3;materials=2"
load_method = MAGAZINE
/obj/item/weapon/gun/projectile/sec/wood
desc = "A Nanotrasen designed sidearm, this one has a sweet wooden grip. Uses less-than-lethal .45 rounds."
name = "\improper Custom NT Mk58"
icon_state = "secgundark"
/obj/item/weapon/gun/projectile/silenced
name = "silenced pistol"
desc = "A small, quiet, easily concealable gun. Uses .45 rounds."
@@ -98,7 +113,7 @@
silenced = 0
origin_tech = "combat=2;materials=2;syndicate=2"
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/mc9mm
magazine_type = /obj/item/ammo_magazine/mc9mm
/obj/item/weapon/gun/projectile/pistol/flash
name = "\improper Stechtkin signal pistol"

View File

@@ -11,33 +11,33 @@
caliber = "shotgun"
origin_tech = "combat=4;materials=2"
load_method = SINGLE_CASING
ammo_type = /obj/item/ammo_casing/shotgun/pellet
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
handle_casings = HOLD_CASINGS
var/recentpump = 0 // to prevent spammage
/obj/item/weapon/gun/projectile/shotgun/pump/consume_next_projectile()
if(chambered)
return chambered.BB
return null
return null
/obj/item/weapon/gun/projectile/shotgun/pump/attack_self(mob/living/user as mob)
if(world.time >= recentpump + 10)
pump(user)
pump(user)
recentpump = world.time
/obj/item/weapon/gun/projectile/shotgun/pump/proc/pump(mob/M as mob)
playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1)
if(chambered)//We have a shell in the chamber
chambered.loc = get_turf(src)//Eject casing
chambered = null
if(loaded.len)
var/obj/item/ammo_casing/AC = loaded[1] //load next casing.
loaded -= AC //Remove casing from loaded list.
chambered = AC
update_icon()
update_icon()
/obj/item/weapon/gun/projectile/shotgun/pump/combat
name = "combat shotgun"
@@ -62,7 +62,7 @@
flags = CONDUCT
slot_flags = SLOT_BACK
caliber = "shotgun"
origin_tech = "combat=3;materials=1"
origin_tech = "combat=3;materials=1"
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
//this is largely hacky and bad :( -Pete
@@ -71,7 +71,7 @@
user << "<span class='notice'>You begin to shorten the barrel of \the [src].</span>"
if(loaded.len)
for(var/i in 1 to max_shells)
afterattack(user, user) //will this work? //it will. we call it twice, for twice the FUN
afterattack(user, user) //will this work? //it will. we call it twice, for twice the FUN
playsound(user, fire_sound, 50, 1)
user.visible_message("<span class='danger'>The shotgun goes off!</span>", "<span class='danger'>The shotgun goes off in your face!</span>")
return

View File

@@ -1,8 +1,8 @@
/obj/item/weapon/gun/projectile/heavysniper
name = "\improper PTRS-7 rifle"
desc = "A portable anti-armour rifle fitted with a scope. Originally designed to used against lightly armoured exosuits, it is capable of punching through non-reinforced walls with ease. Fires 14.5mm AP shells."
desc = "A portable anti-armour rifle fitted with a scope. Originally designed to used against armoured exosuits, it is capable of punching through non-reinforced walls with ease. Fires armor piercing 14.5mm shells."
icon_state = "heavysniper"
item_state = "sniper0"
item_state = "shotgun"
w_class = 4
force = 10
slot_flags = SLOT_BACK

View File

@@ -65,8 +65,15 @@
/obj/item/projectile/proc/on_impact(var/atom/A)
return
//Checks if the projectile is eligible for embedding. Not that it necessarily will.
/obj/item/projectile/proc/can_embed()
//embed must be enabled and damage type must be brute
if(!embed || damage_type != BRUTE)
return 0
return 1
//return 1 if the projectile should be allowed to pass through after all, 0 if not.
/obj/item/projectile/proc/on_penetrate(var/atom/A)
/obj/item/projectile/proc/check_penetrate(var/atom/A)
return 1
/obj/item/projectile/proc/check_fire(atom/target as mob, var/mob/living/user as mob) //Checks if you can hit them or not.
@@ -156,9 +163,12 @@
target_mob.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src.type]</b>"
firer.attack_log += "\[[time_stamp()]\] <b>[firer]/[firer.ckey]</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src.type]</b>"
msg_admin_attack("[firer] ([firer.ckey]) shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
else
else if(firer)
target_mob.attack_log += "\[[time_stamp()]\] <b>UNKNOWN SUBJECT (No longer exists)</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src]</b>"
msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[firer.x];Y=[firer.y];Z=[firer.z]'>JMP</a>)") //BS12 EDIT ALG
else
target_mob.attack_log += "\[[time_stamp()]\] <b>UNKNOWN SUBJECT (No longer exists)</b> shot <b>[target_mob]/[target_mob.ckey]</b> with a <b>[src]</b>"
msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with a [src] (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[target_mob.x];Y=[target_mob.y];Z=[target_mob.z]'>JMP</a>)") //BS12 EDIT ALG
//sometimes bullet_act() will want the projectile to continue flying
if (target_mob.bullet_act(src, def_zone) == -1)
@@ -174,7 +184,7 @@
loc = A.loc
return 0 //cannot shoot yourself
if(bumped)
if(bumped || (A in permutated))
return 0
var/passthrough = 0 //if the projectile should continue flying
@@ -196,19 +206,21 @@
attack_mob(M, distance)
//penetrating projectiles can pass through things that otherwise would not let them
if(penetrating > 0)
if(on_penetrate(A))
if(!passthrough && penetrating > 0)
if(check_penetrate(A))
passthrough = 1
penetrating--
//the bullet passes through a dense object!
if(passthrough)
//move ourselves onto A so we can continue on our way.
if(A)
if(istype(A, /turf))
loc = A
else
loc = A.loc
permutated.Add(A)
bumped = 0 //reset bumped variable!
if(istype(A, /turf))
loc = A
else
loc = A.loc
permutated.Add(A)
return 0
//stop flying

View File

@@ -7,22 +7,37 @@
check_armour = "bullet"
embed = 1
sharp = 1
var/mob_passthrough_check = 0
/obj/item/projectile/bullet/on_hit(var/atom/target, var/blocked = 0)
if (..(target, blocked))
var/mob/living/L = target
shake_camera(L, 3, 2)
/obj/item/projectile/bullet/on_penetrate(var/atom/A)
if(!A) return 1 //if whatever it was got destroyed when we hit it, then I guess we can just keep going
/obj/item/projectile/bullet/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier)
if(penetrating > 0 && damage > 20 && prob(damage))
mob_passthrough_check = 1
else
mob_passthrough_check = 0
..()
/obj/item/projectile/bullet/can_embed()
//prevent embedding if the projectile is passing through the mob
if(mob_passthrough_check)
return 0
return ..()
/obj/item/projectile/bullet/check_penetrate(var/atom/A)
if(!A || !A.density) return 1 //if whatever it was got destroyed when we hit it, then I guess we can just keep going
if(istype(A, /obj/mecha))
return 1 //mecha have their own penetration handling
if(ismob(A))
if(iscarbon(A))
if (damage <= 20 && !prob(damage)) return 0
damage *= 0.7 //squishy mobs absorb KE
if(!mob_passthrough_check)
return 0
if(iscarbon(A))
damage *= 0.7 //squishy mobs absorb KE
return 1
var/chance = 0
@@ -33,10 +48,10 @@
var/obj/machinery/door/D = A
chance = round(damage/D.maxhealth*100)
else if(istype(A, /obj/structure/girder) || istype(A, /obj/structure/cultgirder))
chance = 100
chance = 100
else if(istype(A, /obj/machinery) || istype(A, /obj/structure))
chance = 15
chance = 25
if(prob(chance))
if(A.opacity)
//display a message so that people on the other side aren't so confused
@@ -131,6 +146,10 @@
weaken = 3
penetrating = 5
/obj/item/projectile/bullet/rifle/a556
damage = 50
penetrating = 1
/* Miscellaneous */
/obj/item/projectile/bullet/suffocationbullet//How does this even work?

View File

@@ -1702,8 +1702,8 @@ datum
if(!M) M = holder.my_atom
if(prob(33))
M.take_organ_damage(1*REM, 0)
M.adjustOxyLoss(3)
if(prob(20)) M.emote("gasp")
if(M.losebreath < 15)
M.losebreath++
..()
return
@@ -3180,17 +3180,17 @@ datum
if(!data) data = 1
data++
M.dizziness +=6
if(data >= 15 && data <45)
if (!M.stuttering) M.stuttering = 1
M.stuttering += 3
else if(data >= 45 && prob(50) && data <55)
M.confused = max(M.confused+3,0)
else if(data >=55)
M.druggy = max(M.druggy, 55)
else if(data >=200)
M.adjustToxLoss(2)
switch(data)
if(15 to 45)
M.stuttering = max(M.stuttering+3,0)
if(45 to 55)
if (prob(50))
M.confused = max(M.confused+3,0)
if(55 to 200)
M.druggy = max(M.druggy, 55)
if(200 to INFINITY)
M.adjustToxLoss(2)
..()
return
neurotoxin
name = "Neurotoxin"
@@ -3210,17 +3210,17 @@ datum
if(!data) data = 1
data++
M.dizziness +=6
if(data >= 15 && data <45)
if (!M.stuttering) M.stuttering = 1
M.stuttering += 3
else if(data >= 45 && prob(50) && data <55)
M.confused = max(M.confused+3,0)
else if(data >=55)
M.druggy = max(M.druggy, 55)
else if(data >=200)
M.adjustToxLoss(2)
switch(data)
if(15 to 45)
M.stuttering = max(M.stuttering+3,0)
if(45 to 55)
if (prob(50))
M.confused = max(M.confused+3,0)
if(55 to 200)
M.druggy = max(M.druggy, 55)
if(200 to INFINITY)
M.adjustToxLoss(2)
..()
return
hippies_delight
name = "Hippies' Delight"

View File

@@ -2997,3 +2997,38 @@
..()
reagents.add_reagent("nutriment", 3)
/obj/item/weapon/reagent_containers/food/snacks/liquidfood
name = "\improper LiquidFood Ration"
desc = "A prepackaged grey slurry of all the essential nutrients for a spacefarer on the go. Should this be crunchy?"
icon_state = "liquidfood"
trash = /obj/item/trash/liquidfood
filling_color = "#A8A8A8"
New()
..()
reagents.add_reagent("nutriment", 20)
reagents.add_reagent("iron", 3)
bitesize = 4
/obj/item/weapon/reagent_containers/food/snacks/tastybread
name = "Bread Tube"
desc = "Chewy...and surprisingly tasty."
icon_state = "tastybread"
filling_color = "#A66829"
New()
..()
reagents.add_reagent("nutriment", 12)
bitesize = 2
/obj/item/weapon/reagent_containers/food/snacks/skrellsnacks
name = "\improper SkrellSnax"
desc = "Cured fungus shipped all the way from Jargon 4, almost like jerky! Almost."
icon_state = "skrellsnacks"
filling_color = "#A66829"
New()
..()
reagents.add_reagent("nutriment", 10)
bitesize = 3

View File

@@ -238,3 +238,15 @@
New()
..()
reagents.add_reagent("virusfood", 1000)
/obj/structure/reagent_dispensers/acid
name = "Sulphuric Acid Dispenser"
desc = "A dispenser of acid for industrial processes."
icon = 'icons/obj/objects.dmi'
icon_state = "acidtank"
amount_per_transfer_from_this = 10
anchored = 1
New()
..()
reagents.add_reagent("sacid", 1000)

View File

@@ -103,6 +103,9 @@ proc/do_surgery(mob/living/carbon/M, mob/living/user, obj/item/tool)
else // This failing silently was a pain.
user << "\red You must remain close to your patient to conduct surgery."
M.op_stage.in_progress = 0 // Clear the in-progress flag.
if (ishuman(M))
var/mob/living/carbon/human/H = M
H.update_surgery()
return 1 //don't want to do weapony things after surgery
if (user.a_intent == "help")