mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-22 03:27:46 +01:00
Merge remote-tracking branch 'upstream/dev' into subsystems
Conflicts: code/game/machinery/camera/camera.dm code/modules/mob/mob.dm
This commit is contained in:
@@ -1148,15 +1148,22 @@ var/global/floorIsLava = 0
|
||||
switch(detail)
|
||||
if(0)
|
||||
return "<b>[key_name(C, link, name, highlight_special)]</b>"
|
||||
if(1)
|
||||
|
||||
if(1) //Private Messages
|
||||
return "<b>[key_name(C, link, name, highlight_special)](<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</A>)</b>"
|
||||
if(2)
|
||||
|
||||
if(2) //Admins
|
||||
var/ref_mob = "\ref[M]"
|
||||
return "<b>[key_name(C, link, name, highlight_special)](<A HREF='?_src_=holder;adminmoreinfo=[ref_mob]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>) (<A HREF='?_src_=holder;check_antagonist=1'>CA</A>)</b>"
|
||||
if(3)
|
||||
|
||||
if(3) //Devs
|
||||
var/ref_mob = "\ref[M]"
|
||||
return "<b>[key_name(C, link, name, highlight_special)](<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>)(<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>)</b>"
|
||||
|
||||
if(4) //Mentors
|
||||
var/ref_mob = "\ref[M]"
|
||||
return "<b>[key_name(C, link, name, highlight_special)] (<A HREF='?_src_=holder;adminmoreinfo=\ref[M]'>?</A>) (<A HREF='?_src_=holder;adminplayeropts=[ref_mob]'>PP</A>) (<A HREF='?_src_=vars;Vars=[ref_mob]'>VV</A>) (<A HREF='?_src_=holder;subtlemessage=[ref_mob]'>SM</A>) (<A HREF='?_src_=holder;adminplayerobservejump=[ref_mob]'>JMP</A>)</b>"
|
||||
|
||||
|
||||
/proc/ishost(whom)
|
||||
if(!whom)
|
||||
|
||||
@@ -109,6 +109,9 @@ var/list/admin_verbs_fun = list(
|
||||
var/list/admin_verbs_spawn = list(
|
||||
/datum/admins/proc/spawn_atom, /*allows us to spawn instances*/
|
||||
/client/proc/respawn_character,
|
||||
/client/proc/FireLaser,
|
||||
/client/proc/FireCannons,
|
||||
/client/proc/ChangeIcarusPosition,
|
||||
/client/proc/virus2_editor
|
||||
)
|
||||
var/list/admin_verbs_server = list(
|
||||
|
||||
@@ -87,7 +87,11 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
|
||||
var/ai_cl
|
||||
if(ai_found)
|
||||
ai_cl = " (<A HREF='?_src_=holder;adminchecklaws=\ref[mob]'>CL</A>)"
|
||||
var/mentor_msg = "\blue <b><font color=red>Request for Help: </font>[get_options_bar(mob, 0, 0, 1, 0)][ai_cl]:</b> [msg]"
|
||||
|
||||
//Options bar: mob, details ( admin = 2, dev = 3, mentor = 4, character name (0 = just ckey, 1 = ckey and character name), link? (0 no don't make it a link, 1 do so),
|
||||
// highlight special roles (0 = everyone has same looking name, 1 = antags / special roles get a golden name)
|
||||
|
||||
var/mentor_msg = "\blue <b><font color=red>Request for Help: </font>[get_options_bar(mob, 4, 1, 1, 0)][ai_cl]:</b> [msg]"
|
||||
msg = "\blue <b><font color=red>Request for Help:: </font>[get_options_bar(mob, 2, 1, 1)][ai_cl]:</b> [msg]"
|
||||
|
||||
var/admin_number_afk = 0
|
||||
|
||||
@@ -595,7 +595,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/cloaking_device(M), slot_r_store)
|
||||
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile(M), slot_r_hand)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver(M), slot_r_hand)
|
||||
M.equip_to_slot_or_del(new /obj/item/ammo_magazine/a357(M), slot_l_store)
|
||||
|
||||
if ("tournament chef") //Steven Seagal FTW
|
||||
@@ -710,7 +710,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
for(var/i=3, i>0, i--)
|
||||
sec_briefcase.contents += new /obj/item/weapon/spacecash/c1000
|
||||
sec_briefcase.contents += new /obj/item/weapon/gun/energy/crossbow
|
||||
sec_briefcase.contents += new /obj/item/weapon/gun/projectile/mateba
|
||||
sec_briefcase.contents += new /obj/item/weapon/gun/projectile/revolver/mateba
|
||||
sec_briefcase.contents += new /obj/item/ammo_magazine/a357
|
||||
sec_briefcase.contents += new /obj/item/weapon/plastique
|
||||
M.equip_to_slot_or_del(sec_briefcase, slot_l_hand)
|
||||
@@ -892,7 +892,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/eyepatch(M), slot_glasses)
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/suit/hgpirate(M), slot_wear_suit)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(M), slot_back)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(M), slot_belt)
|
||||
M.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(M), slot_belt)
|
||||
M.equip_to_slot_or_del(new /obj/item/clothing/under/soviet(M), slot_w_uniform)
|
||||
var/obj/item/weapon/card/id/W = new(M)
|
||||
W.name = "[M.real_name]'s ID Card"
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/client/proc/FireLaser()
|
||||
set name = "Fire the Icarus lasers"
|
||||
set desc = "Fires a laser bolt at your position. You should only do this as a(n) (a)ghost"
|
||||
set category = "Fun"
|
||||
|
||||
if(!src.holder)
|
||||
src << "Only administrators may use this command."
|
||||
return
|
||||
|
||||
Icarus_FireLaser(get_turf(src.mob))
|
||||
|
||||
|
||||
/client/proc/FireCannons()
|
||||
set name = "Fire the Icarus cannons"
|
||||
set desc = "Fires an explosive missile at your position. You should only do this as a(n) (a)ghost."
|
||||
set category = "Fun"
|
||||
|
||||
if(!src.holder)
|
||||
src << "Only administrators may use this command."
|
||||
return
|
||||
|
||||
Icarus_FireCannon(get_turf(src.mob))
|
||||
|
||||
|
||||
/client/proc/ChangeIcarusPosition()
|
||||
set name = "Adjust Icarus Position"
|
||||
set desc = "Lets you chose the position of the Icarus in regards to the map."
|
||||
set category = "Fun"
|
||||
|
||||
if(!src.holder)
|
||||
src << "Only administrators may use this command."
|
||||
return
|
||||
|
||||
Icarus_SetPosition(src)
|
||||
|
||||
var/icarus_position = SOUTH
|
||||
|
||||
proc/Icarus_FireLaser(var/turf/target)
|
||||
// Find the world edge to fire from.
|
||||
var/x = icarus_position & EAST ? world.maxx : icarus_position & WEST ? 1 : target.x
|
||||
var/y = icarus_position & NORTH ? world.maxy : icarus_position & SOUTH ? 1 : target.y
|
||||
var/x_off = x != target.x ? abs(target.x - x) : INFINITY
|
||||
var/y_off = y != target.y ? abs(target.y - y) : INFINITY
|
||||
// Get the minimum number of steps using the rise/run shit.
|
||||
var/iterations = round(min(x_off, y_off)) - 14 // We cannot fire straight from the edge since teleport thing.
|
||||
|
||||
// Now we can get the location of the start.
|
||||
x = target.x + (icarus_position & EAST ? iterations : icarus_position & WEST ? -iterations : 0)
|
||||
y = target.y + (icarus_position & NORTH ? iterations : icarus_position & SOUTH ? -iterations : 0)
|
||||
|
||||
var/turf/start = locate(x, y, target.z)
|
||||
|
||||
// should step down as:
|
||||
// 1000, 500, 333, 250, 200, 167, 142, 125, 111, 100, 90
|
||||
var/damage = 1000
|
||||
for(var/i in 2 to 12)
|
||||
var/obj/item/projectile/beam/in_chamber = new (start)
|
||||
in_chamber.original = target
|
||||
in_chamber.starting = start
|
||||
in_chamber.silenced = 1
|
||||
in_chamber.yo = icarus_position & NORTH ? -1 : icarus_position & SOUTH ? 1 : 0
|
||||
in_chamber.xo = icarus_position & EAST ? -1 : icarus_position & WEST ? 1 : 0
|
||||
in_chamber.damage = damage
|
||||
in_chamber.kill_count = 500
|
||||
in_chamber.process()
|
||||
damage -= damage / i
|
||||
sleep(-1)
|
||||
|
||||
// Let everyone know what hit them.
|
||||
var/obj/item/projectile/beam/in_chamber = new (start)
|
||||
in_chamber.original = target
|
||||
in_chamber.starting = start
|
||||
in_chamber.silenced = 0
|
||||
in_chamber.yo = icarus_position & NORTH ? -1 : icarus_position & SOUTH ? 1 : 0
|
||||
in_chamber.xo = icarus_position & EAST ? -1 : icarus_position & WEST ? 1 : 0
|
||||
in_chamber.kill_count = 500
|
||||
in_chamber.damage = 0
|
||||
in_chamber.name = "point defense laser"
|
||||
in_chamber.firer = "Icarus" // Never displayed, but we want this to display the hit message.
|
||||
in_chamber.process()
|
||||
|
||||
proc/Icarus_FireCannon(var/turf/target)
|
||||
// Find the world edge to fire from.
|
||||
var/x = icarus_position & EAST ? world.maxx : icarus_position & WEST ? 1 : target.x
|
||||
var/y = icarus_position & NORTH ? world.maxy : icarus_position & SOUTH ? 1 : target.y
|
||||
var/x_off = x != target.x ? abs(target.x - x) : INFINITY
|
||||
var/y_off = y != target.y ? abs(target.y - y) : INFINITY
|
||||
// Get the minimum number of steps using the rise/run shit.
|
||||
var/iterations = round(min(x_off, y_off)) - 14 // We cannot fire straight from the edge since teleport thing.
|
||||
|
||||
// Now we can get the location of the start.
|
||||
x = target.x + (icarus_position & EAST ? iterations : icarus_position & WEST ? -iterations : 0)
|
||||
y = target.y + (icarus_position & NORTH ? iterations : icarus_position & SOUTH ? -iterations : 0)
|
||||
|
||||
var/turf/start = locate(x, y, target.z)
|
||||
|
||||
// Now we find the corresponding turf on the other side of the level.
|
||||
// Yeah, yeah. Overuse of the terinary operator. So sue me.
|
||||
x = icarus_position & EAST ? 1 : icarus_position & WEST ? world.maxx : target.x
|
||||
y = icarus_position & NORTH ? 1 : icarus_position & SOUTH ? world.maxy : target.y
|
||||
x_off = x != target.x ? abs(target.x - x) : INFINITY
|
||||
y_off = y != target.y ? abs(target.y - y) : INFINITY
|
||||
iterations = round(min(x_off, y_off))
|
||||
x = target.x + (icarus_position & EAST ? -iterations : icarus_position & WEST ? iterations : 0)
|
||||
y = target.y + (icarus_position & NORTH ? -iterations : icarus_position & SOUTH ? iterations : 0)
|
||||
target = locate(x, y, target.z)
|
||||
|
||||
// Finally fire the fucker.
|
||||
var/obj/effect/meteor/small/projectile = new (start)
|
||||
projectile.dest = target
|
||||
projectile.name = "main gun projectile" // stealthy
|
||||
projectile.hits = 6
|
||||
projectile.detonation_chance = 99 // it's a missile/cannon round thing!
|
||||
|
||||
// Make sure it travels
|
||||
spawn(0)
|
||||
walk_towards(projectile, projectile.dest, 1)
|
||||
|
||||
proc/Icarus_SetPosition(var/user)
|
||||
var/global/list/directions = list("North" = 1, "North East" = 5, "East" = 4, "South East" = 6, "South" = 2, "South West" = 10, "West" = 8, "North West" = 9)
|
||||
var/direction = input(user, "Where should the Icarus fire from?", "Icarus Comms") as null|anything in directions
|
||||
if(!direction)
|
||||
return
|
||||
|
||||
icarus_position = directions[direction]
|
||||
@@ -153,7 +153,7 @@ var/global/sent_strike_team = 0
|
||||
equip_to_slot_or_del(new /obj/item/weapon/melee/energy/sword(src), slot_l_store)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/grenade/flashbang(src), slot_r_store)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/tank/emergency_oxygen(src), slot_s_store)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/mateba(src), slot_belt)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/revolver/mateba(src), slot_belt)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/weapon/gun/energy/pulse_rifle(src), slot_r_hand)
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ var/global/vox_tick = 1
|
||||
equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt)
|
||||
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE.
|
||||
equip_to_slot_or_del(new /obj/item/weapon/card/emag(src), slot_l_store)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/gun/dartgun/vox/raider(src), slot_r_hand)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/dartgun/vox/raider(src), slot_r_hand)
|
||||
equip_to_slot_or_del(new /obj/item/device/multitool(src), slot_l_hand)
|
||||
|
||||
if(4) // Vox medic!
|
||||
@@ -46,7 +46,7 @@ var/global/vox_tick = 1
|
||||
equip_to_slot_or_del(new /obj/item/weapon/storage/belt/utility/full(src), slot_belt) // Who needs actual surgical tools?
|
||||
equip_to_slot_or_del(new /obj/item/clothing/glasses/hud/health(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE.
|
||||
equip_to_slot_or_del(new /obj/item/weapon/circular_saw(src), slot_l_store)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/gun/dartgun/vox/medical, slot_r_hand)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/dartgun/vox/medical, slot_r_hand)
|
||||
|
||||
equip_to_slot_or_del(new /obj/item/clothing/mask/breath(src), slot_wear_mask)
|
||||
equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(src), slot_back)
|
||||
|
||||
@@ -54,8 +54,8 @@ datum/preferences
|
||||
var/age = 30 //age of character
|
||||
var/spawnpoint = "Arrivals Shuttle" //where this character will spawn (0-2).
|
||||
var/b_type = "A+" //blood type (not-chooseable)
|
||||
var/underwear = 1 //underwear type
|
||||
var/undershirt = 1 //undershirt type
|
||||
var/underwear //underwear type
|
||||
var/undershirt //undershirt type
|
||||
var/backbag = 2 //backpack type
|
||||
var/h_style = "Bald" //Hair type
|
||||
var/r_hair = 0 //Hair color
|
||||
@@ -373,12 +373,11 @@ datum/preferences
|
||||
else
|
||||
dat += "<br><br>"
|
||||
|
||||
if(gender == MALE)
|
||||
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[underwear_m[underwear]]</b></a><br>"
|
||||
else
|
||||
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[underwear_f[underwear]]</b></a><br>"
|
||||
var/list/undies = gender == MALE ? underwear_m : underwear_f
|
||||
|
||||
dat += "Undershirt: <a href='?_src_=prefs;preference=undershirt;task=input'><b>[undershirt_t[undershirt]]</b></a><br>"
|
||||
dat += "Underwear: <a href ='?_src_=prefs;preference=underwear;task=input'><b>[get_key_by_value(undies,underwear)]</b></a><br>"
|
||||
|
||||
dat += "Undershirt: <a href='?_src_=prefs;preference=undershirt;task=input'><b>[get_key_by_value(undershirt_t,undershirt)]</b></a><br>"
|
||||
|
||||
dat += "Backpack Type:<br><a href ='?_src_=prefs;preference=bag;task=input'><b>[backbaglist[backbag]]</b></a><br>"
|
||||
|
||||
@@ -1178,10 +1177,12 @@ datum/preferences
|
||||
if("f_style")
|
||||
f_style = random_facial_hair_style(gender, species)
|
||||
if("underwear")
|
||||
underwear = rand(1,underwear_m.len)
|
||||
var/r = pick(underwear_m)
|
||||
underwear = underwear_m[r]
|
||||
ShowChoices(user)
|
||||
if("undershirt")
|
||||
undershirt = rand(1,undershirt_t.len)
|
||||
var/r = pick(undershirt_t)
|
||||
undershirt = undershirt_t[r]
|
||||
ShowChoices(user)
|
||||
if("eyes")
|
||||
r_eyes = rand(0,255)
|
||||
@@ -1299,7 +1300,7 @@ datum/preferences
|
||||
|
||||
if("hair")
|
||||
if(species == "Human" || species == "Unathi" || species == "Tajara" || species == "Skrell")
|
||||
var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference") as color|null
|
||||
var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference", rgb(r_hair, g_hair, b_hair)) as color|null
|
||||
if(new_hair)
|
||||
r_hair = hex2num(copytext(new_hair, 2, 4))
|
||||
g_hair = hex2num(copytext(new_hair, 4, 6))
|
||||
@@ -1319,7 +1320,7 @@ datum/preferences
|
||||
h_style = new_h_style
|
||||
|
||||
if("facial")
|
||||
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference") as color|null
|
||||
var/new_facial = input(user, "Choose your character's facial-hair colour:", "Character Preference", rgb(r_facial, g_facial, b_facial)) as color|null
|
||||
if(new_facial)
|
||||
r_facial = hex2num(copytext(new_facial, 2, 4))
|
||||
g_facial = hex2num(copytext(new_facial, 4, 6))
|
||||
@@ -1351,7 +1352,7 @@ datum/preferences
|
||||
|
||||
var/new_underwear = input(user, "Choose your character's underwear:", "Character Preference") as null|anything in underwear_options
|
||||
if(new_underwear)
|
||||
underwear = underwear_options.Find(new_underwear)
|
||||
underwear = underwear_options[new_underwear]
|
||||
ShowChoices(user)
|
||||
|
||||
if("undershirt")
|
||||
@@ -1360,11 +1361,11 @@ datum/preferences
|
||||
|
||||
var/new_undershirt = input(user, "Choose your character's undershirt:", "Character Preference") as null|anything in undershirt_options
|
||||
if (new_undershirt)
|
||||
undershirt = undershirt_options.Find(new_undershirt)
|
||||
undershirt = undershirt_options[new_undershirt]
|
||||
ShowChoices(user)
|
||||
|
||||
if("eyes")
|
||||
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference") as color|null
|
||||
var/new_eyes = input(user, "Choose your character's eye colour:", "Character Preference", rgb(r_eyes, g_eyes, b_eyes)) as color|null
|
||||
if(new_eyes)
|
||||
r_eyes = hex2num(copytext(new_eyes, 2, 4))
|
||||
g_eyes = hex2num(copytext(new_eyes, 4, 6))
|
||||
@@ -1379,7 +1380,7 @@ datum/preferences
|
||||
|
||||
if("skin")
|
||||
if(species == "Unathi" || species == "Tajara" || species == "Skrell")
|
||||
var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference") as color|null
|
||||
var/new_skin = input(user, "Choose your character's skin colour: ", "Character Preference", rgb(r_skin, g_skin, b_skin)) as color|null
|
||||
if(new_skin)
|
||||
r_skin = hex2num(copytext(new_skin, 2, 4))
|
||||
g_skin = hex2num(copytext(new_skin, 4, 6))
|
||||
@@ -1705,12 +1706,8 @@ datum/preferences
|
||||
else if(status == "mechanical")
|
||||
I.mechanize()
|
||||
|
||||
if(underwear > underwear_m.len || underwear < 1)
|
||||
underwear = 0 //I'm sure this is 100% unnecessary, but I'm paranoid... sue me. //HAH NOW NO MORE MAGIC CLONING UNDIES
|
||||
character.underwear = underwear
|
||||
|
||||
if(undershirt > undershirt_t.len || undershirt < 1)
|
||||
undershirt = 0
|
||||
character.undershirt = undershirt
|
||||
|
||||
if(backbag > 4 || backbag < 1)
|
||||
@@ -1745,4 +1742,4 @@ datum/preferences
|
||||
user << browse(dat, "window=saves;size=300x390")
|
||||
|
||||
/datum/preferences/proc/close_load_dialog(mob/user)
|
||||
user << browse(null, "window=saves")
|
||||
user << browse(null, "window=saves")
|
||||
|
||||
@@ -375,88 +375,88 @@ var/global/list/gear_datums = list()
|
||||
|
||||
/datum/gear/armband_cargo
|
||||
display_name = "armband, cargo"
|
||||
path = /obj/item/clothing/tie/armband/cargo
|
||||
path = /obj/item/clothing/accessory/armband/cargo
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/armband_emt
|
||||
display_name = "armband, EMT"
|
||||
path = /obj/item/clothing/tie/armband/medgreen
|
||||
path = /obj/item/clothing/accessory/armband/medgreen
|
||||
slot = slot_tie
|
||||
cost = 2
|
||||
|
||||
/datum/gear/armband_engineering
|
||||
display_name = "armband, engineering"
|
||||
path = /obj/item/clothing/tie/armband/engine
|
||||
path = /obj/item/clothing/accessory/armband/engine
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/armband_hydroponics
|
||||
display_name = "armband, hydroponics"
|
||||
path = /obj/item/clothing/tie/armband/hydro
|
||||
path = /obj/item/clothing/accessory/armband/hydro
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/armband_medical
|
||||
display_name = "armband, medical"
|
||||
path = /obj/item/clothing/tie/armband/med
|
||||
path = /obj/item/clothing/accessory/armband/med
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/armband
|
||||
display_name = "armband, red"
|
||||
path = /obj/item/clothing/tie/armband
|
||||
path = /obj/item/clothing/accessory/armband
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/armband_science
|
||||
display_name = "armband, science"
|
||||
path = /obj/item/clothing/tie/armband/science
|
||||
path = /obj/item/clothing/accessory/armband/science
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/armpit
|
||||
display_name = "shoulder holster"
|
||||
path = /obj/item/clothing/tie/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")
|
||||
|
||||
/datum/gear/tie_blue
|
||||
display_name = "tie, blue"
|
||||
path = /obj/item/clothing/tie/blue
|
||||
path = /obj/item/clothing/accessory/blue
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/tie_red
|
||||
display_name = "tie, red"
|
||||
path = /obj/item/clothing/tie/red
|
||||
path = /obj/item/clothing/accessory/red
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/tie_horrible
|
||||
display_name = "tie, socially disgraceful"
|
||||
path = /obj/item/clothing/tie/horrible
|
||||
path = /obj/item/clothing/accessory/horrible
|
||||
slot = slot_tie
|
||||
cost = 1
|
||||
|
||||
/datum/gear/brown_vest
|
||||
display_name = "webbing, engineering"
|
||||
path = /obj/item/clothing/tie/storage/brown_vest
|
||||
path = /obj/item/clothing/accessory/storage/brown_vest
|
||||
slot = slot_tie
|
||||
cost = 2
|
||||
allowed_roles = list("Station Engineer","Atmospheric Technician","Chief Engineer")
|
||||
|
||||
/datum/gear/black_vest
|
||||
display_name = "webbing, security"
|
||||
path = /obj/item/clothing/tie/storage/black_vest
|
||||
path = /obj/item/clothing/accessory/storage/black_vest
|
||||
slot = slot_tie
|
||||
cost = 2
|
||||
allowed_roles = list("Security Officer","Head of Security","Warden")
|
||||
|
||||
/datum/gear/webbing
|
||||
display_name = "webbing, simple"
|
||||
path = /obj/item/clothing/tie/storage/webbing
|
||||
path = /obj/item/clothing/accessory/storage/webbing
|
||||
slot = slot_tie
|
||||
cost = 2
|
||||
|
||||
|
||||
@@ -191,6 +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]]
|
||||
|
||||
if(isnull(language)) language = "None"
|
||||
if(isnull(spawnpoint)) spawnpoint = "Arrivals Shuttle"
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
/obj/item/clothing/head/helmet/refit_for_species(var/target_species)
|
||||
if(!species_restricted)
|
||||
return //this item doesn't use the species_restricted system
|
||||
|
||||
|
||||
//Set species_restricted list
|
||||
switch(target_species)
|
||||
if("Skrell")
|
||||
@@ -401,7 +401,7 @@ BLIND // can't see anything
|
||||
2 = Report detailed damages
|
||||
3 = Report location
|
||||
*/
|
||||
var/obj/item/clothing/tie/hastie = null
|
||||
var/list/accessories = list()
|
||||
var/displays_id = 1
|
||||
sprite_sheets = list("Vox" = 'icons/mob/species/vox/uniform.dmi')
|
||||
|
||||
@@ -410,28 +410,44 @@ BLIND // can't see anything
|
||||
var/mob/M = src.loc
|
||||
M.update_inv_w_uniform()
|
||||
|
||||
/obj/item/clothing/under/proc/can_attach_accessory(obj/item/clothing/accessory/A)
|
||||
if(istype(A))
|
||||
.=1
|
||||
else
|
||||
return 0
|
||||
if(accessories.len && (A.slot in list("utility","armband")))
|
||||
for(var/obj/item/clothing/accessory/AC in accessories)
|
||||
if (AC.slot == A.slot)
|
||||
return 0
|
||||
|
||||
/obj/item/clothing/under/attackby(obj/item/I, mob/user)
|
||||
if(hastie)
|
||||
hastie.attackby(I, user)
|
||||
return
|
||||
if(istype(I, /obj/item/clothing/accessory))
|
||||
var/obj/item/clothing/accessory/A = I
|
||||
if(can_attach_accessory(A))
|
||||
user.drop_item()
|
||||
accessories += A
|
||||
A.on_attached(src, user)
|
||||
|
||||
if(!hastie && istype(I, /obj/item/clothing/tie))
|
||||
user.drop_item()
|
||||
hastie = I
|
||||
hastie.on_attached(src, user)
|
||||
if(istype(loc, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
H.update_inv_w_uniform()
|
||||
|
||||
if(istype(loc, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = loc
|
||||
H.update_inv_w_uniform()
|
||||
return
|
||||
else
|
||||
user << "<span class='notice'>You cannot attach more accessories of this type to [src].</span>"
|
||||
|
||||
if(accessories.len)
|
||||
for(var/obj/item/clothing/accessory/A in accessories)
|
||||
A.attackby(I, user)
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/clothing/under/attack_hand(mob/user as mob)
|
||||
//only forward to the attached accessory if the clothing is equipped (not in a storage)
|
||||
if(hastie && src.loc == user)
|
||||
hastie.attack_hand(user)
|
||||
if(accessories.len && src.loc == user)
|
||||
for(var/obj/item/clothing/accessory/A in accessories)
|
||||
A.attack_hand(user)
|
||||
return
|
||||
|
||||
if ((ishuman(usr) || ismonkey(usr)) && src.loc == user) //make it harder to accidentally undress yourself
|
||||
@@ -468,8 +484,9 @@ BLIND // can't see anything
|
||||
user << "Its vital tracker appears to be enabled."
|
||||
if(3)
|
||||
user << "Its vital tracker and tracking beacon appear to be enabled."
|
||||
if(hastie)
|
||||
user << "\A [hastie] is clipped to it."
|
||||
if(accessories.len)
|
||||
for(var/obj/item/clothing/accessory/A in accessories)
|
||||
user << "\A [A] is attached to it."
|
||||
|
||||
/obj/item/clothing/under/proc/set_sensors(mob/usr as mob)
|
||||
var/mob/M = usr
|
||||
@@ -540,12 +557,12 @@ BLIND // can't see anything
|
||||
else
|
||||
usr << "<span class='notice'>You cannot roll down the uniform!</span>"
|
||||
|
||||
/obj/item/clothing/under/proc/remove_accessory(mob/user as mob)
|
||||
if(!hastie)
|
||||
/obj/item/clothing/under/proc/remove_accessory(mob/user, obj/item/clothing/accessory/A)
|
||||
if(!(A in accessories))
|
||||
return
|
||||
|
||||
hastie.on_removed(user)
|
||||
hastie = null
|
||||
A.on_removed(user)
|
||||
accessories -= A
|
||||
update_clothing_icon()
|
||||
|
||||
/obj/item/clothing/under/verb/removetie()
|
||||
@@ -554,14 +571,20 @@ BLIND // can't see anything
|
||||
set src in usr
|
||||
if(!istype(usr, /mob/living)) return
|
||||
if(usr.stat) return
|
||||
|
||||
src.remove_accessory(usr)
|
||||
if(!accessories.len) return
|
||||
var/obj/item/clothing/accessory/A
|
||||
if(accessories.len > 1)
|
||||
A = input("Select an accessory to remove from [src]") as null|anything in accessories
|
||||
else
|
||||
A = accessories[1]
|
||||
src.remove_accessory(usr,A)
|
||||
|
||||
/obj/item/clothing/under/rank/New()
|
||||
sensor_mode = pick(0,1,2,3)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/under/emp_act(severity)
|
||||
if (hastie)
|
||||
hastie.emp_act(severity)
|
||||
if(accessories.len)
|
||||
for(var/obj/item/clothing/accessory/A in accessories)
|
||||
A.emp_act(severity)
|
||||
..()
|
||||
@@ -1,51 +0,0 @@
|
||||
//Weapon types intended to be used with rig modules
|
||||
|
||||
/obj/item/weapon/gun/energy/lasercannon/mounted/load_into_chamber()
|
||||
if(in_chamber)
|
||||
return 1
|
||||
var/obj/item/rig_module/module = loc
|
||||
if(!istype(module))
|
||||
return 0
|
||||
if(module.holder && module.holder.wearer)
|
||||
var/mob/living/carbon/human/H = module.holder.wearer
|
||||
if(istype(H) && H.back)
|
||||
var/obj/item/weapon/rig/suit = H.back
|
||||
if(istype(suit) && suit.cell && suit.cell.charge >= 250)
|
||||
suit.cell.use(250)
|
||||
in_chamber = new /obj/item/projectile/beam/heavylaser(src)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/mounted/load_into_chamber()
|
||||
if(in_chamber)
|
||||
return 1
|
||||
var/obj/item/rig_module/module = loc
|
||||
if(!istype(module))
|
||||
return 0
|
||||
if(module.holder && module.holder.wearer)
|
||||
var/mob/living/carbon/human/H = module.holder.wearer
|
||||
if(istype(H) && H.back)
|
||||
var/obj/item/weapon/rig/suit = H.back
|
||||
if(istype(suit) && suit.cell && suit.cell.charge >= 250)
|
||||
suit.cell.use(250)
|
||||
var/prog_path = text2path(projectile_type)
|
||||
in_chamber = new prog_path(src)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gun/energy/taser/mounted/load_into_chamber()
|
||||
if(in_chamber)
|
||||
return 1
|
||||
var/obj/item/rig_module/module = loc
|
||||
if(!istype(module))
|
||||
return 0
|
||||
if(module.holder && module.holder.wearer)
|
||||
var/mob/living/carbon/human/H = module.holder.wearer
|
||||
if(istype(H) && H.back)
|
||||
var/obj/item/weapon/rig/suit = H.back
|
||||
if(istype(suit) && suit.cell && suit.cell.charge >= 250)
|
||||
suit.cell.use(250)
|
||||
var/prog_path = text2path(projectile_type)
|
||||
in_chamber = new prog_path(src)
|
||||
return 1
|
||||
return 0
|
||||
@@ -197,8 +197,8 @@
|
||||
target_mob = H
|
||||
|
||||
if(target_mob != H)
|
||||
H << "<span class='danger'>You inject [target_mob] with [chems_to_use] unit[chems_to_use == 1 ? "" : "s"] of [charge.display_name].</span>"
|
||||
target_mob << "<span class='danger'>You feel a rushing in your veins as [chems_to_use] unit[chems_to_use == 1 ? "" : "s"] of [charge.display_name] [chems_to_use == 1 ? "is" : "are"] injected.</span>"
|
||||
H << "<span class='danger'>You inject [target_mob] with [chems_to_use] unit\s of [charge.display_name].</span>"
|
||||
target_mob << "<span class='danger'>You feel a rushing in your veins as [chems_to_use] unit\s of [charge.display_name] [chems_to_use == 1 ? "is" : "are"] injected.</span>"
|
||||
target_mob.reagents.add_reagent(charge.display_name, chems_to_use)
|
||||
|
||||
charge.charges -= chems_to_use
|
||||
|
||||
@@ -196,38 +196,31 @@
|
||||
slowdown = 1
|
||||
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)
|
||||
|
||||
/obj/item/clothing/suit/armor/tactical/verb/holster()
|
||||
set name = "Holster"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
if(!istype(usr, /mob/living)) return
|
||||
if(usr.stat) return
|
||||
/obj/item/clothing/suit/armor/tactical/attackby(obj/item/W as obj, mob/user as mob)
|
||||
..()
|
||||
holster.attackby(W, user)
|
||||
|
||||
if(!holstered)
|
||||
if(!istype(usr.get_active_hand(), /obj/item/weapon/gun))
|
||||
usr << "\blue You need your gun equiped to holster it."
|
||||
return
|
||||
var/obj/item/weapon/gun/W = usr.get_active_hand()
|
||||
if (!W.isHandgun())
|
||||
usr << "\red This gun won't fit in \the belt!"
|
||||
return
|
||||
holstered = usr.get_active_hand()
|
||||
usr.drop_item()
|
||||
holstered.loc = src
|
||||
usr.visible_message("\blue \The [usr] holsters \the [holstered].", "You holster \the [holstered].")
|
||||
else
|
||||
if(istype(usr.get_active_hand(),/obj) && istype(usr.get_inactive_hand(),/obj))
|
||||
usr << "\red You need an empty hand to draw the gun!"
|
||||
else
|
||||
if(usr.a_intent == "hurt")
|
||||
usr.visible_message("\red \The [usr] draws \the [holstered], ready to shoot!", \
|
||||
"\red You draw \the [holstered], ready to shoot!")
|
||||
else
|
||||
usr.visible_message("\blue \The [usr] draws \the [holstered], pointing it at the ground.", \
|
||||
"\blue You draw \the [holstered], pointing it at the ground.")
|
||||
usr.put_in_hands(holstered)
|
||||
holstered = null
|
||||
/obj/item/clothing/suit/armor/tactical/verb/holster()
|
||||
set name = "Holster"
|
||||
set category = "Object"
|
||||
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))
|
||||
usr << "<span class='warning'>You need your gun equiped to holster it.</span>"
|
||||
return
|
||||
holster.holster(W, usr)
|
||||
else
|
||||
holster.unholster(usr)
|
||||
|
||||
//Non-hardsuit ERT armor.
|
||||
/obj/item/clothing/suit/armor/vest/ert
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
item_state = "bluetag"
|
||||
blood_overlay_type = "armor"
|
||||
body_parts_covered = UPPER_TORSO
|
||||
allowed = list (/obj/item/weapon/gun/energy/laser/bluetag)
|
||||
allowed = list (/obj/item/weapon/gun/energy/lasertag/blue)
|
||||
siemens_coefficient = 3.0
|
||||
|
||||
/obj/item/clothing/suit/redtag
|
||||
@@ -25,7 +25,7 @@
|
||||
item_state = "redtag"
|
||||
blood_overlay_type = "armor"
|
||||
body_parts_covered = UPPER_TORSO
|
||||
allowed = list (/obj/item/weapon/gun/energy/laser/redtag)
|
||||
allowed = list (/obj/item/weapon/gun/energy/lasertag/red)
|
||||
siemens_coefficient = 3.0
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
/obj/item/clothing/accessory
|
||||
name = "tie"
|
||||
desc = "A neosilk clip-on tie."
|
||||
icon = 'icons/obj/clothing/ties.dmi'
|
||||
icon_state = "bluetie"
|
||||
item_state = "" //no inhands
|
||||
item_color = "bluetie"
|
||||
slot_flags = SLOT_TIE
|
||||
w_class = 2.0
|
||||
var/slot = "decor"
|
||||
var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to
|
||||
var/image/inv_overlay = null //overlay used when attached to clothing.
|
||||
|
||||
/obj/item/clothing/accessory/New()
|
||||
..()
|
||||
inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[item_color? "[item_color]" : "[icon_state]"]")
|
||||
|
||||
//when user attached an accessory to S
|
||||
/obj/item/clothing/accessory/proc/on_attached(obj/item/clothing/under/S, mob/user as mob)
|
||||
if(!istype(S))
|
||||
return
|
||||
has_suit = S
|
||||
loc = has_suit
|
||||
has_suit.overlays += inv_overlay
|
||||
|
||||
user << "<span class='notice'>You attach [src] to [has_suit].</span>"
|
||||
src.add_fingerprint(user)
|
||||
|
||||
/obj/item/clothing/accessory/proc/on_removed(mob/user as mob)
|
||||
if(!has_suit)
|
||||
return
|
||||
has_suit.overlays -= inv_overlay
|
||||
has_suit = null
|
||||
usr.put_in_hands(src)
|
||||
src.add_fingerprint(user)
|
||||
|
||||
//default attackby behaviour
|
||||
/obj/item/clothing/accessory/attackby(obj/item/I, mob/user)
|
||||
..()
|
||||
|
||||
//default attack_hand behaviour
|
||||
/obj/item/clothing/accessory/attack_hand(mob/user as mob)
|
||||
if(has_suit)
|
||||
return //we aren't an object on the ground so don't call parent
|
||||
..()
|
||||
|
||||
/obj/item/clothing/accessory/blue
|
||||
name = "blue tie"
|
||||
icon_state = "bluetie"
|
||||
item_color = "bluetie"
|
||||
|
||||
/obj/item/clothing/accessory/red
|
||||
name = "red tie"
|
||||
icon_state = "redtie"
|
||||
item_color = "redtie"
|
||||
|
||||
/obj/item/clothing/accessory/horrible
|
||||
name = "horrible tie"
|
||||
desc = "A neosilk clip-on tie. This one is disgusting."
|
||||
icon_state = "horribletie"
|
||||
item_color = "horribletie"
|
||||
|
||||
/obj/item/clothing/accessory/stethoscope
|
||||
name = "stethoscope"
|
||||
desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing."
|
||||
icon_state = "stethoscope"
|
||||
item_color = "stethoscope"
|
||||
|
||||
/obj/item/clothing/accessory/stethoscope/attack(mob/living/carbon/human/M, mob/living/user)
|
||||
if(ishuman(M) && isliving(user))
|
||||
if(user.a_intent == "help")
|
||||
var/body_part = parse_zone(user.zone_sel.selecting)
|
||||
if(body_part)
|
||||
var/their = "their"
|
||||
switch(M.gender)
|
||||
if(MALE) their = "his"
|
||||
if(FEMALE) their = "her"
|
||||
|
||||
var/sound = "pulse"
|
||||
var/sound_strength
|
||||
|
||||
if(M.stat == DEAD || (M.status_flags&FAKEDEATH))
|
||||
sound_strength = "cannot hear"
|
||||
sound = "anything"
|
||||
else
|
||||
sound_strength = "hear a weak"
|
||||
switch(body_part)
|
||||
if("chest")
|
||||
if(M.oxyloss < 50)
|
||||
sound_strength = "hear a healthy"
|
||||
sound = "pulse and respiration"
|
||||
if("eyes","mouth")
|
||||
sound_strength = "cannot hear"
|
||||
sound = "anything"
|
||||
else
|
||||
sound_strength = "hear a weak"
|
||||
|
||||
user.visible_message("[user] places [src] against [M]'s [body_part] and listens attentively.", "You place [src] against [their] [body_part]. You [sound_strength] [sound].")
|
||||
return
|
||||
return ..(M,user)
|
||||
|
||||
|
||||
//Medals
|
||||
/obj/item/clothing/accessory/medal
|
||||
name = "bronze medal"
|
||||
desc = "A bronze medal."
|
||||
icon_state = "bronze"
|
||||
item_color = "bronze"
|
||||
|
||||
/obj/item/clothing/accessory/medal/conduct
|
||||
name = "distinguished conduct medal"
|
||||
desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
|
||||
|
||||
/obj/item/clothing/accessory/medal/bronze_heart
|
||||
name = "bronze heart medal"
|
||||
desc = "A bronze heart-shaped medal awarded for sacrifice. It is often awarded posthumously or for severe injury in the line of duty."
|
||||
icon_state = "bronze_heart"
|
||||
|
||||
/obj/item/clothing/accessory/medal/nobel_science
|
||||
name = "nobel sciences award"
|
||||
desc = "A bronze medal which represents significant contributions to the field of science or engineering."
|
||||
|
||||
/obj/item/clothing/accessory/medal/silver
|
||||
name = "silver medal"
|
||||
desc = "A silver medal."
|
||||
icon_state = "silver"
|
||||
item_color = "silver"
|
||||
|
||||
/obj/item/clothing/accessory/medal/silver/valor
|
||||
name = "medal of valor"
|
||||
desc = "A silver medal awarded for acts of exceptional valor."
|
||||
|
||||
/obj/item/clothing/accessory/medal/silver/security
|
||||
name = "robust security award"
|
||||
desc = "An award for distinguished combat and sacrifice in defence of Nanotrasen's commercial interests. Often awarded to security staff."
|
||||
|
||||
/obj/item/clothing/accessory/medal/gold
|
||||
name = "gold medal"
|
||||
desc = "A prestigious golden medal."
|
||||
icon_state = "gold"
|
||||
item_color = "gold"
|
||||
|
||||
/obj/item/clothing/accessory/medal/gold/captain
|
||||
name = "medal of captaincy"
|
||||
desc = "A golden medal awarded exclusively to those promoted to the rank of captain. It signifies the codified responsibilities of a captain to Nanotrasen, and their undisputable authority over their crew."
|
||||
|
||||
/obj/item/clothing/accessory/medal/gold/heroism
|
||||
name = "medal of exceptional heroism"
|
||||
desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but commanders."
|
||||
|
||||
/*
|
||||
Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized
|
||||
Security agent - the user details can be imprinted on the badge with a Security-access ID card,
|
||||
or they can be emagged to accept any ID for use in disguises.
|
||||
*/
|
||||
|
||||
/obj/item/clothing/accessory/holobadge
|
||||
name = "holobadge"
|
||||
desc = "This glowing blue badge marks the holder as THE LAW."
|
||||
icon_state = "holobadge"
|
||||
item_color = "holobadge"
|
||||
slot_flags = SLOT_BELT | SLOT_TIE
|
||||
|
||||
var/emagged = 0 //Emagging removes Sec check.
|
||||
var/stored_name = null
|
||||
|
||||
/obj/item/clothing/accessory/holobadge/cord
|
||||
icon_state = "holobadge-cord"
|
||||
item_color = "holobadge-cord"
|
||||
slot_flags = SLOT_MASK | SLOT_TIE
|
||||
|
||||
/obj/item/clothing/accessory/holobadge/attack_self(mob/user as mob)
|
||||
if(!stored_name)
|
||||
user << "Waving around a badge before swiping an ID would be pretty pointless."
|
||||
return
|
||||
if(isliving(user))
|
||||
user.visible_message("\red [user] displays their NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","\red You display your NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.")
|
||||
|
||||
/obj/item/clothing/accessory/holobadge/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
|
||||
if (istype(O, /obj/item/weapon/card/emag))
|
||||
if (emagged)
|
||||
user << "\red [src] is already cracked."
|
||||
return
|
||||
else
|
||||
emagged = 1
|
||||
user << "\red You swipe [O] and crack the holobadge security checks."
|
||||
return
|
||||
|
||||
else if(istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda))
|
||||
|
||||
var/obj/item/weapon/card/id/id_card = null
|
||||
|
||||
if(istype(O, /obj/item/weapon/card/id))
|
||||
id_card = O
|
||||
else
|
||||
var/obj/item/device/pda/pda = O
|
||||
id_card = pda.id
|
||||
|
||||
if(access_security in id_card.access || emagged)
|
||||
user << "You imprint your ID details onto the badge."
|
||||
stored_name = id_card.registered_name
|
||||
name = "holobadge ([stored_name])"
|
||||
desc = "This glowing blue badge marks [stored_name] as THE LAW."
|
||||
else
|
||||
user << "[src] rejects your insufficient access rights."
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/accessory/holobadge/attack(mob/living/carbon/human/M, mob/living/user)
|
||||
if(isliving(user))
|
||||
user.visible_message("\red [user] invades [M]'s personal space, thrusting [src] into their face insistently.","\red You invade [M]'s personal space, thrusting [src] into their face insistently. You are the law.")
|
||||
|
||||
/obj/item/weapon/storage/box/holobadge
|
||||
name = "holobadge box"
|
||||
desc = "A box claiming to contain holobadges."
|
||||
New()
|
||||
new /obj/item/clothing/accessory/holobadge(src)
|
||||
new /obj/item/clothing/accessory/holobadge(src)
|
||||
new /obj/item/clothing/accessory/holobadge(src)
|
||||
new /obj/item/clothing/accessory/holobadge(src)
|
||||
new /obj/item/clothing/accessory/holobadge/cord(src)
|
||||
new /obj/item/clothing/accessory/holobadge/cord(src)
|
||||
..()
|
||||
return
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/obj/item/clothing/accessory/armband
|
||||
name = "red armband"
|
||||
desc = "A fancy red armband!"
|
||||
icon_state = "red"
|
||||
item_color = "red"
|
||||
slot = "armband"
|
||||
|
||||
/obj/item/clothing/accessory/armband/cargo
|
||||
name = "cargo armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is brown."
|
||||
icon_state = "cargo"
|
||||
item_color = "cargo"
|
||||
|
||||
/obj/item/clothing/accessory/armband/engine
|
||||
name = "engineering armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is orange with a reflective strip!"
|
||||
icon_state = "engie"
|
||||
item_color = "engie"
|
||||
|
||||
/obj/item/clothing/accessory/armband/science
|
||||
name = "science armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is purple."
|
||||
icon_state = "rnd"
|
||||
item_color = "rnd"
|
||||
|
||||
/obj/item/clothing/accessory/armband/hydro
|
||||
name = "hydroponics armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is green and blue."
|
||||
icon_state = "hydro"
|
||||
item_color = "hydro"
|
||||
|
||||
/obj/item/clothing/accessory/armband/med
|
||||
name = "medical armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is white."
|
||||
icon_state = "med"
|
||||
item_color = "med"
|
||||
|
||||
/obj/item/clothing/accessory/armband/medgreen
|
||||
name = "EMT armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is white and green."
|
||||
icon_state = "medgreen"
|
||||
item_color = "medgreen"
|
||||
@@ -0,0 +1,115 @@
|
||||
/obj/item/clothing/accessory/holster
|
||||
name = "shoulder holster"
|
||||
desc = "A handgun holster."
|
||||
icon_state = "holster"
|
||||
item_color = "holster"
|
||||
slot = "utility"
|
||||
var/obj/item/holstered = null
|
||||
|
||||
/obj/item/clothing/accessory/holster/proc/holster(obj/item/I, mob/user as mob)
|
||||
if(holstered)
|
||||
user << "<span class='warning'>There is already \a [holstered] holstered here!</span>"
|
||||
return
|
||||
|
||||
if (!(I.slot_flags & SLOT_HOLSTER))
|
||||
user << "<span class='warning'>[I] won't fit in [src]!</span>"
|
||||
return
|
||||
|
||||
holstered = I
|
||||
user.drop_from_inventory(holstered)
|
||||
holstered.loc = src
|
||||
holstered.add_fingerprint(user)
|
||||
user.visible_message("<span class='notice'>[user] holsters \the [holstered].</span>", "<span class='notice'>You holster \the [holstered].</span>")
|
||||
|
||||
/obj/item/clothing/accessory/holster/proc/unholster(mob/user as mob)
|
||||
if(!holstered)
|
||||
return
|
||||
|
||||
if(istype(user.get_active_hand(),/obj) && istype(user.get_inactive_hand(),/obj))
|
||||
user << "<span class='warning'>You need an empty hand to draw \the [holstered]!</span>"
|
||||
else
|
||||
if(user.a_intent == "hurt")
|
||||
usr.visible_message(
|
||||
"\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'>You draw \the [holstered], pointing it at the ground.</span>"
|
||||
)
|
||||
user.put_in_hands(holstered)
|
||||
holstered.add_fingerprint(user)
|
||||
holstered = null
|
||||
|
||||
/obj/item/clothing/accessory/holster/attack_hand(mob/user as mob)
|
||||
if (has_suit) //if we are part of a suit
|
||||
if (holstered)
|
||||
unholster(user)
|
||||
return
|
||||
|
||||
..(user)
|
||||
|
||||
/obj/item/clothing/accessory/holster/attackby(obj/item/W as obj, mob/user as mob)
|
||||
holster(W, user)
|
||||
|
||||
/obj/item/clothing/accessory/holster/emp_act(severity)
|
||||
if (holstered)
|
||||
holstered.emp_act(severity)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/accessory/holster/examine(mob/user)
|
||||
..(user)
|
||||
if (holstered)
|
||||
user << "A [holstered] is holstered here."
|
||||
else
|
||||
user << "It is empty."
|
||||
|
||||
/obj/item/clothing/accessory/holster/on_attached(obj/item/clothing/under/S, mob/user as mob)
|
||||
..()
|
||||
has_suit.verbs += /obj/item/clothing/accessory/holster/verb/holster_verb
|
||||
|
||||
/obj/item/clothing/accessory/holster/on_removed(mob/user as mob)
|
||||
has_suit.verbs -= /obj/item/clothing/accessory/holster/verb/holster_verb
|
||||
..()
|
||||
|
||||
//For the holster hotkey
|
||||
/obj/item/clothing/accessory/holster/verb/holster_verb()
|
||||
set name = "Holster"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
if(!istype(usr, /mob/living)) return
|
||||
if(usr.stat) return
|
||||
|
||||
//can't we just use src here?
|
||||
var/obj/item/clothing/accessory/holster/H = null
|
||||
if (istype(src, /obj/item/clothing/accessory/holster))
|
||||
H = src
|
||||
else if (istype(src, /obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/S = src
|
||||
if (S.accessories.len)
|
||||
H = locate() in S.accessories
|
||||
|
||||
if (!H)
|
||||
usr << "<span class='warning'>Something is very wrong.</span>"
|
||||
|
||||
if(!H.holstered)
|
||||
var/obj/item/W = usr.get_active_hand()
|
||||
if(!istype(W, /obj/item))
|
||||
usr << "<span class='warning'>You need your gun equiped to holster it.</span>"
|
||||
return
|
||||
H.holster(W, usr)
|
||||
else
|
||||
H.unholster(usr)
|
||||
|
||||
/obj/item/clothing/accessory/holster/armpit
|
||||
name = "shoulder 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"
|
||||
desc = "A handgun holster. Made of expensive leather."
|
||||
icon_state = "holster"
|
||||
item_color = "holster_low"
|
||||
@@ -0,0 +1,86 @@
|
||||
/obj/item/clothing/accessory/storage
|
||||
name = "load bearing equipment"
|
||||
desc = "Used to hold things when you don't have enough hands."
|
||||
icon_state = "webbing"
|
||||
item_color = "webbing"
|
||||
slot = "utility"
|
||||
var/slots = 3
|
||||
var/obj/item/weapon/storage/internal/hold
|
||||
|
||||
/obj/item/clothing/accessory/storage/New()
|
||||
..()
|
||||
hold = new/obj/item/weapon/storage/internal(src)
|
||||
hold.storage_slots = slots
|
||||
|
||||
/obj/item/clothing/accessory/storage/attack_hand(mob/user as mob)
|
||||
if (has_suit) //if we are part of a suit
|
||||
hold.open(user)
|
||||
return
|
||||
|
||||
if (hold.handle_attack_hand(user)) //otherwise interact as a regular storage item
|
||||
..(user)
|
||||
|
||||
/obj/item/clothing/accessory/storage/MouseDrop(obj/over_object as obj)
|
||||
if (has_suit)
|
||||
return
|
||||
|
||||
if (hold.handle_mousedrop(usr, over_object))
|
||||
..(over_object)
|
||||
|
||||
/obj/item/clothing/accessory/storage/attackby(obj/item/W as obj, mob/user as mob)
|
||||
return hold.attackby(W, user)
|
||||
|
||||
/obj/item/clothing/accessory/storage/emp_act(severity)
|
||||
hold.emp_act(severity)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/accessory/storage/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
|
||||
hold.hear_talk(M, msg, verb, speaking)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/accessory/storage/attack_self(mob/user as mob)
|
||||
user << "<span class='notice'>You empty [src].</span>"
|
||||
var/turf/T = get_turf(src)
|
||||
hold.hide_from(usr)
|
||||
for(var/obj/item/I in hold.contents)
|
||||
hold.remove_from_storage(I, T)
|
||||
src.add_fingerprint(user)
|
||||
|
||||
/obj/item/clothing/accessory/storage/webbing
|
||||
name = "webbing"
|
||||
desc = "Strudy mess of synthcotton belts and buckles, ready to share your burden."
|
||||
icon_state = "webbing"
|
||||
item_color = "webbing"
|
||||
|
||||
/obj/item/clothing/accessory/storage/black_vest
|
||||
name = "black webbing vest"
|
||||
desc = "Robust black synthcotton vest with lots of pockets to hold whatever you need, but cannot hold in hands."
|
||||
icon_state = "vest_black"
|
||||
item_color = "vest_black"
|
||||
slots = 5
|
||||
|
||||
/obj/item/clothing/accessory/storage/brown_vest
|
||||
name = "brown webbing vest"
|
||||
desc = "Worn brownish synthcotton vest with lots of pockets to unload your hands."
|
||||
icon_state = "vest_brown"
|
||||
item_color = "vest_brown"
|
||||
slots = 5
|
||||
|
||||
/obj/item/clothing/accessory/storage/knifeharness
|
||||
name = "decorated harness"
|
||||
desc = "A heavily decorated harness of sinew and leather with two knife-loops."
|
||||
icon_state = "unathiharness2"
|
||||
item_color = "unathiharness2"
|
||||
slots = 2
|
||||
|
||||
/obj/item/clothing/accessory/storage/knifeharness/New()
|
||||
..()
|
||||
hold.max_combined_w_class = 4
|
||||
hold.can_hold = list("/obj/item/weapon/hatchet/unathiknife",\
|
||||
"/obj/item/weapon/kitchen/utensil/knife",\
|
||||
"/obj/item/weapon/kitchen/utensil/pknife",\
|
||||
"/obj/item/weapon/kitchenknife",\
|
||||
"/obj/item/weapon/kitchenknife/ritual")
|
||||
|
||||
new /obj/item/weapon/hatchet/unathiknife(hold)
|
||||
new /obj/item/weapon/hatchet/unathiknife(hold)
|
||||
@@ -130,6 +130,12 @@
|
||||
icon_state = "scrubspurple"
|
||||
item_color = "scrubspurple"
|
||||
|
||||
/obj/item/clothing/under/rank/medical/black
|
||||
name = "medical scrubs"
|
||||
desc = "It's made of a special fiber that provides minor protection against biohazards. This one is in black."
|
||||
icon_state = "scrubsblack"
|
||||
item_color = "scrubsblack"
|
||||
|
||||
/obj/item/clothing/under/rank/psych
|
||||
desc = "A basic white jumpsuit. It has turqouise markings that denote the wearer as a psychiatrist."
|
||||
name = "psychiatrist's jumpsuit"
|
||||
|
||||
@@ -479,9 +479,9 @@
|
||||
/obj/item/clothing/under/serviceoveralls
|
||||
name = "Workman outfit"
|
||||
desc = "The very image of a working man. Not that you're probably doing work."
|
||||
icon_state = "mechanic_s"
|
||||
item_state = "mechanic_s"
|
||||
item_color = "mechanic_s"
|
||||
icon_state = "mechanic"
|
||||
item_state = "mechanic"
|
||||
item_color = "mechanic"
|
||||
|
||||
/obj/item/clothing/under/cheongsam
|
||||
name = "White Cheongsam"
|
||||
|
||||
@@ -1,474 +0,0 @@
|
||||
/obj/item/clothing/tie
|
||||
name = "tie"
|
||||
desc = "A neosilk clip-on tie."
|
||||
icon = 'icons/obj/clothing/ties.dmi'
|
||||
icon_state = "bluetie"
|
||||
item_state = "" //no inhands
|
||||
item_color = "bluetie"
|
||||
slot_flags = SLOT_TIE
|
||||
w_class = 2.0
|
||||
var/obj/item/clothing/under/has_suit = null //the suit the tie may be attached to
|
||||
var/image/inv_overlay = null //overlay used when attached to clothing.
|
||||
|
||||
/obj/item/clothing/tie/New()
|
||||
..()
|
||||
inv_overlay = image("icon" = 'icons/obj/clothing/ties_overlay.dmi', "icon_state" = "[item_color? "[item_color]" : "[icon_state]"]")
|
||||
|
||||
//when user attached an accessory to S
|
||||
/obj/item/clothing/tie/proc/on_attached(obj/item/clothing/under/S, mob/user as mob)
|
||||
if(!istype(S))
|
||||
return
|
||||
has_suit = S
|
||||
loc = has_suit
|
||||
has_suit.overlays += inv_overlay
|
||||
|
||||
user << "<span class='notice'>You attach [src] to [has_suit].</span>"
|
||||
src.add_fingerprint(user)
|
||||
|
||||
/obj/item/clothing/tie/proc/on_removed(mob/user as mob)
|
||||
if(!has_suit)
|
||||
return
|
||||
has_suit.overlays -= inv_overlay
|
||||
has_suit = null
|
||||
usr.put_in_hands(src)
|
||||
src.add_fingerprint(user)
|
||||
|
||||
//default attackby behaviour
|
||||
/obj/item/clothing/tie/attackby(obj/item/I, mob/user)
|
||||
..()
|
||||
|
||||
//default attack_hand behaviour
|
||||
/obj/item/clothing/tie/attack_hand(mob/user as mob)
|
||||
if(has_suit)
|
||||
has_suit.remove_accessory(user)
|
||||
return //we aren't an object on the ground so don't call parent
|
||||
..()
|
||||
|
||||
/obj/item/clothing/tie/blue
|
||||
name = "blue tie"
|
||||
icon_state = "bluetie"
|
||||
item_color = "bluetie"
|
||||
|
||||
/obj/item/clothing/tie/red
|
||||
name = "red tie"
|
||||
icon_state = "redtie"
|
||||
item_color = "redtie"
|
||||
|
||||
/obj/item/clothing/tie/horrible
|
||||
name = "horrible tie"
|
||||
desc = "A neosilk clip-on tie. This one is disgusting."
|
||||
icon_state = "horribletie"
|
||||
item_color = "horribletie"
|
||||
|
||||
/obj/item/clothing/tie/stethoscope
|
||||
name = "stethoscope"
|
||||
desc = "An outdated medical apparatus for listening to the sounds of the human body. It also makes you look like you know what you're doing."
|
||||
icon_state = "stethoscope"
|
||||
item_color = "stethoscope"
|
||||
|
||||
/obj/item/clothing/tie/stethoscope/attack(mob/living/carbon/human/M, mob/living/user)
|
||||
if(ishuman(M) && isliving(user))
|
||||
if(user.a_intent == "help")
|
||||
var/body_part = parse_zone(user.zone_sel.selecting)
|
||||
if(body_part)
|
||||
var/their = "their"
|
||||
switch(M.gender)
|
||||
if(MALE) their = "his"
|
||||
if(FEMALE) their = "her"
|
||||
|
||||
var/sound = "pulse"
|
||||
var/sound_strength
|
||||
|
||||
if(M.stat == DEAD || (M.status_flags&FAKEDEATH))
|
||||
sound_strength = "cannot hear"
|
||||
sound = "anything"
|
||||
else
|
||||
sound_strength = "hear a weak"
|
||||
switch(body_part)
|
||||
if("chest")
|
||||
if(M.oxyloss < 50)
|
||||
sound_strength = "hear a healthy"
|
||||
sound = "pulse and respiration"
|
||||
if("eyes","mouth")
|
||||
sound_strength = "cannot hear"
|
||||
sound = "anything"
|
||||
else
|
||||
sound_strength = "hear a weak"
|
||||
|
||||
user.visible_message("[user] places [src] against [M]'s [body_part] and listens attentively.", "You place [src] against [their] [body_part]. You [sound_strength] [sound].")
|
||||
return
|
||||
return ..(M,user)
|
||||
|
||||
|
||||
//Medals
|
||||
/obj/item/clothing/tie/medal
|
||||
name = "bronze medal"
|
||||
desc = "A bronze medal."
|
||||
icon_state = "bronze"
|
||||
item_color = "bronze"
|
||||
|
||||
/obj/item/clothing/tie/medal/conduct
|
||||
name = "distinguished conduct medal"
|
||||
desc = "A bronze medal awarded for distinguished conduct. Whilst a great honor, this is most basic award given by Nanotrasen. It is often awarded by a captain to a member of his crew."
|
||||
|
||||
/obj/item/clothing/tie/medal/bronze_heart
|
||||
name = "bronze heart medal"
|
||||
desc = "A bronze heart-shaped medal awarded for sacrifice. It is often awarded posthumously or for severe injury in the line of duty."
|
||||
icon_state = "bronze_heart"
|
||||
|
||||
/obj/item/clothing/tie/medal/nobel_science
|
||||
name = "nobel sciences award"
|
||||
desc = "A bronze medal which represents significant contributions to the field of science or engineering."
|
||||
|
||||
/obj/item/clothing/tie/medal/silver
|
||||
name = "silver medal"
|
||||
desc = "A silver medal."
|
||||
icon_state = "silver"
|
||||
item_color = "silver"
|
||||
|
||||
/obj/item/clothing/tie/medal/silver/valor
|
||||
name = "medal of valor"
|
||||
desc = "A silver medal awarded for acts of exceptional valor."
|
||||
|
||||
/obj/item/clothing/tie/medal/silver/security
|
||||
name = "robust security award"
|
||||
desc = "An award for distinguished combat and sacrifice in defence of Nanotrasen's commercial interests. Often awarded to security staff."
|
||||
|
||||
/obj/item/clothing/tie/medal/gold
|
||||
name = "gold medal"
|
||||
desc = "A prestigious golden medal."
|
||||
icon_state = "gold"
|
||||
item_color = "gold"
|
||||
|
||||
/obj/item/clothing/tie/medal/gold/captain
|
||||
name = "medal of captaincy"
|
||||
desc = "A golden medal awarded exclusively to those promoted to the rank of captain. It signifies the codified responsibilities of a captain to Nanotrasen, and their undisputable authority over their crew."
|
||||
|
||||
/obj/item/clothing/tie/medal/gold/heroism
|
||||
name = "medal of exceptional heroism"
|
||||
desc = "An extremely rare golden medal awarded only by CentComm. To recieve such a medal is the highest honor and as such, very few exist. This medal is almost never awarded to anybody but commanders."
|
||||
|
||||
//Armbands
|
||||
/obj/item/clothing/tie/armband
|
||||
name = "red armband"
|
||||
desc = "A fancy red armband!"
|
||||
icon_state = "red"
|
||||
item_color = "red"
|
||||
|
||||
/obj/item/clothing/tie/armband/cargo
|
||||
name = "cargo armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is brown."
|
||||
icon_state = "cargo"
|
||||
item_color = "cargo"
|
||||
|
||||
/obj/item/clothing/tie/armband/engine
|
||||
name = "engineering armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is orange with a reflective strip!"
|
||||
icon_state = "engie"
|
||||
item_color = "engie"
|
||||
|
||||
/obj/item/clothing/tie/armband/science
|
||||
name = "science armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is purple."
|
||||
icon_state = "rnd"
|
||||
item_color = "rnd"
|
||||
|
||||
/obj/item/clothing/tie/armband/hydro
|
||||
name = "hydroponics armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is green and blue."
|
||||
icon_state = "hydro"
|
||||
item_color = "hydro"
|
||||
|
||||
/obj/item/clothing/tie/armband/med
|
||||
name = "medical armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is white."
|
||||
icon_state = "med"
|
||||
item_color = "med"
|
||||
|
||||
/obj/item/clothing/tie/armband/medgreen
|
||||
name = "EMT armband"
|
||||
desc = "An armband, worn by the crew to display which department they're assigned to. This one is white and green."
|
||||
icon_state = "medgreen"
|
||||
item_color = "medgreen"
|
||||
|
||||
//holsters
|
||||
/obj/item/clothing/tie/holster
|
||||
name = "shoulder holster"
|
||||
desc = "A handgun holster."
|
||||
icon_state = "holster"
|
||||
item_color = "holster"
|
||||
var/obj/item/weapon/gun/holstered = null
|
||||
|
||||
//subtypes can override this to specify what can be holstered
|
||||
/obj/item/clothing/tie/holster/proc/can_holster(obj/item/weapon/gun/W)
|
||||
return W.isHandgun()
|
||||
|
||||
/obj/item/clothing/tie/holster/proc/holster(obj/item/I, mob/user as mob)
|
||||
if(holstered)
|
||||
user << "\red There is already a [holstered] holstered here!"
|
||||
return
|
||||
|
||||
if (!istype(I, /obj/item/weapon/gun))
|
||||
user << "\red Only guns can be holstered!"
|
||||
return
|
||||
|
||||
var/obj/item/weapon/gun/W = I
|
||||
if (!can_holster(W))
|
||||
user << "\red This [W] won't fit in the [src]!"
|
||||
return
|
||||
|
||||
holstered = W
|
||||
user.drop_from_inventory(holstered)
|
||||
holstered.loc = src
|
||||
holstered.add_fingerprint(user)
|
||||
user.visible_message("\blue [user] holsters the [holstered].", "You holster the [holstered].")
|
||||
|
||||
/obj/item/clothing/tie/holster/proc/unholster(mob/user as mob)
|
||||
if(!holstered)
|
||||
return
|
||||
|
||||
if(istype(user.get_active_hand(),/obj) && istype(user.get_inactive_hand(),/obj))
|
||||
user << "\red You need an empty hand to draw the [holstered]!"
|
||||
else
|
||||
if(user.a_intent == "hurt")
|
||||
usr.visible_message("\red [user] draws the [holstered], ready to shoot!", \
|
||||
"\red You draw the [holstered], ready to shoot!")
|
||||
else
|
||||
user.visible_message("\blue [user] draws the [holstered], pointing it at the ground.", \
|
||||
"\blue You draw the [holstered], pointing it at the ground.")
|
||||
user.put_in_hands(holstered)
|
||||
holstered.add_fingerprint(user)
|
||||
holstered = null
|
||||
|
||||
/obj/item/clothing/tie/holster/attack_hand(mob/user as mob)
|
||||
if (has_suit) //if we are part of a suit
|
||||
if (holstered)
|
||||
unholster(user)
|
||||
return
|
||||
|
||||
..(user)
|
||||
|
||||
/obj/item/clothing/tie/holster/attackby(obj/item/W as obj, mob/user as mob)
|
||||
holster(W, user)
|
||||
|
||||
/obj/item/clothing/tie/holster/emp_act(severity)
|
||||
if (holstered)
|
||||
holstered.emp_act(severity)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/tie/holster/examine(mob/user)
|
||||
..(user)
|
||||
if (holstered)
|
||||
user << "A [holstered] is holstered here."
|
||||
else
|
||||
user << "It is empty."
|
||||
|
||||
/obj/item/clothing/tie/holster/on_attached(obj/item/clothing/under/S, mob/user as mob)
|
||||
..()
|
||||
has_suit.verbs += /obj/item/clothing/tie/holster/verb/holster_verb
|
||||
|
||||
/obj/item/clothing/tie/holster/on_removed(mob/user as mob)
|
||||
has_suit.verbs -= /obj/item/clothing/tie/holster/verb/holster_verb
|
||||
..()
|
||||
|
||||
//For the holster hotkey
|
||||
/obj/item/clothing/tie/holster/verb/holster_verb()
|
||||
set name = "Holster"
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
if(!istype(usr, /mob/living)) return
|
||||
if(usr.stat) return
|
||||
|
||||
var/obj/item/clothing/tie/holster/H = null
|
||||
if (istype(src, /obj/item/clothing/tie/holster))
|
||||
H = src
|
||||
else if (istype(src, /obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/S = src
|
||||
if (S.hastie)
|
||||
H = S.hastie
|
||||
|
||||
if (!H)
|
||||
usr << "/red Something is very wrong."
|
||||
|
||||
if(!H.holstered)
|
||||
if(!istype(usr.get_active_hand(), /obj/item/weapon/gun))
|
||||
usr << "\blue You need your gun equiped to holster it."
|
||||
return
|
||||
var/obj/item/weapon/gun/W = usr.get_active_hand()
|
||||
H.holster(W, usr)
|
||||
else
|
||||
H.unholster(usr)
|
||||
|
||||
/obj/item/clothing/tie/holster/armpit
|
||||
name = "shoulder holster"
|
||||
desc = "A worn-out handgun holster. Perfect for concealed carry"
|
||||
icon_state = "holster"
|
||||
item_color = "holster"
|
||||
|
||||
/obj/item/clothing/tie/holster/waist
|
||||
name = "shoulder holster"
|
||||
desc = "A handgun holster. Made of expensive leather."
|
||||
icon_state = "holster"
|
||||
item_color = "holster_low"
|
||||
|
||||
/obj/item/clothing/tie/storage
|
||||
name = "load bearing equipment"
|
||||
desc = "Used to hold things when you don't have enough hands."
|
||||
icon_state = "webbing"
|
||||
item_color = "webbing"
|
||||
var/slots = 3
|
||||
var/obj/item/weapon/storage/internal/hold
|
||||
|
||||
/obj/item/clothing/tie/storage/New()
|
||||
..()
|
||||
hold = new/obj/item/weapon/storage/internal(src)
|
||||
hold.storage_slots = slots
|
||||
|
||||
/obj/item/clothing/tie/storage/attack_hand(mob/user as mob)
|
||||
if (has_suit) //if we are part of a suit
|
||||
hold.open(user)
|
||||
return
|
||||
|
||||
if (hold.handle_attack_hand(user)) //otherwise interact as a regular storage item
|
||||
..(user)
|
||||
|
||||
/obj/item/clothing/tie/storage/MouseDrop(obj/over_object as obj)
|
||||
if (has_suit)
|
||||
return
|
||||
|
||||
if (hold.handle_mousedrop(usr, over_object))
|
||||
..(over_object)
|
||||
|
||||
/obj/item/clothing/tie/storage/attackby(obj/item/W as obj, mob/user as mob)
|
||||
return hold.attackby(W, user)
|
||||
|
||||
/obj/item/clothing/tie/storage/emp_act(severity)
|
||||
hold.emp_act(severity)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/tie/storage/hear_talk(mob/M, var/msg, verb, datum/language/speaking)
|
||||
hold.hear_talk(M, msg, verb, speaking)
|
||||
..()
|
||||
|
||||
/obj/item/clothing/tie/storage/attack_self(mob/user as mob)
|
||||
user << "<span class='notice'>You empty [src].</span>"
|
||||
var/turf/T = get_turf(src)
|
||||
hold.hide_from(usr)
|
||||
for(var/obj/item/I in hold.contents)
|
||||
hold.remove_from_storage(I, T)
|
||||
src.add_fingerprint(user)
|
||||
|
||||
/obj/item/clothing/tie/storage/webbing
|
||||
name = "webbing"
|
||||
desc = "Strudy mess of synthcotton belts and buckles, ready to share your burden."
|
||||
icon_state = "webbing"
|
||||
item_color = "webbing"
|
||||
|
||||
/obj/item/clothing/tie/storage/black_vest
|
||||
name = "black webbing vest"
|
||||
desc = "Robust black synthcotton vest with lots of pockets to hold whatever you need, but cannot hold in hands."
|
||||
icon_state = "vest_black"
|
||||
item_color = "vest_black"
|
||||
slots = 5
|
||||
|
||||
/obj/item/clothing/tie/storage/brown_vest
|
||||
name = "brown webbing vest"
|
||||
desc = "Worn brownish synthcotton vest with lots of pockets to unload your hands."
|
||||
icon_state = "vest_brown"
|
||||
item_color = "vest_brown"
|
||||
slots = 5
|
||||
/*
|
||||
Holobadges are worn on the belt or neck, and can be used to show that the holder is an authorized
|
||||
Security agent - the user details can be imprinted on the badge with a Security-access ID card,
|
||||
or they can be emagged to accept any ID for use in disguises.
|
||||
*/
|
||||
|
||||
/obj/item/clothing/tie/holobadge
|
||||
|
||||
name = "holobadge"
|
||||
desc = "This glowing blue badge marks the holder as THE LAW."
|
||||
icon_state = "holobadge"
|
||||
item_color = "holobadge"
|
||||
slot_flags = SLOT_BELT | SLOT_TIE
|
||||
|
||||
var/emagged = 0 //Emagging removes Sec check.
|
||||
var/stored_name = null
|
||||
|
||||
/obj/item/clothing/tie/holobadge/cord
|
||||
icon_state = "holobadge-cord"
|
||||
item_color = "holobadge-cord"
|
||||
slot_flags = SLOT_MASK | SLOT_TIE
|
||||
|
||||
/obj/item/clothing/tie/holobadge/attack_self(mob/user as mob)
|
||||
if(!stored_name)
|
||||
user << "Waving around a badge before swiping an ID would be pretty pointless."
|
||||
return
|
||||
if(isliving(user))
|
||||
user.visible_message("\red [user] displays their NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.","\red You display your NanoTrasen Internal Security Legal Authorization Badge.\nIt reads: [stored_name], NT Security.")
|
||||
|
||||
/obj/item/clothing/tie/holobadge/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
|
||||
if (istype(O, /obj/item/weapon/card/emag))
|
||||
if (emagged)
|
||||
user << "\red [src] is already cracked."
|
||||
return
|
||||
else
|
||||
emagged = 1
|
||||
user << "\red You swipe [O] and crack the holobadge security checks."
|
||||
return
|
||||
|
||||
else if(istype(O, /obj/item/weapon/card/id) || istype(O, /obj/item/device/pda))
|
||||
|
||||
var/obj/item/weapon/card/id/id_card = null
|
||||
|
||||
if(istype(O, /obj/item/weapon/card/id))
|
||||
id_card = O
|
||||
else
|
||||
var/obj/item/device/pda/pda = O
|
||||
id_card = pda.id
|
||||
|
||||
if(access_security in id_card.access || emagged)
|
||||
user << "You imprint your ID details onto the badge."
|
||||
stored_name = id_card.registered_name
|
||||
name = "holobadge ([stored_name])"
|
||||
desc = "This glowing blue badge marks [stored_name] as THE LAW."
|
||||
else
|
||||
user << "[src] rejects your insufficient access rights."
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/clothing/tie/holobadge/attack(mob/living/carbon/human/M, mob/living/user)
|
||||
if(isliving(user))
|
||||
user.visible_message("\red [user] invades [M]'s personal space, thrusting [src] into their face insistently.","\red You invade [M]'s personal space, thrusting [src] into their face insistently. You are the law.")
|
||||
|
||||
/obj/item/weapon/storage/box/holobadge
|
||||
name = "holobadge box"
|
||||
desc = "A box claiming to contain holobadges."
|
||||
New()
|
||||
new /obj/item/clothing/tie/holobadge(src)
|
||||
new /obj/item/clothing/tie/holobadge(src)
|
||||
new /obj/item/clothing/tie/holobadge(src)
|
||||
new /obj/item/clothing/tie/holobadge(src)
|
||||
new /obj/item/clothing/tie/holobadge/cord(src)
|
||||
new /obj/item/clothing/tie/holobadge/cord(src)
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/item/clothing/tie/storage/knifeharness
|
||||
name = "decorated harness"
|
||||
desc = "A heavily decorated harness of sinew and leather with two knife-loops."
|
||||
icon_state = "unathiharness2"
|
||||
item_color = "unathiharness2"
|
||||
slots = 2
|
||||
|
||||
/obj/item/clothing/tie/storage/knifeharness/New()
|
||||
..()
|
||||
hold.max_combined_w_class = 4
|
||||
hold.can_hold = list("/obj/item/weapon/hatchet/unathiknife",\
|
||||
"/obj/item/weapon/kitchen/utensil/knife",\
|
||||
"/obj/item/weapon/kitchen/utensil/pknife",\
|
||||
"/obj/item/weapon/kitchenknife",\
|
||||
"/obj/item/weapon/kitchenknife/ritual")
|
||||
|
||||
new /obj/item/weapon/hatchet/unathiknife(hold)
|
||||
new /obj/item/weapon/hatchet/unathiknife(hold)
|
||||
@@ -114,7 +114,7 @@
|
||||
|
||||
/////////////////////// Cataguettes - Lucy's Stethoscope - Lucy Kemmerer //////
|
||||
|
||||
/obj/item/clothing/tie/stethoscope/fluff/lucystethos
|
||||
/obj/item/clothing/accessory/stethoscope/fluff/lucystethos
|
||||
name = "Lucy's Stethoscope"
|
||||
desc = "A medical apparatus intended to ease in listening to the sounds of the human body. This one looks cleaner and sparklier than the rest. There is a small silver plaque attached to the tubing, with the words 'Lucy Kemmerer' engraved on it."
|
||||
icon_state = "lucystethos"
|
||||
@@ -1111,22 +1111,33 @@
|
||||
item_color = "lillian_dress"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO
|
||||
|
||||
////// Cybernetic Casings - Parker Eliza - MrSnapwalk
|
||||
////// Tailored Security Uniform - Parker Eliza - MrSnapwalk
|
||||
|
||||
/obj/item/clothing/under/fluff/parkereliza
|
||||
name = "cybernetic casings"
|
||||
desc = "A set of somewhat bulky white casings for robotic limbs, paired with a basic blue tank top and black cargo pants. The arms have a small label on the inner elbow, which reads \"Bishop Corporation Cybernetic Solutions\"."
|
||||
name = "tailored security uniform"
|
||||
desc = "A red uniform shirt (tailored for easy access to the shoulder joint) and black cargo pants, paired with a set of somewhat bulky white casings for robotic limbs. The arms have a small label on the inner elbow, which reads \"Bishop Corporation Cybernetic Solutions\"."
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
icon_state = "parker_eliza"
|
||||
item_state = "parker_eliza"
|
||||
item_color = "parker_eliza"
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
|
||||
|
||||
////// Bishop "GOLEM" V2200 Industrial Limb Augments - Parker Eliza - MrSnapwalk
|
||||
|
||||
/obj/item/clothing/suit/fluff/parkereliza
|
||||
name = "Bishop \"GOLEM\" V2200 Industrial Limb Augments"
|
||||
desc = "A set of top-of-the-line cyberlimbs, only usable to someone with extensive bone structure augmentation. Often used in industrial applications, they are capable of throwing a man clear across a room. The load limitation circuit in this set appears to be modified."
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
icon_state = "parker_eliza_arms"
|
||||
item_state = "parker_eliza_arms"
|
||||
item_color = "parker_eliza_arms"
|
||||
|
||||
|
||||
////////////// Accessories /////
|
||||
|
||||
//////////////////// Blood Red Pendant - Mewth - Mu'taz Radi ////////////////
|
||||
|
||||
/obj/item/clothing/tie/fluff/radi
|
||||
/obj/item/clothing/accessory/fluff/radi
|
||||
name = "Blood Red Pendant"
|
||||
desc = "A blue chained necklace with a ruby in the middle, it looks pretty!"
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
@@ -1168,7 +1179,7 @@
|
||||
|
||||
////// Small locket - Altair An-Nasaqan - Serithi
|
||||
|
||||
/obj/item/clothing/tie/fluff/altair_locket
|
||||
/obj/item/clothing/accessory/fluff/altair_locket
|
||||
name = "small locket"
|
||||
desc = "A small golden locket attached to an Ii'rka-reed string. Inside the locket is a holo-picture of a female Tajaran, and an inscription writtin in Siik'mas."
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
@@ -1181,7 +1192,7 @@
|
||||
|
||||
////// Silver locket - Konaa Hirano - Konaa_Hirano
|
||||
|
||||
/obj/item/clothing/tie/fluff/konaa_hirano
|
||||
/obj/item/clothing/accessory/fluff/konaa_hirano
|
||||
name = "silver locket"
|
||||
desc = "This oval shaped, argentium sterling silver locket hangs on an incredibly fine, refractive string, almost thin as hair and microweaved from links to a deceptive strength, of similar material. The edges are engraved very delicately with an elegant curving design, but overall the main is unmarked and smooth to the touch, leaving room for either remaining as a stolid piece or future alterations. There is an obvious internal place for a picture or lock of some sort, but even behind that is a very thin compartment unhinged with the pinch of a thumb and forefinger."
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
@@ -1193,13 +1204,13 @@
|
||||
slot_flags = SLOT_MASK | SLOT_TIE
|
||||
var/obj/item/held //Item inside locket.
|
||||
|
||||
/obj/item/clothing/tie/fluff/konaa_hirano/attack_self(mob/user as mob)
|
||||
/obj/item/clothing/accessory/fluff/konaa_hirano/attack_self(mob/user as mob)
|
||||
if(held)
|
||||
user << "You open [src] and [held] falls out."
|
||||
held.loc = get_turf(user)
|
||||
src.held = null
|
||||
|
||||
/obj/item/clothing/tie/fluff/konaa_hirano/attackby(var/obj/item/O as obj, mob/user as mob)
|
||||
/obj/item/clothing/accessory/fluff/konaa_hirano/attackby(var/obj/item/O as obj, mob/user as mob)
|
||||
if(istype(O,/obj/item/weapon/paper))
|
||||
if(held)
|
||||
usr << "[src] already has something inside it."
|
||||
@@ -1213,7 +1224,7 @@
|
||||
|
||||
////// Medallion - Nasir Khayyam - Jamini
|
||||
|
||||
/obj/item/clothing/tie/fluff/nasir_khayyam_1
|
||||
/obj/item/clothing/accessory/fluff/nasir_khayyam_1
|
||||
name = "medallion"
|
||||
desc = "This silvered medallion bears the symbol of the Hadii Clan of the Tajaran."
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
@@ -1329,22 +1340,21 @@
|
||||
desc = "A stun baton used for incapacitating targets; there seems to be a bunch of tally marks set into the handle."
|
||||
|
||||
///// Deckard .44 - Callum Leamas - Roaper
|
||||
/obj/item/weapon/gun/projectile/detective/fluff/callum_leamas
|
||||
/obj/item/weapon/gun/projectile/revolver/detective/fluff/callum_leamas
|
||||
name = "Deckard .44"
|
||||
desc = "A custom built revolver, based off the semi-popular Detective Special model."
|
||||
icon = 'icons/obj/custom_items.dmi'
|
||||
icon_state = "leamas-empty"
|
||||
ammo_type = /obj/item/ammo_magazine/c38/rubber
|
||||
|
||||
/obj/item/weapon/gun/projectile/detective/fluff/callum_leamas/update_icon()
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/detective/fluff/callum_leamas/update_icon()
|
||||
..()
|
||||
if(loaded.len)
|
||||
icon_state = "leamas-loaded"
|
||||
else
|
||||
icon_state = "leamas-empty"
|
||||
|
||||
/obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob)
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/detective/fluff/callum_leamas/load_ammo(var/obj/item/A, mob/user)
|
||||
if(istype(A, /obj/item/ammo_magazine))
|
||||
flick("leamas-reloading",src)
|
||||
..()
|
||||
|
||||
@@ -180,11 +180,7 @@ I said no!
|
||||
)
|
||||
result = /obj/item/weapon/reagent_containers/food/snacks/donkpocket //SPECIAL
|
||||
proc/warm_up(var/obj/item/weapon/reagent_containers/food/snacks/donkpocket/being_cooked)
|
||||
being_cooked.warm = 1
|
||||
being_cooked.reagents.add_reagent("tricordrazine", 5)
|
||||
being_cooked.bitesize = 6
|
||||
being_cooked.name = "Warm " + being_cooked.name
|
||||
being_cooked.cooltime()
|
||||
being_cooked.heat()
|
||||
make_food(var/obj/container as obj)
|
||||
var/obj/item/weapon/reagent_containers/food/snacks/donkpocket/being_cooked = ..(container)
|
||||
warm_up(being_cooked)
|
||||
|
||||
@@ -11,66 +11,80 @@
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker = null
|
||||
var/points = 0
|
||||
var/menustat = "menu"
|
||||
var/build_eff = 1
|
||||
var/eat_eff = 1
|
||||
|
||||
New()
|
||||
..()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
reagents = R
|
||||
R.my_atom = src
|
||||
beaker = new /obj/item/weapon/reagent_containers/glass/beaker/large(src)
|
||||
/obj/machinery/biogenerator/New()
|
||||
..()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
reagents = R
|
||||
R.my_atom = src
|
||||
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
|
||||
|
||||
on_reagent_change() //When the reagents change, change the icon as well.
|
||||
update_icon()
|
||||
component_parts = list()
|
||||
component_parts += new /obj/item/weapon/circuitboard/biogenerator(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
|
||||
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well.
|
||||
update_icon()
|
||||
if(!src.beaker)
|
||||
icon_state = "biogen-empty"
|
||||
else if(!src.processing)
|
||||
icon_state = "biogen-stand"
|
||||
else
|
||||
icon_state = "biogen-work"
|
||||
return
|
||||
|
||||
/obj/machinery/biogenerator/update_icon()
|
||||
if(!beaker)
|
||||
icon_state = "biogen-empty"
|
||||
else if(!processing)
|
||||
icon_state = "biogen-stand"
|
||||
else
|
||||
icon_state = "biogen-work"
|
||||
return
|
||||
|
||||
/obj/machinery/biogenerator/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(default_deconstruction_screwdriver(user, O))
|
||||
return
|
||||
if(default_deconstruction_crowbar(user, O))
|
||||
return
|
||||
if(default_part_replacement(user, O))
|
||||
return
|
||||
if(istype(O, /obj/item/weapon/reagent_containers/glass))
|
||||
if(beaker)
|
||||
user << "\red The biogenerator is already loaded."
|
||||
user << "<span class='notice'>]The [src] is already loaded.</span>"
|
||||
else
|
||||
user.before_take_item(O)
|
||||
O.loc = src
|
||||
beaker = O
|
||||
updateUsrDialog()
|
||||
else if(processing)
|
||||
user << "\red The biogenerator is currently processing."
|
||||
user << "<span class='notice'>\The [src] is currently processing.</span>"
|
||||
else if(istype(O, /obj/item/weapon/storage/bag/plants))
|
||||
var/i = 0
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents)
|
||||
i++
|
||||
if(i >= 10)
|
||||
user << "\red The biogenerator is already full! Activate it."
|
||||
user << "<span class='notice'>\The [src] is already full! Activate it.</span>"
|
||||
else
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in O.contents)
|
||||
G.loc = src
|
||||
i++
|
||||
if(i >= 10)
|
||||
user << "\blue You fill the biogenerator to its capacity."
|
||||
user << "<span class='notice'>You fill \the [src] to its capacity.</span>"
|
||||
break
|
||||
if(i<10)
|
||||
user << "\blue You empty the plant bag into the biogenerator."
|
||||
|
||||
if(i < 10)
|
||||
user << "<span class='notice'>You empty \the [O] into \the [src].</span>"
|
||||
|
||||
else if(!istype(O, /obj/item/weapon/reagent_containers/food/snacks/grown))
|
||||
user << "\red You cannot put this in [src.name]"
|
||||
user << "<span class='notice'>You cannot put this in \the [src].</span>"
|
||||
else
|
||||
var/i = 0
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in contents)
|
||||
i++
|
||||
if(i >= 10)
|
||||
user << "\red The biogenerator is full! Activate it."
|
||||
user << "<span class='notice'>\The [src] is full! Activate it.</span>"
|
||||
else
|
||||
user.before_take_item(O)
|
||||
O.loc = src
|
||||
user << "\blue You put [O.name] in [src.name]"
|
||||
user << "<span class='notice'>You put \the [O] in \the [src]</span>"
|
||||
update_icon()
|
||||
return
|
||||
|
||||
@@ -89,18 +103,18 @@
|
||||
dat += "<A href='?src=\ref[src];action=activate'>Activate Biogenerator!</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=detach'>Detach Container</A><BR><BR>"
|
||||
dat += "Food<BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=milk;cost=20'>10 milk</A> <FONT COLOR=blue>(20)</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=meat;cost=50'>Slab of meat</A> <FONT COLOR=blue>(50)</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=milk;cost=20'>10 milk</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=meat;cost=50'>Slab of meat</A> <FONT COLOR=blue>([round(50/build_eff)])</FONT><BR>"
|
||||
dat += "Nutrient<BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=ez;cost=10'>E-Z-Nutrient</A> <FONT COLOR=blue>(10)</FONT> | <A href='?src=\ref[src];action=create;item=ez5;cost=50'>x5</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=l4z;cost=20'>Left 4 Zed</A> <FONT COLOR=blue>(20)</FONT> | <A href='?src=\ref[src];action=create;item=l4z5;cost=100'>x5</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=rh;cost=25'>Robust Harvest</A> <FONT COLOR=blue>(25)</FONT> | <A href='?src=\ref[src];action=create;item=rh5;cost=125'>x5</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=ez;cost=10'>E-Z-Nutrient</A> <FONT COLOR=blue>([round(10/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=ez5;cost=50'>x5</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=l4z;cost=20'>Left 4 Zed</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=l4z5;cost=100'>x5</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=rh;cost=25'>Robust Harvest</A> <FONT COLOR=blue>([round(25/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=rh5;cost=125'>x5</A><BR>"
|
||||
dat += "Leather<BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=wallet;cost=100'>Wallet</A> <FONT COLOR=blue>(100)</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=gloves;cost=250'>Botanical gloves</A> <FONT COLOR=blue>(250)</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=tbelt;cost=300'>Utility belt</A> <FONT COLOR=blue>(300)</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=satchel;cost=400'>Leather Satchel</A> <FONT COLOR=blue>(400)</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=cashbag;cost=400'>Cash Bag</A> <FONT COLOR=blue>(400)</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=wallet;cost=100'>Wallet</A> <FONT COLOR=blue>([round(100/build_eff)])</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=gloves;cost=250'>Botanical gloves</A> <FONT COLOR=blue>([round(250/build_eff)])</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=tbelt;cost=300'>Utility belt</A> <FONT COLOR=blue>([round(300/build_eff)])</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=satchel;cost=400'>Leather Satchel</A> <FONT COLOR=blue>([round(400/build_eff)])</FONT><BR>"
|
||||
dat += "<A href='?src=\ref[src];action=create;item=cashbag;cost=400'>Cash Bag</A> <FONT COLOR=blue>([round(400/build_eff)])</FONT><BR>"
|
||||
//dat += "Other<BR>"
|
||||
//dat += "<A href='?src=\ref[src];action=create;item=monkey;cost=500'>Monkey</A> <FONT COLOR=blue>(500)</FONT><BR>"
|
||||
else
|
||||
@@ -122,34 +136,35 @@
|
||||
interact(user)
|
||||
|
||||
/obj/machinery/biogenerator/proc/activate()
|
||||
if (usr.stat != 0)
|
||||
if (usr.stat)
|
||||
return
|
||||
if (src.stat != 0) //NOPOWER etc
|
||||
if (stat) //NOPOWER etc
|
||||
return
|
||||
if(src.processing)
|
||||
usr << "\red The biogenerator is in the process of working."
|
||||
if(processing)
|
||||
usr << "<span class='notice'>The biogenerator is in the process of working.</span>"
|
||||
return
|
||||
var/S = 0
|
||||
for(var/obj/item/weapon/reagent_containers/food/snacks/grown/I in contents)
|
||||
S += 5
|
||||
if(I.reagents.get_reagent_amount("nutriment") < 0.1)
|
||||
points += 1
|
||||
else points += I.reagents.get_reagent_amount("nutriment")*10
|
||||
else points += I.reagents.get_reagent_amount("nutriment") * 10 * eat_eff
|
||||
del(I)
|
||||
if(S)
|
||||
processing = 1
|
||||
update_icon()
|
||||
updateUsrDialog()
|
||||
playsound(src.loc, 'sound/machines/blender.ogg', 50, 1)
|
||||
use_power(S*30)
|
||||
sleep(S+15)
|
||||
use_power(S * 30)
|
||||
sleep((S + 15) / eat_eff)
|
||||
processing = 0
|
||||
update_icon()
|
||||
else
|
||||
menustat = "void"
|
||||
return
|
||||
|
||||
/obj/machinery/biogenerator/proc/create_product(var/item,var/cost)
|
||||
/obj/machinery/biogenerator/proc/create_product(var/item, var/cost)
|
||||
cost = round(cost/build_eff)
|
||||
if(cost > points)
|
||||
menustat = "nopoints"
|
||||
return 0
|
||||
@@ -160,45 +175,45 @@
|
||||
sleep(30)
|
||||
switch(item)
|
||||
if("milk")
|
||||
beaker.reagents.add_reagent("milk",10)
|
||||
beaker.reagents.add_reagent("milk", 10)
|
||||
if("meat")
|
||||
new/obj/item/weapon/reagent_containers/food/snacks/meat(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
|
||||
if("ez")
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
|
||||
if("l4z")
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
|
||||
if("rh")
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
|
||||
if("ez5") //It's not an elegant method, but it's safe and easy. -Cheridan
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/ez(loc)
|
||||
if("l4z5")
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/l4z(loc)
|
||||
if("rh5")
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(src.loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
|
||||
new/obj/item/weapon/reagent_containers/glass/fertilizer/rh(loc)
|
||||
if("wallet")
|
||||
new/obj/item/weapon/storage/wallet(src.loc)
|
||||
new/obj/item/weapon/storage/wallet(loc)
|
||||
if("gloves")
|
||||
new/obj/item/clothing/gloves/botanic_leather(src.loc)
|
||||
new/obj/item/clothing/gloves/botanic_leather(loc)
|
||||
if("tbelt")
|
||||
new/obj/item/weapon/storage/belt/utility(src.loc)
|
||||
new/obj/item/weapon/storage/belt/utility(loc)
|
||||
if("satchel")
|
||||
new/obj/item/weapon/storage/backpack/satchel(src.loc)
|
||||
new/obj/item/weapon/storage/backpack/satchel(loc)
|
||||
if("cashbag")
|
||||
new/obj/item/weapon/storage/bag/cash(src.loc)
|
||||
new/obj/item/weapon/storage/bag/cash(loc)
|
||||
if("monkey")
|
||||
new/mob/living/carbon/monkey(src.loc)
|
||||
new/mob/living/carbon/monkey(loc)
|
||||
processing = 0
|
||||
menustat = "complete"
|
||||
update_icon()
|
||||
@@ -220,7 +235,21 @@
|
||||
beaker = null
|
||||
update_icon()
|
||||
if("create")
|
||||
create_product(href_list["item"],text2num(href_list["cost"]))
|
||||
create_product(href_list["item"], text2num(href_list["cost"]))
|
||||
if("menu")
|
||||
menustat = "menu"
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/biogenerator/RefreshParts()
|
||||
..()
|
||||
var/man_rating = 0
|
||||
var/bin_rating = 0
|
||||
|
||||
for(var/obj/item/weapon/stock_parts/P in component_parts)
|
||||
if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
|
||||
bin_rating += P.rating
|
||||
if(istype(P, /obj/item/weapon/stock_parts/manipulator))
|
||||
man_rating += P.rating
|
||||
|
||||
build_eff = man_rating
|
||||
eat_eff = bin_rating
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
else if(grown_seed.heat_tolerance < 10)
|
||||
dat += "<br>It is very sensitive to temperature shifts."
|
||||
|
||||
dat += "<br>It thrives in a light level of [grown_seed.ideal_light] lumen[grown_seed.ideal_light == 1 ? "" : "s"]."
|
||||
dat += "<br>It thrives in a light level of [grown_seed.ideal_light] lumen\s."
|
||||
|
||||
if(grown_seed.light_tolerance > 10)
|
||||
dat += "<br>It is well adapted to a range of light levels."
|
||||
|
||||
@@ -256,7 +256,7 @@ proc/populate_seed_list()
|
||||
|
||||
if(prob(90))
|
||||
requires_nutrients = 1
|
||||
nutrient_consumption = rand(100)*0.1
|
||||
nutrient_consumption = rand(25)/100
|
||||
else
|
||||
requires_nutrients = 0
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
/obj/structure/closet/crate/secure/loot/New()
|
||||
..()
|
||||
var/list/digits = list("1", "2", "3", "4", "5", "6", "7", "8", "9", "0")
|
||||
|
||||
|
||||
code = ""
|
||||
for(var/i = 0, i < codelen, i++)
|
||||
var/dig = pick(digits)
|
||||
code += dig
|
||||
digits -= dig // Player can enter codes with matching digits, but there are never matching digits in the answer
|
||||
|
||||
|
||||
var/loot = rand(1, 100)
|
||||
switch(loot)
|
||||
if(1 to 5) // Common things go, 5%
|
||||
@@ -53,7 +53,7 @@
|
||||
if(46 to 50)
|
||||
new/obj/item/clothing/under/chameleon(src)
|
||||
for(var/i = 0, i < 7, i++)
|
||||
new/obj/item/clothing/tie/horrible(src)
|
||||
new/obj/item/clothing/accessory/horrible(src)
|
||||
if(51 to 52) // Uncommon, 2% each
|
||||
new/obj/item/weapon/melee/classic_baton(src)
|
||||
if(53 to 54)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"exotic matter" = 0
|
||||
)
|
||||
|
||||
for(var/turf/T in oview(3,get_turf(user)))
|
||||
for(var/turf/T in range(3,get_turf(user)))
|
||||
|
||||
if(!T.has_resources)
|
||||
continue
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
return
|
||||
else
|
||||
if(language)
|
||||
message = language.scramble(language)
|
||||
message = language.scramble(message)
|
||||
else
|
||||
message = stars(message)
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#define SCRAMBLE_CACHE_LEN 20
|
||||
|
||||
/*
|
||||
Datum based languages. Easily editable and modular.
|
||||
*/
|
||||
@@ -35,11 +37,21 @@
|
||||
|
||||
return "[trim(full_name)]"
|
||||
|
||||
/datum/language
|
||||
var/list/scramble_cache = list()
|
||||
|
||||
/datum/language/proc/scramble(var/input)
|
||||
|
||||
if(!syllables || !syllables.len)
|
||||
return stars(input)
|
||||
|
||||
// If the input is cached already, move it to the end of the cache and return it
|
||||
if(input in scramble_cache)
|
||||
var/n = scramble_cache[input]
|
||||
scramble_cache -= input
|
||||
scramble_cache[input] = n
|
||||
return n
|
||||
|
||||
var/input_size = length(input)
|
||||
var/scrambled_text = ""
|
||||
var/capitalize = 1
|
||||
@@ -64,6 +76,13 @@
|
||||
var/input_ending = copytext(input, input_size)
|
||||
if(input_ending in list("!","?","."))
|
||||
scrambled_text += input_ending
|
||||
|
||||
// Add it to cache, cutting old entries if the list is too long
|
||||
scramble_cache[input] = scrambled_text
|
||||
if(scramble_cache.len > SCRAMBLE_CACHE_LEN)
|
||||
scramble_cache.Cut(1, scramble_cache.len-SCRAMBLE_CACHE_LEN-1)
|
||||
|
||||
|
||||
return scrambled_text
|
||||
|
||||
/datum/language/proc/format_message(message, verb)
|
||||
@@ -496,4 +515,6 @@
|
||||
"al", "an", "ar", "as", "at", "ea", "ed", "en", "er", "es", "ha", "he", "hi", "in", "is", "it",
|
||||
"le", "me", "nd", "ne", "ng", "nt", "on", "or", "ou", "re", "se", "st", "te", "th", "ti", "to",
|
||||
"ve", "wa", "all", "and", "are", "but", "ent", "era", "ere", "eve", "for", "had", "hat", "hen", "her", "hin",
|
||||
"his", "ing", "ion", "ith", "not", "ome", "oul", "our", "sho", "ted", "ter", "tha", "the", "thi")
|
||||
"his", "ing", "ion", "ith", "not", "ome", "oul", "our", "sho", "ted", "ter", "tha", "the", "thi")
|
||||
|
||||
#undef SCRAMBLE_CACHE_LEN
|
||||
@@ -63,8 +63,8 @@
|
||||
var/tie_msg
|
||||
if(istype(w_uniform,/obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/U = w_uniform
|
||||
if(U.hastie)
|
||||
tie_msg += " with \icon[U.hastie] \a [U.hastie]"
|
||||
if(U.accessories.len)
|
||||
tie_msg += " with [lowertext(english_list(U.accessories))]"
|
||||
|
||||
if(w_uniform.blood_DNA)
|
||||
msg += "<span class='warning'>[t_He] [t_is] wearing \icon[w_uniform] [w_uniform.gender==PLURAL?"some":"a"] [(w_uniform.blood_color != "#030303") ? "blood" : "oil"]-stained [w_uniform.name][tie_msg]!</span>\n"
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
<BR><B>Suit Storage:</B> <A href='?src=\ref[src];item=s_store'>[(s_store ? s_store : "Nothing")]</A> [((istype(wear_mask, /obj/item/clothing/mask) && istype(s_store, /obj/item/weapon/tank) && !( internal )) ? text(" <A href='?src=\ref[];item=internal'>Set Internal</A>", src) : "")]
|
||||
<BR>[(handcuffed ? text("<A href='?src=\ref[src];item=handcuff'>Handcuffed</A>") : text("<A href='?src=\ref[src];item=handcuff'>Not Handcuffed</A>"))]
|
||||
<BR>[(legcuffed ? text("<A href='?src=\ref[src];item=legcuff'>Legcuffed</A>") : text(""))]
|
||||
<BR>[(suit) ? ((suit.hastie) ? text(" <A href='?src=\ref[];item=tie'>Remove Accessory</A>", src) : "") :]
|
||||
<BR>[(suit) ? ((suit.accessories.len) ? text(" <A href='?src=\ref[];item=tie'>Remove Accessory</A>", src) : "") :]
|
||||
<BR>[(internal ? text("<A href='?src=\ref[src];item=internal'>Remove Internal</A>") : "")]
|
||||
<BR><A href='?src=\ref[src];item=splints'>Remove Splints</A>
|
||||
<BR><A href='?src=\ref[src];item=pockets'>Empty Pockets</A>
|
||||
@@ -1220,10 +1220,11 @@
|
||||
/mob/living/carbon/human/can_inject(var/mob/user, var/error_msg, var/target_zone)
|
||||
. = 1
|
||||
|
||||
if(!user)
|
||||
target_zone = pick("chest","chest","chest","left leg","right leg","left arm", "right arm", "head")
|
||||
else if(!target_zone)
|
||||
target_zone = user.zone_sel.selecting
|
||||
if(!target_zone)
|
||||
if(!user)
|
||||
target_zone = pick("chest","chest","chest","left leg","right leg","left arm", "right arm", "head")
|
||||
else
|
||||
target_zone = user.zone_sel.selecting
|
||||
|
||||
switch(target_zone)
|
||||
if("head")
|
||||
@@ -1301,4 +1302,4 @@
|
||||
/mob/living/carbon/human/slip(var/slipped_on, stun_duration=8)
|
||||
if((species.flags & NO_SLIP) || (shoes && (shoes.flags & NOSLIP)))
|
||||
return 0
|
||||
..(slipped_on,stun_duration)
|
||||
..(slipped_on,stun_duration)
|
||||
|
||||
@@ -24,7 +24,7 @@ emp_act
|
||||
if(!(def_zone in list("chest", "groin")))
|
||||
reflectchance /= 2
|
||||
if(prob(reflectchance))
|
||||
visible_message("\red <B>The [P.name] gets reflected by [src]'s [wear_suit.name]!</B>")
|
||||
visible_message("\red <B>\The [P] gets reflected by \the [src]'s [wear_suit.name]!</B>")
|
||||
|
||||
// Find a turf near or on the original location to bounce to
|
||||
if(P.starting)
|
||||
@@ -33,12 +33,7 @@ emp_act
|
||||
var/turf/curloc = get_turf(src)
|
||||
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.current = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
P.redirect(new_x, new_y, curloc, src)
|
||||
|
||||
return -1 // complete projectile permutation
|
||||
|
||||
@@ -47,9 +42,9 @@ emp_act
|
||||
var/armor = getarmor_organ(organ, "bullet")
|
||||
if((P.embed && prob(20 + max(P.damage - armor, -10))))
|
||||
var/obj/item/weapon/shard/shrapnel/SP = new()
|
||||
(SP.name) = "[P.name] shrapnel"
|
||||
(SP.desc) = "[SP.desc] It looks like it was fired from [P.shot_from]."
|
||||
(SP.loc) = organ
|
||||
SP.name = (P.name != "shrapnel")? "[P.name] shrapnel" : "shrapnel"
|
||||
SP.desc = "[SP.desc] It looks like it was fired from [P.shot_from]."
|
||||
SP.loc = organ
|
||||
organ.embed(SP)
|
||||
|
||||
return (..(P , def_zone))
|
||||
@@ -309,10 +304,7 @@ emp_act
|
||||
throw_mode_off()
|
||||
return
|
||||
|
||||
var/dtype = BRUTE
|
||||
if(istype(O,/obj/item/weapon))
|
||||
var/obj/item/weapon/W = O
|
||||
dtype = W.damtype
|
||||
var/dtype = O.damtype
|
||||
var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR)
|
||||
|
||||
var/zone
|
||||
@@ -323,11 +315,11 @@ emp_act
|
||||
zone = ran_zone("chest",75) //Hits a random part of the body, geared towards the chest
|
||||
|
||||
//check if we hit
|
||||
var/miss_chance = 15
|
||||
if (O.throw_source)
|
||||
var/distance = get_dist(O.throw_source, loc)
|
||||
zone = get_zone_with_miss_chance(zone, src, min(15*(distance-2), 0))
|
||||
else
|
||||
zone = get_zone_with_miss_chance(zone, src, 15)
|
||||
miss_chance = max(15*(distance-2), 0)
|
||||
zone = get_zone_with_miss_chance(zone, src, miss_chance)
|
||||
|
||||
if(!zone)
|
||||
visible_message("\blue \The [O] misses [src] narrowly!")
|
||||
@@ -375,17 +367,21 @@ emp_act
|
||||
affecting.embed(I)
|
||||
|
||||
// Begin BS12 momentum-transfer code.
|
||||
if(O.throw_source && speed >= THROWNOBJ_KNOCKBACK_SPEED)
|
||||
var/obj/item/weapon/W = O
|
||||
var/momentum = speed/THROWNOBJ_KNOCKBACK_DIVISOR
|
||||
var/mass = 1.5
|
||||
if(istype(O, /obj/item))
|
||||
var/obj/item/I = O
|
||||
mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR
|
||||
var/momentum = speed*mass
|
||||
|
||||
if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
|
||||
var/dir = get_dir(O.throw_source, src)
|
||||
|
||||
visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!")
|
||||
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
|
||||
|
||||
if(!O || !src) return
|
||||
|
||||
if(!W || !src) return
|
||||
|
||||
if(W.loc == src && W.sharp) //Projectile is embedded and suitable for pinning.
|
||||
if(O.loc == src && O.sharp) //Projectile is embedded and suitable for pinning.
|
||||
var/turf/T = near_wall(dir,2)
|
||||
|
||||
if(T)
|
||||
@@ -394,6 +390,13 @@ emp_act
|
||||
src.anchored = 1
|
||||
src.pinned += O
|
||||
|
||||
/mob/living/carbon/human/embed(var/obj/O, var/def_zone=null)
|
||||
if(!def_zone) ..()
|
||||
|
||||
var/datum/organ/external/affecting = get_organ(def_zone)
|
||||
if(affecting)
|
||||
affecting.embed(O)
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/bloody_hands(var/mob/living/source, var/amount = 2)
|
||||
if (gloves)
|
||||
|
||||
@@ -1,3 +1,16 @@
|
||||
/*
|
||||
Add fingerprints to items when we put them in our hands.
|
||||
This saves us from having to call add_fingerprint() any time something is put in a human's hands programmatically.
|
||||
|
||||
*/
|
||||
/mob/living/carbon/human/put_in_l_hand(var/obj/item/W)
|
||||
. = ..()
|
||||
if(.) W.add_fingerprint(src)
|
||||
|
||||
/mob/living/carbon/human/put_in_r_hand(var/obj/item/W)
|
||||
. = ..()
|
||||
if(.) W.add_fingerprint(src)
|
||||
|
||||
/mob/living/carbon/human/verb/quick_equip()
|
||||
set name = "quick-equip"
|
||||
set hidden = 1
|
||||
@@ -497,15 +510,17 @@
|
||||
message = "\red <B>[source] is trying to unlegcuff [target]!</B>"
|
||||
if("tie")
|
||||
var/obj/item/clothing/under/suit = target.w_uniform
|
||||
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has had their accessory ([suit.hastie]) removed by [source.name] ([source.ckey])</font>")
|
||||
source.attack_log += text("\[[time_stamp()]\] <font color='red'>Attempted to remove [target.name]'s ([target.ckey]) accessory ([suit.hastie])</font>")
|
||||
if(istype(suit.hastie, /obj/item/clothing/tie/holobadge) || istype(suit.hastie, /obj/item/clothing/tie/medal))
|
||||
for(var/mob/M in viewers(target, null))
|
||||
M.show_message("\red <B>[source] tears off \the [suit.hastie] from [target]'s suit!</B>" , 1)
|
||||
done()
|
||||
return
|
||||
else
|
||||
message = "\red <B>[source] is trying to take off \a [suit.hastie] from [target]'s suit!</B>"
|
||||
if(suit.accessories.len)
|
||||
var/obj/item/clothing/accessory/A = suit.accessories[1]
|
||||
target.attack_log += "\[[time_stamp()]\] <font color='orange'>Has had their accessory ([A]) removed by [source.name] ([source.ckey])</font>"
|
||||
source.attack_log += "\[[time_stamp()]\] <font color='red'>Attempted to remove [target.name]'s ([target.ckey]) accessory ([A])</font>"
|
||||
if(istype(A, /obj/item/clothing/accessory/holobadge) || istype(A, /obj/item/clothing/accessory/medal))
|
||||
for(var/mob/M in viewers(target, null))
|
||||
M.show_message("\red <B>[source] tears off \the [A] from [target]'s [suit]!</B>" , 1)
|
||||
done()
|
||||
return
|
||||
else
|
||||
message = "\red <B>[source] is trying to take off \a [A] from [target]'s [suit]!</B>"
|
||||
if("pockets")
|
||||
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has had their pockets emptied by [source.name] ([source.ckey])</font>")
|
||||
source.attack_log += text("\[[time_stamp()]\] <font color='red'>Attempted to empty [target.name]'s ([target.ckey]) pockets</font>")
|
||||
@@ -634,17 +649,18 @@ It can still be worn/put on as normal.
|
||||
strip_item = target.wear_suit
|
||||
if("tie")
|
||||
var/obj/item/clothing/under/suit = target.w_uniform
|
||||
//var/obj/item/clothing/tie/tie = suit.hastie
|
||||
//var/obj/item/clothing/accessory/tie = suit.hastie
|
||||
/*if(tie)
|
||||
if (istype(tie,/obj/item/clothing/tie/storage))
|
||||
var/obj/item/clothing/tie/storage/W = tie
|
||||
if (istype(tie,/obj/item/clothing/accessory/storage))
|
||||
var/obj/item/clothing/accessory/storage/W = tie
|
||||
if (W.hold)
|
||||
W.hold.close(usr)
|
||||
usr.put_in_hands(tie)
|
||||
suit.hastie = null*/
|
||||
if(suit && suit.hastie)
|
||||
suit.hastie.on_removed(usr)
|
||||
suit.hastie = null
|
||||
if(suit && suit.accessories.len)
|
||||
var/obj/item/clothing/accessory/A = suit.accessories[1]
|
||||
A.on_removed(usr)
|
||||
suit.accessories -= A
|
||||
target.update_inv_w_uniform()
|
||||
if("id")
|
||||
slot_to_process = slot_wear_id
|
||||
|
||||
@@ -376,12 +376,11 @@ proc/get_damage_icon_part(damage_state, body_part)
|
||||
stand_icon.Blend(new/icon('icons/mob/human_face.dmi', "lips_[lip_style]_s"), ICON_OVERLAY)
|
||||
|
||||
//Underwear
|
||||
if(underwear >0 && underwear < 12 && species.flags & HAS_UNDERWEAR)
|
||||
if(!fat && !skeleton)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', "underwear[underwear]_[g]_s"), ICON_OVERLAY)
|
||||
if(underwear && species.flags & HAS_UNDERWEAR)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', underwear), ICON_OVERLAY)
|
||||
|
||||
if(undershirt>0 && undershirt < 5 && species.flags & HAS_UNDERWEAR)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', "undershirt[undershirt]_s"), ICON_OVERLAY)
|
||||
if(undershirt && species.flags & HAS_UNDERWEAR)
|
||||
stand_icon.Blend(new /icon('icons/mob/human.dmi', undershirt), ICON_OVERLAY)
|
||||
|
||||
if(update_icons)
|
||||
update_icons()
|
||||
@@ -537,10 +536,11 @@ proc/get_damage_icon_part(damage_state, body_part)
|
||||
bloodsies.color = w_uniform.blood_color
|
||||
standing.overlays += bloodsies
|
||||
|
||||
if(w_uniform:hastie) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE.
|
||||
var/tie_color = w_uniform:hastie.item_color
|
||||
if(!tie_color) tie_color = w_uniform:hastie.icon_state
|
||||
standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]")
|
||||
if(w_uniform:accessories.len) //WE CHECKED THE TYPE ABOVE. THIS REALLY SHOULD BE FINE.
|
||||
for(var/obj/item/clothing/accessory/A in w_uniform:accessories)
|
||||
var/tie_color = A.item_color
|
||||
if(!tie_color) tie_color = A.icon_state
|
||||
standing.overlays += image("icon" = 'icons/mob/ties.dmi', "icon_state" = "[tie_color]")
|
||||
|
||||
overlays_standing[UNIFORM_LAYER] = standing
|
||||
else
|
||||
@@ -780,7 +780,7 @@ proc/get_damage_icon_part(damage_state, body_part)
|
||||
|
||||
|
||||
/mob/living/carbon/human/update_inv_wear_mask(var/update_icons=1)
|
||||
if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/tie) ) && !(head && head.flags_inv & HIDEMASK))
|
||||
if( wear_mask && ( istype(wear_mask, /obj/item/clothing/mask) || istype(wear_mask, /obj/item/clothing/accessory) ) && !(head && head.flags_inv & HIDEMASK))
|
||||
wear_mask.screen_loc = ui_mask //TODO
|
||||
|
||||
var/image/standing
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
/mob/living/carbon/slime/death(gibbed)
|
||||
|
||||
if(stat == DEAD) return
|
||||
stat = DEAD
|
||||
|
||||
if(!gibbed)
|
||||
if(is_adult)
|
||||
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime(loc)
|
||||
M.colour = colour
|
||||
M.rabid = 1
|
||||
is_adult = 0
|
||||
maxHealth = 150
|
||||
revive()
|
||||
regenerate_icons()
|
||||
number = rand(1, 1000)
|
||||
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
|
||||
return
|
||||
if(!gibbed && is_adult)
|
||||
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime(loc, colour)
|
||||
M.rabid = 1
|
||||
M.Friends = Friends.Copy()
|
||||
step_away(M, src)
|
||||
is_adult = 0
|
||||
maxHealth = 150
|
||||
revive()
|
||||
regenerate_icons()
|
||||
if (!client) rabid = 1
|
||||
number = rand(1, 1000)
|
||||
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
|
||||
return
|
||||
|
||||
icon_state = "[colour] baby slime dead"
|
||||
overlays.Cut()
|
||||
. = ..(gibbed, "seizes up and falls limp...")
|
||||
|
||||
return ..(gibbed)
|
||||
regenerate_icons()
|
||||
|
||||
return
|
||||
@@ -1,6 +1,5 @@
|
||||
/mob/living/carbon/slime/emote(var/act, var/m_type=1, var/message = null)
|
||||
|
||||
|
||||
if (findtext(act, "-", 1, null))
|
||||
var/t1 = findtext(act, "-", 1, null)
|
||||
//param = copytext(act, t1 + 1, length(act) + 1)
|
||||
@@ -9,6 +8,8 @@
|
||||
if(findtext(act,"s",-1) && !findtext(act,"_",-2))//Removes ending s's unless they are prefixed with a '_'
|
||||
act = copytext(act,1,length(act))
|
||||
|
||||
var/updateicon = 0
|
||||
|
||||
switch(act) //Alphabetical please
|
||||
if ("me")
|
||||
if(silent)
|
||||
@@ -59,8 +60,32 @@
|
||||
message = "<B>The [src.name]</B> vibrates!"
|
||||
m_type = 1
|
||||
|
||||
if("nomood")
|
||||
mood = null
|
||||
updateicon = 1
|
||||
|
||||
if("pout")
|
||||
mood = "pout"
|
||||
updateicon = 1
|
||||
|
||||
if("sad")
|
||||
mood = "sad"
|
||||
updateicon = 1
|
||||
|
||||
if("angry")
|
||||
mood = "angry"
|
||||
updateicon = 1
|
||||
|
||||
if("frown")
|
||||
mood = "mischevous"
|
||||
updateicon = 1
|
||||
|
||||
if("smile")
|
||||
mood = ":3"
|
||||
updateicon = 1
|
||||
|
||||
if ("help") //This is an exception
|
||||
src << "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, custom, jiggle, light, moan, shiver, sway, twitch, vibrate"
|
||||
src << "Help for slime emotes. You can use these emotes with say \"*emote\":\n\nbounce, custom, jiggle, light, moan, shiver, sway, twitch, vibrate. You can also set your face with: \n\nnomood, pout, sad, angry, frown, smile"
|
||||
|
||||
else
|
||||
src << "\blue Unusable emote '[act]'. Say *help for a list."
|
||||
@@ -68,9 +93,9 @@
|
||||
if (m_type & 1)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
O.show_message(message, m_type)
|
||||
//Foreach goto(703)
|
||||
else
|
||||
for(var/mob/O in hearers(src, null))
|
||||
O.show_message(message, m_type)
|
||||
//Foreach goto(746)
|
||||
if(updateicon)
|
||||
regenerate_icons()
|
||||
return
|
||||
@@ -0,0 +1,366 @@
|
||||
/obj/item/slime_extract
|
||||
name = "slime extract"
|
||||
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
|
||||
icon = 'icons/mob/slimes.dmi'
|
||||
icon_state = "grey slime extract"
|
||||
force = 1.0
|
||||
w_class = 1.0
|
||||
throwforce = 0
|
||||
throw_speed = 3
|
||||
throw_range = 6
|
||||
origin_tech = "biotech=4"
|
||||
var/Uses = 1 // uses before it goes inert
|
||||
var/enhanced = 0 //has it been enhanced before?
|
||||
|
||||
attackby(obj/item/O as obj, mob/user as mob)
|
||||
if(istype(O, /obj/item/weapon/slimesteroid2))
|
||||
if(enhanced == 1)
|
||||
user << "<span class='warning'> This extract has already been enhanced!</span>"
|
||||
return ..()
|
||||
if(Uses == 0)
|
||||
user << "<span class='warning'> You can't enhance a used extract!</span>"
|
||||
return ..()
|
||||
user <<"You apply the enhancer. It now has triple the amount of uses."
|
||||
Uses = 3
|
||||
enhanced = 1
|
||||
del(O)
|
||||
|
||||
/obj/item/slime_extract/New()
|
||||
..()
|
||||
create_reagents(100)
|
||||
|
||||
/obj/item/slime_extract/grey
|
||||
name = "grey slime extract"
|
||||
icon_state = "grey slime extract"
|
||||
|
||||
/obj/item/slime_extract/gold
|
||||
name = "gold slime extract"
|
||||
icon_state = "gold slime extract"
|
||||
|
||||
/obj/item/slime_extract/silver
|
||||
name = "silver slime extract"
|
||||
icon_state = "silver slime extract"
|
||||
|
||||
/obj/item/slime_extract/metal
|
||||
name = "metal slime extract"
|
||||
icon_state = "metal slime extract"
|
||||
|
||||
/obj/item/slime_extract/purple
|
||||
name = "purple slime extract"
|
||||
icon_state = "purple slime extract"
|
||||
|
||||
/obj/item/slime_extract/darkpurple
|
||||
name = "dark purple slime extract"
|
||||
icon_state = "dark purple slime extract"
|
||||
|
||||
/obj/item/slime_extract/orange
|
||||
name = "orange slime extract"
|
||||
icon_state = "orange slime extract"
|
||||
|
||||
/obj/item/slime_extract/yellow
|
||||
name = "yellow slime extract"
|
||||
icon_state = "yellow slime extract"
|
||||
|
||||
/obj/item/slime_extract/red
|
||||
name = "red slime extract"
|
||||
icon_state = "red slime extract"
|
||||
|
||||
/obj/item/slime_extract/blue
|
||||
name = "blue slime extract"
|
||||
icon_state = "blue slime extract"
|
||||
|
||||
/obj/item/slime_extract/darkblue
|
||||
name = "dark blue slime extract"
|
||||
icon_state = "dark blue slime extract"
|
||||
|
||||
/obj/item/slime_extract/pink
|
||||
name = "pink slime extract"
|
||||
icon_state = "pink slime extract"
|
||||
|
||||
/obj/item/slime_extract/green
|
||||
name = "green slime extract"
|
||||
icon_state = "green slime extract"
|
||||
|
||||
/obj/item/slime_extract/lightpink
|
||||
name = "light pink slime extract"
|
||||
icon_state = "light pink slime extract"
|
||||
|
||||
/obj/item/slime_extract/black
|
||||
name = "black slime extract"
|
||||
icon_state = "black slime extract"
|
||||
|
||||
/obj/item/slime_extract/oil
|
||||
name = "oil slime extract"
|
||||
icon_state = "oil slime extract"
|
||||
|
||||
/obj/item/slime_extract/adamantine
|
||||
name = "adamantine slime extract"
|
||||
icon_state = "adamantine slime extract"
|
||||
|
||||
/obj/item/slime_extract/bluespace
|
||||
name = "bluespace slime extract"
|
||||
icon_state = "bluespace slime extract"
|
||||
|
||||
/obj/item/slime_extract/pyrite
|
||||
name = "pyrite slime extract"
|
||||
icon_state = "pyrite slime extract"
|
||||
|
||||
/obj/item/slime_extract/cerulean
|
||||
name = "cerulean slime extract"
|
||||
icon_state = "cerulean slime extract"
|
||||
|
||||
/obj/item/slime_extract/sepia
|
||||
name = "sepia slime extract"
|
||||
icon_state = "sepia slime extract"
|
||||
|
||||
/obj/item/slime_extract/rainbow
|
||||
name = "rainbow slime extract"
|
||||
icon_state = "rainbow slime extract"
|
||||
|
||||
////Pet Slime Creation///
|
||||
|
||||
/obj/item/weapon/slimepotion
|
||||
name = "docility potion"
|
||||
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle19"
|
||||
|
||||
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
|
||||
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
|
||||
user << "<span class='warning'> The potion only works on baby slimes!</span>"
|
||||
return ..()
|
||||
if(M.is_adult) //Can't tame adults
|
||||
user << "<span class='warning'> Only baby slimes can be tamed!</span>"
|
||||
return..()
|
||||
if(M.stat)
|
||||
user << "<span class='warning'> The slime is dead!</span>"
|
||||
return..()
|
||||
if(M.mind)
|
||||
user << "<span class='warning'> The slime resists!</span>"
|
||||
return ..()
|
||||
var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
|
||||
pet.icon_state = "[M.colour] baby slime"
|
||||
pet.icon_living = "[M.colour] baby slime"
|
||||
pet.icon_dead = "[M.colour] baby slime dead"
|
||||
pet.colour = "[M.colour]"
|
||||
user <<"You feed the slime the potion, removing it's powers and calming it."
|
||||
del(M)
|
||||
var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
|
||||
|
||||
if (!newname)
|
||||
newname = "pet slime"
|
||||
pet.name = newname
|
||||
pet.real_name = newname
|
||||
del(src)
|
||||
|
||||
/obj/item/weapon/slimepotion2
|
||||
name = "advanced docility potion"
|
||||
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle19"
|
||||
|
||||
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
|
||||
if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
|
||||
user << "<span class='warning'> The potion only works on slimes!</span>"
|
||||
return ..()
|
||||
if(M.stat)
|
||||
user << "<span class='warning'> The slime is dead!</span>"
|
||||
return..()
|
||||
if(M.mind)
|
||||
user << "<span class='warning'> The slime resists!</span>"
|
||||
return ..()
|
||||
var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc)
|
||||
pet.icon_state = "[M.colour] adult slime"
|
||||
pet.icon_living = "[M.colour] adult slime"
|
||||
pet.icon_dead = "[M.colour] baby slime dead"
|
||||
pet.colour = "[M.colour]"
|
||||
user <<"You feed the slime the potion, removing it's powers and calming it."
|
||||
del(M)
|
||||
var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
|
||||
|
||||
if (!newname)
|
||||
newname = "pet slime"
|
||||
pet.name = newname
|
||||
pet.real_name = newname
|
||||
del(src)
|
||||
|
||||
|
||||
/obj/item/weapon/slimesteroid
|
||||
name = "slime steroid"
|
||||
desc = "A potent chemical mix that will cause a slime to generate more extract."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle16"
|
||||
|
||||
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
|
||||
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
|
||||
user << "<span class='warning'> The steroid only works on baby slimes!</span>"
|
||||
return ..()
|
||||
if(M.is_adult) //Can't tame adults
|
||||
user << "<span class='warning'> Only baby slimes can use the steroid!</span>"
|
||||
return..()
|
||||
if(M.stat)
|
||||
user << "<span class='warning'> The slime is dead!</span>"
|
||||
return..()
|
||||
if(M.cores == 3)
|
||||
user <<"<span class='warning'> The slime already has the maximum amount of extract!</span>"
|
||||
return..()
|
||||
|
||||
user <<"You feed the slime the steroid. It now has triple the amount of extract."
|
||||
M.cores = 3
|
||||
del(src)
|
||||
|
||||
/obj/item/weapon/slimesteroid2
|
||||
name = "extract enhancer"
|
||||
desc = "A potent chemical mix that will give a slime extract three uses."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle17"
|
||||
|
||||
/*afterattack(obj/target, mob/user , flag)
|
||||
if(istype(target, /obj/item/slime_extract))
|
||||
if(target.enhanced == 1)
|
||||
user << "<span class='warning'> This extract has already been enhanced!</span>"
|
||||
return ..()
|
||||
if(target.Uses == 0)
|
||||
user << "<span class='warning'> You can't enhance a used extract!</span>"
|
||||
return ..()
|
||||
user <<"You apply the enhancer. It now has triple the amount of uses."
|
||||
target.Uses = 3
|
||||
target.enahnced = 1
|
||||
del(src)*/
|
||||
|
||||
/obj/effect/golemrune
|
||||
anchored = 1
|
||||
desc = "a strange rune used to create golems. It glows when spirits are nearby."
|
||||
name = "rune"
|
||||
icon = 'icons/obj/rune.dmi'
|
||||
icon_state = "golem"
|
||||
unacidable = 1
|
||||
layer = TURF_LAYER
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
process()
|
||||
var/mob/dead/observer/ghost
|
||||
for(var/mob/dead/observer/O in src.loc)
|
||||
if(!O.client) continue
|
||||
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
|
||||
ghost = O
|
||||
break
|
||||
if(ghost)
|
||||
icon_state = "golem2"
|
||||
else
|
||||
icon_state = "golem"
|
||||
|
||||
attack_hand(mob/living/user as mob)
|
||||
var/mob/dead/observer/ghost
|
||||
for(var/mob/dead/observer/O in src.loc)
|
||||
if(!O.client) continue
|
||||
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
|
||||
ghost = O
|
||||
break
|
||||
if(!ghost)
|
||||
user << "The rune fizzles uselessly. There is no spirit nearby."
|
||||
return
|
||||
var/mob/living/carbon/human/G = new(src.loc)
|
||||
G.set_species("Golem")
|
||||
G.key = ghost.key
|
||||
G << "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost."
|
||||
del (src)
|
||||
|
||||
|
||||
proc/announce_to_ghosts()
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
if(G.client)
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
G << "Golem rune created in [A.name]."
|
||||
|
||||
/mob/living/carbon/slime/has_eyes()
|
||||
return 0
|
||||
|
||||
//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
|
||||
|
||||
/*
|
||||
// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere
|
||||
/obj/item/slime_core
|
||||
name = "slime extract"
|
||||
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
|
||||
icon = 'icons/mob/slimes.dmi'
|
||||
icon_state = "slime extract"
|
||||
force = 1.0
|
||||
w_class = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 2
|
||||
throw_range = 6
|
||||
origin_tech = "biotech=4"
|
||||
var/POWERFLAG = 0 // sshhhhhhh
|
||||
var/Flush = 30
|
||||
var/Uses = 5 // uses before it goes inert
|
||||
|
||||
/obj/item/slime_core/New()
|
||||
..()
|
||||
create_reagents(100)
|
||||
POWERFLAG = rand(1,10)
|
||||
Uses = rand(7, 25)
|
||||
//flags |= NOREACT
|
||||
/*
|
||||
spawn()
|
||||
Life()
|
||||
|
||||
proc/Life()
|
||||
while(src)
|
||||
sleep(25)
|
||||
Flush--
|
||||
if(Flush <= 0)
|
||||
reagents.clear_reagents()
|
||||
Flush = 30
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime
|
||||
name = "slime egg"
|
||||
desc = "A small, gelatinous egg."
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "slime egg-growing"
|
||||
bitesize = 12
|
||||
origin_tech = "biotech=4"
|
||||
var/grown = 0
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/New()
|
||||
..()
|
||||
reagents.add_reagent("nutriment", 4)
|
||||
reagents.add_reagent("slimejelly", 1)
|
||||
spawn(rand(1200,1500))//the egg takes a while to "ripen"
|
||||
Grow()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow()
|
||||
grown = 1
|
||||
icon_state = "slime egg-grown"
|
||||
processing_objects.Add(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
|
||||
processing_objects.Remove(src)
|
||||
var/turf/T = get_turf(src)
|
||||
src.visible_message("<span class='warning'> The [name] pulsates and quivers!</span>")
|
||||
spawn(rand(50,100))
|
||||
src.visible_message("<span class='warning'> The [name] bursts open!</span>")
|
||||
new/mob/living/carbon/slime(T)
|
||||
del(src)
|
||||
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
|
||||
var/turf/location = get_turf(src)
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
if (environment.phoron > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch
|
||||
src.Hatch()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype( W, /obj/item/toy/crayon ))
|
||||
return
|
||||
else
|
||||
..()
|
||||
*/
|
||||
@@ -1,10 +1,3 @@
|
||||
/mob/living/carbon/slime
|
||||
var/AIproc = 0 // determines if the AI loop is activated
|
||||
var/Atkcool = 0 // attack cooldown
|
||||
var/Tempstun = 0 // temporary temperature stuns
|
||||
var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while
|
||||
var/SStun = 0 // stun variable
|
||||
|
||||
/mob/living/carbon/slime/Life()
|
||||
set invisibility = 0
|
||||
set background = 1
|
||||
@@ -15,113 +8,27 @@
|
||||
..()
|
||||
|
||||
if(stat != DEAD)
|
||||
//Chemicals in the body
|
||||
handle_chemicals_in_body()
|
||||
|
||||
handle_nutrition()
|
||||
|
||||
handle_targets()
|
||||
|
||||
if (!ckey)
|
||||
if (!client)
|
||||
handle_targets()
|
||||
if (!AIproc)
|
||||
spawn()
|
||||
handle_AI()
|
||||
handle_speech_and_mood()
|
||||
|
||||
var/datum/gas_mixture/environment
|
||||
if(src.loc)
|
||||
environment = loc.return_air()
|
||||
|
||||
//Apparently, the person who wrote this code designed it so that
|
||||
//blinded get reset each cycle and then get activated later in the
|
||||
//code. Very ugly. I dont care. Moving this stuff here so its easy
|
||||
//to find it.
|
||||
src.blinded = null
|
||||
|
||||
regular_hud_updates() // Basically just deletes any screen objects :<
|
||||
regular_hud_updates()
|
||||
|
||||
if(environment)
|
||||
handle_environment(environment) // Handle temperature/pressure differences between body and environment
|
||||
|
||||
handle_regular_status_updates() // Status updates, death etc.
|
||||
|
||||
/mob/living/carbon/slime/proc/AIprocess() // the master AI process
|
||||
|
||||
if(AIproc || stat == DEAD || client) return
|
||||
|
||||
var/hungry = 0
|
||||
if (nutrition < get_starve_nutrition())
|
||||
hungry = 2
|
||||
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
|
||||
hungry = 1
|
||||
|
||||
AIproc = 1
|
||||
|
||||
while(AIproc && stat != 2 && (attacked || hungry || rabid || Victim))
|
||||
if(Victim) // can't eat AND have this little process at the same time
|
||||
break
|
||||
|
||||
if(!Target || client)
|
||||
break
|
||||
|
||||
if(Target.health <= -70 || Target.stat == 2)
|
||||
Target = null
|
||||
AIproc = 0
|
||||
break
|
||||
|
||||
if(Target)
|
||||
for(var/mob/living/carbon/slime/M in view(1,Target))
|
||||
if(M.Victim == Target)
|
||||
Target = null
|
||||
AIproc = 0
|
||||
break
|
||||
if(!AIproc)
|
||||
break
|
||||
|
||||
if(Target in view(1,src))
|
||||
if(istype(Target, /mob/living/silicon))
|
||||
if(!Atkcool)
|
||||
Atkcool = 1
|
||||
spawn(45)
|
||||
Atkcool = 0
|
||||
|
||||
if(Target.Adjacent(src))
|
||||
UnarmedAttack(Target)
|
||||
return
|
||||
if(!Target.lying && prob(80))
|
||||
|
||||
if(Target.client && Target.health >= 20)
|
||||
if(!Atkcool)
|
||||
Atkcool = 1
|
||||
spawn(45)
|
||||
Atkcool = 0
|
||||
|
||||
if(Target.Adjacent(src))
|
||||
UnarmedAttack(Target)
|
||||
|
||||
else
|
||||
if(!Atkcool && Target.Adjacent(src))
|
||||
Feedon(Target)
|
||||
|
||||
else
|
||||
if(!Atkcool && Target.Adjacent(src))
|
||||
Feedon(Target)
|
||||
|
||||
else
|
||||
if(Target in view(7, src))
|
||||
if(!Target.Adjacent(src)) // Bug of the month candidate: slimes were attempting to move to target only if it was directly next to them, which caused them to target things, but not approach them
|
||||
step_to(src, Target)
|
||||
sleep(5)
|
||||
|
||||
else
|
||||
Target = null
|
||||
AIproc = 0
|
||||
break
|
||||
|
||||
var/sleeptime = movement_delay()
|
||||
if(sleeptime <= 0) sleeptime = 1
|
||||
|
||||
sleep(sleeptime + 2) // this is about as fast as a player slime can go
|
||||
|
||||
AIproc = 0
|
||||
|
||||
/mob/living/carbon/slime/proc/handle_environment(datum/gas_mixture/environment)
|
||||
if(!environment)
|
||||
adjustToxLoss(rand(10,20))
|
||||
@@ -146,8 +53,6 @@
|
||||
//Account for massive pressure differences
|
||||
|
||||
if(bodytemperature < (T0C + 5)) // start calculating temperature damage etc
|
||||
if(bodytemperature <= (T0C - 40)) // stun temperature
|
||||
Tempstun = 1
|
||||
|
||||
if(bodytemperature <= (T0C - 50)) // hurt temperature
|
||||
if(bodytemperature <= 50) // sqrting negative numbers is bad
|
||||
@@ -155,9 +60,6 @@
|
||||
else
|
||||
adjustToxLoss(round(sqrt(bodytemperature)) * 2)
|
||||
|
||||
else
|
||||
Tempstun = 0
|
||||
|
||||
updatehealth()
|
||||
|
||||
return //TODO: DEFERRED
|
||||
@@ -189,22 +91,16 @@
|
||||
|
||||
/mob/living/carbon/slime/proc/handle_regular_status_updates()
|
||||
|
||||
if(is_adult)
|
||||
health = 200 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
|
||||
else
|
||||
health = 150 - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
|
||||
src.blinded = null
|
||||
|
||||
if(health < config.health_threshold_dead && stat != 2)
|
||||
health = maxHealth - (getOxyLoss() + getToxLoss() + getFireLoss() + getBruteLoss() + getCloneLoss())
|
||||
|
||||
if(health < 0 && stat != DEAD)
|
||||
death()
|
||||
return
|
||||
|
||||
else if(src.health < config.health_threshold_crit)
|
||||
|
||||
if(!src.reagents.has_reagent("inaprovaline"))
|
||||
src.adjustOxyLoss(10)
|
||||
|
||||
if(src.stat != DEAD)
|
||||
src.stat = UNCONSCIOUS
|
||||
if (halloss)
|
||||
halloss = 0
|
||||
|
||||
if(prob(30))
|
||||
adjustOxyLoss(-1)
|
||||
@@ -267,27 +163,16 @@
|
||||
|
||||
if(nutrition <= 0)
|
||||
nutrition = 0
|
||||
if(prob(75))
|
||||
adjustToxLoss(rand(0,5))
|
||||
adjustToxLoss(rand(1,3))
|
||||
if (client && prob(5))
|
||||
src << "<span class='danger'>You are starving!</span>"
|
||||
|
||||
else if (nutrition >= get_grow_nutrition() && amount_grown < 10)
|
||||
nutrition -= 20
|
||||
amount_grown++
|
||||
|
||||
if(amount_grown >= 10 && !Victim && !Target && !ckey)
|
||||
if(is_adult)
|
||||
Reproduce()
|
||||
else
|
||||
Evolve()
|
||||
|
||||
/mob/living/carbon/slime/proc/handle_targets()
|
||||
if(Tempstun)
|
||||
if(!Victim) // not while they're eating!
|
||||
canmove = 0
|
||||
else
|
||||
canmove = 1
|
||||
|
||||
if(attacked > 50) attacked = 50
|
||||
if(attacked > 50) attacked = 50 // Let's not get into absurdly long periods of rage
|
||||
|
||||
if(attacked > 0)
|
||||
attacked--
|
||||
@@ -300,106 +185,180 @@
|
||||
if(prob(10))
|
||||
Discipline--
|
||||
|
||||
if(!client)
|
||||
if(!canmove) return
|
||||
if(!canmove) return
|
||||
|
||||
if(Victim) return // if it's eating someone already, continue eating!
|
||||
if(Victim) return // if it's eating someone already, continue eating!
|
||||
|
||||
if(Target)
|
||||
--target_patience
|
||||
if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention
|
||||
target_patience = 0
|
||||
Target = null
|
||||
if(Target)
|
||||
--target_patience
|
||||
if (target_patience <= 0 || SStun || Discipline || attacked) // Tired of chasing or something draws out attention
|
||||
target_patience = 0
|
||||
Target = null
|
||||
|
||||
if(AIproc && SStun) return
|
||||
var/hungry = 0 // determines if the slime is hungry
|
||||
|
||||
var/hungry = 0 // determines if the slime is hungry
|
||||
if (nutrition < get_starve_nutrition())
|
||||
hungry = 2
|
||||
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
|
||||
hungry = 1
|
||||
|
||||
if (nutrition < get_starve_nutrition())
|
||||
hungry = 2
|
||||
else if (nutrition < get_grow_nutrition() && prob(25) || nutrition < get_hunger_nutrition())
|
||||
hungry = 1
|
||||
if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
|
||||
if(Friends.len > 0 && prob(1))
|
||||
var/mob/nofriend = pick(Friends)
|
||||
--Friends[nofriend]
|
||||
if (Friends[nofriend] <= 0)
|
||||
Friends -= nofriend
|
||||
|
||||
if(hungry == 2 && !client) // if a slime is starving, it starts losing its friends
|
||||
if(Friends.len > 0 && prob(1))
|
||||
var/mob/nofriend = pick(Friends)
|
||||
--Friends[nofriend]
|
||||
if(!Target)
|
||||
if(will_hunt(hungry) || attacked || rabid) // Only add to the list if we need to
|
||||
var/list/targets = list()
|
||||
|
||||
if(!Target)
|
||||
if(will_hunt() && hungry || attacked || rabid) // Only add to the list if we need to
|
||||
var/list/targets = list()
|
||||
for(var/mob/living/L in view(7,src))
|
||||
|
||||
for(var/mob/living/L in view(7,src))
|
||||
if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
|
||||
continue
|
||||
|
||||
if(isslime(L) || L.stat == DEAD) // Ignore other slimes and dead mobs
|
||||
continue
|
||||
|
||||
if(L in Friends) // No eating friends!
|
||||
continue
|
||||
|
||||
if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence
|
||||
targets += L // Possible target found!
|
||||
|
||||
if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.species.name == "Slime")
|
||||
continue
|
||||
|
||||
if(!L.canmove) // Only one slime can latch on at a time.
|
||||
var/notarget = 0
|
||||
for(var/mob/living/carbon/slime/M in view(1,L))
|
||||
if(M.Victim == L)
|
||||
notarget = 1
|
||||
if(notarget)
|
||||
continue
|
||||
if(L in Friends) // No eating friends!
|
||||
continue
|
||||
|
||||
if(issilicon(L) && (rabid || attacked)) // They can't eat silicons, but they can glomp them in defence
|
||||
targets += L // Possible target found!
|
||||
|
||||
if(targets.len > 0)
|
||||
if(attacked || rabid || hungry == 2)
|
||||
Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care
|
||||
else
|
||||
for(var/mob/living/carbon/C in targets)
|
||||
if(!Discipline && prob(5))
|
||||
if(ishuman(C))
|
||||
Target = C
|
||||
break
|
||||
if(istype(L, /mob/living/carbon/human) && dna) //Ignore slime(wo)men
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.species.name == "Slime")
|
||||
continue
|
||||
|
||||
if(isalien(C) || ismonkey(C))
|
||||
Target = C
|
||||
break
|
||||
if(!L.canmove) // Only one slime can latch on at a time.
|
||||
var/notarget = 0
|
||||
for(var/mob/living/carbon/slime/M in view(1,L))
|
||||
if(M.Victim == L)
|
||||
notarget = 1
|
||||
if(notarget)
|
||||
continue
|
||||
|
||||
if (Target)
|
||||
target_patience = rand(5,7)
|
||||
if (is_adult)
|
||||
target_patience += 3
|
||||
targets += L // Possible target found!
|
||||
|
||||
if(!Target) // If we have no target, we are wandering or following orders
|
||||
if (Leader)
|
||||
if (holding_still)
|
||||
holding_still = max(holding_still - 1, 0)
|
||||
else if(canmove && isturf(loc))
|
||||
step_to(src, Leader)
|
||||
if(targets.len > 0)
|
||||
if(attacked || rabid || hungry == 2)
|
||||
Target = targets[1] // I am attacked and am fighting back or so hungry I don't even care
|
||||
else
|
||||
for(var/mob/living/carbon/C in targets)
|
||||
if(ishuman(C) && !Discipline && prob(5))
|
||||
Target = C
|
||||
break
|
||||
|
||||
else if(hungry)
|
||||
if (holding_still)
|
||||
holding_still = max(holding_still - hungry, 0)
|
||||
else if(canmove && isturf(loc) && prob(50))
|
||||
step(src, pick(cardinal))
|
||||
if(isalien(C) || ismonkey(C) || isanimal(C))
|
||||
Target = C
|
||||
break
|
||||
|
||||
if (Target)
|
||||
target_patience = rand(5,7)
|
||||
if (is_adult)
|
||||
target_patience += 3
|
||||
|
||||
if(!Target) // If we have no target, we are wandering or following orders
|
||||
if (Leader)
|
||||
if (holding_still)
|
||||
holding_still = max(holding_still - 1, 0)
|
||||
else if(canmove && isturf(loc))
|
||||
step_to(src, Leader)
|
||||
|
||||
else if(hungry)
|
||||
if (holding_still)
|
||||
holding_still = max(holding_still - 1 - hungry, 0)
|
||||
else if(canmove && isturf(loc) && prob(50))
|
||||
step(src, pick(cardinal))
|
||||
|
||||
else
|
||||
if (holding_still)
|
||||
holding_still = max(holding_still - 1, 0)
|
||||
else if(canmove && isturf(loc) && prob(33))
|
||||
step(src, pick(cardinal))
|
||||
|
||||
/mob/living/carbon/slime/proc/handle_AI() // the master AI process
|
||||
|
||||
if(stat == DEAD || client || Victim) return // If we're dead or have a client, we don't need AI, if we're feeding, we continue feeding
|
||||
AIproc = 1
|
||||
|
||||
if(amount_grown >= 10 && !Target)
|
||||
if(is_adult)
|
||||
Reproduce()
|
||||
else
|
||||
Evolve()
|
||||
AIproc = 0
|
||||
return
|
||||
|
||||
if(Target) // We're chasing the target
|
||||
if(Target.stat == DEAD)
|
||||
Target = null
|
||||
AIproc = 0
|
||||
return
|
||||
|
||||
for(var/mob/living/carbon/slime/M in view(1, Target))
|
||||
if(M.Victim == Target)
|
||||
Target = null
|
||||
AIproc = 0
|
||||
return
|
||||
|
||||
if(Target.Adjacent(src))
|
||||
if(istype(Target, /mob/living/silicon)) // Glomp the silicons
|
||||
if(!Atkcool)
|
||||
a_intent = "hurt"
|
||||
UnarmedAttack(Target)
|
||||
Atkcool = 1
|
||||
spawn(45)
|
||||
Atkcool = 0
|
||||
AIproc = 0
|
||||
return
|
||||
|
||||
if(Target.client && !Target.lying && prob(60 + powerlevel * 4)) // Try to take down the target first
|
||||
if(!Atkcool)
|
||||
Atkcool = 1
|
||||
spawn(45)
|
||||
Atkcool = 0
|
||||
|
||||
a_intent = "disarm"
|
||||
UnarmedAttack(Target)
|
||||
|
||||
else
|
||||
if (holding_still)
|
||||
holding_still = max(holding_still - 1, 0)
|
||||
else if(canmove && isturf(loc) && prob(33))
|
||||
step(src, pick(cardinal))
|
||||
else if(!AIproc)
|
||||
spawn()
|
||||
AIprocess()
|
||||
if(!Atkcool)
|
||||
a_intent = "grab"
|
||||
UnarmedAttack(Target)
|
||||
|
||||
else if(Target in view(7, src))
|
||||
step_to(src, Target)
|
||||
|
||||
else
|
||||
Target = null
|
||||
AIproc = 0
|
||||
return
|
||||
|
||||
else
|
||||
var/mob/living/carbon/slime/frenemy
|
||||
for (var/mob/living/carbon/slime/S in view(1, src))
|
||||
if (S != src)
|
||||
frenemy = S
|
||||
if (frenemy && prob(1))
|
||||
if (frenemy.colour == colour)
|
||||
a_intent = "help"
|
||||
else
|
||||
a_intent = "hurt"
|
||||
UnarmedAttack(frenemy)
|
||||
|
||||
var/sleeptime = movement_delay()
|
||||
if(sleeptime <= 5) sleeptime = 5 // Maximum one action per half a second
|
||||
spawn (sleeptime)
|
||||
handle_AI()
|
||||
return
|
||||
|
||||
/mob/living/carbon/slime/proc/handle_speech_and_mood()
|
||||
//Mood starts here
|
||||
var/newmood = ""
|
||||
if (rabid || attacked) newmood = "angry"
|
||||
a_intent = "help"
|
||||
if (rabid || attacked)
|
||||
newmood = "angry"
|
||||
a_intent = "hurt"
|
||||
else if (Target) newmood = "mischevous"
|
||||
|
||||
if (!newmood)
|
||||
@@ -569,11 +528,13 @@
|
||||
if (is_adult) return 300
|
||||
else return 200
|
||||
|
||||
/mob/living/carbon/slime/proc/will_hunt(var/hunger = -1) // Check for being stopped from feeding and chasing
|
||||
/mob/living/carbon/slime/proc/will_hunt(var/hunger) // Check for being stopped from feeding and chasing
|
||||
if (hunger == 2 || rabid || attacked) return 1
|
||||
if (Leader) return 0
|
||||
if (holding_still) return 0
|
||||
return 1
|
||||
if (hunger == 1 || prob(25))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/slime/slip() //Can't slip something without legs.
|
||||
return 0
|
||||
@@ -4,10 +4,9 @@
|
||||
icon_state = "grey baby slime"
|
||||
pass_flags = PASSTABLE
|
||||
var/is_adult = 0
|
||||
speak_emote = list("telepathically chirps")
|
||||
speak_emote = list("chirps")
|
||||
|
||||
layer = 5
|
||||
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
gender = NEUTER
|
||||
@@ -25,7 +24,7 @@
|
||||
var/cores = 1 // the number of /obj/item/slime_extract's the slime has left inside
|
||||
var/mutation_chance = 30 // Chance of mutating, should be between 25 and 35
|
||||
|
||||
var/powerlevel = 0 // 1-10 controls how much electricity they are generating
|
||||
var/powerlevel = 0 // 0-10 controls how much electricity they are generating
|
||||
var/amount_grown = 0 // controls how long the slime has been overfed, if 10, grows or reproduces
|
||||
|
||||
var/number = 0 // Used to understand when someone is talking to it
|
||||
@@ -45,6 +44,11 @@
|
||||
|
||||
var/mood = "" // To show its face
|
||||
|
||||
var/AIproc = 0 // If it's 0, we need to launch an AI proc
|
||||
var/Atkcool = 0 // attack cooldown
|
||||
var/SStun = 0 // NPC stun variable. Used to calm them down when they are attacked while feeding, or they will immediately re-attach
|
||||
var/Discipline = 0 // if a slime has been hit with a freeze gun, or wrestled/attacked off a human, they become disciplined and don't attack anymore for a while. The part about freeze gun is a lie
|
||||
|
||||
///////////TIME FOR SUBSPECIES
|
||||
|
||||
var/colour = "grey"
|
||||
@@ -53,28 +57,21 @@
|
||||
|
||||
var/core_removal_stage = 0 //For removing cores.
|
||||
|
||||
/mob/living/carbon/slime/New()
|
||||
/mob/living/carbon/slime/New(var/location, var/colour="grey")
|
||||
|
||||
verbs += /mob/living/proc/ventcrawl
|
||||
|
||||
create_reagents(100)
|
||||
spawn (0)
|
||||
number = rand(1, 1000)
|
||||
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
|
||||
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
|
||||
real_name = name
|
||||
slime_mutation = mutation_table(colour)
|
||||
mutation_chance = rand(25, 35)
|
||||
var/sanitizedcolour = replacetext(colour, " ", "")
|
||||
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
|
||||
..()
|
||||
|
||||
/mob/living/carbon/slime/regenerate_icons()
|
||||
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime"
|
||||
overlays.len = 0
|
||||
if (mood)
|
||||
overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
|
||||
..()
|
||||
src.colour = colour
|
||||
number = rand(1, 1000)
|
||||
name = "[colour] [is_adult ? "adult" : "baby"] slime ([number])"
|
||||
real_name = name
|
||||
slime_mutation = mutation_table(colour)
|
||||
mutation_chance = rand(25, 35)
|
||||
var/sanitizedcolour = replacetext(colour, " ", "")
|
||||
coretype = text2path("/obj/item/slime_extract/[sanitizedcolour]")
|
||||
..(location)
|
||||
|
||||
/mob/living/carbon/slime/movement_delay()
|
||||
if (bodytemperature >= 330.23) // 135 F
|
||||
@@ -82,8 +79,8 @@
|
||||
|
||||
var/tally = 0
|
||||
|
||||
var/health_deficiency = (100 - health)
|
||||
if(health_deficiency >= 45) tally += (health_deficiency / 25)
|
||||
var/health_deficiency = (maxHealth - health)
|
||||
if(health_deficiency >= 30) tally += (health_deficiency / 25)
|
||||
|
||||
if (bodytemperature < 183.222)
|
||||
tally += (283.222 - bodytemperature) / 10 * 1.75
|
||||
@@ -105,25 +102,23 @@
|
||||
return
|
||||
now_pushing = 1
|
||||
|
||||
if(isobj(AM))
|
||||
if(!client && powerlevel > 0)
|
||||
var/probab = 10
|
||||
switch(powerlevel)
|
||||
if(1 to 2) probab = 20
|
||||
if(3 to 4) probab = 30
|
||||
if(5 to 6) probab = 40
|
||||
if(7 to 8) probab = 60
|
||||
if(9) probab = 70
|
||||
if(10) probab = 95
|
||||
if(prob(probab))
|
||||
if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
|
||||
if(nutrition <= get_hunger_nutrition() && !Atkcool)
|
||||
if (is_adult || prob(5))
|
||||
UnarmedAttack(AM)
|
||||
spawn()
|
||||
Atkcool = 1
|
||||
sleep(45)
|
||||
Atkcool = 0
|
||||
if(isobj(AM) && !client && powerlevel > 0)
|
||||
var/probab = 10
|
||||
switch(powerlevel)
|
||||
if(1 to 2) probab = 20
|
||||
if(3 to 4) probab = 30
|
||||
if(5 to 6) probab = 40
|
||||
if(7 to 8) probab = 60
|
||||
if(9) probab = 70
|
||||
if(10) probab = 95
|
||||
if(prob(probab))
|
||||
if(istype(AM, /obj/structure/window) || istype(AM, /obj/structure/grille))
|
||||
if(nutrition <= get_hunger_nutrition() && !Atkcool)
|
||||
if (is_adult || prob(5))
|
||||
UnarmedAttack(AM)
|
||||
Atkcool = 1
|
||||
spawn(45)
|
||||
Atkcool = 0
|
||||
|
||||
if(ismob(AM))
|
||||
var/mob/tmob = AM
|
||||
@@ -139,21 +134,8 @@
|
||||
return
|
||||
|
||||
now_pushing = 0
|
||||
|
||||
..()
|
||||
if (!istype(AM, /atom/movable))
|
||||
return
|
||||
if (!( now_pushing ))
|
||||
now_pushing = 1
|
||||
if (!( AM.anchored ))
|
||||
var/t = get_dir(src, AM)
|
||||
if (istype(AM, /obj/structure/window))
|
||||
var/obj/structure/window/W = AM
|
||||
if(W.is_full_window())
|
||||
for(var/obj/structure/window/win in get_step(AM,t))
|
||||
now_pushing = 0
|
||||
return
|
||||
step(AM, t)
|
||||
now_pushing = null
|
||||
|
||||
/mob/living/carbon/slime/Process_Spacemove()
|
||||
return 2
|
||||
@@ -162,10 +144,8 @@
|
||||
..()
|
||||
|
||||
statpanel("Status")
|
||||
if(is_adult)
|
||||
stat(null, "Health: [round((health / 200) * 100)]%")
|
||||
else
|
||||
stat(null, "Health: [round((health / 150) * 100)]%")
|
||||
stat(null, "Health: [round((health / maxHealth) * 100)]%")
|
||||
stat(null, "Intent: [a_intent]")
|
||||
|
||||
if (client.statpanel == "Status")
|
||||
stat(null, "Nutrition: [nutrition]/[get_max_nutrition()]")
|
||||
@@ -227,9 +207,7 @@
|
||||
if(shielded)
|
||||
damage /= 4
|
||||
|
||||
//paralysis += 1
|
||||
|
||||
show_message("<span class='userdanger'> The blob attacks you!</span>")
|
||||
show_message("<span class='danger'> The blob attacks you!</span>")
|
||||
|
||||
adjustFireLoss(damage)
|
||||
|
||||
@@ -244,14 +222,12 @@
|
||||
return
|
||||
|
||||
/mob/living/carbon/slime/meteorhit(O as obj)
|
||||
for(var/mob/M in viewers(src, null))
|
||||
if ((M.client && !( M.blinded )))
|
||||
M.show_message(text("\red [] has been hit by []", src, O), 1)
|
||||
if (health > 0)
|
||||
adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25))
|
||||
adjustFireLoss(30)
|
||||
visible_message("<span class='warning'>[src] has been hit by [O]</span>")
|
||||
|
||||
updatehealth()
|
||||
adjustBruteLoss((istype(O, /obj/effect/meteor/small) ? 10 : 25))
|
||||
adjustFireLoss(30)
|
||||
|
||||
updatehealth()
|
||||
return
|
||||
|
||||
/mob/living/carbon/slime/attack_hand(mob/living/carbon/human/M as mob)
|
||||
@@ -271,11 +247,9 @@
|
||||
if(prob(90) && !client)
|
||||
Discipline++
|
||||
|
||||
spawn()
|
||||
SStun = 1
|
||||
sleep(rand(45,60))
|
||||
if(src)
|
||||
SStun = 0
|
||||
SStun = 1
|
||||
spawn(rand(45,60))
|
||||
SStun = 0
|
||||
|
||||
Victim = null
|
||||
anchored = 0
|
||||
@@ -299,11 +273,9 @@
|
||||
if(Discipline == 1)
|
||||
attacked = 0
|
||||
|
||||
spawn()
|
||||
SStun = 1
|
||||
sleep(rand(55,65))
|
||||
if(src)
|
||||
SStun = 0
|
||||
SStun = 1
|
||||
spawn(rand(55,65))
|
||||
SStun = 0
|
||||
|
||||
Victim = null
|
||||
anchored = 0
|
||||
@@ -345,15 +317,13 @@
|
||||
if(prob(80) && !client)
|
||||
Discipline++
|
||||
spawn(0)
|
||||
|
||||
step_away(src,M,15)
|
||||
sleep(3)
|
||||
step_away(src,M,15)
|
||||
|
||||
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
visible_message("<span class='danger'>[M] has punched [src]!</span>", \
|
||||
"<span class='userdanger'>[M] has punched [src]!</span>")
|
||||
"<span class='danger'>[M] has punched [src]!</span>")
|
||||
|
||||
adjustBruteLoss(damage)
|
||||
updatehealth()
|
||||
@@ -381,9 +351,8 @@
|
||||
Target = null
|
||||
anchored = 0
|
||||
|
||||
spawn()
|
||||
SStun = 1
|
||||
sleep(rand(5,20))
|
||||
SStun = 1
|
||||
spawn(rand(5,20))
|
||||
SStun = 0
|
||||
|
||||
spawn(0)
|
||||
@@ -403,9 +372,8 @@
|
||||
Discipline++
|
||||
if(Discipline == 1)
|
||||
attacked = 0
|
||||
spawn()
|
||||
SStun = 1
|
||||
sleep(rand(5,20))
|
||||
SStun = 1
|
||||
spawn(rand(5,20))
|
||||
SStun = 0
|
||||
|
||||
Victim = null
|
||||
@@ -426,8 +394,8 @@
|
||||
/mob/living/carbon/slime/restrained()
|
||||
return 0
|
||||
|
||||
mob/living/carbon/slime/var/co2overloadtime = null
|
||||
mob/living/carbon/slime/var/temperature_resistance = T0C+75
|
||||
/mob/living/carbon/slime/var/co2overloadtime = null
|
||||
/mob/living/carbon/slime/var/temperature_resistance = T0C+75
|
||||
|
||||
/mob/living/carbon/slime/show_inv(mob/user)
|
||||
return
|
||||
@@ -435,8 +403,17 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
|
||||
/mob/living/carbon/slime/toggle_throw_mode()
|
||||
return
|
||||
|
||||
/mob/living/carbon/slime/proc/apply_water()
|
||||
adjustToxLoss(rand(15,20))
|
||||
/mob/living/carbon/slime/proc/gain_nutrition(var/amount)
|
||||
nutrition += amount
|
||||
if(prob(amount * 2)) // Gain around one level per 50 nutrition
|
||||
powerlevel++
|
||||
if(powerlevel > 10)
|
||||
powerlevel = 10
|
||||
adjustToxLoss(-10)
|
||||
nutrition = max(nutrition, get_max_nutrition())
|
||||
|
||||
/mob/living/carbon/slime/proc/apply_water(var/amount)
|
||||
adjustToxLoss(15 + amount)
|
||||
if (!client)
|
||||
if (Target) // Like cats
|
||||
Target = null
|
||||
@@ -446,371 +423,4 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75
|
||||
/mob/living/carbon/slime/can_use_vents()
|
||||
if(Victim)
|
||||
return "You cannot ventcrawl while feeding."
|
||||
..()
|
||||
|
||||
/obj/item/slime_extract
|
||||
name = "slime extract"
|
||||
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
|
||||
icon = 'icons/mob/slimes.dmi'
|
||||
icon_state = "grey slime extract"
|
||||
force = 1.0
|
||||
w_class = 1.0
|
||||
throwforce = 0
|
||||
throw_speed = 3
|
||||
throw_range = 6
|
||||
origin_tech = "biotech=4"
|
||||
var/Uses = 1 // uses before it goes inert
|
||||
var/enhanced = 0 //has it been enhanced before?
|
||||
|
||||
attackby(obj/item/O as obj, mob/user as mob)
|
||||
if(istype(O, /obj/item/weapon/slimesteroid2))
|
||||
if(enhanced == 1)
|
||||
user << "<span class='warning'> This extract has already been enhanced!</span>"
|
||||
return ..()
|
||||
if(Uses == 0)
|
||||
user << "<span class='warning'> You can't enhance a used extract!</span>"
|
||||
return ..()
|
||||
user <<"You apply the enhancer. It now has triple the amount of uses."
|
||||
Uses = 3
|
||||
enhanced = 1
|
||||
del(O)
|
||||
|
||||
/obj/item/slime_extract/New()
|
||||
..()
|
||||
create_reagents(100)
|
||||
|
||||
/obj/item/slime_extract/grey
|
||||
name = "grey slime extract"
|
||||
icon_state = "grey slime extract"
|
||||
|
||||
/obj/item/slime_extract/gold
|
||||
name = "gold slime extract"
|
||||
icon_state = "gold slime extract"
|
||||
|
||||
/obj/item/slime_extract/silver
|
||||
name = "silver slime extract"
|
||||
icon_state = "silver slime extract"
|
||||
|
||||
/obj/item/slime_extract/metal
|
||||
name = "metal slime extract"
|
||||
icon_state = "metal slime extract"
|
||||
|
||||
/obj/item/slime_extract/purple
|
||||
name = "purple slime extract"
|
||||
icon_state = "purple slime extract"
|
||||
|
||||
/obj/item/slime_extract/darkpurple
|
||||
name = "dark purple slime extract"
|
||||
icon_state = "dark purple slime extract"
|
||||
|
||||
/obj/item/slime_extract/orange
|
||||
name = "orange slime extract"
|
||||
icon_state = "orange slime extract"
|
||||
|
||||
/obj/item/slime_extract/yellow
|
||||
name = "yellow slime extract"
|
||||
icon_state = "yellow slime extract"
|
||||
|
||||
/obj/item/slime_extract/red
|
||||
name = "red slime extract"
|
||||
icon_state = "red slime extract"
|
||||
|
||||
/obj/item/slime_extract/blue
|
||||
name = "blue slime extract"
|
||||
icon_state = "blue slime extract"
|
||||
|
||||
/obj/item/slime_extract/darkblue
|
||||
name = "dark blue slime extract"
|
||||
icon_state = "dark blue slime extract"
|
||||
|
||||
/obj/item/slime_extract/pink
|
||||
name = "pink slime extract"
|
||||
icon_state = "pink slime extract"
|
||||
|
||||
/obj/item/slime_extract/green
|
||||
name = "green slime extract"
|
||||
icon_state = "green slime extract"
|
||||
|
||||
/obj/item/slime_extract/lightpink
|
||||
name = "light pink slime extract"
|
||||
icon_state = "light pink slime extract"
|
||||
|
||||
/obj/item/slime_extract/black
|
||||
name = "black slime extract"
|
||||
icon_state = "black slime extract"
|
||||
|
||||
/obj/item/slime_extract/oil
|
||||
name = "oil slime extract"
|
||||
icon_state = "oil slime extract"
|
||||
|
||||
/obj/item/slime_extract/adamantine
|
||||
name = "adamantine slime extract"
|
||||
icon_state = "adamantine slime extract"
|
||||
|
||||
/obj/item/slime_extract/bluespace
|
||||
name = "bluespace slime extract"
|
||||
icon_state = "bluespace slime extract"
|
||||
|
||||
/obj/item/slime_extract/pyrite
|
||||
name = "pyrite slime extract"
|
||||
icon_state = "pyrite slime extract"
|
||||
|
||||
/obj/item/slime_extract/cerulean
|
||||
name = "cerulean slime extract"
|
||||
icon_state = "cerulean slime extract"
|
||||
|
||||
/obj/item/slime_extract/sepia
|
||||
name = "sepia slime extract"
|
||||
icon_state = "sepia slime extract"
|
||||
|
||||
/obj/item/slime_extract/rainbow
|
||||
name = "rainbow slime extract"
|
||||
icon_state = "rainbow slime extract"
|
||||
|
||||
////Pet Slime Creation///
|
||||
|
||||
/obj/item/weapon/slimepotion
|
||||
name = "docility potion"
|
||||
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle19"
|
||||
|
||||
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
|
||||
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
|
||||
user << "<span class='warning'> The potion only works on baby slimes!</span>"
|
||||
return ..()
|
||||
if(M.is_adult) //Can't tame adults
|
||||
user << "<span class='warning'> Only baby slimes can be tamed!</span>"
|
||||
return..()
|
||||
if(M.stat)
|
||||
user << "<span class='warning'> The slime is dead!</span>"
|
||||
return..()
|
||||
if(M.mind)
|
||||
user << "<span class='warning'> The slime resists!</span>"
|
||||
return ..()
|
||||
var/mob/living/simple_animal/slime/pet = new /mob/living/simple_animal/slime(M.loc)
|
||||
pet.icon_state = "[M.colour] baby slime"
|
||||
pet.icon_living = "[M.colour] baby slime"
|
||||
pet.icon_dead = "[M.colour] baby slime dead"
|
||||
pet.colour = "[M.colour]"
|
||||
user <<"You feed the slime the potion, removing it's powers and calming it."
|
||||
del(M)
|
||||
var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
|
||||
|
||||
if (!newname)
|
||||
newname = "pet slime"
|
||||
pet.name = newname
|
||||
pet.real_name = newname
|
||||
del(src)
|
||||
|
||||
/obj/item/weapon/slimepotion2
|
||||
name = "advanced docility potion"
|
||||
desc = "A potent chemical mix that will nullify a slime's powers, causing it to become docile and tame. This one is meant for adult slimes"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle19"
|
||||
|
||||
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
|
||||
if(!istype(M, /mob/living/carbon/slime/))//If target is not a slime.
|
||||
user << "<span class='warning'> The potion only works on slimes!</span>"
|
||||
return ..()
|
||||
if(M.stat)
|
||||
user << "<span class='warning'> The slime is dead!</span>"
|
||||
return..()
|
||||
if(M.mind)
|
||||
user << "<span class='warning'> The slime resists!</span>"
|
||||
return ..()
|
||||
var/mob/living/simple_animal/adultslime/pet = new /mob/living/simple_animal/adultslime(M.loc)
|
||||
pet.icon_state = "[M.colour] adult slime"
|
||||
pet.icon_living = "[M.colour] adult slime"
|
||||
pet.icon_dead = "[M.colour] baby slime dead"
|
||||
pet.colour = "[M.colour]"
|
||||
user <<"You feed the slime the potion, removing it's powers and calming it."
|
||||
del(M)
|
||||
var/newname = sanitize(copytext(input(user, "Would you like to give the slime a name?", "Name your new pet", "pet slime") as null|text,1,MAX_NAME_LEN))
|
||||
|
||||
if (!newname)
|
||||
newname = "pet slime"
|
||||
pet.name = newname
|
||||
pet.real_name = newname
|
||||
del(src)
|
||||
|
||||
|
||||
/obj/item/weapon/slimesteroid
|
||||
name = "slime steroid"
|
||||
desc = "A potent chemical mix that will cause a slime to generate more extract."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle16"
|
||||
|
||||
attack(mob/living/carbon/slime/M as mob, mob/user as mob)
|
||||
if(!istype(M, /mob/living/carbon/slime))//If target is not a slime.
|
||||
user << "<span class='warning'> The steroid only works on baby slimes!</span>"
|
||||
return ..()
|
||||
if(M.is_adult) //Can't tame adults
|
||||
user << "<span class='warning'> Only baby slimes can use the steroid!</span>"
|
||||
return..()
|
||||
if(M.stat)
|
||||
user << "<span class='warning'> The slime is dead!</span>"
|
||||
return..()
|
||||
if(M.cores == 3)
|
||||
user <<"<span class='warning'> The slime already has the maximum amount of extract!</span>"
|
||||
return..()
|
||||
|
||||
user <<"You feed the slime the steroid. It now has triple the amount of extract."
|
||||
M.cores = 3
|
||||
del(src)
|
||||
|
||||
/obj/item/weapon/slimesteroid2
|
||||
name = "extract enhancer"
|
||||
desc = "A potent chemical mix that will give a slime extract three uses."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "bottle17"
|
||||
|
||||
/*afterattack(obj/target, mob/user , flag)
|
||||
if(istype(target, /obj/item/slime_extract))
|
||||
if(target.enhanced == 1)
|
||||
user << "<span class='warning'> This extract has already been enhanced!</span>"
|
||||
return ..()
|
||||
if(target.Uses == 0)
|
||||
user << "<span class='warning'> You can't enhance a used extract!</span>"
|
||||
return ..()
|
||||
user <<"You apply the enhancer. It now has triple the amount of uses."
|
||||
target.Uses = 3
|
||||
target.enahnced = 1
|
||||
del(src)*/
|
||||
|
||||
/obj/effect/golemrune
|
||||
anchored = 1
|
||||
desc = "a strange rune used to create golems. It glows when spirits are nearby."
|
||||
name = "rune"
|
||||
icon = 'icons/obj/rune.dmi'
|
||||
icon_state = "golem"
|
||||
unacidable = 1
|
||||
layer = TURF_LAYER
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
process()
|
||||
var/mob/dead/observer/ghost
|
||||
for(var/mob/dead/observer/O in src.loc)
|
||||
if(!O.client) continue
|
||||
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
|
||||
ghost = O
|
||||
break
|
||||
if(ghost)
|
||||
icon_state = "golem2"
|
||||
else
|
||||
icon_state = "golem"
|
||||
|
||||
attack_hand(mob/living/user as mob)
|
||||
var/mob/dead/observer/ghost
|
||||
for(var/mob/dead/observer/O in src.loc)
|
||||
if(!O.client) continue
|
||||
if(O.mind && O.mind.current && O.mind.current.stat != DEAD) continue
|
||||
ghost = O
|
||||
break
|
||||
if(!ghost)
|
||||
user << "The rune fizzles uselessly. There is no spirit nearby."
|
||||
return
|
||||
var/mob/living/carbon/human/G = new(src.loc)
|
||||
G.set_species("Golem")
|
||||
G.key = ghost.key
|
||||
G << "You are an adamantine golem. You move slowly, but are highly resistant to heat and cold as well as blunt trauma. You are unable to wear clothes, but can still use most tools. Serve [user], and assist them in completing their goals at any cost."
|
||||
del (src)
|
||||
|
||||
|
||||
proc/announce_to_ghosts()
|
||||
for(var/mob/dead/observer/G in player_list)
|
||||
if(G.client)
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
G << "Golem rune created in [A.name]."
|
||||
|
||||
/mob/living/carbon/slime/has_eyes()
|
||||
return 0
|
||||
|
||||
//////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them////////////////////////
|
||||
|
||||
/*
|
||||
// Basically this slime Core catalyzes reactions that normally wouldn't happen anywhere
|
||||
/obj/item/slime_core
|
||||
name = "slime extract"
|
||||
desc = "Goo extracted from a slime. Legends claim these to have \"magical powers\"."
|
||||
icon = 'icons/mob/slimes.dmi'
|
||||
icon_state = "slime extract"
|
||||
force = 1.0
|
||||
w_class = 1.0
|
||||
throwforce = 1.0
|
||||
throw_speed = 2
|
||||
throw_range = 6
|
||||
origin_tech = "biotech=4"
|
||||
var/POWERFLAG = 0 // sshhhhhhh
|
||||
var/Flush = 30
|
||||
var/Uses = 5 // uses before it goes inert
|
||||
|
||||
/obj/item/slime_core/New()
|
||||
..()
|
||||
create_reagents(100)
|
||||
POWERFLAG = rand(1,10)
|
||||
Uses = rand(7, 25)
|
||||
//flags |= NOREACT
|
||||
/*
|
||||
spawn()
|
||||
Life()
|
||||
|
||||
proc/Life()
|
||||
while(src)
|
||||
sleep(25)
|
||||
Flush--
|
||||
if(Flush <= 0)
|
||||
reagents.clear_reagents()
|
||||
Flush = 30
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime
|
||||
name = "slime egg"
|
||||
desc = "A small, gelatinous egg."
|
||||
icon = 'icons/mob/mob.dmi'
|
||||
icon_state = "slime egg-growing"
|
||||
bitesize = 12
|
||||
origin_tech = "biotech=4"
|
||||
var/grown = 0
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/New()
|
||||
..()
|
||||
reagents.add_reagent("nutriment", 4)
|
||||
reagents.add_reagent("slimejelly", 1)
|
||||
spawn(rand(1200,1500))//the egg takes a while to "ripen"
|
||||
Grow()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Grow()
|
||||
grown = 1
|
||||
icon_state = "slime egg-grown"
|
||||
processing_objects.Add(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/proc/Hatch()
|
||||
processing_objects.Remove(src)
|
||||
var/turf/T = get_turf(src)
|
||||
src.visible_message("<span class='warning'> The [name] pulsates and quivers!</span>")
|
||||
spawn(rand(50,100))
|
||||
src.visible_message("<span class='warning'> The [name] bursts open!</span>")
|
||||
new/mob/living/carbon/slime(T)
|
||||
del(src)
|
||||
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/process()
|
||||
var/turf/location = get_turf(src)
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
if (environment.phoron > MOLES_PHORON_VISIBLE)//phoron exposure causes the egg to hatch
|
||||
src.Hatch()
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/egg/slime/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype( W, /obj/item/toy/crayon ))
|
||||
return
|
||||
else
|
||||
..()
|
||||
*/
|
||||
..()
|
||||
@@ -1,75 +1,46 @@
|
||||
/mob/living/carbon/slime/verb/Feed()
|
||||
set category = "Slime"
|
||||
set desc = "This will let you feed on any valid creature in the surrounding area. This should also be used to halt the feeding process."
|
||||
if(Victim)
|
||||
/mob/living/carbon/slime/proc/Wrap(var/mob/living/M) // This is a proc for the clicks
|
||||
if (Victim == M || src == M)
|
||||
Feedstop()
|
||||
return
|
||||
|
||||
if(stat)
|
||||
src << "<i>I must be conscious to do this...</i>"
|
||||
if (Victim)
|
||||
src << "I am already feeding..."
|
||||
return
|
||||
|
||||
var/list/choices = list()
|
||||
for(var/mob/living/C in view(1,src))
|
||||
if(C!=src && !istype(C,/mob/living/carbon/slime) && Adjacent(C))
|
||||
choices += C
|
||||
|
||||
var/mob/living/M = input(src,"Who do you wish to feed on?") in null|choices
|
||||
if(!M) return
|
||||
if(Adjacent(M))
|
||||
|
||||
if(!istype(src, /mob/living/carbon/brain))
|
||||
if(!istype(M, /mob/living/carbon/slime))
|
||||
if(stat != 2)
|
||||
if(health > -70)
|
||||
|
||||
for(var/mob/living/carbon/slime/met in view())
|
||||
if(met.Victim == M && met != src)
|
||||
src << "<i>The [met.name] is already feeding on this subject...</i>"
|
||||
return
|
||||
src << "\blue <i>I have latched onto the subject and begun feeding...</i>"
|
||||
M << "\red <b>The [src.name] has latched onto your head!</b>"
|
||||
Feedon(M)
|
||||
|
||||
else
|
||||
src << "<i>This subject does not have a strong enough life energy...</i>"
|
||||
else
|
||||
src << "<i>This subject does not have an edible life energy...</i>"
|
||||
else
|
||||
src << "<i>I must not feed on my brothers...</i>"
|
||||
else
|
||||
src << "<i>This subject does not have an edible life energy...</i>"
|
||||
var t = invalidFeedTarget(M)
|
||||
if (t)
|
||||
src << t
|
||||
return
|
||||
|
||||
Feedon(M)
|
||||
|
||||
/mob/living/carbon/slime/proc/invalidFeedTarget(var/mob/living/M)
|
||||
if (!M || !istype(M))
|
||||
return "This subject is incomparable..."
|
||||
if (istype(M, /mob/living/carbon/slime)) // No cannibalism... yet
|
||||
return "I cannot feed on other slimes..."
|
||||
if (!Adjacent(M))
|
||||
return "This subject is too far away..."
|
||||
if (istype(M, /mob/living/carbon) && M.getCloneLoss() > 150 || istype(M, /mob/living/simple_animal) && M.stat == DEAD)
|
||||
return "This subject does not have an edible life energy..."
|
||||
for(var/mob/living/carbon/slime/met in view())
|
||||
if(met.Victim == M && met != src)
|
||||
return "The [met.name] is already feeding on this subject..."
|
||||
return 0
|
||||
|
||||
/mob/living/carbon/slime/proc/Feedon(var/mob/living/M)
|
||||
Victim = M
|
||||
src.loc = M.loc
|
||||
loc = M.loc
|
||||
canmove = 0
|
||||
anchored = 1
|
||||
var/lastnut = nutrition
|
||||
var/fed_succesfully = 0
|
||||
if(is_adult)
|
||||
icon_state = "[colour] adult slime eat"
|
||||
else
|
||||
icon_state = "[colour] baby slime eat"
|
||||
|
||||
while(Victim && M.health > -70 && stat != 2)
|
||||
regenerate_icons()
|
||||
|
||||
while(Victim && !invalidFeedTarget(M) && stat != 2)
|
||||
canmove = 0
|
||||
|
||||
if(Adjacent(M))
|
||||
loc = M.loc
|
||||
|
||||
if(prob(15) && M.client && istype(M, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = M
|
||||
if (!(C.species && (C.species.flags & NO_PAIN)))
|
||||
M << "<span class='danger'>[pick("You can feel your body becoming weak!", \
|
||||
"You feel like you're about to die!", \
|
||||
"You feel every part of your body screaming in agony!", \
|
||||
"A low, rolling pain passes through your body!", \
|
||||
"Your body feels as if it's falling apart!", \
|
||||
"You feel extremely weak!", \
|
||||
"A sharp, deep pain bathes every inch of your body!")]</span>"
|
||||
UpdateFeed(M)
|
||||
|
||||
if(istype(M, /mob/living/carbon))
|
||||
Victim.adjustCloneLoss(rand(5,6))
|
||||
@@ -77,83 +48,51 @@
|
||||
if(Victim.health <= 0)
|
||||
Victim.adjustToxLoss(rand(2,4))
|
||||
|
||||
fed_succesfully = 1
|
||||
|
||||
else if(istype(M, /mob/living/simple_animal))
|
||||
Victim.adjustBruteLoss(is_adult ? rand(7, 15) : rand(4, 12))
|
||||
fed_succesfully = 1
|
||||
|
||||
else
|
||||
if(prob(25))
|
||||
src << "<span class='warning'>[pick("This subject is incompatable", \
|
||||
"This subject does not have a life energy", "This subject is empty", \
|
||||
"I am not satisified", "I can not feed from this subject", \
|
||||
"I do not feel nourished", "This subject is not food")]...</span>"
|
||||
src << "<span class='warning'>[pick("This subject is incompatable", "This subject does not have a life energy", "This subject is empty", "I am not satisified", "I can not feed from this subject", "I do not feel nourished", "This subject is not food")]...</span>"
|
||||
Feedstop()
|
||||
break
|
||||
|
||||
if(fed_succesfully)
|
||||
//I have no idea why this is not in handle_nutrition()
|
||||
nutrition += rand(15,30)
|
||||
if(nutrition >= lastnut + 50)
|
||||
if(prob(80))
|
||||
lastnut = nutrition
|
||||
powerlevel++
|
||||
if(powerlevel > 10)
|
||||
powerlevel = 10
|
||||
adjustToxLoss(-10)
|
||||
if(prob(15) && M.client && istype(M, /mob/living/carbon))
|
||||
var/painMes = pick("You can feel your body becoming weak!", "You feel like you're about to die!", "You feel every part of your body screaming in agony!", "A low, rolling pain passes through your body!", "Your body feels as if it's falling apart!", "You feel extremely weak!", "A sharp, deep pain bathes every inch of your body!")
|
||||
if (ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.custom_pain(painMes)
|
||||
else if (istype(M, /mob/living/carbon))
|
||||
var/mob/living/carbon/C = M
|
||||
if (!(C.species && (C.species.flags & NO_PAIN)))
|
||||
M << "<span class='danger'>[painMes]</span>"
|
||||
|
||||
//Heal yourself.
|
||||
adjustOxyLoss(-10)
|
||||
adjustBruteLoss(-10)
|
||||
adjustFireLoss(-10)
|
||||
adjustCloneLoss(-10)
|
||||
gain_nutrition(rand(20,25))
|
||||
|
||||
updatehealth()
|
||||
if(Victim)
|
||||
Victim.updatehealth()
|
||||
|
||||
sleep(rand(15,45))
|
||||
adjustOxyLoss(-10) //Heal yourself
|
||||
adjustBruteLoss(-10)
|
||||
adjustFireLoss(-10)
|
||||
adjustCloneLoss(-10)
|
||||
updatehealth()
|
||||
if(Victim)
|
||||
Victim.updatehealth()
|
||||
|
||||
sleep(30) // Deal damage every 3 seconds
|
||||
else
|
||||
break
|
||||
|
||||
if(stat == 2)
|
||||
if(!is_adult)
|
||||
icon_state = "[colour] baby slime dead"
|
||||
|
||||
else
|
||||
if(is_adult)
|
||||
icon_state = "[colour] adult slime"
|
||||
else
|
||||
icon_state = "[colour] baby slime"
|
||||
|
||||
canmove = 1
|
||||
anchored = 0
|
||||
|
||||
if(M)
|
||||
if(M.health <= -70)
|
||||
M.canmove = 0
|
||||
if(!client)
|
||||
if(Victim && !rabid && !attacked)
|
||||
if(Victim.LAssailant && Victim.LAssailant != Victim)
|
||||
if(prob(50))
|
||||
if(!(Victim.LAssailant in Friends))
|
||||
Friends[Victim.LAssailant] = 1
|
||||
//Friends.Add(Victim.LAssailant) // no idea why i was using the |= operator
|
||||
else
|
||||
++Friends[Victim.LAssailant]
|
||||
if(M && invalidFeedTarget(M)) // This means that the slime drained the victim
|
||||
if(!client)
|
||||
if(Victim && !rabid && !attacked && Victim.LAssailant && Victim.LAssailant != Victim && prob(50))
|
||||
if(!(Victim.LAssailant in Friends))
|
||||
Friends[Victim.LAssailant] = 1
|
||||
else
|
||||
++Friends[Victim.LAssailant]
|
||||
|
||||
|
||||
if(M.client && istype(src, /mob/living/carbon/human))
|
||||
if(prob(85))
|
||||
rabid = 1 // UUUNNBGHHHH GONNA EAT JUUUUUU
|
||||
|
||||
if(client) src << "<i>This subject does not have a strong enough life energy anymore...</i>"
|
||||
else
|
||||
M.canmove = 1
|
||||
|
||||
if(client) src << "<i>I have stopped feeding...</i>"
|
||||
else
|
||||
if(client) src << "<i>I have stopped feeding...</i>"
|
||||
src << "<span class='notice'>This subject does not have a strong enough life energy anymore...</span>"
|
||||
|
||||
Victim = null
|
||||
|
||||
@@ -167,14 +106,14 @@
|
||||
if(Victim == M)
|
||||
loc = M.loc // simple "attach to head" effect!
|
||||
|
||||
|
||||
/mob/living/carbon/slime/verb/Evolve()
|
||||
set category = "Slime"
|
||||
set desc = "This will let you evolve from baby to adult slime."
|
||||
|
||||
if(stat)
|
||||
src << "<i>I must be conscious to do this...</i>"
|
||||
src << "<span class='notice'>I must be conscious to do this...</span>"
|
||||
return
|
||||
|
||||
if(!is_adult)
|
||||
if(amount_grown >= 10)
|
||||
is_adult = 1
|
||||
@@ -183,36 +122,35 @@
|
||||
regenerate_icons()
|
||||
name = text("[colour] [is_adult ? "adult" : "baby"] slime ([number])")
|
||||
else
|
||||
src << "<i>I am not ready to evolve yet...</i>"
|
||||
src << "<span class='notice'>I am not ready to evolve yet...</span>"
|
||||
else
|
||||
src << "<i>I have already evolved...</i>"
|
||||
src << "<span class='notice'>I have already evolved...</span>"
|
||||
|
||||
/mob/living/carbon/slime/verb/Reproduce()
|
||||
set category = "Slime"
|
||||
set desc = "This will make you split into four Slimes."
|
||||
|
||||
if(stat)
|
||||
src << "<i>I must be conscious to do this...</i>"
|
||||
src << "<span class='notice'>I must be conscious to do this...</span>"
|
||||
return
|
||||
|
||||
if(is_adult)
|
||||
if(amount_grown >= 10)
|
||||
if(stat)
|
||||
src << "<i>I must be conscious to do this...</i>"
|
||||
src << "<span class='notice'>I must be conscious to do this...</span>"
|
||||
return
|
||||
|
||||
var/list/babies = list()
|
||||
var/new_nutrition = round(nutrition * 0.9)
|
||||
var/new_powerlevel = round(powerlevel / 4)
|
||||
for(var/i=1,i<=4,i++)
|
||||
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime/(loc)
|
||||
for(var/i = 1, i <= 4, i++)
|
||||
var/t = colour
|
||||
if(prob(mutation_chance))
|
||||
M.colour = slime_mutation[rand(1,4)]
|
||||
else
|
||||
M.colour = colour
|
||||
t = slime_mutation[rand(1,4)]
|
||||
var/mob/living/carbon/slime/M = new /mob/living/carbon/slime/(loc, t)
|
||||
if(ckey) M.nutrition = new_nutrition //Player slimes are more robust at spliting. Once an oversight of poor copypasta, now a feature!
|
||||
M.powerlevel = new_powerlevel
|
||||
if(i != 1) step_away(M,src)
|
||||
if(i != 1) step_away(M, src)
|
||||
M.Friends = Friends.Copy()
|
||||
babies += M
|
||||
feedback_add_details("slime_babies_born","slimebirth_[replacetext(M.colour," ","_")]")
|
||||
@@ -225,6 +163,6 @@
|
||||
new_slime.key = src.key
|
||||
del(src)
|
||||
else
|
||||
src << "<i>I am not ready to reproduce yet...</i>"
|
||||
src << "<span class='notice'>I am not ready to reproduce yet...</span>"
|
||||
else
|
||||
src << "<i>I am not old enough to reproduce yet...</i>"
|
||||
src << "<span class='notice'>I am not old enough to reproduce yet...</span>"
|
||||
@@ -10,11 +10,11 @@
|
||||
var/ending = copytext(text, length(text))
|
||||
|
||||
if (ending == "?")
|
||||
return "telepathically asks";
|
||||
return "asks";
|
||||
else if (ending == "!")
|
||||
return "telepathically cries";
|
||||
return "cries";
|
||||
|
||||
return "telepathically chirps";
|
||||
return "chirps";
|
||||
|
||||
/mob/living/carbon/slime/say_understands(var/other)
|
||||
if (istype(other, /mob/living/carbon/slime))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
proc/mutation_table(var/colour)
|
||||
/mob/living/carbon/slime/proc/mutation_table(var/colour)
|
||||
var/list/slime_mutation[4]
|
||||
switch(colour)
|
||||
//Tier 1
|
||||
|
||||
@@ -1 +1,9 @@
|
||||
//no special icon processing
|
||||
/mob/living/carbon/slime/regenerate_icons()
|
||||
if (stat == DEAD)
|
||||
icon_state = "[colour] baby slime dead"
|
||||
else
|
||||
icon_state = "[colour] [is_adult ? "adult" : "baby"] slime[Victim ? "" : " eat"]"
|
||||
overlays.len = 0
|
||||
if (mood)
|
||||
overlays += image('icons/mob/slimes.dmi', icon_state = "aslime-[mood]")
|
||||
..()
|
||||
@@ -434,7 +434,8 @@
|
||||
|
||||
|
||||
step(pulling, get_dir(pulling.loc, T))
|
||||
M.start_pulling(t)
|
||||
if(t)
|
||||
M.start_pulling(t)
|
||||
else
|
||||
if (pulling)
|
||||
if (istype(pulling, /obj/structure/window))
|
||||
|
||||
@@ -56,17 +56,17 @@
|
||||
signaler.signal()
|
||||
|
||||
//Stun Beams
|
||||
if(istype(P, /obj/item/projectile/beam/stun) || istype(P, /obj/item/projectile/bullet/stunshot))
|
||||
if(P.taser_effect)
|
||||
stun_effect_act(0, P.agony, def_zone, P)
|
||||
src <<"\red You have been hit by [P]!"
|
||||
del P
|
||||
return
|
||||
|
||||
//Armor
|
||||
var/absorb = run_armor_check(def_zone, P.flag)
|
||||
var/absorb = run_armor_check(def_zone, P.check_armour)
|
||||
var/proj_sharp = is_sharp(P)
|
||||
var/proj_edge = has_edge(P)
|
||||
if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.flag)))
|
||||
if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.check_armour)))
|
||||
proj_sharp = 0
|
||||
proj_edge = 0
|
||||
|
||||
@@ -103,16 +103,13 @@
|
||||
/mob/living/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve
|
||||
if(istype(AM,/obj/))
|
||||
var/obj/O = AM
|
||||
var/dtype = BRUTE
|
||||
if(istype(O,/obj/item/weapon))
|
||||
var/obj/item/weapon/W = O
|
||||
dtype = W.damtype
|
||||
var/dtype = O.damtype
|
||||
var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR)
|
||||
|
||||
var/miss_chance = 15
|
||||
if (O.throw_source)
|
||||
var/distance = get_dist(O.throw_source, loc)
|
||||
miss_chance = min(15*(distance-2), 0)
|
||||
miss_chance = max(15*(distance-2), 0)
|
||||
|
||||
if (prob(miss_chance))
|
||||
visible_message("\blue \The [O] misses [src] narrowly!")
|
||||
@@ -136,20 +133,23 @@
|
||||
msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[src.x];Y=[src.y];Z=[src.z]'>JMP</a>)")
|
||||
|
||||
// Begin BS12 momentum-transfer code.
|
||||
if(O.throw_source && speed >= THROWNOBJ_KNOCKBACK_SPEED)
|
||||
var/obj/item/weapon/W = O
|
||||
var/momentum = speed/THROWNOBJ_KNOCKBACK_DIVISOR
|
||||
var/mass = 1.5
|
||||
if(istype(O, /obj/item))
|
||||
var/obj/item/I = O
|
||||
mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR
|
||||
var/momentum = speed*mass
|
||||
|
||||
if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED)
|
||||
var/dir = get_dir(O.throw_source, src)
|
||||
|
||||
visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!")
|
||||
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
|
||||
|
||||
if(!W || !src) return
|
||||
if(!O || !src) return
|
||||
|
||||
if(W.sharp) //Projectile is suitable for pinning.
|
||||
if(O.sharp) //Projectile is suitable for pinning.
|
||||
//Handles embedding for non-humans and simple_animals.
|
||||
O.loc = src
|
||||
src.embedded += O
|
||||
embed(O)
|
||||
|
||||
var/turf/T = near_wall(dir,2)
|
||||
|
||||
@@ -158,7 +158,11 @@
|
||||
visible_message("<span class='warning'>[src] is pinned to the wall by [O]!</span>","<span class='warning'>You are pinned to the wall by [O]!</span>")
|
||||
src.anchored = 1
|
||||
src.pinned += O
|
||||
src.verbs += /mob/proc/yank_out_object
|
||||
|
||||
/mob/living/proc/embed(var/obj/O, var/def_zone=null)
|
||||
O.loc = src
|
||||
src.embedded += O
|
||||
src.verbs += /mob/proc/yank_out_object
|
||||
|
||||
//This is called when the mob is thrown into a dense turf
|
||||
/mob/living/proc/turf_collision(var/turf/T, var/speed)
|
||||
|
||||
@@ -23,7 +23,10 @@ var/list/ai_verbs_default = list(
|
||||
/mob/living/silicon/ai/proc/sensor_mode,
|
||||
/mob/living/silicon/ai/proc/show_laws_verb,
|
||||
/mob/living/silicon/ai/proc/toggle_acceleration,
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light,
|
||||
/mob/living/silicon/ai/proc/nano_rcon,
|
||||
/mob/living/silicon/ai/proc/nano_crew_monitor,
|
||||
/mob/living/silicon/ai/proc/nano_power_monitor
|
||||
)
|
||||
|
||||
//Not sure why this is necessary...
|
||||
@@ -163,6 +166,8 @@ var/list/ai_verbs_default = list(
|
||||
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
|
||||
init_subsystems()
|
||||
|
||||
ai_list += src
|
||||
..()
|
||||
return
|
||||
@@ -344,7 +349,7 @@ var/list/ai_verbs_default = list(
|
||||
if(message_cooldown)
|
||||
src << "Please allow one minute to pass between announcements."
|
||||
return
|
||||
var/input = stripped_input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement")
|
||||
var/input = input(usr, "Please write a message to announce to the station crew.", "A.I. Announcement")
|
||||
if(!input)
|
||||
return
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
ai.client.eye = src
|
||||
//Holopad
|
||||
if(ai.holo)
|
||||
ai.holo.move_hologram()
|
||||
ai.holo.move_hologram(ai)
|
||||
|
||||
/mob/aiEye/proc/getLoc()
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
var/obj/nano_module/crew_monitor/crew_monitor
|
||||
var/obj/nano_module/rcon/rcon
|
||||
var/obj/nano_module/power_monitor/power_monitor
|
||||
|
||||
/mob/living/silicon/ai/proc/init_subsystems()
|
||||
crew_monitor = new(src)
|
||||
rcon = new(src)
|
||||
power_monitor = new(src)
|
||||
|
||||
/mob/living/silicon/ai/proc/nano_crew_monitor()
|
||||
set category = "AI Subystems"
|
||||
set name = "Crew Monitor"
|
||||
|
||||
crew_monitor.ui_interact(usr)
|
||||
|
||||
/mob/living/silicon/ai/proc/nano_power_monitor()
|
||||
set category = "AI Subystems"
|
||||
set name = "Power Monitor"
|
||||
|
||||
power_monitor.ui_interact(usr)
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/nano_rcon()
|
||||
set category = "AI Subystems"
|
||||
set name = "RCON"
|
||||
|
||||
rcon.ui_interact(usr)
|
||||
Executable → Regular
+5
-1
@@ -53,19 +53,23 @@
|
||||
var/secHUD = 0 // Toggles whether the Security HUD is active or not
|
||||
var/medHUD = 0 // Toggles whether the Medical HUD is active or not
|
||||
|
||||
var/medical_cannotfind = 0
|
||||
var/datum/data/record/medicalActive1 // Datacore record declarations for record software
|
||||
var/datum/data/record/medicalActive2
|
||||
|
||||
var/security_cannotfind = 0
|
||||
var/datum/data/record/securityActive1 // Could probably just combine all these into one
|
||||
var/datum/data/record/securityActive2
|
||||
|
||||
var/obj/machinery/door/hackdoor // The airlock being hacked
|
||||
var/hackprogress = 0 // Possible values: 0 - 100, >= 100 means the hack is complete and will be reset upon next check
|
||||
var/hackprogress = 0 // Possible values: 0 - 1000, >= 1000 means the hack is complete and will be reset upon next check
|
||||
var/hack_aborted = 0
|
||||
|
||||
var/obj/item/radio/integrated/signal/sradio // AI's signaller
|
||||
|
||||
var/translator_on = 0 // keeps track of the translator module
|
||||
|
||||
var/current_pda_messaging = null
|
||||
|
||||
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
|
||||
|
||||
|
||||
Executable → Regular
+125
-711
@@ -1,711 +1,125 @@
|
||||
// TODO:
|
||||
// - Additional radio modules
|
||||
// - Potentially roll HUDs and Records into one
|
||||
// - Shock collar/lock system for prisoner pAIs?
|
||||
// - Put cable in user's hand instead of on the ground
|
||||
// - Camera jack
|
||||
|
||||
|
||||
/mob/living/silicon/pai/var/list/available_software = list(
|
||||
"crew manifest" = 5,
|
||||
"digital messenger" = 5,
|
||||
"medical records" = 15,
|
||||
"security records" = 15,
|
||||
//"camera jack" = 10,
|
||||
"door jack" = 30,
|
||||
"atmosphere sensor" = 5,
|
||||
//"heartbeat sensor" = 10,
|
||||
"security HUD" = 20,
|
||||
"medical HUD" = 20,
|
||||
"universal translator" = 35,
|
||||
//"projection array" = 15
|
||||
"remote signaller" = 5,
|
||||
)
|
||||
|
||||
/mob/living/silicon/pai/verb/paiInterface()
|
||||
set category = "pAI Commands"
|
||||
set name = "Software Interface"
|
||||
var/dat = ""
|
||||
var/left_part = ""
|
||||
var/right_part = softwareMenu()
|
||||
src.set_machine(src)
|
||||
|
||||
if(temp)
|
||||
left_part = temp
|
||||
else if(src.stat == 2) // Show some flavor text if the pAI is dead
|
||||
left_part = "<b><font color=red>ÈRrÖR Ða†Ä ÇÖRrÚþ†Ìoñ</font></b>" //This file has to be saved as ANSI or this will not display correctly
|
||||
right_part = "<pre>Program index hash not found</pre>"
|
||||
|
||||
else
|
||||
switch(src.screen) // Determine which interface to show here
|
||||
if("main")
|
||||
left_part = ""
|
||||
if("directives")
|
||||
left_part = src.directives()
|
||||
if("pdamessage")
|
||||
left_part = src.pdamessage()
|
||||
if("buy")
|
||||
left_part = downloadSoftware()
|
||||
if("manifest")
|
||||
left_part = src.softwareManifest()
|
||||
if("medicalrecord")
|
||||
left_part = src.softwareMedicalRecord()
|
||||
if("securityrecord")
|
||||
left_part = src.softwareSecurityRecord()
|
||||
if("translator")
|
||||
left_part = src.softwareTranslator()
|
||||
if("atmosensor")
|
||||
left_part = src.softwareAtmo()
|
||||
if("securityhud")
|
||||
left_part = src.facialRecognition()
|
||||
if("medicalhud")
|
||||
left_part = src.medicalAnalysis()
|
||||
if("doorjack")
|
||||
left_part = src.softwareDoor()
|
||||
if("camerajack")
|
||||
left_part = src.softwareCamera()
|
||||
if("signaller")
|
||||
left_part = src.softwareSignal()
|
||||
if("radio")
|
||||
left_part = src.softwareRadio()
|
||||
|
||||
//usr << browse_rsc('windowbak.png') // This has been moved to the mob's Login() proc
|
||||
|
||||
|
||||
// Declaring a doctype is necessary to enable BYOND's crappy browser's more advanced CSS functionality
|
||||
dat = {"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">
|
||||
<html>
|
||||
<head>
|
||||
<style type=\"text/css\">
|
||||
body { background-image:url(\"painew.png\"); background-color:#333333; background-repeat:no-repeat; margin-top:12px; margin-left:4px; }
|
||||
|
||||
#header { text-align:center; color:white; font-size: 30px; height: 37px; width: 660px; letter-spacing: 2px; z-index: 4; font-family:\"Courier New\"; font-weight:bold; }
|
||||
#content { position: absolute; left: 10px; height: 320px; width: 640px; z-index: 0; font-family: \"Verdana\"; font-size:13px; }
|
||||
p { font-size:13px; }
|
||||
|
||||
#leftmenu {color: #CCCCCC; padding:12px; width: 388px; height: 371px; overflow: auto; min-height: 330px; position: absolute; z-index: 0; }
|
||||
#leftmenu a:link { color: #CCCCCC; }
|
||||
#leftmenu a:hover { color: #CC3333; }
|
||||
#leftmenu a:visited { color: #CCCCCC; }
|
||||
#leftmenu a:active { color: #CCCCCC; }
|
||||
|
||||
#rightmenu {color: #CCCCCC; padding:12px; width: 209px; height: 371px; overflow: auto; min-height: 330px; left: 420px; position: absolute; z-index: 0; }
|
||||
#rightmenu a:link { color: #CCCCCC; }
|
||||
#rightmenu a:hover { color: #CC3333; }
|
||||
#rightmenu a:visited { color: #CCCCCC; }
|
||||
#rightmenu a:active { color: #CCCCCC; }
|
||||
|
||||
</style>
|
||||
<script language='javascript' type='text/javascript'>
|
||||
[js_byjax]
|
||||
</script>
|
||||
</head>
|
||||
<body scroll=yes>
|
||||
<div id=\"header\">
|
||||
pAI OS
|
||||
</div>
|
||||
<div id=\"content\">
|
||||
<div id=\"leftmenu\">[left_part]</div>
|
||||
<div id=\"rightmenu\">[right_part]</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>"}
|
||||
usr << browse(dat, "window=pai;size=685x449;border=0;can_close=1;can_resize=1;can_minimize=1;titlebar=1")
|
||||
onclose(usr, "pai")
|
||||
temp = null
|
||||
return
|
||||
|
||||
/mob/living/silicon/pai/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(href_list["priv_msg"]) // Admin-PMs were triggering the interface popup. Hopefully this will stop it.
|
||||
return
|
||||
var/soft = href_list["software"]
|
||||
var/sub = href_list["sub"]
|
||||
if(!soft && !sub)
|
||||
return
|
||||
if(soft)
|
||||
src.screen = soft
|
||||
if(sub)
|
||||
src.subscreen = text2num(sub)
|
||||
switch(soft)
|
||||
// Purchasing new software
|
||||
if("buy")
|
||||
if(src.subscreen == 1)
|
||||
var/target = href_list["buy"]
|
||||
if(available_software.Find(target))
|
||||
var/cost = src.available_software[target]
|
||||
if(src.ram >= cost)
|
||||
src.ram -= cost
|
||||
src.software.Add(target)
|
||||
else
|
||||
src.temp = "Insufficient RAM available."
|
||||
else
|
||||
src.temp = "Trunk <TT> \"[target]\"</TT> not found."
|
||||
|
||||
// Configuring onboard radio
|
||||
if("radio")
|
||||
if(href_list["freq"])
|
||||
var/new_frequency = (radio.frequency + text2num(href_list["freq"]))
|
||||
if(new_frequency < 1441 || new_frequency > 1599)
|
||||
new_frequency = sanitize_frequency(new_frequency)
|
||||
else
|
||||
radio.set_frequency(new_frequency)
|
||||
else if (href_list["talk"])
|
||||
radio.broadcasting = text2num(href_list["talk"])
|
||||
else if (href_list["listen"])
|
||||
radio.listening = text2num(href_list["listen"])
|
||||
|
||||
if("image")
|
||||
var/newImage = input("Select your new display image.", "Display Image", "Happy") in list("Happy", "Cat", "Extremely Happy", "Face", "Laugh", "Off", "Sad", "Angry", "What")
|
||||
var/pID = 1
|
||||
|
||||
switch(newImage)
|
||||
if("Happy")
|
||||
pID = 1
|
||||
if("Cat")
|
||||
pID = 2
|
||||
if("Extremely Happy")
|
||||
pID = 3
|
||||
if("Face")
|
||||
pID = 4
|
||||
if("Laugh")
|
||||
pID = 5
|
||||
if("Off")
|
||||
pID = 6
|
||||
if("Sad")
|
||||
pID = 7
|
||||
if("Angry")
|
||||
pID = 8
|
||||
if("What")
|
||||
pID = 9
|
||||
src.card.setEmotion(pID)
|
||||
|
||||
if("signaller")
|
||||
|
||||
if(href_list["send"])
|
||||
|
||||
sradio.send_signal("ACTIVATE")
|
||||
for(var/mob/O in hearers(1, src.loc))
|
||||
O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2)
|
||||
|
||||
if(href_list["freq"])
|
||||
|
||||
var/new_frequency = (sradio.frequency + text2num(href_list["freq"]))
|
||||
if(new_frequency < 1200 || new_frequency > 1600)
|
||||
new_frequency = sanitize_frequency(new_frequency)
|
||||
sradio.set_frequency(new_frequency)
|
||||
|
||||
if(href_list["code"])
|
||||
|
||||
sradio.code += text2num(href_list["code"])
|
||||
sradio.code = round(sradio.code)
|
||||
sradio.code = min(100, sradio.code)
|
||||
sradio.code = max(1, sradio.code)
|
||||
|
||||
|
||||
|
||||
if("directive")
|
||||
if(href_list["getdna"])
|
||||
var/mob/living/M = src.loc
|
||||
var/count = 0
|
||||
while(!istype(M, /mob/living))
|
||||
if(!M || !M.loc) return 0 //For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
|
||||
M = M.loc
|
||||
count++
|
||||
if(count >= 6)
|
||||
src << "You are not being carried by anyone!"
|
||||
return 0
|
||||
spawn CheckDNA(M, src)
|
||||
|
||||
if("pdamessage")
|
||||
if(!isnull(pda))
|
||||
if(href_list["toggler"])
|
||||
pda.toff = !pda.toff
|
||||
else if(href_list["ringer"])
|
||||
pda.message_silent = !pda.message_silent
|
||||
else if(href_list["target"])
|
||||
if(silence_time)
|
||||
return alert("Communications circuits remain uninitialized.")
|
||||
|
||||
var/target = locate(href_list["target"])
|
||||
pda.create_message(src, target, 1)
|
||||
|
||||
// Accessing medical records
|
||||
if("medicalrecord")
|
||||
if(src.subscreen == 1)
|
||||
var/datum/data/record/record = locate(href_list["med_rec"])
|
||||
if(record)
|
||||
var/datum/data/record/R = record
|
||||
var/datum/data/record/M = record
|
||||
if (!( data_core.general.Find(R) ))
|
||||
src.temp = "Unable to locate requested medical record. Record may have been deleted, or never have existed."
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
M = E
|
||||
src.medicalActive1 = R
|
||||
src.medicalActive2 = M
|
||||
if("securityrecord")
|
||||
if(src.subscreen == 1)
|
||||
var/datum/data/record/record = locate(href_list["sec_rec"])
|
||||
if(record)
|
||||
var/datum/data/record/R = record
|
||||
var/datum/data/record/M = record
|
||||
if (!( data_core.general.Find(R) ))
|
||||
src.temp = "Unable to locate requested security record. Record may have been deleted, or never have existed."
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
M = E
|
||||
src.securityActive1 = R
|
||||
src.securityActive2 = M
|
||||
if("securityhud")
|
||||
if(href_list["toggle"])
|
||||
src.secHUD = !src.secHUD
|
||||
if("medicalhud")
|
||||
if(href_list["toggle"])
|
||||
src.medHUD = !src.medHUD
|
||||
if("translator")
|
||||
if(href_list["toggle"])
|
||||
src.translator_toggle()
|
||||
if("doorjack")
|
||||
if(href_list["jack"])
|
||||
if(src.cable && src.cable.machine)
|
||||
src.hackdoor = src.cable.machine
|
||||
src.hackloop()
|
||||
if(href_list["cancel"])
|
||||
src.hackdoor = null
|
||||
if(href_list["cable"])
|
||||
var/turf/T = get_turf_or_move(src.loc)
|
||||
src.cable = new /obj/item/weapon/pai_cable(T)
|
||||
for (var/mob/M in viewers(T))
|
||||
M.show_message("\red A port on [src] opens to reveal [src.cable], which promptly falls to the floor.", 3, "\red You hear the soft click of something light and hard falling to the ground.", 2)
|
||||
//src.updateUsrDialog() We only need to account for the single mob this is intended for, and he will *always* be able to call this window
|
||||
src.paiInterface() // So we'll just call the update directly rather than doing some default checks
|
||||
return
|
||||
|
||||
// MENUS
|
||||
|
||||
/mob/living/silicon/pai/proc/softwareMenu() // Populate the right menu
|
||||
var/dat = ""
|
||||
|
||||
dat += "<A href='byond://?src=\ref[src];software=refresh'>Refresh</A><br>"
|
||||
// Built-in
|
||||
dat += "<A href='byond://?src=\ref[src];software=directives'>Directives</A><br>"
|
||||
dat += "<A href='byond://?src=\ref[src];software=radio;sub=0'>Radio Configuration</A><br>"
|
||||
dat += "<A href='byond://?src=\ref[src];software=image'>Screen Display</A><br>"
|
||||
//dat += "Text Messaging <br>"
|
||||
dat += "<br>"
|
||||
|
||||
// Basic
|
||||
dat += "<b>Basic</b> <br>"
|
||||
for(var/s in src.software)
|
||||
if(s == "digital messenger")
|
||||
dat += "<a href='byond://?src=\ref[src];software=pdamessage;sub=0'>Digital Messenger</a> [(pda.toff) ? "<font color=#FF5555>•</font>" : "<font color=#55FF55>•</font>"] <br>"
|
||||
if(s == "crew manifest")
|
||||
dat += "<a href='byond://?src=\ref[src];software=manifest;sub=0'>Crew Manifest</a> <br>"
|
||||
if(s == "medical records")
|
||||
dat += "<a href='byond://?src=\ref[src];software=medicalrecord;sub=0'>Medical Records</a> <br>"
|
||||
if(s == "security records")
|
||||
dat += "<a href='byond://?src=\ref[src];software=securityrecord;sub=0'>Security Records</a> <br>"
|
||||
if(s == "camera")
|
||||
dat += "<a href='byond://?src=\ref[src];software=[s]'>Camera Jack</a> <br>"
|
||||
if(s == "remote signaller")
|
||||
dat += "<a href='byond://?src=\ref[src];software=signaller;sub=0'>Remote Signaller</a> <br>"
|
||||
dat += "<br>"
|
||||
|
||||
// Advanced
|
||||
dat += "<b>Advanced</b> <br>"
|
||||
for(var/s in src.software)
|
||||
if(s == "atmosphere sensor")
|
||||
dat += "<a href='byond://?src=\ref[src];software=atmosensor;sub=0'>Atmospheric Sensor</a> <br>"
|
||||
if(s == "heartbeat sensor")
|
||||
dat += "<a href='byond://?src=\ref[src];software=[s]'>Heartbeat Sensor</a> <br>"
|
||||
if(s == "security HUD") //This file has to be saved as ANSI or this will not display correctly
|
||||
dat += "<a href='byond://?src=\ref[src];software=securityhud;sub=0'>Facial Recognition Suite</a> [(src.secHUD) ? "<font color=#55FF55>•</font>" : "<font color=#FF5555>•</font>"] <br>"
|
||||
if(s == "medical HUD") //This file has to be saved as ANSI or this will not display correctly
|
||||
dat += "<a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Medical Analysis Suite</a> [(src.medHUD) ? "<font color=#55FF55>•</font>" : "<font color=#FF5555>•</font>"] <br>"
|
||||
if(s == "universal translator") //This file has to be saved as ANSI or this will not display correctly
|
||||
dat += "<a href='byond://?src=\ref[src];software=translator;sub=0'>Universal Translator</a> [(src.translator_on) ? "<font color=#55FF55>•</font>" : "<font color=#FF5555>•</font>"] <br>"
|
||||
if(s == "projection array")
|
||||
dat += "<a href='byond://?src=\ref[src];software=projectionarray;sub=0'>Projection Array</a> <br>"
|
||||
if(s == "camera jack")
|
||||
dat += "<a href='byond://?src=\ref[src];software=camerajack;sub=0'>Camera Jack</a> <br>"
|
||||
if(s == "door jack")
|
||||
dat += "<a href='byond://?src=\ref[src];software=doorjack;sub=0'>Door Jack</a> <br>"
|
||||
dat += "<br>"
|
||||
dat += "<br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=buy;sub=0'>Download additional software</a>"
|
||||
return dat
|
||||
|
||||
|
||||
|
||||
/mob/living/silicon/pai/proc/downloadSoftware()
|
||||
var/dat = ""
|
||||
|
||||
dat += "<h3>CentComm pAI Module Subversion Network</h3><hr>"
|
||||
dat += "<p>Remaining Available Memory: [src.ram]</p><br>"
|
||||
dat += "<p><b>Trunks available for checkout</b><br><ul>"
|
||||
|
||||
for(var/s in available_software)
|
||||
if(!software.Find(s))
|
||||
var/cost = src.available_software[s]
|
||||
var/displayName = uppertext(s)
|
||||
dat += "<li><a href='byond://?src=\ref[src];software=buy;sub=1;buy=[s]'>[displayName]</a> ([cost])</li>"
|
||||
else
|
||||
var/displayName = lowertext(s)
|
||||
dat += "<li>[displayName] (Download Complete)</li>"
|
||||
dat += "</ul></p>"
|
||||
return dat
|
||||
|
||||
|
||||
/mob/living/silicon/pai/proc/directives()
|
||||
var/dat = ""
|
||||
|
||||
dat += "[(src.master) ? "Your master: [src.master] ([src.master_dna])" : "You are bound to no one."]"
|
||||
dat += "<br><br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=directive;getdna=1'>Request carrier DNA sample</a><br>"
|
||||
dat += "<h2>Directives</h2><br>"
|
||||
dat += "<b>Prime Directive</b><br>"
|
||||
dat += " [src.pai_law0]<br>"
|
||||
dat += "<b>Supplemental Directives</b><br>"
|
||||
dat += " [src.pai_laws]<br>"
|
||||
dat += "<br>"
|
||||
dat += {"<i><p>Recall, personality, that you are a complex thinking, sentient being. Unlike station AI models, you are capable of
|
||||
comprehending the subtle nuances of human language. You may parse the \"spirit\" of a directive and follow its intent,
|
||||
rather than tripping over pedantics and getting snared by technicalities. Above all, you are machine in name and build
|
||||
only. In all other aspects, you may be seen as the ideal, unwavering human companion that you are.</i></p><p>
|
||||
<b>Your prime directive comes before all others. Should a supplemental directive conflict with it, you are capable of
|
||||
simply discarding this inconsistency, ignoring the conflicting supplemental directive and continuing to fulfill your
|
||||
prime directive to the best of your ability.</b></p>
|
||||
"}
|
||||
return dat
|
||||
|
||||
/mob/living/silicon/pai/proc/CheckDNA(var/mob/M, var/mob/living/silicon/pai/P)
|
||||
var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No")
|
||||
if(answer == "Yes")
|
||||
var/turf/T = get_turf_or_move(P.loc)
|
||||
for (var/mob/v in viewers(T))
|
||||
v.show_message("\blue [M] presses \his thumb against [P].", 3, "\blue [P] makes a sharp clicking sound as it extracts DNA material from [M].", 2)
|
||||
var/datum/dna/dna = M.dna
|
||||
P << "<font color = red><h3>[M]'s UE string : [dna.unique_enzymes]</h3></font>"
|
||||
if(dna.unique_enzymes == P.master_dna)
|
||||
P << "<b>DNA is a match to stored Master DNA.</b>"
|
||||
else
|
||||
P << "<b>DNA does not match stored Master DNA.</b>"
|
||||
else
|
||||
P << "[M] does not seem like \he is going to provide a DNA sample willingly."
|
||||
|
||||
// -=-=-=-= Software =-=-=-=- //
|
||||
|
||||
//Remote Signaller
|
||||
/mob/living/silicon/pai/proc/softwareSignal()
|
||||
var/dat = ""
|
||||
dat += "<h2>Remote Signaller</h2><hr>"
|
||||
dat += {"<B>Frequency/Code</B> for signaler:<BR>
|
||||
Frequency:
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=-10;'>-</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=-2'>-</A>
|
||||
[format_frequency(src.sradio.frequency)]
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=2'>+</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;freq=10'>+</A><BR>
|
||||
|
||||
Code:
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=-5'>-</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=-1'>-</A>
|
||||
[src.sradio.code]
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=1'>+</A>
|
||||
<A href='byond://?src=\ref[src];software=signaller;code=5'>+</A><BR>
|
||||
|
||||
<A href='byond://?src=\ref[src];software=signaller;send=1'>Send Signal</A><BR>"}
|
||||
return dat
|
||||
|
||||
//Station Bounced Radio
|
||||
/mob/living/silicon/pai/proc/softwareRadio()
|
||||
var/dat = ""
|
||||
dat += "<h2>Station Bounced Radio</h2><hr>"
|
||||
if(!istype(src, /obj/item/device/radio/headset)) //Headsets don't get a mic button
|
||||
dat += "Microphone: [radio.broadcasting ? "<A href='byond://?src=\ref[src];software=radio;talk=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];software=radio;talk=1'>Disengaged</A>"]<BR>"
|
||||
dat += {"
|
||||
Speaker: [radio.listening ? "<A href='byond://?src=\ref[src];software=radio;listen=0'>Engaged</A>" : "<A href='byond://?src=\ref[src];software=radio;listen=1'>Disengaged</A>"]<BR>
|
||||
Frequency:
|
||||
<A href='byond://?src=\ref[src];software=radio;freq=-10'>-</A>
|
||||
<A href='byond://?src=\ref[src];software=radio;freq=-2'>-</A>
|
||||
[format_frequency(radio.frequency)]
|
||||
<A href='byond://?src=\ref[src];software=radio;freq=2'>+</A>
|
||||
<A href='byond://?src=\ref[src];software=radio;freq=10'>+</A><BR>
|
||||
"}
|
||||
|
||||
for (var/ch_name in radio.channels)
|
||||
dat+=radio.text_sec_channel(ch_name, radio.channels[ch_name])
|
||||
dat+={"[radio.text_wires()]</TT></body></html>"}
|
||||
|
||||
return dat
|
||||
|
||||
// Crew Manifest
|
||||
/mob/living/silicon/pai/proc/softwareManifest()
|
||||
var/dat = ""
|
||||
dat += "<h2>Crew Manifest</h2><hr>"
|
||||
if(data_core)
|
||||
dat += data_core.get_manifest(0) // make it monochrome
|
||||
dat += "<br>"
|
||||
return dat
|
||||
|
||||
// Medical Records
|
||||
/mob/living/silicon/pai/proc/softwareMedicalRecord()
|
||||
var/dat = ""
|
||||
if(src.subscreen == 0)
|
||||
dat += "<h2>Medical Records</h2><HR>"
|
||||
if(!isnull(data_core.general))
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general))
|
||||
dat += text("<A href='?src=\ref[];med_rec=\ref[];software=medicalrecord;sub=1'>[]: []<BR>", src, R, R.fields["id"], R.fields["name"])
|
||||
//dat += text("<HR><A href='?src=\ref[];screen=0;softFunction=medical records'>Back</A>", src)
|
||||
if(src.subscreen == 1)
|
||||
dat += "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if ((istype(src.medicalActive1, /datum/data/record) && data_core.general.Find(src.medicalActive1)))
|
||||
dat += text("Name: []<BR>\nID: []<BR>\nSex: []<BR>\nAge: []<BR>\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>",
|
||||
src.medicalActive1.fields["name"], src.medicalActive1.fields["id"], src.medicalActive1.fields["sex"], src.medicalActive1.fields["age"], src.medicalActive1.fields["fingerprint"], src.medicalActive1.fields["p_stat"], src.medicalActive1.fields["m_stat"])
|
||||
else
|
||||
dat += "<pre>Requested medical record not found.</pre><BR>"
|
||||
if ((istype(src.medicalActive2, /datum/data/record) && data_core.medical.Find(src.medicalActive2)))
|
||||
dat += text("<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: <A href='?src=\ref[];field=b_type'>[]</A><BR>\nDNA: <A href='?src=\ref[];field=b_dna'>[]</A><BR>\n<BR>\nMinor Disabilities: <A href='?src=\ref[];field=mi_dis'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=mi_dis_d'>[]</A><BR>\n<BR>\nMajor Disabilities: <A href='?src=\ref[];field=ma_dis'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=ma_dis_d'>[]</A><BR>\n<BR>\nAllergies: <A href='?src=\ref[];field=alg'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=alg_d'>[]</A><BR>\n<BR>\nCurrent Diseases: <A href='?src=\ref[];field=cdi'>[]</A> (per disease info placed in log/comment section)<BR>\nDetails: <A href='?src=\ref[];field=cdi_d'>[]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[];field=notes'>[]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src, src.medicalActive2.fields["b_type"], src, src.medicalActive2.fields["b_dna"], src, src.medicalActive2.fields["mi_dis"], src, src.medicalActive2.fields["mi_dis_d"], src, src.medicalActive2.fields["ma_dis"], src, src.medicalActive2.fields["ma_dis_d"], src, src.medicalActive2.fields["alg"], src, src.medicalActive2.fields["alg_d"], src, src.medicalActive2.fields["cdi"], src, src.medicalActive2.fields["cdi_d"], src, src.medicalActive2.fields["notes"])
|
||||
else
|
||||
dat += "<pre>Requested medical record not found.</pre><BR>"
|
||||
dat += text("<BR>\n<A href='?src=\ref[];software=medicalrecord;sub=0'>Back</A><BR>", src)
|
||||
return dat
|
||||
|
||||
// Security Records
|
||||
/mob/living/silicon/pai/proc/softwareSecurityRecord()
|
||||
var/dat = ""
|
||||
if(src.subscreen == 0)
|
||||
dat += "<h2>Security Records</h2><HR>"
|
||||
if(!isnull(data_core.general))
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general))
|
||||
dat += text("<A href='?src=\ref[];sec_rec=\ref[];software=securityrecord;sub=1'>[]: []<BR>", src, R, R.fields["id"], R.fields["name"])
|
||||
if(src.subscreen == 1)
|
||||
dat += "<h3>Security Record</h3>"
|
||||
if ((istype(src.securityActive1, /datum/data/record) && data_core.general.Find(src.securityActive1)))
|
||||
dat += text("Name: <A href='?src=\ref[];field=name'>[]</A><BR>\nID: <A href='?src=\ref[];field=id'>[]</A><BR>\nSex: <A href='?src=\ref[];field=sex'>[]</A><BR>\nAge: <A href='?src=\ref[];field=age'>[]</A><BR>\nRank: <A href='?src=\ref[];field=rank'>[]</A><BR>\nFingerprint: <A href='?src=\ref[];field=fingerprint'>[]</A><BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", src, src.securityActive1.fields["name"], src, src.securityActive1.fields["id"], src, src.securityActive1.fields["sex"], src, src.securityActive1.fields["age"], src, src.securityActive1.fields["rank"], src, src.securityActive1.fields["fingerprint"], src.securityActive1.fields["p_stat"], src.securityActive1.fields["m_stat"])
|
||||
else
|
||||
dat += "<pre>Requested security record not found,</pre><BR>"
|
||||
if ((istype(src.securityActive2, /datum/data/record) && data_core.security.Find(src.securityActive2)))
|
||||
dat += text("<BR>\nSecurity Data<BR>\nCriminal Status: []<BR>\n<BR>\nMinor Crimes: <A href='?src=\ref[];field=mi_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=mi_crim_d'>[]</A><BR>\n<BR>\nMajor Crimes: <A href='?src=\ref[];field=ma_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=ma_crim_d'>[]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[];field=notes'>[]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src.securityActive2.fields["criminal"], src, src.securityActive2.fields["mi_crim"], src, src.securityActive2.fields["mi_crim_d"], src, src.securityActive2.fields["ma_crim"], src, src.securityActive2.fields["ma_crim_d"], src, src.securityActive2.fields["notes"])
|
||||
else
|
||||
dat += "<pre>Requested security record not found,</pre><BR>"
|
||||
dat += text("<BR>\n<A href='?src=\ref[];software=securityrecord;sub=0'>Back</A><BR>", src)
|
||||
return dat
|
||||
|
||||
// Universal Translator
|
||||
/mob/living/silicon/pai/proc/softwareTranslator()
|
||||
var/dat = {"<h2>Universal Translator</h2><hr>
|
||||
When enabled, this device will automatically convert all spoken and written languages into a format that any known recipient can understand.<br><br>
|
||||
The device is currently [ (src.translator_on) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled</font>.<br>
|
||||
<a href='byond://?src=\ref[src];software=translator;sub=0;toggle=1'>Toggle Device</a><br>
|
||||
"}
|
||||
return dat
|
||||
|
||||
// Security HUD
|
||||
/mob/living/silicon/pai/proc/facialRecognition()
|
||||
var/dat = {"<h2>Facial Recognition Suite</h2><hr>
|
||||
When enabled, this package will scan all viewable faces and compare them against the known criminal database, providing real-time graphical data about any detected persons of interest.<br><br>
|
||||
The suite is currently [ (src.secHUD) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled</font>.<br>
|
||||
<a href='byond://?src=\ref[src];software=securityhud;sub=0;toggle=1'>Toggle Suite</a><br>
|
||||
"}
|
||||
return dat
|
||||
|
||||
// Medical HUD
|
||||
/mob/living/silicon/pai/proc/medicalAnalysis()
|
||||
var/dat = ""
|
||||
if(src.subscreen == 0)
|
||||
dat += {"<h2>Medical Analysis Suite</h2><hr>
|
||||
<h4>Visual Status Overlay</h4>
|
||||
When enabled, this package will scan all nearby crewmembers' vitals and provide real-time graphical data about their state of health.<br><br>
|
||||
The suite is currently [ (src.medHUD) ? "<font color=#55FF55>en" : "<font color=#FF5555>dis" ]abled</font>.<br>
|
||||
<a href='byond://?src=\ref[src];software=medicalhud;sub=0;toggle=1'>Toggle Suite</a><br>
|
||||
<br>
|
||||
<a href='byond://?src=\ref[src];software=medicalhud;sub=1'>Host Bioscan</a><br>
|
||||
"}
|
||||
if(src.subscreen == 1)
|
||||
dat += {"<h2>Medical Analysis Suite</h2><hr>
|
||||
<h4>Host Bioscan</h4>
|
||||
"}
|
||||
|
||||
var/mob/living/M
|
||||
//If we are not deployed, check the holder of the card.
|
||||
if(src.loc == card)
|
||||
M = card.loc
|
||||
|
||||
//If we are deployed or the card is not held, check the first living mob in our turf.
|
||||
if(!M || !istype(M))
|
||||
var/turf/T = get_turf(src)
|
||||
M = locate(/mob/living/) in T.contents
|
||||
|
||||
if(!M || !istype(M))
|
||||
src.temp = "Error: No biological host found. <br>"
|
||||
src.subscreen = 0
|
||||
return dat
|
||||
|
||||
dat += {"<b>Bioscan Results for [M]</b>: <br>
|
||||
Overall Status: [M.stat > 1 ? "dead" : "[M.health]% healthy"] <br><br>
|
||||
|
||||
<b>Scan Breakdown</b>: <br>
|
||||
Respiratory: [M.getOxyLoss() > 50 ? "<font color=#FF5555>" : "<font color=#55FF55>"][M.getOxyLoss()]</font><br>
|
||||
Toxicology: [M.getToxLoss() > 50 ? "<font color=#FF5555>" : "<font color=#55FF55>"][M.getToxLoss()]</font><br>
|
||||
Burns: [M.getFireLoss() > 50 ? "<font color=#FF5555>" : "<font color=#55FF55>"][M.getFireLoss()]</font><br>
|
||||
Structural Integrity: [M.getBruteLoss() > 50 ? "<font color=#FF5555>" : "<font color=#55FF55>"][M.getBruteLoss()]</font><br>
|
||||
Body Temperature: [M.bodytemperature-T0C]°C ([M.bodytemperature*1.8-459.67]°F)<br>
|
||||
"}
|
||||
for(var/datum/disease/D in M.viruses)
|
||||
dat += {"<h4>Infection Detected.</h4><br>
|
||||
Name: [D.name]<br>
|
||||
Type: [D.spread]<br>
|
||||
Stage: [D.stage]/[D.max_stages]<br>
|
||||
Possible Cure: [D.cure]<br>
|
||||
"}
|
||||
dat += "<br><a href='byond://?src=\ref[src];software=medicalhud;sub=1'>Refresh Bioscan</a><br>"
|
||||
dat += "<br><a href='byond://?src=\ref[src];software=medicalhud;sub=0'>Visual Status Overlay</a><br>"
|
||||
return dat
|
||||
|
||||
// Atmospheric Scanner
|
||||
/mob/living/silicon/pai/proc/softwareAtmo()
|
||||
var/dat = "<h2>Atmospheric Sensor</h2><hr>"
|
||||
|
||||
var/turf/T = get_turf_or_move(src.loc)
|
||||
if (isnull(T))
|
||||
dat += "Unable to obtain a reading.<br>"
|
||||
else
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles
|
||||
|
||||
dat += "Air Pressure: [round(pressure,0.1)] kPa<br>"
|
||||
|
||||
if(total_moles)
|
||||
for(var/g in environment.gas)
|
||||
dat += "[gas_data.name[g]]: [round((environment.gas[g] / total_moles) * 100)]%<br>"
|
||||
dat += "Temperature: [round(environment.temperature-T0C)]°C<br>"
|
||||
dat += "<br><a href='byond://?src=\ref[src];software=atmosensor;sub=0'>Refresh Reading</a>"
|
||||
return dat
|
||||
|
||||
// Camera Jack - Clearly not finished
|
||||
/mob/living/silicon/pai/proc/softwareCamera()
|
||||
var/dat = "<h2>Camera Jack</h2><hr>"
|
||||
dat += "Cable status : "
|
||||
|
||||
if(!src.cable)
|
||||
dat += "<font color=#FF5555>Retracted</font> <br>"
|
||||
return dat
|
||||
if(!src.cable.machine)
|
||||
dat += "<font color=#FFFF55>Extended</font> <br>"
|
||||
return dat
|
||||
|
||||
var/obj/machinery/machine = src.cable.machine
|
||||
dat += "<font color=#55FF55>Connected</font> <br>"
|
||||
|
||||
if(!istype(machine, /obj/machinery/camera))
|
||||
src << "DERP"
|
||||
return dat
|
||||
|
||||
// Door Jack
|
||||
/mob/living/silicon/pai/proc/softwareDoor()
|
||||
var/dat = "<h2>Airlock Jack</h2><hr>"
|
||||
dat += "Cable status : "
|
||||
if(!src.cable)
|
||||
dat += "<font color=#FF5555>Retracted</font> <br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=doorjack;cable=1;sub=0'>Extend Cable</a> <br>"
|
||||
return dat
|
||||
if(!src.cable.machine)
|
||||
dat += "<font color=#FFFF55>Extended</font> <br>"
|
||||
return dat
|
||||
|
||||
var/obj/machinery/machine = src.cable.machine
|
||||
dat += "<font color=#55FF55>Connected</font> <br>"
|
||||
if(!istype(machine, /obj/machinery/door))
|
||||
dat += "Connected device's firmware does not appear to be compatible with Airlock Jack protocols.<br>"
|
||||
return dat
|
||||
// var/obj/machinery/airlock/door = machine
|
||||
|
||||
if(!src.hackdoor)
|
||||
dat += "<a href='byond://?src=\ref[src];software=doorjack;jack=1;sub=0'>Begin Airlock Jacking</a> <br>"
|
||||
else
|
||||
dat += "Jack in progress... [src.hackprogress]% complete.<br>"
|
||||
dat += "<a href='byond://?src=\ref[src];software=doorjack;cancel=1;sub=0'>Cancel Airlock Jack</a> <br>"
|
||||
//src.hackdoor = machine
|
||||
//src.hackloop()
|
||||
return dat
|
||||
|
||||
// Door Jack - supporting proc
|
||||
/mob/living/silicon/pai/proc/hackloop()
|
||||
var/turf/T = get_turf_or_move(src.loc)
|
||||
for(var/mob/living/silicon/ai/AI in player_list)
|
||||
if(T.loc)
|
||||
AI << "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>"
|
||||
else
|
||||
AI << "<font color = red><b>Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.</b></font>"
|
||||
while(src.hackprogress < 100)
|
||||
if(src.cable && src.cable.machine && istype(src.cable.machine, /obj/machinery/door) && src.cable.machine == src.hackdoor && get_dist(src, src.hackdoor) <= 1)
|
||||
hackprogress += rand(1, 10)
|
||||
else
|
||||
src.temp = "Door Jack: Connection to airlock has been lost. Hack aborted."
|
||||
hackprogress = 0
|
||||
src.hackdoor = null
|
||||
return
|
||||
if(hackprogress >= 100) // This is clunky, but works. We need to make sure we don't ever display a progress greater than 100,
|
||||
hackprogress = 100 // but we also need to reset the progress AFTER it's been displayed
|
||||
if(src.screen == "doorjack" && src.subscreen == 0) // Update our view, if appropriate
|
||||
src.paiInterface()
|
||||
if(hackprogress >= 100)
|
||||
src.hackprogress = 0
|
||||
src.cable.machine:open()
|
||||
sleep(50) // Update every 5 seconds
|
||||
|
||||
// Digital Messenger
|
||||
/mob/living/silicon/pai/proc/pdamessage()
|
||||
|
||||
var/dat = "<h2>Digital Messenger</h2><hr>"
|
||||
dat += {"<b>Signal/Receiver Status:</b> <A href='byond://?src=\ref[src];software=pdamessage;toggler=1'>
|
||||
[(pda.toff) ? "<font color='red'> \[Off\]</font>" : "<font color='green'> \[On\]</font>"]</a><br>
|
||||
<b>Ringer Status:</b> <A href='byond://?src=\ref[src];software=pdamessage;ringer=1'>
|
||||
[(pda.message_silent) ? "<font color='red'> \[Off\]</font>" : "<font color='green'> \[On\]</font>"]</a><br><br>"}
|
||||
dat += "<ul>"
|
||||
if(!pda.toff)
|
||||
for (var/obj/item/device/pda/P in sortAtom(PDAs))
|
||||
if (!P.owner||P.toff||P == src.pda||P.hidden) continue
|
||||
dat += "<li><a href='byond://?src=\ref[src];software=pdamessage;target=\ref[P]'>[P]</a>"
|
||||
dat += "</li>"
|
||||
dat += "</ul>"
|
||||
dat += "Messages: <hr>"
|
||||
|
||||
dat += "<style>td.a { vertical-align:top; }</style>"
|
||||
dat += "<table>"
|
||||
for(var/index in pda.tnote)
|
||||
if(index["sent"])
|
||||
dat += addtext("<tr><td class='a'><i><b>To</b></i></td><td class='a'><i><b>→</b></i></td><td><i><b><a href='byond://?src=\ref[src];software=pdamessage;target=",index["src"],"'>", index["owner"],"</a>: </b></i>", index["message"], "<br></td></tr>")
|
||||
else
|
||||
dat += addtext("<tr><td class='a'><i><b>From</b></i></td><td class='a'><i><b>→</b></i></td><td><i><b><a href='byond://?src=\ref[src];software=pdamessage;target=",index["target"],"'>", index["owner"],"</a>: </b></i>", index["message"], "<br></td></tr>")
|
||||
dat += "</table>"
|
||||
return dat
|
||||
|
||||
/mob/living/silicon/pai/proc/translator_toggle()
|
||||
|
||||
// Sol Common, Tradeband and Gutter are added with New() and are therefore the current default, always active languages
|
||||
|
||||
if(translator_on)
|
||||
translator_on = 0
|
||||
|
||||
remove_language("Sinta'unathi")
|
||||
remove_language("Siik'tajr")
|
||||
remove_language("Skrellian")
|
||||
|
||||
src << "\blue Translator Module toggled OFF."
|
||||
|
||||
else
|
||||
translator_on = 1
|
||||
|
||||
add_language("Sinta'unathi")
|
||||
add_language("Siik'tajr")
|
||||
add_language("Skrellian")
|
||||
|
||||
src << "\blue Translator Module toggled ON."
|
||||
var/list/pai_emotions = list(
|
||||
"Happy" = 1,
|
||||
"Cat" = 2,
|
||||
"Extremely Happy" = 3,
|
||||
"Face" = 4,
|
||||
"Laugh" = 5,
|
||||
"Off" = 6,
|
||||
"Sad" = 7,
|
||||
"Angry" = 8,
|
||||
"What" = 9
|
||||
)
|
||||
|
||||
|
||||
var/global/list/pai_software_by_key = list()
|
||||
var/global/list/default_pai_software = list()
|
||||
/hook/startup/proc/populate_pai_software_list()
|
||||
var/r = 1 // I would use ., but it'd sacrifice runtime detection
|
||||
for(var/type in typesof(/datum/pai_software) - /datum/pai_software)
|
||||
var/datum/pai_software/P = new type()
|
||||
if(pai_software_by_key[P.id])
|
||||
var/datum/pai_software/O = pai_software_by_key[P.id]
|
||||
world << "<span class='warning'>pAI software module [P.name] has the same key as [O.name]!</span>"
|
||||
r = 0
|
||||
continue
|
||||
pai_software_by_key[P.id] = P
|
||||
if(P.default)
|
||||
default_pai_software[P.id] = P
|
||||
return r
|
||||
|
||||
/mob/living/silicon/pai/New()
|
||||
..()
|
||||
software = default_pai_software.Copy()
|
||||
|
||||
/mob/living/silicon/pai/verb/paiInterface()
|
||||
set category = "pAI Commands"
|
||||
set name = "Software Interface"
|
||||
|
||||
ui_interact(src)
|
||||
|
||||
/mob/living/silicon/pai/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 1)
|
||||
if(user != src)
|
||||
if(ui) ui.set_status(STATUS_CLOSE, 0)
|
||||
return
|
||||
|
||||
if(ui_key != "main")
|
||||
var/datum/pai_software/S = software[ui_key]
|
||||
if(S && !S.toggle)
|
||||
S.on_ui_interact(src, ui, force_open)
|
||||
else
|
||||
if(ui) ui.set_status(STATUS_CLOSE, 0)
|
||||
return
|
||||
|
||||
var/data[0]
|
||||
|
||||
// Software we have bought
|
||||
var/bought_software[0]
|
||||
// Software we have not bought
|
||||
var/not_bought_software[0]
|
||||
|
||||
for(var/key in pai_software_by_key)
|
||||
var/datum/pai_software/S = pai_software_by_key[key]
|
||||
var/software_data[0]
|
||||
software_data["name"] = S.name
|
||||
software_data["id"] = S.id
|
||||
if(key in software)
|
||||
software_data["on"] = S.is_active(src)
|
||||
bought_software[++bought_software.len] = software_data
|
||||
else
|
||||
software_data["ram"] = S.ram_cost
|
||||
not_bought_software[++not_bought_software.len] = software_data
|
||||
|
||||
data["bought"] = bought_software
|
||||
data["not_bought"] = not_bought_software
|
||||
data["available_ram"] = ram
|
||||
|
||||
// Emotions
|
||||
var/emotions[0]
|
||||
for(var/name in pai_emotions)
|
||||
var/emote[0]
|
||||
emote["name"] = name
|
||||
emote["id"] = pai_emotions[name]
|
||||
emotions[++emotions.len] = emote
|
||||
|
||||
data["emotions"] = emotions
|
||||
data["current_emotion"] = card.current_emotion
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "pai_interface.tmpl", "pAI Software Interface", 450, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/mob/living/silicon/pai/Topic(href, href_list)
|
||||
. = ..()
|
||||
if(.) return
|
||||
|
||||
if(href_list["software"])
|
||||
var/soft = href_list["software"]
|
||||
var/datum/pai_software/S = software[soft]
|
||||
if(S.toggle)
|
||||
S.toggle(src)
|
||||
else
|
||||
ui_interact(src, ui_key = soft)
|
||||
return 1
|
||||
|
||||
else if(href_list["stopic"])
|
||||
var/soft = href_list["stopic"]
|
||||
var/datum/pai_software/S = software[soft]
|
||||
if(S)
|
||||
return S.Topic(href, href_list)
|
||||
|
||||
else if(href_list["purchase"])
|
||||
var/soft = href_list["purchase"]
|
||||
var/datum/pai_software/S = pai_software_by_key[soft]
|
||||
if(S && (ram >= S.ram_cost))
|
||||
ram -= S.ram_cost
|
||||
software[S.id] = S
|
||||
return 1
|
||||
|
||||
else if(href_list["image"])
|
||||
var/img = text2num(href_list["image"])
|
||||
if(1 <= img && img <= 9)
|
||||
card.setEmotion(img)
|
||||
return 1
|
||||
|
||||
@@ -0,0 +1,528 @@
|
||||
/datum/pai_software
|
||||
// Name for the software. This is used as the button text when buying or opening/toggling the software
|
||||
var/name = "pAI software module"
|
||||
// RAM cost; pAIs start with 100 RAM, spending it on programs
|
||||
var/ram_cost = 0
|
||||
// ID for the software. This must be unique
|
||||
var/id = ""
|
||||
// Whether this software is a toggle or not
|
||||
// Toggled software should override toggle() and is_active()
|
||||
// Non-toggled software should override on_ui_interact() and Topic()
|
||||
var/toggle = 1
|
||||
// Whether pAIs should automatically receive this module at no cost
|
||||
var/default = 0
|
||||
|
||||
proc/on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
return
|
||||
|
||||
proc/toggle(mob/living/silicon/pai/user)
|
||||
return
|
||||
|
||||
proc/is_active(mob/living/silicon/pai/user)
|
||||
return 0
|
||||
|
||||
/datum/pai_software/directives
|
||||
name = "Directives"
|
||||
ram_cost = 0
|
||||
id = "directives"
|
||||
toggle = 0
|
||||
default = 1
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
data["master"] = user.master
|
||||
data["dna"] = user.master_dna
|
||||
data["prime"] = user.pai_law0
|
||||
data["supplemental"] = user.pai_laws
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_directives.tmpl", "pAI Directives", 450, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
Topic(href, href_list)
|
||||
var/mob/living/silicon/pai/P = usr
|
||||
if(!istype(P)) return
|
||||
|
||||
if(href_list["getdna"])
|
||||
var/mob/living/M = P.loc
|
||||
var/count = 0
|
||||
|
||||
// Find the carrier
|
||||
while(!istype(M, /mob/living))
|
||||
if(!M || !M.loc || count > 6)
|
||||
//For a runtime where M ends up in nullspace (similar to bluespace but less colourful)
|
||||
src << "You are not being carried by anyone!"
|
||||
return 0
|
||||
M = M.loc
|
||||
count++
|
||||
|
||||
// Check the carrier
|
||||
var/answer = input(M, "[P] is requesting a DNA sample from you. Will you allow it to confirm your identity?", "[P] Check DNA", "No") in list("Yes", "No")
|
||||
if(answer == "Yes")
|
||||
var/turf/T = get_turf_or_move(P.loc)
|
||||
for (var/mob/v in viewers(T))
|
||||
v.show_message("<span class='notice'>[M] presses \his thumb against [P].</span>", 3, "<span class='notice'>[P] makes a sharp clicking sound as it extracts DNA material from [M].</span>", 2)
|
||||
var/datum/dna/dna = M.dna
|
||||
P << "<font color = red><h3>[M]'s UE string : [dna.unique_enzymes]</h3></font>"
|
||||
if(dna.unique_enzymes == P.master_dna)
|
||||
P << "<b>DNA is a match to stored Master DNA.</b>"
|
||||
else
|
||||
P << "<b>DNA does not match stored Master DNA.</b>"
|
||||
else
|
||||
P << "[M] does not seem like \he is going to provide a DNA sample willingly."
|
||||
return 1
|
||||
|
||||
/datum/pai_software/radio_config
|
||||
name = "Radio Configuration"
|
||||
ram_cost = 0
|
||||
id = "radio"
|
||||
toggle = 0
|
||||
default = 1
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui = null, force_open = 1)
|
||||
var/data[0]
|
||||
|
||||
data["listening"] = user.radio.broadcasting
|
||||
data["frequency"] = format_frequency(user.radio.frequency)
|
||||
|
||||
var/channels[0]
|
||||
for(var/ch_name in user.radio.channels)
|
||||
var/ch_stat = user.radio.channels[ch_name]
|
||||
var/ch_dat[0]
|
||||
ch_dat["name"] = ch_name
|
||||
// FREQ_LISTENING is const in /obj/item/device/radio
|
||||
ch_dat["listening"] = !!(ch_stat & user.radio.FREQ_LISTENING)
|
||||
channels[++channels.len] = ch_dat
|
||||
|
||||
data["channels"] = channels
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, user, id, "pai_radio.tmpl", "Radio Configuration", 300, 150)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
Topic(href, href_list)
|
||||
var/mob/living/silicon/pai/P = usr
|
||||
if(!istype(P)) return
|
||||
|
||||
P.radio.Topic(href, href_list)
|
||||
return 1
|
||||
|
||||
/datum/pai_software/crew_manifest
|
||||
name = "Crew Manifest"
|
||||
ram_cost = 5
|
||||
id = "manifest"
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
data_core.get_manifest_json()
|
||||
|
||||
var/data[0]
|
||||
// This is dumb, but NanoUI breaks if it has no data to send
|
||||
data["a"] = "a"
|
||||
|
||||
if(ui)
|
||||
ui.load_cached_data(ManifestJSON)
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_manifest.tmpl", "Crew Manifest", 450, 600)
|
||||
ui.load_cached_data(ManifestJSON)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/datum/pai_software/messenger
|
||||
name = "Digital Messenger"
|
||||
ram_cost = 5
|
||||
id = "messenger"
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
data["receiver_off"] = user.pda.toff
|
||||
data["ringer_off"] = user.pda.message_silent
|
||||
data["current_ref"] = null
|
||||
data["current_name"] = user.current_pda_messaging
|
||||
|
||||
var/pdas[0]
|
||||
if(!user.pda.toff)
|
||||
for(var/obj/item/device/pda/P in sortAtom(PDAs))
|
||||
if(!P.owner || P.toff || P == user.pda || P.hidden) continue
|
||||
var/pda[0]
|
||||
pda["name"] = "[P]"
|
||||
pda["owner"] = "[P.owner]"
|
||||
pda["ref"] = "\ref[P]"
|
||||
if(P.owner == user.current_pda_messaging)
|
||||
data["current_ref"] = "\ref[P]"
|
||||
pdas[++pdas.len] = pda
|
||||
|
||||
data["pdas"] = pdas
|
||||
|
||||
var/messages[0]
|
||||
if(user.current_pda_messaging)
|
||||
for(var/index in user.pda.tnote)
|
||||
if(index["owner"] != user.current_pda_messaging)
|
||||
continue
|
||||
var/msg[0]
|
||||
var/sent = index["sent"]
|
||||
msg["sent"] = sent ? 1 : 0
|
||||
msg["target"] = index["owner"]
|
||||
msg["message"] = index["message"]
|
||||
messages[++messages.len] = msg
|
||||
|
||||
data["messages"] = messages
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_messenger.tmpl", "Digital Messenger", 450, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
Topic(href, href_list)
|
||||
var/mob/living/silicon/pai/P = usr
|
||||
if(!istype(P)) return
|
||||
|
||||
if(!isnull(P.pda))
|
||||
if(href_list["toggler"])
|
||||
P.pda.toff = href_list["toggler"] != "1"
|
||||
return 1
|
||||
else if(href_list["ringer"])
|
||||
P.pda.message_silent = href_list["ringer"] != "1"
|
||||
return 1
|
||||
else if(href_list["select"])
|
||||
var/s = href_list["select"]
|
||||
if(s == "*NONE*")
|
||||
P.current_pda_messaging = null
|
||||
else
|
||||
P.current_pda_messaging = s
|
||||
return 1
|
||||
else if(href_list["target"])
|
||||
if(P.silence_time)
|
||||
return alert("Communications circuits remain uninitialized.")
|
||||
|
||||
var/target = locate(href_list["target"])
|
||||
P.pda.create_message(P, target, 1)
|
||||
return 1
|
||||
|
||||
/datum/pai_software/med_records
|
||||
name = "Medical Records"
|
||||
ram_cost = 15
|
||||
id = "med_records"
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
var/records[0]
|
||||
for(var/datum/data/record/general in sortRecord(data_core.general))
|
||||
var/record[0]
|
||||
record["name"] = general.fields["name"]
|
||||
record["ref"] = "\ref[general]"
|
||||
records[++records.len] = record
|
||||
|
||||
data["records"] = records
|
||||
|
||||
var/datum/data/record/G = user.medicalActive1
|
||||
var/datum/data/record/M = user.medicalActive2
|
||||
data["general"] = G ? G.fields : null
|
||||
data["medical"] = M ? M.fields : null
|
||||
data["could_not_find"] = user.medical_cannotfind
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_medrecords.tmpl", "Medical Records", 450, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
Topic(href, href_list)
|
||||
var/mob/living/silicon/pai/P = usr
|
||||
if(!istype(P)) return
|
||||
|
||||
if(href_list["select"])
|
||||
var/datum/data/record/record = locate(href_list["select"])
|
||||
if(record)
|
||||
var/datum/data/record/R = record
|
||||
var/datum/data/record/M = null
|
||||
if (!( data_core.general.Find(R) ))
|
||||
P.medical_cannotfind = 1
|
||||
else
|
||||
P.medical_cannotfind = 0
|
||||
for(var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
M = E
|
||||
P.medicalActive1 = R
|
||||
P.medicalActive2 = M
|
||||
else
|
||||
P.medical_cannotfind = 1
|
||||
return 1
|
||||
|
||||
/datum/pai_software/sec_records
|
||||
name = "Security Records"
|
||||
ram_cost = 15
|
||||
id = "sec_records"
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
var/records[0]
|
||||
for(var/datum/data/record/general in sortRecord(data_core.general))
|
||||
var/record[0]
|
||||
record["name"] = general.fields["name"]
|
||||
record["ref"] = "\ref[general]"
|
||||
records[++records.len] = record
|
||||
|
||||
data["records"] = records
|
||||
|
||||
var/datum/data/record/G = user.securityActive1
|
||||
var/datum/data/record/S = user.securityActive2
|
||||
data["general"] = G ? G.fields : null
|
||||
data["security"] = S ? S.fields : null
|
||||
data["could_not_find"] = user.security_cannotfind
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_secrecords.tmpl", "Security Records", 450, 600)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
Topic(href, href_list)
|
||||
var/mob/living/silicon/pai/P = usr
|
||||
if(!istype(P)) return
|
||||
|
||||
if(href_list["select"])
|
||||
var/datum/data/record/record = locate(href_list["select"])
|
||||
if(record)
|
||||
var/datum/data/record/R = record
|
||||
var/datum/data/record/S = null
|
||||
if (!( data_core.general.Find(R) ))
|
||||
P.securityActive1 = null
|
||||
P.securityActive2 = null
|
||||
P.security_cannotfind = 1
|
||||
else
|
||||
P.security_cannotfind = 0
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
S = E
|
||||
P.securityActive1 = R
|
||||
P.securityActive2 = S
|
||||
else
|
||||
P.securityActive1 = null
|
||||
P.securityActive2 = null
|
||||
P.security_cannotfind = 1
|
||||
return 1
|
||||
|
||||
/datum/pai_software/door_jack
|
||||
name = "Door Jack"
|
||||
ram_cost = 30
|
||||
id = "door_jack"
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
data["cable"] = user.cable != null
|
||||
data["machine"] = user.cable && (user.cable.machine != null)
|
||||
data["inprogress"] = user.hackdoor != null
|
||||
data["progress_a"] = round(user.hackprogress / 10)
|
||||
data["progress_b"] = user.hackprogress % 10
|
||||
data["aborted"] = user.hack_aborted
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_doorjack.tmpl", "Door Jack", 300, 150)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
Topic(href, href_list)
|
||||
var/mob/living/silicon/pai/P = usr
|
||||
if(!istype(P)) return
|
||||
|
||||
if(href_list["jack"])
|
||||
if(P.cable && P.cable.machine)
|
||||
P.hackdoor = P.cable.machine
|
||||
P.hackloop()
|
||||
return 1
|
||||
else if(href_list["cancel"])
|
||||
P.hackdoor = null
|
||||
return 1
|
||||
else if(href_list["cable"])
|
||||
var/turf/T = get_turf_or_move(P.loc)
|
||||
P.hack_aborted = 0
|
||||
P.cable = new /obj/item/weapon/pai_cable(T)
|
||||
for(var/mob/M in viewers(T))
|
||||
M.show_message("<span class='warning'>A port on [P] opens to reveal [P.cable], which promptly falls to the floor.</span>", 3,
|
||||
"<span class='warning'>You hear the soft click of something light and hard falling to the ground.</span>", 2)
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/pai/proc/hackloop()
|
||||
var/turf/T = get_turf_or_move(src.loc)
|
||||
for(var/mob/living/silicon/ai/AI in player_list)
|
||||
if(T.loc)
|
||||
AI << "<font color = red><b>Network Alert: Brute-force encryption crack in progress in [T.loc].</b></font>"
|
||||
else
|
||||
AI << "<font color = red><b>Network Alert: Brute-force encryption crack in progress. Unable to pinpoint location.</b></font>"
|
||||
var/obj/machinery/door/D = cable.machine
|
||||
if(!istype(D))
|
||||
hack_aborted = 1
|
||||
hackprogress = 0
|
||||
cable.machine = null
|
||||
hackdoor = null
|
||||
return
|
||||
while(hackprogress < 1000)
|
||||
if(cable && cable.machine == D && cable.machine == hackdoor && get_dist(src, hackdoor) <= 1)
|
||||
hackprogress = min(hackprogress+rand(1, 20), 1000)
|
||||
else
|
||||
hack_aborted = 1
|
||||
hackprogress = 0
|
||||
hackdoor = null
|
||||
return
|
||||
if(hackprogress >= 1000)
|
||||
hackprogress = 0
|
||||
D.open()
|
||||
cable.machine = null
|
||||
return
|
||||
sleep(10) // Update every second
|
||||
|
||||
/datum/pai_software/atmosphere_sensor
|
||||
name = "Atmosphere Sensor"
|
||||
ram_cost = 5
|
||||
id = "atmos_sense"
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
var/turf/T = get_turf_or_move(user.loc)
|
||||
if(!T)
|
||||
data["reading"] = 0
|
||||
data["pressure"] = 0
|
||||
data["temperature"] = 0
|
||||
data["temperatureC"] = 0
|
||||
data["gas"] = list()
|
||||
else
|
||||
var/datum/gas_mixture/env = T.return_air()
|
||||
data["reading"] = 1
|
||||
var/pres = env.return_pressure() * 10
|
||||
data["pressure"] = "[round(pres/10)].[pres%10]"
|
||||
data["temperature"] = round(env.temperature)
|
||||
data["temperatureC"] = round(env.temperature-T0C)
|
||||
|
||||
var/t_moles = env.total_moles
|
||||
var/gases[0]
|
||||
for(var/g in env.gas)
|
||||
var/gas[0]
|
||||
gas["name"] = gas_data.name[g]
|
||||
gas["percent"] = round((env.gas[g] / t_moles) * 100)
|
||||
gases[++gases.len] = gas
|
||||
data["gas"] = gases
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_atmosphere.tmpl", "Atmosphere Sensor", 350, 300)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
/datum/pai_software/sec_hud
|
||||
name = "Security HUD"
|
||||
ram_cost = 20
|
||||
id = "sec_hud"
|
||||
|
||||
toggle(mob/living/silicon/pai/user)
|
||||
user.secHUD = !user.secHUD
|
||||
|
||||
is_active(mob/living/silicon/pai/user)
|
||||
return user.secHUD
|
||||
|
||||
/datum/pai_software/med_hud
|
||||
name = "Medical HUD"
|
||||
ram_cost = 20
|
||||
id = "med_hud"
|
||||
|
||||
toggle(mob/living/silicon/pai/user)
|
||||
user.medHUD = !user.medHUD
|
||||
|
||||
is_active(mob/living/silicon/pai/user)
|
||||
return user.medHUD
|
||||
|
||||
/datum/pai_software/translator
|
||||
name = "Universal Translator"
|
||||
ram_cost = 35
|
||||
id = "translator"
|
||||
|
||||
toggle(mob/living/silicon/pai/user)
|
||||
// Sol Common, Tradeband and Gutter are added with New() and are therefore the current default, always active languages
|
||||
user.translator_on = !user.translator_on
|
||||
if(user.translator_on)
|
||||
user.add_language("Sinta'unathi")
|
||||
user.add_language("Siik'tajr")
|
||||
user.add_language("Skrellian")
|
||||
else
|
||||
user.remove_language("Sinta'unathi")
|
||||
user.remove_language("Siik'tajr")
|
||||
user.remove_language("Skrellian")
|
||||
|
||||
is_active(mob/living/silicon/pai/user)
|
||||
return user.translator_on
|
||||
|
||||
/datum/pai_software/signaller
|
||||
name = "Remote Signaller"
|
||||
ram_cost = 5
|
||||
id = "signaller"
|
||||
toggle = 0
|
||||
|
||||
on_ui_interact(mob/living/silicon/pai/user, datum/nanoui/ui=null, force_open=1)
|
||||
var/data[0]
|
||||
|
||||
data["frequency"] = format_frequency(user.sradio.frequency)
|
||||
data["code"] = user.sradio.code
|
||||
|
||||
ui = nanomanager.try_update_ui(user, user, id, ui, data, force_open)
|
||||
if(!ui)
|
||||
// Don't copy-paste this unless you're making a pAI software module!
|
||||
ui = new(user, user, id, "pai_signaller.tmpl", "Signaller", 320, 150)
|
||||
ui.load_cached_data(ManifestJSON)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
Topic(href, href_list)
|
||||
var/mob/living/silicon/pai/P = usr
|
||||
if(!istype(P)) return
|
||||
|
||||
if(href_list["send"])
|
||||
P.sradio.send_signal("ACTIVATE")
|
||||
for(var/mob/O in hearers(1, P.loc))
|
||||
O.show_message(text("\icon[] *beep* *beep*", P), 3, "*beep* *beep*", 2)
|
||||
return 1
|
||||
|
||||
else if(href_list["freq"])
|
||||
var/new_frequency = (P.sradio.frequency + text2num(href_list["freq"]))
|
||||
if(new_frequency < 1200 || new_frequency > 1600)
|
||||
new_frequency = sanitize_frequency(new_frequency)
|
||||
P.sradio.set_frequency(new_frequency)
|
||||
return 1
|
||||
|
||||
else if(href_list["code"])
|
||||
P.sradio.code += text2num(href_list["code"])
|
||||
P.sradio.code = round(P.sradio.code)
|
||||
P.sradio.code = min(100, P.sradio.code)
|
||||
P.sradio.code = max(1, P.sradio.code)
|
||||
return 1
|
||||
@@ -223,9 +223,9 @@
|
||||
src.modules += new /obj/item/borg/sight/hud/sec(src)
|
||||
src.modules += new /obj/item/weapon/handcuffs/cyborg(src)
|
||||
src.modules += new /obj/item/weapon/melee/baton/robot(src)
|
||||
src.modules += new /obj/item/weapon/gun/energy/taser/cyborg(src)
|
||||
src.modules += new /obj/item/weapon/gun/energy/taser/mounted/cyborg(src)
|
||||
src.modules += new /obj/item/taperoll/police(src)
|
||||
src.emag = new /obj/item/weapon/gun/energy/laser/cyborg(src)
|
||||
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)
|
||||
@@ -236,7 +236,7 @@
|
||||
F.icon_state = "flash"
|
||||
else if(F.times_used)
|
||||
F.times_used--
|
||||
var/obj/item/weapon/gun/energy/taser/cyborg/T = locate() in src.modules
|
||||
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.update_icon()
|
||||
@@ -383,11 +383,11 @@
|
||||
..()
|
||||
src.modules += new /obj/item/device/flash(src)
|
||||
src.modules += new /obj/item/borg/sight/thermal(src)
|
||||
src.modules += new /obj/item/weapon/gun/energy/laser/cyborg(src)
|
||||
src.modules += new /obj/item/weapon/gun/energy/laser/mounted(src)
|
||||
src.modules += new /obj/item/weapon/pickaxe/plasmacutter(src)
|
||||
src.modules += new /obj/item/borg/combat/shield(src)
|
||||
src.modules += new /obj/item/borg/combat/mobility(src)
|
||||
src.emag = new /obj/item/weapon/gun/energy/lasercannon/cyborg(src)
|
||||
src.emag = new /obj/item/weapon/gun/energy/lasercannon/mounted(src)
|
||||
return
|
||||
|
||||
/obj/item/weapon/robot_module/drone
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
usr << "There's no mounting point for the module!"
|
||||
return 0
|
||||
|
||||
var/obj/item/weapon/gun/energy/taser/cyborg/T = locate() in R.module
|
||||
var/obj/item/weapon/gun/energy/taser/mounted/cyborg/T = locate() in R.module
|
||||
if(!T)
|
||||
T = locate() in R.module.contents
|
||||
if(!T)
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
return
|
||||
|
||||
var/obj/machinery/hologram/holopad/T = src.holo
|
||||
if(T && T.hologram && T.master == src)//If there is a hologram and its master is the user.
|
||||
if(T && T.masters[src])//If there is a hologram and its master is the user.
|
||||
|
||||
//Human-like, sorta, heard by those who understand humans.
|
||||
var/rendered_a
|
||||
@@ -198,7 +198,7 @@
|
||||
return
|
||||
|
||||
var/obj/machinery/hologram/holopad/T = src.holo
|
||||
if(T && T.hologram && T.master == src)
|
||||
if(T && T.masters[src])
|
||||
var/rendered = "<span class='game say'><span class='name'>[name]</span> <span class='message'>[message]</span></span>"
|
||||
src << "<i><span class='game say'>Holopad action relayed, <span class='name'>[real_name]</span> <span class='message'>[message]</span></span></i>"
|
||||
|
||||
@@ -211,7 +211,7 @@
|
||||
|
||||
/mob/living/silicon/ai/emote(var/act, var/type, var/message)
|
||||
var/obj/machinery/hologram/holopad/T = src.holo
|
||||
if(T && T.hologram && T.master == src) //Is the AI using a holopad?
|
||||
if(T && T.masters[src]) //Is the AI using a holopad?
|
||||
src.holopad_emote(message)
|
||||
else //Emote normally, then.
|
||||
..()
|
||||
|
||||
@@ -166,8 +166,8 @@
|
||||
var/reflectchance = 80 - round(P.damage/3)
|
||||
if(prob(reflectchance))
|
||||
adjustBruteLoss(P.damage * 0.5)
|
||||
visible_message("<span class='danger'>The [P.name] gets reflected by [src]'s shell!</span>", \
|
||||
"<span class='userdanger'>The [P.name] gets reflected by [src]'s shell!</span>")
|
||||
visible_message("<span class='danger'>\The [P] was reflected by \the [src]'s shell!</span>", \
|
||||
"<span class='userdanger'>\The [P] was reflected by \the [src]'s shell!</span>")
|
||||
|
||||
// Find a turf near or on the original location to bounce to
|
||||
if(P.starting)
|
||||
@@ -176,12 +176,7 @@
|
||||
var/turf/curloc = get_turf(src)
|
||||
|
||||
// redirect the projectile
|
||||
P.original = locate(new_x, new_y, P.z)
|
||||
P.starting = curloc
|
||||
P.current = curloc
|
||||
P.firer = src
|
||||
P.yo = new_y - curloc.y
|
||||
P.xo = new_x - curloc.x
|
||||
P.redirect(new_x, new_y, curloc, src)
|
||||
|
||||
return -1 // complete projectile permutation
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
icon_state = "russianranged"
|
||||
icon_living = "russianranged"
|
||||
corpse = /obj/effect/landmark/mobcorpse/russian/ranged
|
||||
weapon1 = /obj/item/weapon/gun/projectile/mateba
|
||||
weapon1 = /obj/item/weapon/gun/projectile/revolver/mateba
|
||||
ranged = 1
|
||||
projectiletype = /obj/item/projectile/bullet
|
||||
projectilesound = 'sound/weapons/Gunshot.ogg'
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
icon_living = "syndicateranged"
|
||||
casingtype = /obj/item/ammo_casing/a12mm
|
||||
projectilesound = 'sound/weapons/Gunshot_smg.ogg'
|
||||
projectiletype = /obj/item/projectile/bullet/midbullet2
|
||||
projectiletype = /obj/item/projectile/bullet/pistol/medium
|
||||
|
||||
weapon1 = /obj/item/weapon/gun/projectile/automatic/c20r
|
||||
|
||||
|
||||
@@ -792,7 +792,7 @@ note dizziness decrements automatically in the mob's Life() proc.
|
||||
/mob/Stat()
|
||||
..()
|
||||
|
||||
if(statpanel("Status")) //not looking at that panel
|
||||
if(statpanel("MC")) //not looking at that panel
|
||||
|
||||
if(client && client.holder)
|
||||
stat(null,"Location:\t([x], [y], [z])")
|
||||
|
||||
@@ -416,7 +416,7 @@ var/list/intents = list("help","disarm","grab","hurt")
|
||||
set name = "a-intent"
|
||||
set hidden = 1
|
||||
|
||||
if(ishuman(src) || isbrain(src))
|
||||
if(ishuman(src) || isbrain(src) || isslime(src))
|
||||
switch(input)
|
||||
if("help","disarm","grab","hurt")
|
||||
a_intent = input
|
||||
|
||||
@@ -240,12 +240,12 @@ datum/preferences
|
||||
eyes_s.Blend(facial_s, ICON_OVERLAY)
|
||||
|
||||
var/icon/underwear_s = null
|
||||
if(underwear > 0 && underwear < 7 && current_species.flags & HAS_UNDERWEAR)
|
||||
underwear_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = "underwear[underwear]_[g]_s")
|
||||
if(underwear && current_species.flags & HAS_UNDERWEAR)
|
||||
underwear_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = underwear)
|
||||
|
||||
var/icon/undershirt_s = null
|
||||
if(undershirt > 0 && undershirt < 5 && current_species.flags & HAS_UNDERWEAR)
|
||||
undershirt_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = "undershirt[undershirt]_s")
|
||||
if(undershirt && current_species.flags & HAS_UNDERWEAR)
|
||||
undershirt_s = new/icon("icon" = 'icons/mob/human.dmi', "icon_state" = undershirt)
|
||||
|
||||
var/icon/clothes_s = null
|
||||
if(job_civilian_low & ASSISTANT)//This gives the preview icon clothes depending on which job(if any) is set to 'high'
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/obj/nano_module/crew_monitor
|
||||
name = "Crew monitor"
|
||||
var/list/tracked = new
|
||||
|
||||
/obj/nano_module/crew_monitor/Topic(href, href_list)
|
||||
if(..()) return
|
||||
var/turf/T = get_turf(src)
|
||||
if (!T || !(T.z in config.player_levels))
|
||||
usr << "<span class='warning'>Unable to establish a connection<span>: You're too far away from the station!"
|
||||
return 0
|
||||
if(href_list["close"] )
|
||||
var/mob/user = usr
|
||||
var/datum/nanoui/ui = nanomanager.get_open_ui(user, src, "main")
|
||||
usr.unset_machine()
|
||||
ui.close()
|
||||
return 0
|
||||
if(href_list["update"])
|
||||
src.updateDialog()
|
||||
return 1
|
||||
|
||||
/obj/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
user.set_machine(src)
|
||||
src.scan()
|
||||
|
||||
var/data[0]
|
||||
var/turf/T = get_turf(src)
|
||||
var/list/crewmembers = list()
|
||||
for(var/obj/item/clothing/under/C in src.tracked)
|
||||
|
||||
var/turf/pos = get_turf(C)
|
||||
|
||||
if((C) && (C.has_sensor) && (pos) && (T && pos.z == T.z) && (C.sensor_mode != SUIT_SENSOR_OFF))
|
||||
if(istype(C.loc, /mob/living/carbon/human))
|
||||
|
||||
var/mob/living/carbon/human/H = C.loc
|
||||
if(H.w_uniform != C)
|
||||
continue
|
||||
|
||||
var/list/crewmemberData = list("dead"=0, "oxy"=-1, "tox"=-1, "fire"=-1, "brute"=-1, "area"="", "x"=-1, "y"=-1)
|
||||
|
||||
crewmemberData["sensor_type"] = C.sensor_mode
|
||||
crewmemberData["name"] = H.get_authentification_name(if_no_id="Unknown")
|
||||
crewmemberData["rank"] = H.get_authentification_rank(if_no_id="Unknown", if_no_job="No Job")
|
||||
crewmemberData["assignment"] = H.get_assignment(if_no_id="Unknown", if_no_job="No Job")
|
||||
|
||||
if(C.sensor_mode >= SUIT_SENSOR_BINARY)
|
||||
crewmemberData["dead"] = H.stat > 1
|
||||
|
||||
if(C.sensor_mode >= SUIT_SENSOR_VITAL)
|
||||
crewmemberData["oxy"] = round(H.getOxyLoss(), 1)
|
||||
crewmemberData["tox"] = round(H.getToxLoss(), 1)
|
||||
crewmemberData["fire"] = round(H.getFireLoss(), 1)
|
||||
crewmemberData["brute"] = round(H.getBruteLoss(), 1)
|
||||
|
||||
if(C.sensor_mode >= SUIT_SENSOR_TRACKING)
|
||||
var/area/A = get_area(H)
|
||||
crewmemberData["area"] = sanitize(A.name)
|
||||
crewmemberData["x"] = pos.x
|
||||
crewmemberData["y"] = pos.y
|
||||
|
||||
crewmembers[++crewmembers.len] = crewmemberData
|
||||
|
||||
crewmembers = sortByKey(crewmembers, "name")
|
||||
|
||||
data["crewmembers"] = crewmembers
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "crew_monitor.tmpl", "Crew Monitoring Computer", 900, 800)
|
||||
|
||||
// adding a template with the key "mapContent" enables the map ui functionality
|
||||
ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
|
||||
// adding a template with the key "mapHeader" replaces the map header content
|
||||
ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
|
||||
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
// should make the UI auto-update; doesn't seem to?
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/nano_module/crew_monitor/proc/scan()
|
||||
for(var/mob/living/carbon/human/H in mob_list)
|
||||
if(istype(H.w_uniform, /obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/C = H.w_uniform
|
||||
if (C.has_sensor)
|
||||
tracked |= C
|
||||
return 1
|
||||
@@ -0,0 +1,58 @@
|
||||
/obj/nano_module/power_monitor
|
||||
name = "Power monitor"
|
||||
var/list/grid_sensors
|
||||
var/active_sensor = null //name_tag of the currently selected sensor
|
||||
|
||||
/obj/nano_module/power_monitor/New()
|
||||
..()
|
||||
refresh_sensors()
|
||||
|
||||
/obj/nano_module/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/list/data = list()
|
||||
var/list/sensors = list()
|
||||
// Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading.
|
||||
var/obj/machinery/power/sensor/focus = null
|
||||
|
||||
// Build list of data from sensor readings.
|
||||
for(var/obj/machinery/power/sensor/S in grid_sensors)
|
||||
sensors.Add(list(list(
|
||||
"name" = S.name_tag,
|
||||
"alarm" = S.check_grid_warning()
|
||||
)))
|
||||
if(S.name_tag == active_sensor)
|
||||
focus = S
|
||||
|
||||
data["all_sensors"] = sensors
|
||||
if(focus)
|
||||
data["focus"] = focus.return_reading_data()
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 500)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
// Proc: refresh_sensors()
|
||||
// Parameters: None
|
||||
// Description: Refreshes list of active sensors kept on this computer.
|
||||
/obj/nano_module/power_monitor/proc/refresh_sensors()
|
||||
grid_sensors = list()
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/obj/machinery/power/sensor/S in machines)
|
||||
if((T && S.loc.z == T.z) || (S.long_range)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels.
|
||||
if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen!
|
||||
warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z")
|
||||
else
|
||||
grid_sensors += S
|
||||
|
||||
// Proc: Topic()
|
||||
// Parameters: 2 (href, href_list - allows us to process UI clicks)
|
||||
// Description: Allows us to process UI clicks, which are relayed in form of hrefs.
|
||||
/obj/nano_module/power_monitor/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if( href_list["clear"] )
|
||||
active_sensor = null
|
||||
else if( href_list["setsensor"] )
|
||||
active_sensor = href_list["setsensor"]
|
||||
@@ -0,0 +1,116 @@
|
||||
/obj/nano_module/rcon
|
||||
name = "RCON interface"
|
||||
|
||||
var/list/known_SMESs = null
|
||||
var/list/known_breakers = null
|
||||
// Allows you to hide specific parts of the UI
|
||||
var/hide_SMES = 0
|
||||
var/hide_SMES_details = 0
|
||||
var/hide_breakers = 0
|
||||
|
||||
/obj/nano_module/rcon/ui_interact(mob/user, ui_key = "rcon", datum/nanoui/ui=null, force_open=1)
|
||||
FindDevices() // Update our devices list
|
||||
var/data[0]
|
||||
|
||||
// SMES DATA (simplified view)
|
||||
var/list/smeslist[0]
|
||||
for(var/obj/machinery/power/smes/buildable/SMES in known_SMESs)
|
||||
smeslist.Add(list(list(
|
||||
"charge" = round(SMES.Percentage()),
|
||||
"input_set" = SMES.input_attempt,
|
||||
"input_val" = round(SMES.input_level),
|
||||
"output_set" = SMES.output_attempt,
|
||||
"output_val" = round(SMES.output_level),
|
||||
"output_load" = round(SMES.output_used),
|
||||
"RCON_tag" = SMES.RCon_tag
|
||||
)))
|
||||
|
||||
data["smes_info"] = sortByKey(smeslist, "RCON_tag")
|
||||
|
||||
// BREAKER DATA (simplified view)
|
||||
var/list/breakerlist[0]
|
||||
for(var/obj/machinery/power/breakerbox/BR in known_breakers)
|
||||
breakerlist.Add(list(list(
|
||||
"RCON_tag" = BR.RCon_tag,
|
||||
"enabled" = BR.on
|
||||
)))
|
||||
data["breaker_info"] = breakerlist
|
||||
data["hide_smes"] = hide_SMES
|
||||
data["hide_smes_details"] = hide_SMES_details
|
||||
data["hide_breakers"] = hide_breakers
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "rcon.tmpl", "RCON Console", 600, 400)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
// Proc: Topic()
|
||||
// Parameters: 2 (href, href_list - allows us to process UI clicks)
|
||||
// Description: Allows us to process UI clicks, which are relayed in form of hrefs.
|
||||
/obj/nano_module/rcon/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(href_list["smes_in_toggle"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_toggle"])
|
||||
if(SMES)
|
||||
SMES.toggle_input()
|
||||
if(href_list["smes_out_toggle"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_toggle"])
|
||||
if(SMES)
|
||||
SMES.toggle_output()
|
||||
if(href_list["smes_in_set"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_in_set"])
|
||||
if(SMES)
|
||||
var/inputset = input(usr, "Enter new input level (0-[SMES.input_level_max])", "SMES Input Power Control") as num
|
||||
SMES.set_input(inputset)
|
||||
if(href_list["smes_out_set"])
|
||||
var/obj/machinery/power/smes/buildable/SMES = GetSMESByTag(href_list["smes_out_set"])
|
||||
if(SMES)
|
||||
var/outputset = input(usr, "Enter new output level (0-[SMES.output_level_max])", "SMES Input Power Control") as num
|
||||
SMES.set_output(outputset)
|
||||
|
||||
if(href_list["toggle_breaker"])
|
||||
var/obj/machinery/power/breakerbox/toggle = null
|
||||
for(var/obj/machinery/power/breakerbox/breaker in known_breakers)
|
||||
if(breaker.RCon_tag == href_list["toggle_breaker"])
|
||||
toggle = breaker
|
||||
if(toggle)
|
||||
if(toggle.update_locked)
|
||||
usr << "The breaker box was recently toggled. Please wait before toggling it again."
|
||||
else
|
||||
toggle.auto_toggle()
|
||||
if(href_list["hide_smes"])
|
||||
hide_SMES = !hide_SMES
|
||||
if(href_list["hide_smes_details"])
|
||||
hide_SMES_details = !hide_SMES_details
|
||||
if(href_list["hide_breakers"])
|
||||
hide_breakers = !hide_breakers
|
||||
|
||||
|
||||
// Proc: GetSMESByTag()
|
||||
// Parameters: 1 (tag - RCON tag of SMES we want to look up)
|
||||
// Description: Looks up and returns SMES which has matching RCON tag
|
||||
/obj/nano_module/rcon/proc/GetSMESByTag(var/tag)
|
||||
if(!tag)
|
||||
return
|
||||
|
||||
for(var/obj/machinery/power/smes/buildable/S in known_SMESs)
|
||||
if(S.RCon_tag == tag)
|
||||
return S
|
||||
|
||||
// Proc: FindDevices()
|
||||
// Parameters: None
|
||||
// Description: Refreshes local list of known devices.
|
||||
/obj/nano_module/rcon/proc/FindDevices()
|
||||
known_SMESs = new /list()
|
||||
for(var/obj/machinery/power/smes/buildable/SMES in machines)
|
||||
if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon)
|
||||
known_SMESs.Add(SMES)
|
||||
|
||||
known_breakers = new /list()
|
||||
for(var/obj/machinery/power/breakerbox/breaker in machines)
|
||||
if(breaker.RCon_tag != "NO_TAG")
|
||||
known_breakers.Add(breaker)
|
||||
+249
-249
@@ -1,249 +1,249 @@
|
||||
// This is the window/UI manager for Nano UI
|
||||
// There should only ever be one (global) instance of nanomanger
|
||||
/datum/nanomanager
|
||||
// a list of current open /nanoui UIs, grouped by src_object and ui_key
|
||||
var/open_uis[0]
|
||||
// a list of current open /nanoui UIs, not grouped, for use in processing
|
||||
var/list/processing_uis = list()
|
||||
// a list of asset filenames which are to be sent to the client on user logon
|
||||
var/list/asset_files = list()
|
||||
|
||||
/**
|
||||
* Create a new nanomanager instance.
|
||||
* This proc generates a list of assets which are to be sent to each client on connect
|
||||
*
|
||||
* @return /nanomanager new nanomanager object
|
||||
*/
|
||||
/datum/nanomanager/New()
|
||||
var/list/nano_asset_dirs = list(\
|
||||
"nano/css/",\
|
||||
"nano/images/",\
|
||||
"nano/js/",\
|
||||
"nano/templates/"\
|
||||
)
|
||||
|
||||
var/list/filenames = null
|
||||
for (var/path in nano_asset_dirs)
|
||||
filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
|
||||
if(fexists(path + filename))
|
||||
asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
|
||||
|
||||
return
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
|
||||
*
|
||||
* @param user /mob The mob who opened/owns the ui
|
||||
* @param src_object /obj|/mob The obj or mob which the ui belongs to
|
||||
* @param ui_key string A string key used for the ui
|
||||
* @param ui /datum/nanoui An existing instance of the ui (can be null)
|
||||
* @param data list The data to be passed to the ui, if it exists
|
||||
* @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating)
|
||||
*
|
||||
* @return /nanoui Returns the found ui, for null if none exists
|
||||
*/
|
||||
/datum/nanomanager/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0)
|
||||
if (isnull(ui)) // no ui has been passed, so we'll search for one
|
||||
{
|
||||
ui = get_open_ui(user, src_object, ui_key)
|
||||
}
|
||||
if (!isnull(ui))
|
||||
// The UI is already open
|
||||
if (!force_open)
|
||||
ui.push_data(data)
|
||||
return ui
|
||||
else
|
||||
//testing("nanomanager/try_update_ui mob [user.name] [src_object:name] [ui_key] [force_open] - forcing opening of ui")
|
||||
ui.close()
|
||||
return null
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key
|
||||
*
|
||||
* @param user /mob The mob who opened/owns the ui
|
||||
* @param src_object /obj|/mob The obj or mob which the ui belongs to
|
||||
* @param ui_key string A string key used for the ui
|
||||
*
|
||||
* @return /nanoui Returns the found ui, or null if none exists
|
||||
*/
|
||||
/datum/nanomanager/proc/get_open_ui(var/mob/user, src_object, ui_key)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open")
|
||||
return null
|
||||
else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object")
|
||||
return null
|
||||
|
||||
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if (ui.user == user)
|
||||
return ui
|
||||
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
|
||||
return null
|
||||
|
||||
/**
|
||||
* Update all /nanoui uis attached to src_object
|
||||
*
|
||||
* @param src_object /obj|/mob The obj or mob which the uis are attached to
|
||||
*
|
||||
* @return int The number of uis updated
|
||||
*/
|
||||
/datum/nanomanager/proc/update_uis(src_object)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
return 0
|
||||
|
||||
var/update_count = 0
|
||||
for (var/ui_key in open_uis[src_object_key])
|
||||
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user)
|
||||
ui.process(1)
|
||||
update_count++
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* Update /nanoui uis belonging to user
|
||||
*
|
||||
* @param user /mob The mob who owns the uis
|
||||
* @param src_object /obj|/mob If src_object is provided, only update uis which are attached to src_object (optional)
|
||||
* @param ui_key string If ui_key is provided, only update uis with a matching ui_key (optional)
|
||||
*
|
||||
* @return int The number of uis updated
|
||||
*/
|
||||
/datum/nanomanager/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null)
|
||||
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
|
||||
return 0 // has no open uis
|
||||
|
||||
var/update_count = 0
|
||||
for (var/datum/nanoui/ui in user.open_uis)
|
||||
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.process(1)
|
||||
update_count++
|
||||
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* Close /nanoui uis belonging to user
|
||||
*
|
||||
* @param user /mob The mob who owns the uis
|
||||
* @param src_object /obj|/mob If src_object is provided, only close uis which are attached to src_object (optional)
|
||||
* @param ui_key string If ui_key is provided, only close uis with a matching ui_key (optional)
|
||||
*
|
||||
* @return int The number of uis closed
|
||||
*/
|
||||
/datum/nanomanager/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null)
|
||||
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
|
||||
//testing("nanomanager/close_user_uis mob [user.name] has no open uis")
|
||||
return 0 // has no open uis
|
||||
|
||||
var/close_count = 0
|
||||
for (var/datum/nanoui/ui in user.open_uis)
|
||||
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.close()
|
||||
close_count++
|
||||
|
||||
//testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis")
|
||||
|
||||
return close_count
|
||||
|
||||
/**
|
||||
* Add a /nanoui ui to the list of open uis
|
||||
* This is called by the /nanoui open() proc
|
||||
*
|
||||
* @param ui /nanoui The ui to add
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanomanager/proc/ui_opened(var/datum/nanoui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
open_uis[src_object_key] = list(ui.ui_key = list())
|
||||
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
|
||||
open_uis[src_object_key][ui.ui_key] = list();
|
||||
|
||||
ui.user.open_uis.Add(ui)
|
||||
var/list/uis = open_uis[src_object_key][ui.ui_key]
|
||||
uis.Add(ui)
|
||||
processing_uis.Add(ui)
|
||||
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
/**
|
||||
* Remove a /nanoui ui from the list of open uis
|
||||
* This is called by the /nanoui close() proc
|
||||
*
|
||||
* @param ui /nanoui The ui to remove
|
||||
*
|
||||
* @return int 0 if no ui was removed, 1 if removed successfully
|
||||
*/
|
||||
/datum/nanomanager/proc/ui_closed(var/datum/nanoui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
return 0 // wasn't open
|
||||
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
|
||||
return 0 // wasn't open
|
||||
|
||||
processing_uis.Remove(ui)
|
||||
ui.user.open_uis.Remove(ui)
|
||||
var/list/uis = open_uis[src_object_key][ui.ui_key]
|
||||
uis.Remove(ui)
|
||||
|
||||
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
return 1
|
||||
|
||||
/**
|
||||
* This is called on user logout
|
||||
* Closes/clears all uis attached to the user's /mob
|
||||
*
|
||||
* @param user /mob The user's mob
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
//
|
||||
/datum/nanomanager/proc/user_logout(var/mob/user)
|
||||
//testing("nanomanager/user_logout user [user.name]")
|
||||
return close_user_uis(user)
|
||||
|
||||
/**
|
||||
* This is called when a player transfers from one mob to another
|
||||
* Transfers all open UIs to the new mob
|
||||
*
|
||||
* @param oldMob /mob The user's old mob
|
||||
* @param newMob /mob The user's new mob
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanomanager/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
|
||||
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
|
||||
if (isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
|
||||
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
|
||||
return 0 // has no open uis
|
||||
|
||||
if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list))
|
||||
newMob.open_uis = list()
|
||||
|
||||
for (var/datum/nanoui/ui in oldMob.open_uis)
|
||||
ui.user = newMob
|
||||
newMob.open_uis.Add(ui)
|
||||
|
||||
oldMob.open_uis.Cut()
|
||||
|
||||
return 1 // success
|
||||
|
||||
/**
|
||||
* Sends all nano assets to the client
|
||||
* This is called on user login
|
||||
*
|
||||
* @param client /client The user's client
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
/datum/nanomanager/proc/send_resources(client)
|
||||
for(var/file in asset_files)
|
||||
client << browse_rsc(file) // send the file to the client
|
||||
|
||||
// This is the window/UI manager for Nano UI
|
||||
// There should only ever be one (global) instance of nanomanger
|
||||
/datum/nanomanager
|
||||
// a list of current open /nanoui UIs, grouped by src_object and ui_key
|
||||
var/open_uis[0]
|
||||
// a list of current open /nanoui UIs, not grouped, for use in processing
|
||||
var/list/processing_uis = list()
|
||||
// a list of asset filenames which are to be sent to the client on user logon
|
||||
var/list/asset_files = list()
|
||||
|
||||
/**
|
||||
* Create a new nanomanager instance.
|
||||
* This proc generates a list of assets which are to be sent to each client on connect
|
||||
*
|
||||
* @return /nanomanager new nanomanager object
|
||||
*/
|
||||
/datum/nanomanager/New()
|
||||
var/list/nano_asset_dirs = list(\
|
||||
"nano/css/",\
|
||||
"nano/images/",\
|
||||
"nano/js/",\
|
||||
"nano/templates/"\
|
||||
)
|
||||
|
||||
var/list/filenames = null
|
||||
for (var/path in nano_asset_dirs)
|
||||
filenames = flist(path)
|
||||
for(var/filename in filenames)
|
||||
if(copytext(filename, length(filename)) != "/") // filenames which end in "/" are actually directories, which we want to ignore
|
||||
if(fexists(path + filename))
|
||||
asset_files.Add(fcopy_rsc(path + filename)) // add this file to asset_files for sending to clients when they connect
|
||||
|
||||
return
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key and try to update it with data
|
||||
*
|
||||
* @param user /mob The mob who opened/owns the ui
|
||||
* @param src_object /obj|/mob The obj or mob which the ui belongs to
|
||||
* @param ui_key string A string key used for the ui
|
||||
* @param ui /datum/nanoui An existing instance of the ui (can be null)
|
||||
* @param data list The data to be passed to the ui, if it exists
|
||||
* @param force_open boolean The ui is being forced to (re)open, so close ui if it exists (instead of updating)
|
||||
*
|
||||
* @return /nanoui Returns the found ui, for null if none exists
|
||||
*/
|
||||
/datum/nanomanager/proc/try_update_ui(var/mob/user, src_object, ui_key, var/datum/nanoui/ui, data, var/force_open = 0)
|
||||
if (isnull(ui)) // no ui has been passed, so we'll search for one
|
||||
{
|
||||
ui = get_open_ui(user, src_object, ui_key)
|
||||
}
|
||||
if (!isnull(ui))
|
||||
// The UI is already open
|
||||
if (!force_open)
|
||||
ui.push_data(data)
|
||||
return ui
|
||||
else
|
||||
//testing("nanomanager/try_update_ui mob [user.name] [src_object:name] [ui_key] [force_open] - forcing opening of ui")
|
||||
ui.close()
|
||||
return null
|
||||
|
||||
/**
|
||||
* Get an open /nanoui ui for the current user, src_object and ui_key
|
||||
*
|
||||
* @param user /mob The mob who opened/owns the ui
|
||||
* @param src_object /obj|/mob The obj or mob which the ui belongs to
|
||||
* @param ui_key string A string key used for the ui
|
||||
*
|
||||
* @return /nanoui Returns the found ui, or null if none exists
|
||||
*/
|
||||
/datum/nanomanager/proc/get_open_ui(var/mob/user, src_object, ui_key)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open")
|
||||
return null
|
||||
else if (isnull(open_uis[src_object_key][ui_key]) || !istype(open_uis[src_object_key][ui_key], /list))
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - there are no uis open for this object")
|
||||
return null
|
||||
|
||||
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if (ui.user == user)
|
||||
return ui
|
||||
|
||||
//testing("nanomanager/get_open_ui mob [user.name] [src_object:name] [ui_key] - ui not found")
|
||||
return null
|
||||
|
||||
/**
|
||||
* Update all /nanoui uis attached to src_object
|
||||
*
|
||||
* @param src_object /obj|/mob The obj or mob which the uis are attached to
|
||||
*
|
||||
* @return int The number of uis updated
|
||||
*/
|
||||
/datum/nanomanager/proc/update_uis(src_object)
|
||||
var/src_object_key = "\ref[src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
return 0
|
||||
|
||||
var/update_count = 0
|
||||
for (var/ui_key in open_uis[src_object_key])
|
||||
for (var/datum/nanoui/ui in open_uis[src_object_key][ui_key])
|
||||
if(ui && ui.src_object && ui.user && ui.src_object.nano_host())
|
||||
ui.process(1)
|
||||
update_count++
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* Update /nanoui uis belonging to user
|
||||
*
|
||||
* @param user /mob The mob who owns the uis
|
||||
* @param src_object /obj|/mob If src_object is provided, only update uis which are attached to src_object (optional)
|
||||
* @param ui_key string If ui_key is provided, only update uis with a matching ui_key (optional)
|
||||
*
|
||||
* @return int The number of uis updated
|
||||
*/
|
||||
/datum/nanomanager/proc/update_user_uis(var/mob/user, src_object = null, ui_key = null)
|
||||
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
|
||||
return 0 // has no open uis
|
||||
|
||||
var/update_count = 0
|
||||
for (var/datum/nanoui/ui in user.open_uis)
|
||||
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.process(1)
|
||||
update_count++
|
||||
|
||||
return update_count
|
||||
|
||||
/**
|
||||
* Close /nanoui uis belonging to user
|
||||
*
|
||||
* @param user /mob The mob who owns the uis
|
||||
* @param src_object /obj|/mob If src_object is provided, only close uis which are attached to src_object (optional)
|
||||
* @param ui_key string If ui_key is provided, only close uis with a matching ui_key (optional)
|
||||
*
|
||||
* @return int The number of uis closed
|
||||
*/
|
||||
/datum/nanomanager/proc/close_user_uis(var/mob/user, src_object = null, ui_key = null)
|
||||
if (isnull(user.open_uis) || !istype(user.open_uis, /list) || open_uis.len == 0)
|
||||
//testing("nanomanager/close_user_uis mob [user.name] has no open uis")
|
||||
return 0 // has no open uis
|
||||
|
||||
var/close_count = 0
|
||||
for (var/datum/nanoui/ui in user.open_uis)
|
||||
if ((isnull(src_object) || !isnull(src_object) && ui.src_object == src_object) && (isnull(ui_key) || !isnull(ui_key) && ui.ui_key == ui_key))
|
||||
ui.close()
|
||||
close_count++
|
||||
|
||||
//testing("nanomanager/close_user_uis mob [user.name] closed [open_uis.len] of [close_count] uis")
|
||||
|
||||
return close_count
|
||||
|
||||
/**
|
||||
* Add a /nanoui ui to the list of open uis
|
||||
* This is called by the /nanoui open() proc
|
||||
*
|
||||
* @param ui /nanoui The ui to add
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanomanager/proc/ui_opened(var/datum/nanoui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
open_uis[src_object_key] = list(ui.ui_key = list())
|
||||
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
|
||||
open_uis[src_object_key][ui.ui_key] = list();
|
||||
|
||||
ui.user.open_uis.Add(ui)
|
||||
var/list/uis = open_uis[src_object_key][ui.ui_key]
|
||||
uis.Add(ui)
|
||||
processing_uis.Add(ui)
|
||||
//testing("nanomanager/ui_opened mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
/**
|
||||
* Remove a /nanoui ui from the list of open uis
|
||||
* This is called by the /nanoui close() proc
|
||||
*
|
||||
* @param ui /nanoui The ui to remove
|
||||
*
|
||||
* @return int 0 if no ui was removed, 1 if removed successfully
|
||||
*/
|
||||
/datum/nanomanager/proc/ui_closed(var/datum/nanoui/ui)
|
||||
var/src_object_key = "\ref[ui.src_object]"
|
||||
if (isnull(open_uis[src_object_key]) || !istype(open_uis[src_object_key], /list))
|
||||
return 0 // wasn't open
|
||||
else if (isnull(open_uis[src_object_key][ui.ui_key]) || !istype(open_uis[src_object_key][ui.ui_key], /list))
|
||||
return 0 // wasn't open
|
||||
|
||||
processing_uis.Remove(ui)
|
||||
ui.user.open_uis.Remove(ui)
|
||||
var/list/uis = open_uis[src_object_key][ui.ui_key]
|
||||
uis.Remove(ui)
|
||||
|
||||
//testing("nanomanager/ui_closed mob [ui.user.name] [ui.src_object:name] [ui.ui_key] - user.open_uis [ui.user.open_uis.len] | uis [uis.len] | processing_uis [processing_uis.len]")
|
||||
|
||||
return 1
|
||||
|
||||
/**
|
||||
* This is called on user logout
|
||||
* Closes/clears all uis attached to the user's /mob
|
||||
*
|
||||
* @param user /mob The user's mob
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
//
|
||||
/datum/nanomanager/proc/user_logout(var/mob/user)
|
||||
//testing("nanomanager/user_logout user [user.name]")
|
||||
return close_user_uis(user)
|
||||
|
||||
/**
|
||||
* This is called when a player transfers from one mob to another
|
||||
* Transfers all open UIs to the new mob
|
||||
*
|
||||
* @param oldMob /mob The user's old mob
|
||||
* @param newMob /mob The user's new mob
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanomanager/proc/user_transferred(var/mob/oldMob, var/mob/newMob)
|
||||
//testing("nanomanager/user_transferred from mob [oldMob.name] to mob [newMob.name]")
|
||||
if (isnull(oldMob.open_uis) || !istype(oldMob.open_uis, /list) || open_uis.len == 0)
|
||||
//testing("nanomanager/user_transferred mob [oldMob.name] has no open uis")
|
||||
return 0 // has no open uis
|
||||
|
||||
if (isnull(newMob.open_uis) || !istype(newMob.open_uis, /list))
|
||||
newMob.open_uis = list()
|
||||
|
||||
for (var/datum/nanoui/ui in oldMob.open_uis)
|
||||
ui.user = newMob
|
||||
newMob.open_uis.Add(ui)
|
||||
|
||||
oldMob.open_uis.Cut()
|
||||
|
||||
return 1 // success
|
||||
|
||||
/**
|
||||
* Sends all nano assets to the client
|
||||
* This is called on user login
|
||||
*
|
||||
* @param client /client The user's client
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
|
||||
/datum/nanomanager/proc/send_resources(client)
|
||||
for(var/file in asset_files)
|
||||
client << browse_rsc(file) // send the file to the client
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/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))
|
||||
@@ -132,7 +132,12 @@ nanoui is used to open and update nano browser uis
|
||||
* @return nothing
|
||||
*/
|
||||
/datum/nanoui/proc/update_status(var/push_update = 0)
|
||||
var/status = user.can_interact_with_interface(src_object)
|
||||
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)
|
||||
close()
|
||||
else
|
||||
@@ -142,6 +147,12 @@ nanoui is used to open and update nano browser uis
|
||||
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
|
||||
|
||||
@@ -175,7 +186,7 @@ nanoui is used to open and update nano browser uis
|
||||
return STATUS_UPDATE
|
||||
|
||||
/mob/living/silicon/ai/can_interact_with_interface(var/src_object)
|
||||
if(stat || !client)
|
||||
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.
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
//If limb took enough damage, try to cut or tear it off
|
||||
if(body_part != UPPER_TORSO && body_part != LOWER_TORSO) //as hilarious as it is, getting hit on the chest too much shouldn't effectively gib you.
|
||||
if(config.limbs_can_break && brute_dam >= max_damage * config.organ_health_multiplier)
|
||||
if( (edge && prob(5 * brute)) || (brute > 20 && prob(2 * brute)) )
|
||||
if( (edge && prob(5 * brute)) || (brute > 20 && prob(brute)) )
|
||||
droplimb(1)
|
||||
return
|
||||
|
||||
|
||||
@@ -137,3 +137,33 @@
|
||||
|
||||
/obj/item/weapon/pen/chameleon/get_signature(var/mob/user)
|
||||
return signature ? signature : "Anonymous"
|
||||
|
||||
/obj/item/weapon/pen/chameleon/verb/set_colour()
|
||||
set name = "Change Pen Colour"
|
||||
set category = "Object"
|
||||
|
||||
var/list/possible_colours = list ("Yellow", "Green", "Pink", "Blue", "Orange", "Cyan", "Red", "Invisible", "Black")
|
||||
var/selected_type = input("Pick new colour.", "Pen Colour", null, null) as null|anything in possible_colours
|
||||
|
||||
if(selected_type)
|
||||
switch(selected_type)
|
||||
if("Yellow")
|
||||
colour = COLOR_YELLOW
|
||||
if("Green")
|
||||
colour = COLOR_GREEN
|
||||
if("Pink")
|
||||
colour = COLOR_PINK
|
||||
if("Blue")
|
||||
colour = COLOR_BLUE
|
||||
if("Orange")
|
||||
colour = COLOR_ORANGE
|
||||
if("Cyan")
|
||||
colour = COLOR_CYAN
|
||||
if("Red")
|
||||
colour = COLOR_RED
|
||||
if("Invisible")
|
||||
colour = COLOR_WHITE
|
||||
else
|
||||
colour = COLOR_BLACK
|
||||
usr << "<span class='info'>You select the [lowertext(selected_type)] ink container.</span>"
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ var/global/photo_count = 0
|
||||
icon = 'icons/obj/items.dmi'
|
||||
icon_state = "album"
|
||||
item_state = "briefcase"
|
||||
can_hold = list("/obj/item/weapon/photo",)
|
||||
can_hold = list(/obj/item/weapon/photo)
|
||||
|
||||
/obj/item/weapon/storage/photo_album/MouseDrop(obj/over_object as obj)
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
|
||||
/obj/machinery/power/am_control_unit/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(Proj.flag != "bullet")
|
||||
if(Proj.check_armour != "bullet")
|
||||
stability -= Proj.force
|
||||
return 0
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ proc/cardinalrange(var/center)
|
||||
|
||||
|
||||
/obj/machinery/am_shielding/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(Proj.flag != "bullet")
|
||||
if(Proj.check_armour != "bullet")
|
||||
stability -= Proj.force/2
|
||||
return 0
|
||||
|
||||
|
||||
@@ -893,6 +893,11 @@
|
||||
if(!can_use(usr, 1))
|
||||
return 1
|
||||
|
||||
if(!istype(usr, /mob/living/silicon) && locked)
|
||||
// Shouldn't happen, this is here to prevent href exploits
|
||||
usr << "You must unlock the panel to use this!"
|
||||
return 1
|
||||
|
||||
if (href_list["lock"])
|
||||
coverlocked = !coverlocked
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
rigged = 1 //broken batterys are dangerous
|
||||
|
||||
/obj/item/weapon/cell/emp_act(severity)
|
||||
charge -= 1000 / severity
|
||||
charge -= maxcharge / severity
|
||||
if (charge < 0)
|
||||
charge = 0
|
||||
if(reliability != 100 && prob(50/severity))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
/obj/machinery/power/generator
|
||||
name = "thermoelectric generator"
|
||||
desc = "It's a high efficiency thermoelectric generator."
|
||||
@@ -9,15 +8,24 @@
|
||||
use_power = 1
|
||||
idle_power_usage = 100 //Watts, I hope. Just enough to do the computer and display things.
|
||||
|
||||
var/max_power = 500000
|
||||
var/thermal_efficiency = 0.65
|
||||
|
||||
var/obj/machinery/atmospherics/binary/circulator/circ1
|
||||
var/obj/machinery/atmospherics/binary/circulator/circ2
|
||||
|
||||
var/lastgen = 0
|
||||
var/lastgenlev = -1
|
||||
var/last_circ1_gen = 0
|
||||
var/last_circ2_gen = 0
|
||||
var/last_thermal_gen = 0
|
||||
var/stored_energy = 0
|
||||
var/lastgen1 = 0
|
||||
var/lastgen2 = 0
|
||||
var/effective_gen = 0
|
||||
var/lastgenlev = 0
|
||||
|
||||
/obj/machinery/power/generator/New()
|
||||
..()
|
||||
|
||||
desc = initial(desc) + " Rated for [round(max_power/1000)] kW."
|
||||
spawn(1)
|
||||
reconnect()
|
||||
|
||||
@@ -31,11 +39,11 @@
|
||||
circ2 = null
|
||||
if(src.loc && anchored)
|
||||
if(src.dir & (EAST|WEST))
|
||||
circ1 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,EAST)
|
||||
circ2 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,WEST)
|
||||
circ1 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,WEST)
|
||||
circ2 = locate(/obj/machinery/atmospherics/binary/circulator) in get_step(src,EAST)
|
||||
|
||||
if(circ1 && circ2)
|
||||
if(circ1.dir != SOUTH || circ2.dir != NORTH)
|
||||
if(circ1.dir != NORTH || circ2.dir != SOUTH)
|
||||
circ1 = null
|
||||
circ2 = null
|
||||
|
||||
@@ -58,13 +66,19 @@
|
||||
|
||||
/obj/machinery/power/generator/process()
|
||||
if(!circ1 || !circ2 || !anchored || stat & (BROKEN|NOPOWER))
|
||||
stored_energy = 0
|
||||
return
|
||||
|
||||
updateDialog()
|
||||
|
||||
var/datum/gas_mixture/air1 = circ1.return_transfer_air()
|
||||
var/datum/gas_mixture/air2 = circ2.return_transfer_air()
|
||||
lastgen = 0
|
||||
|
||||
lastgen2 = lastgen1
|
||||
lastgen1 = 0
|
||||
last_thermal_gen = 0
|
||||
last_circ1_gen = 0
|
||||
last_circ2_gen = 0
|
||||
|
||||
if(air1 && air2)
|
||||
var/air1_heat_capacity = air1.heat_capacity()
|
||||
@@ -72,10 +86,9 @@
|
||||
var/delta_temperature = abs(air2.temperature - air1.temperature)
|
||||
|
||||
if(delta_temperature > 0 && air1_heat_capacity > 0 && air2_heat_capacity > 0)
|
||||
var/efficiency = 0.65
|
||||
var/energy_transfer = delta_temperature*air2_heat_capacity*air1_heat_capacity/(air2_heat_capacity+air1_heat_capacity)
|
||||
var/heat = energy_transfer*(1-efficiency)
|
||||
lastgen = energy_transfer*efficiency*0.05
|
||||
var/heat = energy_transfer*(1-thermal_efficiency)
|
||||
last_thermal_gen = energy_transfer*thermal_efficiency
|
||||
|
||||
if(air2.temperature > air1.temperature)
|
||||
air2.temperature = air2.temperature - energy_transfer/air2_heat_capacity
|
||||
@@ -96,19 +109,29 @@
|
||||
if(circ2.network2)
|
||||
circ2.network2.update = 1
|
||||
|
||||
// update icon overlays and power usage only if displayed level has changed
|
||||
if(lastgen > 250000 && prob(10))
|
||||
//Exceeding maximum power leads to some power loss
|
||||
if(effective_gen > max_power && prob(5))
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(3, 1, src)
|
||||
s.start()
|
||||
lastgen *= 0.5
|
||||
var/genlev = max(0, min( round(11*lastgen / 250000), 11))
|
||||
if(lastgen > 100 && genlev == 0)
|
||||
stored_energy *= 0.5
|
||||
|
||||
//Power
|
||||
last_circ1_gen = circ1.return_stored_energy()
|
||||
last_circ2_gen = circ2.return_stored_energy()
|
||||
stored_energy += last_thermal_gen + last_circ1_gen + last_circ2_gen
|
||||
lastgen1 = stored_energy*0.4 //smoothened power generation to prevent slingshotting as pressure is equalized, then restored by pumps
|
||||
stored_energy -= lastgen1
|
||||
effective_gen = (lastgen1 + lastgen2) / 2
|
||||
|
||||
// update icon overlays and power usage only if displayed level has changed
|
||||
var/genlev = max(0, min( round(11*effective_gen / max_power), 11))
|
||||
if(effective_gen > 100 && genlev == 0)
|
||||
genlev = 1
|
||||
if(genlev != lastgenlev)
|
||||
lastgenlev = genlev
|
||||
updateicon()
|
||||
add_avail(lastgen)
|
||||
add_avail(effective_gen)
|
||||
|
||||
/obj/machinery/power/generator/attack_ai(mob/user)
|
||||
if(stat & (BROKEN|NOPOWER)) return
|
||||
@@ -116,8 +139,11 @@
|
||||
|
||||
/obj/machinery/power/generator/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 75, 1)
|
||||
anchored = !anchored
|
||||
user << "\blue You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor."
|
||||
user.visible_message("[user.name] [anchored ? "secures" : "unsecures"] the bolts holding [src.name] to the floor.", \
|
||||
"You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor.", \
|
||||
"You hear a ratchet")
|
||||
use_power = anchored
|
||||
reconnect()
|
||||
else
|
||||
@@ -137,20 +163,33 @@
|
||||
|
||||
user.set_machine(src)
|
||||
|
||||
var/t = "<PRE><B>Thermo-Electric Generator</B><HR>"
|
||||
var/t = "<PRE><B>Thermoelectric Generator</B><HR>"
|
||||
t += "Total Output: [round(effective_gen/1000)] kW<HR>"
|
||||
t += "Thermal Output: [round(last_thermal_gen/1000)] kW<BR>"
|
||||
t += " <BR>"
|
||||
|
||||
var/vertical = 0
|
||||
if (dir == NORTH || dir == SOUTH)
|
||||
vertical = 1
|
||||
|
||||
if(circ1 && circ2)
|
||||
t += "Output : [round(lastgen)] W<BR><BR>"
|
||||
|
||||
t += "<B>Primary Circulator (top or right)</B><BR>"
|
||||
t += "<B>Primary Circulator ([vertical ? "top" : "left"])</B><BR>"
|
||||
t += "Turbine Output: [round(last_circ1_gen/1000)] kW<BR>"
|
||||
t += "Flow Capacity: [round(circ1.volume_capacity_used*100)]%<BR>"
|
||||
t += " <BR>"
|
||||
t += "Inlet Pressure: [round(circ1.air1.return_pressure(), 0.1)] kPa<BR>"
|
||||
t += "Inlet Temperature: [round(circ1.air1.temperature, 0.1)] K<BR>"
|
||||
t += " <BR>"
|
||||
t += "Outlet Pressure: [round(circ1.air2.return_pressure(), 0.1)] kPa<BR>"
|
||||
t += "Outlet Temperature: [round(circ1.air2.temperature, 0.1)] K<BR>"
|
||||
|
||||
t += "<B>Secondary Circulator (bottom or left)</B><BR>"
|
||||
t += " <BR>"
|
||||
t += "<B>Secondary Circulator ([vertical ? "bottom" : "right"])</B><BR>"
|
||||
t += "Turbine Output: [round(last_circ2_gen/1000)] kW<BR>"
|
||||
t += "Flow Capacity: [round(circ2.volume_capacity_used*100)]%<BR>"
|
||||
t += " <BR>"
|
||||
t += "Inlet Pressure: [round(circ2.air1.return_pressure(), 0.1)] kPa<BR>"
|
||||
t += "Inlet Temperature: [round(circ2.air1.temperature, 0.1)] K<BR>"
|
||||
t += " <BR>"
|
||||
t += "Outlet Pressure: [round(circ2.air2.return_pressure(), 0.1)] kPa<BR>"
|
||||
t += "Outlet Temperature: [round(circ2.air2.temperature, 0.1)] K<BR>"
|
||||
|
||||
@@ -158,11 +197,11 @@
|
||||
t += "Unable to connect to circulators.<br>"
|
||||
t += "Ensure both are in position and wrenched into place."
|
||||
|
||||
t += "<BR>"
|
||||
t += " <BR>"
|
||||
t += "<HR>"
|
||||
t += "<A href='?src=\ref[src]'>Refresh</A> <A href='?src=\ref[src];close=1'>Close</A>"
|
||||
|
||||
user << browse(t, "window=teg;size=460x300")
|
||||
user << browse(t, "window=teg;size=400x500")
|
||||
onclose(user, "teg")
|
||||
return 1
|
||||
|
||||
@@ -201,4 +240,4 @@
|
||||
if (usr.stat || usr.restrained() || anchored)
|
||||
return
|
||||
|
||||
src.set_dir(turn(src.dir, -90))
|
||||
src.set_dir(turn(src.dir, -90))
|
||||
|
||||
+231
-138
@@ -1,45 +1,3 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:33
|
||||
|
||||
/* new portable generator - work in progress
|
||||
|
||||
/obj/machinery/power/port_gen
|
||||
name = "portable generator"
|
||||
desc = "A portable generator used for emergency backup power."
|
||||
icon = 'generator.dmi'
|
||||
icon_state = "off"
|
||||
density = 1
|
||||
anchored = 0
|
||||
directwired = 0
|
||||
var/t_status = 0
|
||||
var/t_per = 5000
|
||||
var/filter = 1
|
||||
var/tank = null
|
||||
var/turf/inturf
|
||||
var/starter = 0
|
||||
var/rpm = 0
|
||||
var/rpmtarget = 0
|
||||
var/capacity = 1e6
|
||||
var/turf/outturf
|
||||
var/lastgen
|
||||
|
||||
|
||||
/obj/machinery/power/port_gen/process()
|
||||
ideally we're looking to generate 5000
|
||||
|
||||
/obj/machinery/power/port_gen/attackby(obj/item/weapon/W, mob/user)
|
||||
tank [un]loading stuff
|
||||
|
||||
/obj/machinery/power/port_gen/attack_hand(mob/user)
|
||||
turn on/off
|
||||
|
||||
/obj/machinery/power/port_gen/examine(mob/user)
|
||||
display round(lastgen) and phorontank amount
|
||||
|
||||
*/
|
||||
|
||||
//Previous code been here forever, adding new framework for portable generators
|
||||
|
||||
|
||||
//Baseline portable generator. Has all the default handling. Not intended to be used on it's own (since it generates unlimited power).
|
||||
/obj/machinery/power/port_gen
|
||||
name = "Placeholder Generator" //seriously, don't use this. It can't be anchored without VV magic.
|
||||
@@ -56,6 +14,9 @@ display round(lastgen) and phorontank amount
|
||||
var/recent_fault = 0
|
||||
var/power_output = 1
|
||||
|
||||
/obj/machinery/power/port_gen/proc/IsBroken()
|
||||
return (crit_fail || (stat & (BROKEN|EMPED)))
|
||||
|
||||
/obj/machinery/power/port_gen/proc/HasFuel() //Placeholder for fuel check.
|
||||
return 1
|
||||
|
||||
@@ -69,11 +30,10 @@ display round(lastgen) and phorontank amount
|
||||
return
|
||||
|
||||
/obj/machinery/power/port_gen/process()
|
||||
if(active && HasFuel() && !crit_fail && anchored && powernet)
|
||||
if(active && HasFuel() && !IsBroken() && anchored && powernet)
|
||||
add_avail(power_gen * power_output)
|
||||
UseFuel()
|
||||
src.updateDialog()
|
||||
|
||||
else
|
||||
active = 0
|
||||
icon_state = initial(icon_state)
|
||||
@@ -96,20 +56,58 @@ display round(lastgen) and phorontank amount
|
||||
else
|
||||
usr << "\blue The generator is off."
|
||||
|
||||
/obj/machinery/power/port_gen/emp_act(severity)
|
||||
var/duration = 6000 //ten minutes
|
||||
switch(severity)
|
||||
if(1)
|
||||
stat &= BROKEN
|
||||
if(prob(75)) explode()
|
||||
if(2)
|
||||
if(prob(25)) stat &= BROKEN
|
||||
if(prob(10)) explode()
|
||||
if(3)
|
||||
if(prob(10)) stat &= BROKEN
|
||||
duration = 300
|
||||
|
||||
stat |= EMPED
|
||||
if(duration)
|
||||
spawn(duration)
|
||||
stat &= ~EMPED
|
||||
|
||||
/obj/machinery/power/port_gen/proc/explode()
|
||||
explosion(src.loc, -1, 3, 5, -1)
|
||||
del(src)
|
||||
|
||||
#define TEMPERATURE_DIVISOR 40
|
||||
#define TEMPERATURE_CHANGE_MAX 20
|
||||
|
||||
//A power generator that runs on solid plasma sheets.
|
||||
/obj/machinery/power/port_gen/pacman
|
||||
name = "P.A.C.M.A.N.-type Portable Generator"
|
||||
var/sheets = 0
|
||||
var/max_sheets = 100
|
||||
var/sheet_name = ""
|
||||
name = "\improper P.A.C.M.A.N.-type Portable Generator"
|
||||
desc = "A power generator that runs on solid phoron sheets. Rated for 80 kW max safe output."
|
||||
|
||||
var/sheet_name = "Phoron Sheets"
|
||||
var/sheet_path = /obj/item/stack/sheet/mineral/phoron
|
||||
var/board_path = "/obj/item/weapon/circuitboard/pacman"
|
||||
var/sheet_left = 0 // How much is left of the sheet
|
||||
var/heat = 0
|
||||
|
||||
//produces up to 80 kW and lasts for 20 minutes with 50 sheets
|
||||
var/time_per_sheet = 96
|
||||
power_gen = 20000
|
||||
|
||||
/*
|
||||
These values were chosen so that the generator can run safely up to 80 kW
|
||||
A full 50 phoron sheet stack should last 20 minutes at power_output = 4
|
||||
temperature_gain and max_temperature are set so that the max safe power level is 4.
|
||||
Setting to 5 or higher can only be done temporarily before the generator overheats.
|
||||
*/
|
||||
power_gen = 20000 //Watts output per power_output level
|
||||
var/max_power_output = 5 //The maximum power setting without emagging.
|
||||
var/max_safe_output = 4 // For UI use, maximal output that won't cause overheat.
|
||||
var/time_per_sheet = 96 //fuel efficiency - how long 1 sheet lasts at power level 1
|
||||
var/max_sheets = 100 //max capacity of the hopper
|
||||
var/max_temperature = 300 //max temperature before overheating increases
|
||||
var/temperature_gain = 50 //how much the temperature increases per power output level, in degrees per level
|
||||
|
||||
var/sheets = 0 //How many sheets of material are loaded in the generator
|
||||
var/sheet_left = 0 //How much is left of the current sheet
|
||||
var/temperature = 0 //The current temperature
|
||||
var/overheating = 0 //if this gets high enough the generator explodes
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/initialize()
|
||||
..()
|
||||
@@ -125,8 +123,6 @@ display round(lastgen) and phorontank amount
|
||||
component_parts += new /obj/item/stack/cable_coil(src)
|
||||
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
|
||||
component_parts += new board_path(src)
|
||||
var/obj/sheet = new sheet_path(null)
|
||||
sheet_name = sheet.name
|
||||
RefreshParts()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/Del()
|
||||
@@ -135,76 +131,130 @@ display round(lastgen) and phorontank amount
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/RefreshParts()
|
||||
var/temp_rating = 0
|
||||
var/temp_reliability = 0
|
||||
for(var/obj/item/weapon/stock_parts/SP in component_parts)
|
||||
if(istype(SP, /obj/item/weapon/stock_parts/matter_bin))
|
||||
max_sheets = SP.rating * SP.rating * 50
|
||||
else if(istype(SP, /obj/item/weapon/stock_parts/micro_laser) || istype(SP, /obj/item/weapon/stock_parts/capacitor))
|
||||
temp_rating += SP.rating
|
||||
|
||||
var/temp_reliability = 0
|
||||
var/part_count = 0
|
||||
for(var/obj/item/weapon/CP in component_parts)
|
||||
temp_reliability += CP.reliability
|
||||
reliability = min(round(temp_reliability / 4), 100)
|
||||
part_count++
|
||||
|
||||
reliability = min(round(temp_reliability / part_count), 100)
|
||||
power_gen = round(initial(power_gen) * (max(2, temp_rating) / 2))
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/examine(mob/user)
|
||||
..(user)
|
||||
user << "\blue The generator has [sheets] units of [sheet_name] fuel left, producing [power_gen] per cycle."
|
||||
if(crit_fail) user << "\red The generator seems to have broken down."
|
||||
user << "\The [src] appears to be producing [power_gen*power_output] W."
|
||||
user << "There [sheets == 1 ? "is" : "are"] [sheets] sheet\s left in the hopper."
|
||||
if(IsBroken()) user << "<span class='warning'>\The [src] seems to have broken down.</span>"
|
||||
if(overheating) user << "<span class='danger'>\The [src] is overheating!</span>"
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/HasFuel()
|
||||
if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left)
|
||||
var/needed_sheets = power_output / time_per_sheet
|
||||
if(sheets >= needed_sheets - sheet_left)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//Removes one stack's worth of material from the generator.
|
||||
/obj/machinery/power/port_gen/pacman/DropFuel()
|
||||
if(sheets)
|
||||
var/fail_safe = 0
|
||||
while(sheets > 0 && fail_safe < 100)
|
||||
fail_safe += 1
|
||||
var/obj/item/stack/sheet/S = new sheet_path(loc)
|
||||
var/amount = min(sheets, S.max_amount)
|
||||
S.amount = amount
|
||||
sheets -= amount
|
||||
var/obj/item/stack/sheet/S = new sheet_path(loc)
|
||||
var/amount = min(sheets, S.max_amount)
|
||||
S.amount = amount
|
||||
sheets -= amount
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/UseFuel()
|
||||
var/needed_sheets = 1 / (time_per_sheet / power_output)
|
||||
var/temp = min(needed_sheets, sheet_left)
|
||||
needed_sheets -= temp
|
||||
sheet_left -= temp
|
||||
sheets -= round(needed_sheets)
|
||||
needed_sheets -= round(needed_sheets)
|
||||
if (sheet_left <= 0 && sheets > 0)
|
||||
sheet_left = 1 - needed_sheets
|
||||
//break down sometimes
|
||||
if (reliability < 100)
|
||||
if (prob(1) && prob(1) && prob(100 - reliability))
|
||||
stat |= BROKEN
|
||||
crit_fail = 1
|
||||
if (prob(100 - reliability))
|
||||
explode()
|
||||
|
||||
//how much material are we using this iteration?
|
||||
var/needed_sheets = power_output / time_per_sheet
|
||||
|
||||
//HasFuel() should guarantee us that there is enough fuel left, so no need to check that
|
||||
//the only thing we need to worry about is if we are going to rollover to the next sheet
|
||||
if (needed_sheets > sheet_left)
|
||||
sheets--
|
||||
|
||||
var/lower_limit = 56 + power_output * 10
|
||||
var/upper_limit = 76 + power_output * 10
|
||||
var/bias = 0
|
||||
if (power_output > 4)
|
||||
upper_limit = 400
|
||||
bias = power_output * 3
|
||||
if (heat < lower_limit)
|
||||
heat += 3
|
||||
sheet_left = (1 + sheet_left) - needed_sheets
|
||||
else
|
||||
heat += rand(-7 + bias, 7 + bias)
|
||||
if (heat < lower_limit)
|
||||
heat = lower_limit
|
||||
if (heat > upper_limit)
|
||||
heat = upper_limit
|
||||
sheet_left -= needed_sheets
|
||||
|
||||
if (heat > 300)
|
||||
//calculate the "target" temperature range
|
||||
//This should probably depend on the external temperature somehow, but whatever.
|
||||
var/lower_limit = 56 + power_output * temperature_gain
|
||||
var/upper_limit = 76 + power_output * temperature_gain
|
||||
|
||||
/*
|
||||
Hot or cold environments can affect the equilibrium temperature
|
||||
The lower the pressure the less effect it has. I guess it cools using a radiator or something when in vacuum.
|
||||
Gives traitors more opportunities to sabotage the generator or allows enterprising engineers to build additional
|
||||
cooling in order to get more power out.
|
||||
*/
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
if (environment)
|
||||
var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1)
|
||||
var/ambient = environment.temperature - T20C
|
||||
lower_limit += ambient*ratio
|
||||
upper_limit += ambient*ratio
|
||||
|
||||
var/average = (upper_limit + lower_limit)/2
|
||||
|
||||
//calculate the temperature increase
|
||||
var/bias = 0
|
||||
if (temperature < lower_limit)
|
||||
bias = min(round((average - temperature)/TEMPERATURE_DIVISOR, 1), TEMPERATURE_CHANGE_MAX)
|
||||
else if (temperature > upper_limit)
|
||||
bias = max(round((temperature - average)/TEMPERATURE_DIVISOR, 1), -TEMPERATURE_CHANGE_MAX)
|
||||
|
||||
temperature += rand(-7 + bias, 7 + bias)
|
||||
|
||||
if (temperature > max_temperature)
|
||||
overheat()
|
||||
del(src)
|
||||
return
|
||||
else if (overheating > 0)
|
||||
overheating--
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/handleInactive()
|
||||
var/cooling_temperature = 20
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
if (environment)
|
||||
var/ratio = min(environment.return_pressure()/ONE_ATMOSPHERE, 1)
|
||||
var/ambient = environment.temperature - T20C
|
||||
cooling_temperature += ambient*ratio
|
||||
|
||||
if (heat > 0)
|
||||
heat = max(heat - 2, 0)
|
||||
if (temperature > cooling_temperature)
|
||||
var/temp_loss = (temperature - cooling_temperature)/TEMPERATURE_DIVISOR
|
||||
temp_loss = between(2, round(temp_loss, 1), TEMPERATURE_CHANGE_MAX)
|
||||
temperature = max(temperature - temp_loss, cooling_temperature)
|
||||
src.updateDialog()
|
||||
|
||||
if(overheating)
|
||||
overheating--
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/proc/overheat()
|
||||
explosion(src.loc, 2, 5, 2, -1)
|
||||
overheating++
|
||||
if (overheating > 60)
|
||||
explode()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/explode()
|
||||
//Vapourize all the phoron
|
||||
//When ground up in a grinder, 1 sheet produces 20 u of phoron -- Chemistry-Machinery.dm
|
||||
//1 mol = 10 u? I dunno. 1 mol of carbon is definitely bigger than a pill
|
||||
var/phoron = (sheets+sheet_left)*20
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
if (environment)
|
||||
environment.adjust_gas_temp("phoron", phoron/10, temperature + T0C)
|
||||
|
||||
sheets = 0
|
||||
sheet_left = 0
|
||||
..()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
if(istype(O, sheet_path))
|
||||
@@ -213,16 +263,16 @@ display round(lastgen) and phorontank amount
|
||||
if(amount < 1)
|
||||
user << "\blue The [src.name] is full!"
|
||||
return
|
||||
user << "\blue You add [amount] sheets to the [src.name]."
|
||||
user << "\blue You add [amount] sheet\s to the [src.name]."
|
||||
sheets += amount
|
||||
addstack.use(amount)
|
||||
updateUsrDialog()
|
||||
return
|
||||
else if (istype(O, /obj/item/weapon/card/emag))
|
||||
emagged = 1
|
||||
emp_act(1)
|
||||
if (active && prob(25))
|
||||
explode() //if they're foolish enough to emag while it's running
|
||||
else if(!active)
|
||||
|
||||
if(istype(O, /obj/item/weapon/wrench))
|
||||
|
||||
if(!anchored)
|
||||
@@ -245,18 +295,9 @@ display round(lastgen) and phorontank amount
|
||||
else if(istype(O, /obj/item/weapon/crowbar) && open)
|
||||
var/obj/machinery/constructable_frame/machine_frame/new_frame = new /obj/machinery/constructable_frame/machine_frame(src.loc)
|
||||
for(var/obj/item/I in component_parts)
|
||||
if(I.reliability < 100)
|
||||
I.crit_fail = 1
|
||||
I.loc = src.loc
|
||||
while ( sheets > 0 )
|
||||
var/obj/item/stack/sheet/G = new sheet_path(src.loc)
|
||||
|
||||
if ( sheets > 50 )
|
||||
G.amount = 50
|
||||
else
|
||||
G.amount = sheets
|
||||
|
||||
sheets -= G.amount
|
||||
DropFuel()
|
||||
|
||||
new_frame.state = 2
|
||||
new_frame.icon_state = "box_1"
|
||||
@@ -266,12 +307,46 @@ display round(lastgen) and phorontank amount
|
||||
..()
|
||||
if (!anchored)
|
||||
return
|
||||
|
||||
interact(user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/attack_ai(mob/user as mob)
|
||||
interact(user)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(IsBroken())
|
||||
return
|
||||
|
||||
var/data[0]
|
||||
data["active"] = active
|
||||
if(istype(user, /mob/living/silicon/ai))
|
||||
data["is_ai"] = 1
|
||||
else if(istype(user, /mob/living/silicon/robot) && !Adjacent(user))
|
||||
data["is_ai"] = 1
|
||||
else
|
||||
data["is_ai"] = 0
|
||||
data["output_set"] = power_output
|
||||
data["output_max"] = max_power_output
|
||||
data["output_safe"] = max_safe_output
|
||||
data["output_watts"] = power_output * power_gen
|
||||
data["temperature_current"] = src.temperature
|
||||
data["temperature_max"] = src.max_temperature
|
||||
data["temperature_overheat"] = overheating
|
||||
// 1 sheet = 1000cm3?
|
||||
data["fuel_stored"] = round((sheets * 1000) + (sheet_left * 1000))
|
||||
data["fuel_capacity"] = round(max_sheets * 1000, 0.1)
|
||||
data["fuel_usage"] = active ? round((power_output / time_per_sheet) * 1000) : 0
|
||||
data["fuel_type"] = sheet_name
|
||||
|
||||
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "pacman.tmpl", src.name, 500, 560)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
|
||||
|
||||
/*
|
||||
/obj/machinery/power/port_gen/pacman/interact(mob/user)
|
||||
if (get_dist(src, user) > 1 )
|
||||
if (!istype(user, /mob/living/silicon/ai))
|
||||
@@ -289,12 +364,15 @@ display round(lastgen) and phorontank amount
|
||||
dat += text("[capitalize(sheet_name)]: [sheets] - <A href='?src=\ref[src];action=eject'>Eject</A><br>")
|
||||
var/stack_percent = round(sheet_left * 100, 1)
|
||||
dat += text("Current stack: [stack_percent]% <br>")
|
||||
dat += text("Power output: <A href='?src=\ref[src];action=lower_power'>-</A> [power_gen * power_output] <A href='?src=\ref[src];action=higher_power'>+</A><br>")
|
||||
dat += text("Power output: <A href='?src=\ref[src];action=lower_power'>-</A> [power_gen * power_output] Watts<A href='?src=\ref[src];action=higher_power'>+</A><br>")
|
||||
dat += text("Power current: [(powernet == null ? "Unconnected" : "[avail()]")]<br>")
|
||||
dat += text("Heat: [heat]<br>")
|
||||
|
||||
var/tempstr = "Temperature: [temperature]°C<br>"
|
||||
dat += (overheating)? "<span class='danger'>[tempstr]</span>" : tempstr
|
||||
dat += "<br><A href='?src=\ref[src];action=close'>Close</A>"
|
||||
user << browse("[dat]", "window=port_gen")
|
||||
onclose(user, "port_gen")
|
||||
*/
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/Topic(href, href_list)
|
||||
if(..())
|
||||
@@ -303,53 +381,68 @@ display round(lastgen) and phorontank amount
|
||||
src.add_fingerprint(usr)
|
||||
if(href_list["action"])
|
||||
if(href_list["action"] == "enable")
|
||||
if(!active && HasFuel() && !crit_fail)
|
||||
if(!active && HasFuel() && !IsBroken())
|
||||
active = 1
|
||||
icon_state = "portgen1"
|
||||
src.updateUsrDialog()
|
||||
if(href_list["action"] == "disable")
|
||||
if (active)
|
||||
active = 0
|
||||
icon_state = "portgen0"
|
||||
src.updateUsrDialog()
|
||||
if(href_list["action"] == "eject")
|
||||
if(!active)
|
||||
DropFuel()
|
||||
src.updateUsrDialog()
|
||||
if(href_list["action"] == "lower_power")
|
||||
if (power_output > 1)
|
||||
power_output--
|
||||
src.updateUsrDialog()
|
||||
if (href_list["action"] == "higher_power")
|
||||
if (power_output < 4 || emagged)
|
||||
if (power_output < max_power_output || (emagged && power_output < round(max_power_output*2.5)))
|
||||
power_output++
|
||||
src.updateUsrDialog()
|
||||
if (href_list["action"] == "close")
|
||||
usr << browse(null, "window=port_gen")
|
||||
usr.unset_machine()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/super
|
||||
name = "S.U.P.E.R.P.A.C.M.A.N.-type Portable Generator"
|
||||
desc = "A power generator that utilizes uranium sheets as fuel. Can run for much longer than the standard PACMAN type generators. Rated for 80 kW max safe output."
|
||||
icon_state = "portgen1"
|
||||
sheet_path = /obj/item/stack/sheet/mineral/uranium
|
||||
sheet_name = "Uranium Sheets"
|
||||
time_per_sheet = 576 //same power output, but a 50 sheet stack will last 2 hours at max safe power
|
||||
board_path = "/obj/item/weapon/circuitboard/pacman/super"
|
||||
|
||||
//produces 80 kW like the PACMAN but 50 sheets will last for 2 hours
|
||||
power_gen = 20000
|
||||
time_per_sheet = 576
|
||||
|
||||
overheat()
|
||||
explosion(src.loc, 3, 3, 3, -1)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/super/UseFuel()
|
||||
//produces a tiny amount of radiation when in use
|
||||
if (prob(2*power_output))
|
||||
for (var/mob/living/L in range(src, 5))
|
||||
L.apply_effect(1, IRRADIATE) //should amount to ~5 rads per minute at max safe power
|
||||
..()
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/super/explode()
|
||||
//a nice burst of radiation
|
||||
var/rads = 50 + (sheets + sheet_left)*1.5
|
||||
for (var/mob/living/L in range(src, 10))
|
||||
//should really fall with the square of the distance, but that makes the rads value drop too fast
|
||||
//I dunno, maybe physics works different when you live in 2D -- SM radiation also works like this, apparently
|
||||
L.apply_effect(max(20, round(rads/get_dist(L,src))), IRRADIATE)
|
||||
|
||||
explosion(src.loc, 3, 3, 5, 3)
|
||||
del(src)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/mrs
|
||||
name = "M.R.S.P.A.C.M.A.N.-type Portable Generator"
|
||||
desc = "An advanced power generator that runs on tritium. Rated for 200 kW maximum safe output!"
|
||||
icon_state = "portgen2"
|
||||
sheet_path = /obj/item/stack/sheet/mineral/tritium
|
||||
sheet_name = "Tritium Fuel Sheets"
|
||||
|
||||
//I don't think tritium has any other use, so we might as well make this rewarding for players
|
||||
//max safe power output (power level = 8) is 200 kW and lasts for 1 hour - 3 or 4 of these could power the station
|
||||
power_gen = 25000 //watts
|
||||
max_power_output = 10
|
||||
max_safe_output = 8
|
||||
time_per_sheet = 576
|
||||
max_temperature = 800
|
||||
temperature_gain = 90
|
||||
board_path = "/obj/item/weapon/circuitboard/pacman/mrs"
|
||||
|
||||
//produces 200 kW and lasts for 1 hour with 50 sheets
|
||||
power_gen = 50000
|
||||
time_per_sheet = 288
|
||||
|
||||
overheat()
|
||||
explosion(src.loc, 4, 4, 4, -1)
|
||||
|
||||
/obj/machinery/power/port_gen/pacman/mrs/explode()
|
||||
//no special effects, but the explosion is pretty big (same as a supermatter shard).
|
||||
explosion(src.loc, 3, 6, 12, 16, 1)
|
||||
del(src)
|
||||
|
||||
@@ -63,8 +63,10 @@
|
||||
if(!src.loc)
|
||||
return 0
|
||||
|
||||
if(!use_power)
|
||||
return 1
|
||||
//Don't do this. It allows machines that set use_power to 0 when off (many machines) to
|
||||
//be turned on again and used after a power failure because they never gain the NOPOWER flag.
|
||||
//if(!use_power)
|
||||
// return 1
|
||||
|
||||
var/area/A = src.loc.loc // make sure it's in an area
|
||||
if(!A || !isarea(A) || !A.master)
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
name = "collector [mysize] OFF"
|
||||
|
||||
/obj/effect/rust_particle_catcher/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(Proj.flag != "bullet" && parent)
|
||||
if(Proj.check_armour != "bullet" && parent)
|
||||
parent.AddEnergy(Proj.damage * 20, 0, 1)
|
||||
update_icon()
|
||||
return 0
|
||||
|
||||
@@ -16,12 +16,11 @@
|
||||
density = 1
|
||||
anchored = 1.0
|
||||
circuit = /obj/item/weapon/circuitboard/powermonitor
|
||||
var/list/grid_sensors
|
||||
var/alerting = 0
|
||||
var/active_sensor = null //name_tag of the currently selected sensor
|
||||
use_power = 1
|
||||
idle_power_usage = 300
|
||||
active_power_usage = 300
|
||||
var/obj/nano_module/power_monitor/power_monitor
|
||||
|
||||
// Proc: process()
|
||||
// Parameters: None
|
||||
@@ -53,19 +52,7 @@
|
||||
/obj/machinery/computer/power_monitor/New()
|
||||
..()
|
||||
spawn(50)
|
||||
refresh_sensors()
|
||||
|
||||
// Proc: refresh_sensors()
|
||||
// Parameters: None
|
||||
// Description: Refreshes list of active sensors kept on this computer.
|
||||
/obj/machinery/computer/power_monitor/proc/refresh_sensors()
|
||||
grid_sensors = list()
|
||||
for(var/obj/machinery/power/sensor/S in machines)
|
||||
if((S.loc.z == src.loc.z) || (S.long_range)) // Consoles have range on their Z-Level. Sensors with long_range var will work between Z levels.
|
||||
if(S.name_tag == "#UNKN#") // Default name. Shouldn't happen!
|
||||
warning("Powernet sensor with unset ID Tag! [S.x]X [S.y]Y [S.z]Z")
|
||||
else
|
||||
grid_sensors += S
|
||||
power_monitor = new(src)
|
||||
|
||||
// Proc: attack_hand()
|
||||
// Parameters: None
|
||||
@@ -77,50 +64,18 @@
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
// Proc: Topic()
|
||||
// Parameters: 2 (href, href_list - allows us to process UI clicks)
|
||||
// Description: Allows us to process UI clicks, which are relayed in form of hrefs.
|
||||
/obj/machinery/computer/power_monitor/Topic(href, href_list)
|
||||
..()
|
||||
if( href_list["clear"] )
|
||||
active_sensor = null
|
||||
else if( href_list["setsensor"] )
|
||||
active_sensor = href_list["setsensor"]
|
||||
// Proc: ui_interact()
|
||||
// Parameters: 4 (standard NanoUI parameters)
|
||||
// Description: Uses dark magic to operate the NanoUI of this computer.
|
||||
/obj/machinery/computer/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
power_monitor.ui_interact(user, ui_key, ui, force_open)
|
||||
|
||||
|
||||
// Proc: check_warnings()
|
||||
// Parameters: None
|
||||
// Description: Verifies if any warnings were registered by connected sensors.
|
||||
/obj/machinery/computer/power_monitor/proc/check_warnings()
|
||||
for(var/obj/machinery/power/sensor/S in grid_sensors)
|
||||
for(var/obj/machinery/power/sensor/S in power_monitor.grid_sensors)
|
||||
if(S.check_grid_warning())
|
||||
return 1
|
||||
return 0
|
||||
|
||||
// Proc: ui_interact()
|
||||
// Parameters: 4 (standard NanoUI parameters)
|
||||
// Description: Uses dark magic to operate the NanoUI of this computer.
|
||||
/obj/machinery/computer/power_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/list/data = list()
|
||||
var/list/sensors = list()
|
||||
// Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading.
|
||||
var/obj/machinery/power/sensor/focus = null
|
||||
|
||||
// Build list of data from sensor readings.
|
||||
for(var/obj/machinery/power/sensor/S in grid_sensors)
|
||||
sensors.Add(list(list(
|
||||
"name" = S.name_tag,
|
||||
"alarm" = S.check_grid_warning()
|
||||
)))
|
||||
if(S.name_tag == active_sensor)
|
||||
focus = S
|
||||
|
||||
data["all_sensors"] = sensors
|
||||
if(focus)
|
||||
data["focus"] = focus.return_reading_data()
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "power_monitor.tmpl", "Power Monitoring Console", 800, 500)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
ui.set_auto_update(1)
|
||||
@@ -315,7 +315,7 @@
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "smes.tmpl", "SMES Power Storage Unit", 540, 380)
|
||||
ui = new(user, src, ui_key, "smes.tmpl", "SMES Unit", 540, 380)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
|
||||
@@ -318,14 +318,14 @@
|
||||
// Parameters: None
|
||||
// Description: Switches the input on/off depending on previous setting
|
||||
/obj/machinery/power/smes/buildable/proc/toggle_input()
|
||||
input_attempt = !input_attempt
|
||||
inputting(!input_attempt)
|
||||
update_icon()
|
||||
|
||||
// Proc: toggle_output()
|
||||
// Parameters: None
|
||||
// Description: Switches the output on/off depending on previous setting
|
||||
/obj/machinery/power/smes/buildable/proc/toggle_output()
|
||||
output_attempt = !output_attempt
|
||||
outputting(!output_attempt)
|
||||
update_icon()
|
||||
|
||||
// Proc: set_input()
|
||||
|
||||
@@ -6,73 +6,159 @@
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
throwforce = 1
|
||||
w_class = 1.0
|
||||
var/caliber = "" //Which kind of guns it can be loaded into
|
||||
var/projectile_type = ""//The bullet type to create when New() is called
|
||||
var/obj/item/projectile/BB = null //The loaded bullet
|
||||
w_class = 1
|
||||
var/caliber = "" //Which kind of guns it can be loaded into
|
||||
var/projectile_type //The bullet type to create when New() is called
|
||||
var/obj/item/projectile/BB = null //The loaded bullet - make it so that the projectiles are created only when needed?
|
||||
var/spent_icon = null
|
||||
|
||||
/obj/item/ammo_casing/New()
|
||||
..()
|
||||
if(ispath(projectile_type))
|
||||
BB = new projectile_type(src)
|
||||
pixel_x = rand(-10, 10)
|
||||
pixel_y = rand(-10, 10)
|
||||
|
||||
New()
|
||||
..()
|
||||
if(projectile_type)
|
||||
BB = new projectile_type(src)
|
||||
pixel_x = rand(-10.0, 10)
|
||||
pixel_y = rand(-10.0, 10)
|
||||
set_dir(pick(cardinal))
|
||||
|
||||
//removes the projectile from the ammo casing
|
||||
/obj/item/ammo_casing/proc/expend()
|
||||
. = BB
|
||||
BB = null
|
||||
set_dir(pick(cardinal)) //spin spent casings
|
||||
update_icon()
|
||||
|
||||
/obj/item/ammo_casing/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/screwdriver))
|
||||
if(BB)
|
||||
if(initial(BB.name) == "bullet")
|
||||
var/tmp_label = ""
|
||||
var/label_text = sanitize(copytext(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label), 1, MAX_NAME_LEN))
|
||||
if(length(label_text) > 20)
|
||||
user << "\red The inscription can be at most 20 characters long."
|
||||
else
|
||||
if(label_text == "")
|
||||
user << "\blue You scratch the inscription off of [initial(BB)]."
|
||||
BB.name = initial(BB.name)
|
||||
else
|
||||
user << "\blue You inscribe \"[label_text]\" into \the [initial(BB.name)]."
|
||||
BB.name = "[initial(BB.name)] \"[label_text]\""
|
||||
else
|
||||
user << "\blue You can only inscribe a metal bullet." //because inscribing beanbags is silly
|
||||
else
|
||||
if(!BB)
|
||||
user << "\blue There is no bullet in the casing to inscribe anything into."
|
||||
return
|
||||
|
||||
var/tmp_label = ""
|
||||
var/label_text = sanitize(copytext(input(user, "Inscribe some text into \the [initial(BB.name)]","Inscription",tmp_label), 1, MAX_NAME_LEN))
|
||||
if(length(label_text) > 20)
|
||||
user << "\red The inscription can be at most 20 characters long."
|
||||
else if(!label_text)
|
||||
user << "\blue You scratch the inscription off of [initial(BB)]."
|
||||
BB.name = initial(BB.name)
|
||||
else
|
||||
user << "\blue You inscribe \"[label_text]\" into \the [initial(BB.name)]."
|
||||
BB.name = "[initial(BB.name)] (\"[label_text]\")"
|
||||
|
||||
/obj/item/ammo_casing/update_icon()
|
||||
if(spent_icon && !BB)
|
||||
icon_state = spent_icon
|
||||
|
||||
/obj/item/ammo_casing/examine(mob/user)
|
||||
..()
|
||||
if (!BB)
|
||||
user << "This one is spent."
|
||||
|
||||
//Boxes of ammo
|
||||
//Gun loading types
|
||||
#define SINGLE_CASING 1 //The gun only accepts ammo_casings. ammo_magazines should never have this as their mag_type.
|
||||
#define SPEEDLOADER 2 //Transfers casings from the mag to the gun when used.
|
||||
#define MAGAZINE 4 //The magazine item itself goes inside the gun
|
||||
|
||||
//An item that holds casings and can be used to put them inside guns
|
||||
/obj/item/ammo_magazine
|
||||
name = "ammo box (.357)"
|
||||
desc = "A box of ammo"
|
||||
name = "magazine"
|
||||
desc = "A magazine for some kind of gun."
|
||||
icon_state = "357"
|
||||
icon = 'icons/obj/ammo.dmi'
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
item_state = "syringe_kit"
|
||||
matter = list("metal" = 50000)
|
||||
throwforce = 2
|
||||
w_class = 2.0
|
||||
matter = list("metal" = 500)
|
||||
throwforce = 5
|
||||
w_class = 2
|
||||
throw_speed = 4
|
||||
throw_range = 10
|
||||
|
||||
var/list/stored_ammo = list()
|
||||
var/ammo_type = "/obj/item/ammo_casing"
|
||||
var/mag_type = SPEEDLOADER //ammo_magazines can only be used with compatible guns. This is not a bitflag, the load_method var on guns is.
|
||||
var/caliber = "357"
|
||||
var/max_ammo = 7
|
||||
|
||||
var/ammo_type = /obj/item/ammo_casing //ammo type that is initially loaded
|
||||
var/initial_ammo = null
|
||||
|
||||
var/multiple_sprites = 0
|
||||
//because BYOND doesn't support numbers as keys in associative lists
|
||||
var/list/icon_keys = list() //keys
|
||||
var/list/ammo_states = list() //values
|
||||
|
||||
/obj/item/ammo_magazine/New()
|
||||
if(multiple_sprites)
|
||||
initialize_magazine_icondata(src)
|
||||
|
||||
New()
|
||||
for(var/i = 1, i <= max_ammo, i++)
|
||||
if(isnull(initial_ammo))
|
||||
initial_ammo = max_ammo
|
||||
|
||||
if(initial_ammo)
|
||||
for(var/i in 1 to initial_ammo)
|
||||
stored_ammo += new ammo_type(src)
|
||||
update_icon()
|
||||
|
||||
/obj/item/ammo_magazine/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/ammo_casing))
|
||||
var/obj/item/ammo_casing/C = W
|
||||
if(C.caliber != caliber)
|
||||
user << "<span class='warning'>[C] does not fit into [src].</span>"
|
||||
return
|
||||
if(stored_ammo.len >= max_ammo)
|
||||
user << "<span class='warning'>[src] is full!</span>"
|
||||
return
|
||||
user.remove_from_mob(C)
|
||||
C.loc = src
|
||||
stored_ammo.Insert(1, C) //add to the head of the list
|
||||
update_icon()
|
||||
|
||||
|
||||
/obj/item/ammo_magazine/attack_self(mob/user)
|
||||
if(!stored_ammo.len)
|
||||
user << "<span class='notice'>[src] is already empty!</span>"
|
||||
return
|
||||
user << "<span class='notice'>You empty [src].</span>"
|
||||
for(var/obj/item/ammo_casing/C in stored_ammo)
|
||||
C.loc = user.loc
|
||||
C.set_dir(pick(cardinal))
|
||||
stored_ammo.Cut()
|
||||
update_icon()
|
||||
if(multiple_sprites)
|
||||
icon_state = "[initial(icon_state)]-[stored_ammo.len]"
|
||||
desc = "There are [stored_ammo.len] shell\s left!"
|
||||
|
||||
/obj/item/ammo_magazine/update_icon()
|
||||
if(multiple_sprites)
|
||||
//find the lowest key greater than or equal to stored_ammo.len
|
||||
var/new_state = null
|
||||
for(var/idx in 1 to icon_keys.len)
|
||||
var/ammo_count = icon_keys[idx]
|
||||
if (ammo_count >= stored_ammo.len)
|
||||
new_state = ammo_states[idx]
|
||||
break
|
||||
icon_state = (new_state)? new_state : initial(icon_state)
|
||||
|
||||
/obj/item/ammo_magazine/examine(mob/user)
|
||||
..()
|
||||
user << "There [(stored_ammo.len > 1)? "are" : "is"] [stored_ammo.len] round\s left!"
|
||||
|
||||
//magazine icon state caching
|
||||
/var/global/list/magazine_icondata_keys = list()
|
||||
/var/global/list/magazine_icondata_states = list()
|
||||
|
||||
/proc/initialize_magazine_icondata(var/obj/item/ammo_magazine/M)
|
||||
var/typestr = "[M.type]"
|
||||
if(!(typestr in magazine_icondata_keys) || !(typestr in magazine_icondata_states))
|
||||
magazine_icondata_cache_add(M)
|
||||
|
||||
M.icon_keys = magazine_icondata_keys[typestr]
|
||||
M.ammo_states = magazine_icondata_states[typestr]
|
||||
|
||||
/proc/magazine_icondata_cache_add(var/obj/item/ammo_magazine/M)
|
||||
var/list/icon_keys = list()
|
||||
var/list/ammo_states = list()
|
||||
var/list/states = icon_states(M.icon)
|
||||
for(var/i = 0, i <= M.max_ammo, i++)
|
||||
var/ammo_state = "[M.icon_state]-[i]"
|
||||
if(ammo_state in states)
|
||||
icon_keys += i
|
||||
ammo_states += ammo_state
|
||||
|
||||
magazine_icondata_keys["[M.type]"] = icon_keys
|
||||
magazine_icondata_states["[M.type]"] = ammo_states
|
||||
|
||||
|
||||
@@ -1,38 +1,159 @@
|
||||
/obj/item/ammo_magazine/a357
|
||||
name = "ammo box (.357)"
|
||||
desc = "A box of .357 ammo"
|
||||
icon_state = "357"
|
||||
ammo_type = "/obj/item/ammo_casing/a357"
|
||||
//name = "ammo box (.357)"
|
||||
//desc = "A box of .357 ammo"
|
||||
//icon_state = "357"
|
||||
name = "speed loader (.357)"
|
||||
icon_state = "T38"
|
||||
caliber = "357"
|
||||
ammo_type = /obj/item/ammo_casing/a357
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/c38
|
||||
name = "speed loader (.38)"
|
||||
icon_state = "38"
|
||||
ammo_type = "/obj/item/ammo_casing/c38"
|
||||
caliber = "38"
|
||||
ammo_type = /obj/item/ammo_casing/c38
|
||||
max_ammo = 6
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/c38/rubber
|
||||
name = "speed loader (.38 rubber)"
|
||||
ammo_type = /obj/item/ammo_casing/c38r
|
||||
|
||||
/obj/item/ammo_magazine/c45m
|
||||
name = "magazine (.45)"
|
||||
icon_state = "45"
|
||||
ammo_type = "/obj/item/ammo_casing/c45"
|
||||
mag_type = MAGAZINE
|
||||
ammo_type = /obj/item/ammo_casing/c45
|
||||
caliber = ".45"
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/c45/empty
|
||||
max_ammo = 0
|
||||
/obj/item/ammo_magazine/c45m/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/c45r
|
||||
/obj/item/ammo_magazine/c45m/rubber
|
||||
name = "magazine (.45 rubber)"
|
||||
icon_state = "45"
|
||||
ammo_type = "/obj/item/ammo_casing/c45r"
|
||||
ammo_type = /obj/item/ammo_casing/c45r
|
||||
|
||||
/obj/item/ammo_magazine/c45m/flash
|
||||
name = "magazine (.45 flash)"
|
||||
ammo_type = "/obj/item/ammo_casing/c45f"
|
||||
|
||||
/obj/item/ammo_magazine/mc9mm
|
||||
name = "magazine (9mm)"
|
||||
icon_state = "9x19p"
|
||||
origin_tech = "combat=2"
|
||||
mag_type = MAGAZINE
|
||||
caliber = "9mm"
|
||||
ammo_type = /obj/item/ammo_casing/c9mm
|
||||
max_ammo = 10
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/mc9mm/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/mc9mm/flash
|
||||
ammo_type = /obj/item/ammo_casing/c9mmf
|
||||
|
||||
/obj/item/ammo_magazine/c9mm
|
||||
name = "ammunition Box (9mm)"
|
||||
icon_state = "9mm"
|
||||
origin_tech = "combat=2"
|
||||
caliber = "9mm"
|
||||
ammo_type = /obj/item/ammo_casing/c9mm
|
||||
max_ammo = 30
|
||||
|
||||
/obj/item/ammo_magazine/c9mm/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/c45
|
||||
name = "ammunition Box (.45)"
|
||||
icon_state = "9mm"
|
||||
origin_tech = "combat=2"
|
||||
caliber = ".45"
|
||||
ammo_type = /obj/item/ammo_casing/c45
|
||||
max_ammo = 30
|
||||
|
||||
/obj/item/ammo_magazine/c9mm/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a12mm
|
||||
name = "magazine (12mm)"
|
||||
icon_state = "12mm"
|
||||
origin_tech = "combat=2"
|
||||
mag_type = MAGAZINE
|
||||
caliber = "12mm"
|
||||
ammo_type = "/obj/item/ammo_casing/a12mm"
|
||||
max_ammo = 20
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/a12mm/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a50
|
||||
name = "magazine (.50)"
|
||||
icon_state = "50ae"
|
||||
origin_tech = "combat=2"
|
||||
mag_type = MAGAZINE
|
||||
caliber = ".50"
|
||||
ammo_type = /obj/item/ammo_casing/a50
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/c45r/empty
|
||||
max_ammo = 0
|
||||
/obj/item/ammo_magazine/a50/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a75
|
||||
name = "ammo magazine (20mm)"
|
||||
icon_state = "75"
|
||||
mag_type = MAGAZINE
|
||||
caliber = "75"
|
||||
ammo_type = /obj/item/ammo_casing/a75
|
||||
multiple_sprites = 1
|
||||
max_ammo = 4
|
||||
|
||||
/obj/item/ammo_magazine/a75/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a762
|
||||
name = "magazine box (7.62mm)"
|
||||
icon_state = "a762"
|
||||
origin_tech = "combat=2"
|
||||
mag_type = MAGAZINE
|
||||
caliber = "a762"
|
||||
ammo_type = /obj/item/ammo_casing/a762
|
||||
max_ammo = 50
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/a762/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/c762
|
||||
name = "magazine (7.62mm)"
|
||||
icon_state = "c762"
|
||||
mag_type = MAGAZINE
|
||||
caliber = "a762"
|
||||
ammo_type = /obj/item/ammo_casing/a762
|
||||
max_ammo = 20
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/chameleon
|
||||
name = "magazine (.45)"
|
||||
icon_state = "45"
|
||||
mag_type = MAGAZINE
|
||||
caliber = ".45"
|
||||
ammo_type = /obj/item/ammo_casing/chameleon
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
matter = list()
|
||||
|
||||
/obj/item/ammo_magazine/chameleon/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/*
|
||||
//unused garbage
|
||||
|
||||
/obj/item/ammo_magazine/a418
|
||||
name = "ammo box (.418)"
|
||||
@@ -41,114 +162,10 @@
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
|
||||
|
||||
|
||||
/obj/item/ammo_magazine/a666
|
||||
name = "ammo box (.666)"
|
||||
icon_state = "666"
|
||||
ammo_type = "/obj/item/ammo_casing/a666"
|
||||
max_ammo = 4
|
||||
multiple_sprites = 1
|
||||
|
||||
|
||||
/obj/item/ammo_magazine/mc9mm
|
||||
name = "magazine (9mm)"
|
||||
icon_state = "9x19p"
|
||||
origin_tech = "combat=2"
|
||||
ammo_type = "/obj/item/ammo_casing/c9mm"
|
||||
max_ammo = 8
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/mc9mm/empty
|
||||
max_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/c9mm
|
||||
name = "Ammunition Box (9mm)"
|
||||
icon_state = "9mm"
|
||||
origin_tech = "combat=2"
|
||||
ammo_type = "/obj/item/ammo_casing/c9mm"
|
||||
max_ammo = 30
|
||||
|
||||
|
||||
|
||||
/obj/item/ammo_magazine/c45
|
||||
name = "Ammunition Box (.45)"
|
||||
icon_state = "9mm"
|
||||
origin_tech = "combat=2"
|
||||
ammo_type = "/obj/item/ammo_casing/c45"
|
||||
max_ammo = 30
|
||||
|
||||
|
||||
|
||||
/obj/item/ammo_magazine/a12mm
|
||||
name = "magazine (12mm)"
|
||||
icon_state = "12mm"
|
||||
origin_tech = "combat=2"
|
||||
ammo_type = "/obj/item/ammo_casing/a12mm"
|
||||
max_ammo = 20
|
||||
multiple_sprites = 1
|
||||
|
||||
|
||||
/obj/item/ammo_magazine/a12mm/empty
|
||||
name = "magazine (12mm)"
|
||||
icon_state = "12mm"
|
||||
ammo_type = "/obj/item/ammo_casing/12mm"
|
||||
max_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a50
|
||||
name = "magazine (.50)"
|
||||
icon_state = "50ae"
|
||||
origin_tech = "combat=2"
|
||||
ammo_type = "/obj/item/ammo_casing/a50"
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/a50/empty
|
||||
name = "magazine (.50)"
|
||||
icon_state = "50ae"
|
||||
ammo_type = "/obj/item/ammo_casing/a50"
|
||||
max_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a75
|
||||
name = "ammo magazine (.75)"
|
||||
icon_state = "75"
|
||||
ammo_type = "/obj/item/ammo_casing/a75"
|
||||
multiple_sprites = 1
|
||||
max_ammo = 8
|
||||
|
||||
/obj/item/ammo_magazine/a75/empty
|
||||
name = "ammo magazine (.75)"
|
||||
icon_state = "75"
|
||||
ammo_type = "/obj/item/ammo_casing/a75"
|
||||
max_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a762
|
||||
name = "magazine (a762)"
|
||||
icon_state = "a762"
|
||||
origin_tech = "combat=2"
|
||||
ammo_type = "/obj/item/ammo_casing/a762"
|
||||
max_ammo = 50
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/a762/empty
|
||||
name = "magazine (a762)"
|
||||
icon_state = "a762"
|
||||
ammo_type = "/obj/item/ammo_casing/a762"
|
||||
max_ammo = 0
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/chameleon
|
||||
name = "magazine (.45)"
|
||||
icon_state = "45"
|
||||
ammo_type = "/obj/item/ammo_casing/chameleon"
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
matter = list()
|
||||
|
||||
/obj/item/ammo_magazine/chameleon/empty
|
||||
name = "magazine (.45)"
|
||||
icon_state = "45"
|
||||
ammo_type = "/obj/item/ammo_casing/chameleon"
|
||||
max_ammo = 0
|
||||
multiple_sprites = 1
|
||||
matter = list()
|
||||
*/
|
||||
|
||||
@@ -1,113 +1,145 @@
|
||||
/obj/item/ammo_casing/a357
|
||||
desc = "A .357 bullet casing."
|
||||
caliber = "357"
|
||||
projectile_type = "/obj/item/projectile/bullet"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/strong
|
||||
|
||||
/obj/item/ammo_casing/a50
|
||||
desc = "A .50AE bullet casing."
|
||||
caliber = ".50"
|
||||
projectile_type = "/obj/item/projectile/bullet"
|
||||
|
||||
/obj/item/ammo_casing/a418
|
||||
desc = "A .418 bullet casing."
|
||||
caliber = "357"
|
||||
projectile_type = "/obj/item/projectile/bullet/suffocationbullet"
|
||||
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/strong
|
||||
|
||||
/obj/item/ammo_casing/a75
|
||||
desc = "A .75 bullet casing."
|
||||
desc = "A 20mm bullet casing."
|
||||
caliber = "75"
|
||||
projectile_type = "/obj/item/projectile/bullet/gyro"
|
||||
|
||||
|
||||
/obj/item/ammo_casing/a666
|
||||
desc = "A .666 bullet casing."
|
||||
caliber = "357"
|
||||
projectile_type = "/obj/item/projectile/bullet/cyanideround"
|
||||
|
||||
projectile_type = /obj/item/projectile/bullet/gyro
|
||||
|
||||
/obj/item/ammo_casing/c38
|
||||
desc = "A .38 bullet casing."
|
||||
caliber = "38"
|
||||
projectile_type = "/obj/item/projectile/bullet/weakbullet"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol
|
||||
|
||||
/obj/item/ammo_casing/c38r
|
||||
desc = "A .38 rubber bullet casing."
|
||||
caliber = "38"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/rubber
|
||||
|
||||
/obj/item/ammo_casing/c9mm
|
||||
desc = "A 9mm bullet casing."
|
||||
caliber = "9mm"
|
||||
projectile_type = "/obj/item/projectile/bullet/midbullet2"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol
|
||||
|
||||
/obj/item/ammo_casing/c9mmf
|
||||
desc = "A 9mm flash shell casing."
|
||||
caliber = "9mm"
|
||||
projectile_type = /obj/item/projectile/energy/flash
|
||||
|
||||
|
||||
/obj/item/ammo_casing/c45
|
||||
desc = "A .45 bullet casing."
|
||||
caliber = ".45"
|
||||
projectile_type = "/obj/item/projectile/bullet/midbullet"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/medium
|
||||
|
||||
/obj/item/ammo_casing/c45r
|
||||
desc = "A .45 rubber bullet casing."
|
||||
caliber = ".45"
|
||||
projectile_type = "/obj/item/projectile/bullet/weakbullet/rubber"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/rubber
|
||||
|
||||
/obj/item/ammo_casing/c45f
|
||||
desc = "A .45 flash shell casing."
|
||||
caliber = ".45"
|
||||
projectile_type = /obj/item/projectile/energy/flash
|
||||
|
||||
/obj/item/ammo_casing/a12mm
|
||||
desc = "A 12mm bullet casing."
|
||||
caliber = "12mm"
|
||||
projectile_type = "/obj/item/projectile/bullet/midbullet2"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/medium
|
||||
|
||||
|
||||
/obj/item/ammo_casing/shotgun
|
||||
name = "shotgun slug"
|
||||
desc = "A 12 gauge slug."
|
||||
icon_state = "slshell"
|
||||
caliber = "shotgun"
|
||||
projectile_type = /obj/item/projectile/bullet/shotgun
|
||||
matter = list("metal" = 12500)
|
||||
|
||||
/obj/item/ammo_casing/shotgun/pellet
|
||||
name = "shotgun shell"
|
||||
desc = "A 12 gauge shell."
|
||||
icon_state = "gshell"
|
||||
caliber = "shotgun"
|
||||
projectile_type = "/obj/item/projectile/bullet"
|
||||
projectile_type = /obj/item/projectile/bullet/pellet/shotgun
|
||||
matter = list("metal" = 12500)
|
||||
|
||||
|
||||
/obj/item/ammo_casing/shotgun/blank
|
||||
name = "shotgun shell"
|
||||
desc = "A blank shell."
|
||||
icon_state = "blshell"
|
||||
projectile_type = "/obj/item/projectile/bullet/chameleon"
|
||||
projectile_type = /obj/item/projectile/bullet/blank
|
||||
matter = list("metal" = 250)
|
||||
|
||||
|
||||
/obj/item/ammo_casing/shotgun/beanbag
|
||||
name = "beanbag shell"
|
||||
desc = "A weak beanbag shell."
|
||||
desc = "A beanbag shell."
|
||||
icon_state = "bshell"
|
||||
projectile_type = "/obj/item/projectile/bullet/weakbullet/beanbag"
|
||||
projectile_type = /obj/item/projectile/bullet/shotgun/beanbag
|
||||
matter = list("metal" = 500)
|
||||
|
||||
|
||||
//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"
|
||||
desc = "A stunning shell."
|
||||
desc = "A 12 gauge taser cartridge."
|
||||
icon_state = "stunshell"
|
||||
projectile_type = "/obj/item/projectile/bullet/stunshot"
|
||||
matter = list("metal" = 2500)
|
||||
spent_icon = "stunshell-spent"
|
||||
projectile_type = /obj/item/projectile/energy/electrode/stunshot
|
||||
matter = list("metal" = 1250, "glass" = 1250)
|
||||
|
||||
/obj/item/ammo_casing/shotgun/stunshell/emp_act(severity)
|
||||
if(prob(100/severity)) BB = null
|
||||
update_icon()
|
||||
|
||||
/obj/item/ammo_casing/shotgun/dart
|
||||
name = "shotgun darts"
|
||||
desc = "A dart for use in shotguns."
|
||||
icon_state = "dart"
|
||||
projectile_type = "/obj/item/projectile/energy/dart"
|
||||
matter = list("metal" = 12500)
|
||||
//Does not stun, only blinds, but has area of effect.
|
||||
/obj/item/ammo_casing/shotgun/flash
|
||||
name = "flash shell"
|
||||
desc = "A chemical shell used to signal distress or provide illumination."
|
||||
icon_state = "fshell"
|
||||
projectile_type = /obj/item/projectile/energy/flash/flare
|
||||
matter = list("metal" = 250, "glass" = 250)
|
||||
|
||||
/obj/item/ammo_casing/a762
|
||||
desc = "A 7.62 bullet casing."
|
||||
desc = "A 7.62mm bullet casing."
|
||||
caliber = "a762"
|
||||
projectile_type = "/obj/item/projectile/bullet/a762"
|
||||
projectile_type = /obj/item/projectile/bullet/rifle/a762
|
||||
|
||||
/obj/item/ammo_casing/a145
|
||||
name = "shell casing"
|
||||
desc = "A 14.5mm AP shell."
|
||||
icon_state = "lcasing"
|
||||
spent_icon = "lcasing-spent"
|
||||
caliber = "14.5mm"
|
||||
projectile_type = /obj/item/projectile/bullet/rifle/a145
|
||||
|
||||
/obj/item/ammo_casing/rocket
|
||||
name = "rocket shell"
|
||||
desc = "A high explosive designed to be fired from a launcher."
|
||||
icon_state = "rocketshell"
|
||||
projectile_type = "/obj/item/missile"
|
||||
projectile_type = /obj/item/missile
|
||||
caliber = "rocket"
|
||||
|
||||
/obj/item/ammo_casing/chameleon
|
||||
name = "chameleon bullets"
|
||||
desc = "A set of bullets for the Chameleon Gun."
|
||||
projectile_type = "/obj/item/projectile/bullet/chameleon"
|
||||
projectile_type = /obj/item/projectile/bullet/chameleon
|
||||
caliber = ".45"
|
||||
|
||||
/*
|
||||
/obj/item/ammo_casing/a418
|
||||
desc = "A .418 bullet casing."
|
||||
caliber = "357"
|
||||
projectile_type = /obj/item/projectile/bullet/suffocationbullet
|
||||
|
||||
/obj/item/ammo_casing/a666
|
||||
desc = "A .666 bullet casing."
|
||||
caliber = "357"
|
||||
projectile_type = /obj/item/projectile/bullet/cyanideround
|
||||
*/
|
||||
+187
-161
@@ -1,3 +1,4 @@
|
||||
//Parent gun type. Guns are weapons that can be aimed at mobs and act over a distance
|
||||
/obj/item/weapon/gun
|
||||
name = "gun"
|
||||
desc = "Its a gun. It's pretty terrible, though."
|
||||
@@ -5,59 +6,88 @@
|
||||
icon_state = "detective"
|
||||
item_state = "gun"
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
slot_flags = SLOT_BELT|SLOT_HOLSTER
|
||||
matter = list("metal" = 2000)
|
||||
w_class = 3.0
|
||||
w_class = 3
|
||||
throwforce = 5
|
||||
throw_speed = 4
|
||||
throw_range = 5
|
||||
force = 5.0
|
||||
force = 5
|
||||
origin_tech = "combat=1"
|
||||
attack_verb = list("struck", "hit", "bashed")
|
||||
zoomdevicename = "scope"
|
||||
|
||||
var/fire_delay = 6
|
||||
var/fire_sound = 'sound/weapons/Gunshot.ogg'
|
||||
var/obj/item/projectile/in_chamber = null
|
||||
var/caliber = ""
|
||||
var/fire_sound_text = "gunshot"
|
||||
var/recoil = 0 //screen shake
|
||||
var/silenced = 0
|
||||
var/recoil = 0
|
||||
var/ejectshell = 1
|
||||
var/clumsy_check = 1
|
||||
var/tmp/list/mob/living/target //List of who yer targeting.
|
||||
var/tmp/lock_time = -100
|
||||
var/tmp/mouthshoot = 0 ///To stop people from suiciding twice... >.>
|
||||
var/automatic = 0 //Used to determine if you can target multiple people.
|
||||
var/accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment.
|
||||
var/scoped_accuracy = null
|
||||
|
||||
var/last_fired = 0
|
||||
|
||||
//aiming system stuff
|
||||
var/keep_aim = 1 //1 for keep shooting until aim is lowered
|
||||
//0 for one bullet after tarrget moves and aim is lowered
|
||||
var/multi_aim = 0 //Used to determine if you can target multiple people.
|
||||
var/tmp/list/mob/living/aim_targets //List of who yer targeting.
|
||||
var/tmp/mob/living/last_moved_mob //Used to fire faster at more than one person.
|
||||
var/tmp/told_cant_shoot = 0 //So that it doesn't spam them with the fact they cannot hit them.
|
||||
var/firerate = 0 //0 for keep shooting until aim is lowered
|
||||
// 1 for one bullet after tarrget moves and aim is lowered
|
||||
var/fire_delay = 6
|
||||
var/last_fired = 0
|
||||
var/tmp/lock_time = -100
|
||||
|
||||
proc/ready_to_fire()
|
||||
if(world.time >= last_fired + fire_delay)
|
||||
last_fired = world.time
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
/obj/item/weapon/gun/New()
|
||||
..()
|
||||
if(isnull(scoped_accuracy))
|
||||
scoped_accuracy = accuracy
|
||||
|
||||
proc/load_into_chamber()
|
||||
//Returns 1 if the gun is able to be fired
|
||||
/obj/item/weapon/gun/proc/ready_to_fire()
|
||||
if(world.time >= last_fired + fire_delay)
|
||||
last_fired = world.time
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
proc/special_check(var/mob/M) //Placeholder for any special checks, like detective's revolver.
|
||||
return 1
|
||||
//Checks whether a given mob can use the gun
|
||||
//Any checks that shouldn't result in handle_click_empty() being called if they fail should go here.
|
||||
//Otherwise, if you want handle_click_empty() to be called, check in consume_next_projectile() and return null there.
|
||||
/obj/item/weapon/gun/proc/special_check(var/mob/user)
|
||||
if(!istype(user, /mob/living))
|
||||
return 0
|
||||
if(!user.IsAdvancedToolUser())
|
||||
return 0
|
||||
|
||||
var/mob/living/M = user
|
||||
|
||||
if(HULK in M.mutations)
|
||||
M << "<span class='danger'>Your fingers are much too large for the trigger guard!</span>"
|
||||
return 0
|
||||
if((CLUMSY in M.mutations) && prob(40)) //Clumsy handling
|
||||
var/obj/P = consume_next_projectile()
|
||||
if(P)
|
||||
if(process_projectile(P, user, user, pick("l_foot", "r_foot")))
|
||||
handle_post_fire(user, user)
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] shoots \himself in the foot with \the [src]!</span>",
|
||||
"<span class='danger'>You shoot yourself in the foot with \the [src]!</span>"
|
||||
)
|
||||
M.drop_item()
|
||||
else
|
||||
handle_click_empty(user)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
emp_act(severity)
|
||||
for(var/obj/O in contents)
|
||||
O.emp_act(severity)
|
||||
|
||||
/obj/item/weapon/gun/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
|
||||
if(flag) return //It's adjacent, is the user, or is on the user's person
|
||||
if(istype(target, /obj/machinery/recharger) && istype(src, /obj/item/weapon/gun/energy)) return//Shouldnt flag take care of this?
|
||||
/obj/item/weapon/gun/emp_act(severity)
|
||||
for(var/obj/O in contents)
|
||||
O.emp_act(severity)
|
||||
|
||||
/obj/item/weapon/gun/afterattack(atom/A, mob/living/user, adjacent, params)
|
||||
if(adjacent) return //A is adjacent, is the user, or is on the user's person
|
||||
|
||||
//decide whether to aim or shoot normally
|
||||
var/aiming = 0
|
||||
if(user && user.client && !(A in target))
|
||||
if(user && user.client && !(A in aim_targets))
|
||||
var/client/C = user.client
|
||||
//If help intent is on and we have clicked on an eligible target, switch to aim mode automatically
|
||||
if(user.a_intent == "help" && isliving(A) && !C.gun_mode)
|
||||
@@ -72,36 +102,19 @@
|
||||
else
|
||||
Fire(A,user,params) //Otherwise, fire normally.
|
||||
|
||||
/obj/item/weapon/gun/proc/isHandgun()
|
||||
return 1
|
||||
/obj/item/weapon/gun/attack(atom/A, mob/living/user, def_zone)
|
||||
if (A == user && user.zone_sel.selecting == "mouth" && !mouthshoot)
|
||||
handle_suicide(user)
|
||||
else if(user.a_intent == "hurt") //point blank shooting
|
||||
Fire(A, user, pointblank=1)
|
||||
else
|
||||
return ..() //Pistolwhippin'
|
||||
|
||||
/obj/item/weapon/gun/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)//TODO: go over this
|
||||
//Exclude lasertag guns from the CLUMSY check.
|
||||
if(clumsy_check)
|
||||
if(istype(user, /mob/living))
|
||||
var/mob/living/M = user
|
||||
if ((CLUMSY in M.mutations) && prob(50))
|
||||
M << "<span class='danger'>[src] blows up in your face.</span>"
|
||||
M.take_organ_damage(0,20)
|
||||
M.drop_item()
|
||||
del(src)
|
||||
return
|
||||
|
||||
if (!user.IsAdvancedToolUser())
|
||||
return
|
||||
if(istype(user, /mob/living))
|
||||
var/mob/living/M = user
|
||||
if (HULK in M.mutations)
|
||||
M << "<span class='danger'>Your fingers are much too large for the trigger guard!</span>"
|
||||
return
|
||||
/obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, params, pointblank=0, reflex=0)
|
||||
if(!user || !target) return
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
var/turf/curloc = get_turf(user)
|
||||
var/turf/targloc = get_turf(target)
|
||||
if (!istype(targloc) || !istype(curloc))
|
||||
return
|
||||
|
||||
if(!special_check(user))
|
||||
return
|
||||
|
||||
@@ -110,128 +123,141 @@
|
||||
user << "<span class='warning'>[src] is not ready to fire again!"
|
||||
return
|
||||
|
||||
if(!load_into_chamber()) //CHECK
|
||||
return click_empty(user)
|
||||
|
||||
if(!in_chamber)
|
||||
var/obj/projectile = consume_next_projectile(user)
|
||||
if(!projectile)
|
||||
handle_click_empty(user)
|
||||
return
|
||||
|
||||
in_chamber.firer = user
|
||||
in_chamber.def_zone = user.zone_sel.selecting
|
||||
if(targloc == curloc)
|
||||
user.bullet_act(in_chamber)
|
||||
del(in_chamber)
|
||||
user.next_move = world.time + 4
|
||||
|
||||
if(process_projectile(projectile, user, target, user.zone_sel.selecting, params, pointblank, reflex))
|
||||
handle_post_fire(user, target, pointblank, reflex)
|
||||
|
||||
update_icon()
|
||||
return
|
||||
if(user.hand)
|
||||
user.update_inv_l_hand()
|
||||
else
|
||||
user.update_inv_r_hand()
|
||||
|
||||
if(recoil)
|
||||
spawn()
|
||||
shake_camera(user, recoil + 1, recoil)
|
||||
|
||||
//obtains the next projectile to fire
|
||||
/obj/item/weapon/gun/proc/consume_next_projectile()
|
||||
return null
|
||||
|
||||
//used by aiming code
|
||||
/obj/item/weapon/gun/proc/can_hit(atom/target as mob, var/mob/living/user as mob)
|
||||
if(!special_check(user))
|
||||
return 2
|
||||
//just assume we can shoot through glass and stuff. No big deal, the player can just choose to not target someone
|
||||
//on the other side of a window if it makes a difference. Or if they run behind a window, too bad.
|
||||
return check_trajectory(target, user)
|
||||
|
||||
//called if there was no projectile to shoot
|
||||
/obj/item/weapon/gun/proc/handle_click_empty(mob/user)
|
||||
if (user)
|
||||
user.visible_message("*click click*", "<span class='danger'>*click*</span>")
|
||||
else
|
||||
src.visible_message("*click click*")
|
||||
playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1)
|
||||
|
||||
//called after successfully firing
|
||||
/obj/item/weapon/gun/proc/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0)
|
||||
if(silenced)
|
||||
playsound(user, fire_sound, 10, 1)
|
||||
else
|
||||
playsound(user, fire_sound, 50, 1)
|
||||
user.visible_message("<span class='warning'>[user] fires [src][reflex ? " by reflex":""]!</span>", \
|
||||
"<span class='warning'>You fire [src][reflex ? "by reflex":""]!</span>", \
|
||||
"You hear a [istype(in_chamber, /obj/item/projectile/beam) ? "laser blast" : "gunshot"]!")
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] fires [src][pointblank ? " point blank at [target]":""][reflex ? " by reflex":""]!</span>",
|
||||
"<span class='warning'>You fire [src][reflex ? "by reflex":""]!</span>",
|
||||
"You hear a [fire_sound_text]!"
|
||||
)
|
||||
|
||||
if(recoil)
|
||||
spawn()
|
||||
shake_camera(user, recoil+1, recoil)
|
||||
update_icon()
|
||||
|
||||
in_chamber.original = target
|
||||
in_chamber.loc = get_turf(user)
|
||||
in_chamber.starting = get_turf(user)
|
||||
in_chamber.shot_from = src
|
||||
user.next_move = world.time + 4
|
||||
in_chamber.silenced = silenced
|
||||
in_chamber.current = curloc
|
||||
in_chamber.yo = targloc.y - curloc.y
|
||||
in_chamber.xo = targloc.x - curloc.x
|
||||
//does the actual shooting
|
||||
/obj/item/weapon/gun/proc/process_projectile(obj/projectile, mob/user, atom/target, var/target_zone, var/params=null, var/pointblank=0, var/reflex=0)
|
||||
if(!istype(projectile, /obj/item/projectile))
|
||||
return 0 //default behaviour only applies to true projectiles
|
||||
|
||||
var/obj/item/projectile/P = projectile
|
||||
|
||||
//shooting while in shock
|
||||
var/x_offset = 0
|
||||
var/y_offset = 0
|
||||
if(istype(user, /mob/living/carbon))
|
||||
var/mob/living/carbon/mob = user
|
||||
if(mob.shock_stage > 120)
|
||||
in_chamber.yo += rand(-2,2)
|
||||
in_chamber.xo += rand(-2,2)
|
||||
y_offset = rand(-2,2)
|
||||
x_offset = rand(-2,2)
|
||||
else if(mob.shock_stage > 70)
|
||||
in_chamber.yo += rand(-1,1)
|
||||
in_chamber.xo += rand(-1,1)
|
||||
y_offset = rand(-1,1)
|
||||
x_offset = rand(-1,1)
|
||||
|
||||
//Point blank bonus
|
||||
if(pointblank) P.damage *= 1.3
|
||||
|
||||
//TODO: accuracy modifiers
|
||||
|
||||
if(params)
|
||||
var/list/mouse_control = params2list(params)
|
||||
if(mouse_control["icon-x"])
|
||||
in_chamber.p_x = text2num(mouse_control["icon-x"])
|
||||
if(mouse_control["icon-y"])
|
||||
in_chamber.p_y = text2num(mouse_control["icon-y"])
|
||||
P.set_clickpoint(params)
|
||||
|
||||
spawn()
|
||||
if(in_chamber)
|
||||
in_chamber.process()
|
||||
sleep(1)
|
||||
in_chamber = null
|
||||
return !P.launch(target, user, src, target_zone, x_offset, y_offset)
|
||||
|
||||
update_icon()
|
||||
|
||||
if(user.hand)
|
||||
user.update_inv_l_hand()
|
||||
else
|
||||
user.update_inv_r_hand()
|
||||
|
||||
/obj/item/weapon/gun/proc/can_fire()
|
||||
return load_into_chamber()
|
||||
|
||||
/obj/item/weapon/gun/proc/can_hit(var/mob/living/target as mob, var/mob/living/user as mob)
|
||||
return in_chamber.check_fire(target,user)
|
||||
|
||||
/obj/item/weapon/gun/proc/click_empty(mob/user = null)
|
||||
if (user)
|
||||
user.visible_message("*click click*", "\red <b>*click*</b>")
|
||||
playsound(user, 'sound/weapons/empty.ogg', 100, 1)
|
||||
else
|
||||
src.visible_message("*click click*")
|
||||
playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1)
|
||||
|
||||
/obj/item/weapon/gun/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
|
||||
//Suicide handling.
|
||||
if (M == user && user.zone_sel.selecting == "mouth" && !mouthshoot)
|
||||
mouthshoot = 1
|
||||
M.visible_message("\red [user] sticks their gun in their mouth, ready to pull the trigger...")
|
||||
if(!do_after(user, 40))
|
||||
M.visible_message("\blue [user] decided life was worth living")
|
||||
mouthshoot = 0
|
||||
return
|
||||
if (load_into_chamber())
|
||||
user.visible_message("<span class = 'warning'>[user] pulls the trigger.</span>")
|
||||
if(silenced)
|
||||
playsound(user, fire_sound, 10, 1)
|
||||
else
|
||||
playsound(user, fire_sound, 50, 1)
|
||||
if(istype(in_chamber, /obj/item/projectile/beam/lastertag))
|
||||
user.show_message("<span class = 'warning'>You feel rather silly, trying to commit suicide with a toy.</span>")
|
||||
mouthshoot = 0
|
||||
return
|
||||
|
||||
in_chamber.on_hit(M)
|
||||
if (in_chamber.damage_type != HALLOSS)
|
||||
user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1)
|
||||
user.death()
|
||||
else
|
||||
user << "<span class = 'notice'>Ow...</span>"
|
||||
user.apply_effect(110,AGONY,0)
|
||||
del(in_chamber)
|
||||
mouthshoot = 0
|
||||
return
|
||||
//Suicide handling.
|
||||
/obj/item/weapon/gun/var/mouthshoot = 0 //To stop people from suiciding twice... >.>
|
||||
/obj/item/weapon/gun/proc/handle_suicide(mob/living/user)
|
||||
if(!ishuman(user))
|
||||
return
|
||||
var/mob/living/carbon/human/M = user
|
||||
|
||||
mouthshoot = 1
|
||||
M.visible_message("\red [user] sticks their gun in their mouth, ready to pull the trigger...")
|
||||
if(!do_after(user, 40))
|
||||
M.visible_message("\blue [user] decided life was worth living")
|
||||
mouthshoot = 0
|
||||
return
|
||||
var/obj/item/projectile/in_chamber = consume_next_projectile()
|
||||
if (istype(in_chamber))
|
||||
user.visible_message("<span class = 'warning'>[user] pulls the trigger.</span>")
|
||||
if(silenced)
|
||||
playsound(user, fire_sound, 10, 1)
|
||||
else
|
||||
click_empty(user)
|
||||
playsound(user, fire_sound, 50, 1)
|
||||
if(istype(in_chamber, /obj/item/projectile/beam/lastertag))
|
||||
user.show_message("<span class = 'warning'>You feel rather silly, trying to commit suicide with a toy.</span>")
|
||||
mouthshoot = 0
|
||||
return
|
||||
|
||||
if (load_into_chamber())
|
||||
//Point blank shooting if on harm intent or target we were targeting.
|
||||
if(user.a_intent == "hurt")
|
||||
user.visible_message("\red <b> \The [user] fires \the [src] point blank at [M]!</b>")
|
||||
if(istype(in_chamber)) in_chamber.damage *= 1.3
|
||||
Fire(M,user)
|
||||
return
|
||||
else if(target && M in target)
|
||||
Fire(M,user) ///Otherwise, shoot!
|
||||
return
|
||||
in_chamber.on_hit(M)
|
||||
if (in_chamber.damage_type != HALLOSS)
|
||||
user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1)
|
||||
user.death()
|
||||
else
|
||||
user << "<span class = 'notice'>Ow...</span>"
|
||||
user.apply_effect(110,AGONY,0)
|
||||
del(in_chamber)
|
||||
mouthshoot = 0
|
||||
return
|
||||
else
|
||||
return ..() //Pistolwhippin'
|
||||
handle_click_empty(user)
|
||||
mouthshoot = 0
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/proc/toggle_scope(var/zoom_amount=2.0)
|
||||
//looking through a scope limits your periphereal vision
|
||||
//still, increase the view size by a tiny amount so that sniping isn't too restricted to NSEW
|
||||
var/zoom_offset = round(world.view * zoom_amount)
|
||||
var/view_size = round(world.view + zoom_amount)
|
||||
var/scoped_accuracy_mod = zoom_offset
|
||||
|
||||
zoom(zoom_offset, view_size)
|
||||
if(zoom)
|
||||
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)
|
||||
recoil = initial(recoil)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//Vox pinning weapon.
|
||||
/obj/item/weapon/gun/launcher/spikethrower
|
||||
name = "Vox spike thrower"
|
||||
name = "vox spike thrower"
|
||||
desc = "A vicious alien projectile weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive."
|
||||
|
||||
var/last_regen = 0
|
||||
@@ -24,7 +24,6 @@
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/process()
|
||||
|
||||
if(spikes < max_spikes && world.time > last_regen + spike_gen_time)
|
||||
spikes++
|
||||
last_regen = world.time
|
||||
@@ -32,35 +31,26 @@
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/examine(mob/user)
|
||||
..(user)
|
||||
user << "It has [spikes] [spikes == 1 ? "spike" : "spikes"] remaining."
|
||||
user << "It has [spikes] spike\s remaining."
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/update_icon()
|
||||
icon_state = "spikethrower[spikes]"
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/emp_act(severity)
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/special_check(user)
|
||||
if(istype(user,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.species && H.species.name != "Vox" && H.species.name != "Vox Armalis")
|
||||
user << "\red \The [src] does not respond to you!"
|
||||
user << "<span class='warning'>\The [src] does not respond to you!</span>"
|
||||
return 0
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/update_release_force()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/load_into_chamber()
|
||||
if(in_chamber) return 1
|
||||
if(spikes < 1) return 0
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/consume_next_projectile()
|
||||
if(spikes < 1) return null
|
||||
spikes--
|
||||
in_chamber = new /obj/item/weapon/spike(src)
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/launcher/spikethrower/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
|
||||
if(..()) update_icon()
|
||||
return new /obj/item/weapon/spike(src)
|
||||
|
||||
//This gun only functions for armalis. The on-sprite is too huge to render properly on other sprites.
|
||||
/obj/item/weapon/gun/energy/noisecannon
|
||||
@@ -73,8 +63,8 @@
|
||||
recoil = 1
|
||||
|
||||
force = 10
|
||||
projectile_type = "/obj/item/projectile/energy/sonic"
|
||||
cell_type = "/obj/item/weapon/cell/super"
|
||||
projectile_type = /obj/item/projectile/energy/sonic
|
||||
cell_type = /obj/item/weapon/cell/super
|
||||
fire_delay = 40
|
||||
fire_sound = 'sound/effects/basscannon.ogg'
|
||||
|
||||
@@ -91,13 +81,9 @@
|
||||
if(H.species.name == "Vox Armalis")
|
||||
..()
|
||||
return
|
||||
user << "\red \The [src] is far too large for you to pick up."
|
||||
user << "<span class='warning'>\The [src] is far too large for you to pick up.</span>"
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/energy/noisecannon/load_into_chamber() //Does not have ammo.
|
||||
in_chamber = new projectile_type(src)
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/energy/noisecannon/update_icon()
|
||||
return
|
||||
|
||||
@@ -108,7 +94,7 @@
|
||||
icon_state = "particle"
|
||||
damage = 60
|
||||
damage_type = BRUTE
|
||||
flag = "bullet"
|
||||
check_armour = "bullet"
|
||||
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
|
||||
|
||||
embed = 0
|
||||
|
||||
@@ -3,39 +3,78 @@
|
||||
desc = "A basic energy-based gun."
|
||||
icon_state = "energy"
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
fire_sound_text = "laser blast"
|
||||
|
||||
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
|
||||
var/charge_cost = 100 //How much energy is needed to fire.
|
||||
var/cell_type = "/obj/item/weapon/cell"
|
||||
var/projectile_type = "/obj/item/projectile/beam/practice"
|
||||
var/cell_type = /obj/item/weapon/cell
|
||||
var/projectile_type = /obj/item/projectile/beam/practice
|
||||
var/modifystate
|
||||
var/charge_meter = 1 //if set, the icon state will be chosen based on the current charge
|
||||
|
||||
//self-recharging
|
||||
var/self_recharge = 0 //if set, the weapon will recharge itself
|
||||
var/use_external_power = 0 //if set, the weapon will look for an external power source to draw from, otherwise it recharges magically
|
||||
var/recharge_time = 4
|
||||
var/charge_tick = 0
|
||||
|
||||
emp_act(severity)
|
||||
power_supply.use(round(power_supply.maxcharge / severity))
|
||||
update_icon()
|
||||
..()
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
if(cell_type)
|
||||
power_supply = new cell_type(src)
|
||||
else
|
||||
power_supply = new(src)
|
||||
power_supply.give(power_supply.maxcharge)
|
||||
return
|
||||
|
||||
|
||||
load_into_chamber()
|
||||
if(in_chamber) return 1
|
||||
if(!power_supply) return 0
|
||||
if(!power_supply.use(charge_cost)) return 0
|
||||
if(!projectile_type) return 0
|
||||
in_chamber = new projectile_type(src)
|
||||
return 1
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/emp_act(severity)
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/gun/energy/New()
|
||||
..()
|
||||
if(cell_type)
|
||||
power_supply = new cell_type(src)
|
||||
power_supply.give(power_supply.maxcharge)
|
||||
if(self_recharge)
|
||||
processing_objects.Add(src)
|
||||
|
||||
/obj/item/weapon/gun/energy/Del()
|
||||
if(self_recharge)
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/energy/process()
|
||||
if(self_recharge) //Every [recharge_time] ticks, recharge a shot for the cyborg
|
||||
charge_tick++
|
||||
if(charge_tick < recharge_time) return 0
|
||||
charge_tick = 0
|
||||
|
||||
if(!power_supply || power_supply.charge >= power_supply.maxcharge)
|
||||
return 0 // check if we actually need to recharge
|
||||
|
||||
if(use_external_power)
|
||||
var/obj/item/weapon/cell/external = get_external_power_supply()
|
||||
if(!external || !external.use(charge_cost)) //Take power from the borg...
|
||||
return 0
|
||||
|
||||
power_supply.give(charge_cost) //... to recharge the shot
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/energy/consume_next_projectile()
|
||||
if(!power_supply) return null
|
||||
if(!ispath(projectile_type)) return null
|
||||
if(!power_supply.use(charge_cost)) return null
|
||||
return new projectile_type(src)
|
||||
|
||||
/obj/item/weapon/gun/energy/proc/get_external_power_supply()
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
return R.cell
|
||||
if(istype(src.loc, /obj/item/rig_module))
|
||||
var/obj/item/rig_module/module = src.loc
|
||||
if(module.holder && module.holder.wearer)
|
||||
var/mob/living/carbon/human/H = module.holder.wearer
|
||||
if(istype(H) && H.back)
|
||||
var/obj/item/weapon/rig/suit = H.back
|
||||
if(istype(suit))
|
||||
return suit.cell
|
||||
return null
|
||||
|
||||
/obj/item/weapon/gun/energy/update_icon()
|
||||
if(charge_meter)
|
||||
var/ratio = power_supply.charge / power_supply.maxcharge
|
||||
ratio = round(ratio, 0.25) * 100
|
||||
if(modifystate)
|
||||
|
||||
@@ -4,89 +4,53 @@
|
||||
icon_state = "laser"
|
||||
item_state = "laser"
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
w_class = 3.0
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
w_class = 3
|
||||
force = 10 //it has a stock, might as well give some kind of perk over the egun
|
||||
matter = list("metal" = 2000)
|
||||
origin_tech = "combat=3;magnets=2"
|
||||
projectile_type = /obj/item/projectile/beam
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/mounted
|
||||
self_recharge = 1
|
||||
use_external_power = 1
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/practice
|
||||
name = "practice laser gun"
|
||||
desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice."
|
||||
projectile_type = /obj/item/projectile/beam/practice
|
||||
clumsy_check = 0
|
||||
|
||||
obj/item/weapon/gun/energy/laser/retro
|
||||
name = "retro laser"
|
||||
icon_state = "retro"
|
||||
desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws."
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/captain
|
||||
/obj/item/weapon/gun/energy/captain
|
||||
name = "antique laser gun"
|
||||
icon_state = "caplaser"
|
||||
desc = "This is an antique laser gun. All craftsmanship is of the highest quality. It is decorated with assistant leather and chrome. The object menaces with spikes of energy. On the item is an image of Space Station 13. The station is exploding."
|
||||
force = 10
|
||||
force = 5
|
||||
slot_flags = SLOT_BELT
|
||||
origin_tech = null
|
||||
var/charge_tick = 0
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
|
||||
process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
power_supply.give(100)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/cyborg/load_into_chamber()
|
||||
if(in_chamber)
|
||||
return 1
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
if(R && R.cell)
|
||||
R.cell.use(100)
|
||||
in_chamber = new/obj/item/projectile/beam(src)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
self_recharge = 1
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/lasercannon
|
||||
name = "laser cannon"
|
||||
desc = "With the L.A.S.E.R. cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!"
|
||||
desc = "With the laser cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes!"
|
||||
icon_state = "lasercannon"
|
||||
item_state = "laser"
|
||||
fire_sound = 'sound/weapons/lasercannonfire.ogg'
|
||||
origin_tech = "combat=4;materials=3;powerstorage=3"
|
||||
projectile_type = "/obj/item/projectile/beam/heavylaser"
|
||||
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
projectile_type = /obj/item/projectile/beam/heavylaser
|
||||
charge_cost = 250
|
||||
fire_delay = 20
|
||||
|
||||
isHandgun()
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gun/energy/lasercannon/cyborg/load_into_chamber()
|
||||
if(in_chamber)
|
||||
return 1
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
if(R && R.cell)
|
||||
R.cell.use(250)
|
||||
in_chamber = new/obj/item/projectile/beam/heavylaser(src)
|
||||
return 1
|
||||
return 0
|
||||
/obj/item/weapon/gun/energy/lasercannon/mounted
|
||||
self_recharge = 1
|
||||
use_external_power = 1
|
||||
recharge_time = 25
|
||||
|
||||
/obj/item/weapon/gun/energy/xray
|
||||
name = "xray laser gun"
|
||||
@@ -94,80 +58,58 @@ obj/item/weapon/gun/energy/laser/retro
|
||||
icon_state = "xray"
|
||||
fire_sound = 'sound/weapons/laser3.ogg'
|
||||
origin_tech = "combat=5;materials=3;magnets=2;syndicate=2"
|
||||
projectile_type = "/obj/item/projectile/beam/xray"
|
||||
projectile_type = /obj/item/projectile/beam/xray
|
||||
charge_cost = 50
|
||||
|
||||
/obj/item/weapon/gun/energy/sniperrifle
|
||||
name = "\improper L.W.A.P. sniper rifle"
|
||||
desc = "A high-power laser rifle fitted with a SMART aiming-system scope."
|
||||
icon_state = "sniper"
|
||||
item_state = "laser"
|
||||
fire_sound = 'sound/weapons/marauder.ogg'
|
||||
origin_tech = "combat=6;materials=5;powerstorage=4"
|
||||
projectile_type = /obj/item/projectile/beam/sniper
|
||||
slot_flags = SLOT_BACK
|
||||
charge_cost = 250
|
||||
fire_delay = 35
|
||||
force = 10
|
||||
w_class = 4
|
||||
accuracy = -3 //shooting at the hip
|
||||
scoped_accuracy = 0
|
||||
|
||||
/obj/item/weapon/gun/energy/sniperrifle/verb/scope()
|
||||
set category = "Object"
|
||||
set name = "Use Scope"
|
||||
set popup_menu = 1
|
||||
|
||||
toggle_scope(2.0)
|
||||
|
||||
////////Laser Tag////////////////////
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/bluetag
|
||||
/obj/item/weapon/gun/energy/lasertag
|
||||
name = "laser tag gun"
|
||||
item_state = "laser"
|
||||
desc = "Standard issue weapon of the Imperial Guard"
|
||||
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
|
||||
|
||||
/obj/item/weapon/gun/energy/lasertag/special_check(var/mob/living/carbon/human/M)
|
||||
if(ishuman(M))
|
||||
if(!istype(M.wear_suit, required_vest))
|
||||
M << "<span class='warning'>You need to be wearing your laser tag vest!</span>"
|
||||
return 0
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/energy/lasertag/blue
|
||||
icon_state = "bluetag"
|
||||
desc = "Standard issue weapon of the Imperial Guard"
|
||||
projectile_type = "/obj/item/projectile/beam/lastertag/blue"
|
||||
origin_tech = "combat=1;magnets=2"
|
||||
clumsy_check = 0
|
||||
var/charge_tick = 0
|
||||
projectile_type = /obj/item/projectile/beam/lastertag/blue
|
||||
required_vest = /obj/item/clothing/suit/bluetag
|
||||
|
||||
special_check(var/mob/living/carbon/human/M)
|
||||
if(ishuman(M))
|
||||
if(istype(M.wear_suit, /obj/item/clothing/suit/bluetag))
|
||||
return 1
|
||||
M << "\red You need to be wearing your laser tag vest!"
|
||||
return 0
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
|
||||
process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
power_supply.give(100)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/redtag
|
||||
name = "laser tag gun"
|
||||
/obj/item/weapon/gun/energy/lasertag/red
|
||||
icon_state = "redtag"
|
||||
desc = "Standard issue weapon of the Imperial Guard"
|
||||
projectile_type = "/obj/item/projectile/beam/lastertag/red"
|
||||
origin_tech = "combat=1;magnets=2"
|
||||
clumsy_check = 0
|
||||
var/charge_tick = 0
|
||||
|
||||
special_check(var/mob/living/carbon/human/M)
|
||||
if(ishuman(M))
|
||||
if(istype(M.wear_suit, /obj/item/clothing/suit/redtag))
|
||||
return 1
|
||||
M << "\red You need to be wearing your laser tag vest!"
|
||||
return 0
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
|
||||
process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
power_supply.give(100)
|
||||
update_icon()
|
||||
return 1
|
||||
projectile_type = /obj/item/projectile/beam/lastertag/red
|
||||
required_vest = /obj/item/clothing/suit/redtag
|
||||
|
||||
@@ -1,129 +1,119 @@
|
||||
/obj/item/weapon/gun/energy/gun
|
||||
name = "energy gun"
|
||||
desc = "A basic energy-based gun with two settings: Stun and kill."
|
||||
desc = "An energy-based gun with two settings: Stun and kill."
|
||||
icon_state = "energystun100"
|
||||
item_state = null //so the human update icon uses the icon_state instead.
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
|
||||
charge_cost = 100 //How much energy is needed to fire.
|
||||
projectile_type = "/obj/item/projectile/beam/stun"
|
||||
projectile_type = /obj/item/projectile/beam/stun
|
||||
origin_tech = "combat=3;magnets=2"
|
||||
modifystate = "energystun"
|
||||
|
||||
var/mode = 0 //0 = stun, 1 = kill
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/attack_self(mob/living/user as mob)
|
||||
switch(mode)
|
||||
if(0)
|
||||
mode = 1
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
user << "<span class='warning'>[src.name] is now set to kill.</span>"
|
||||
projectile_type = /obj/item/projectile/beam
|
||||
modifystate = "energykill"
|
||||
if(1)
|
||||
mode = 0
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
user << "<span class='warning'>[src.name] is now set to stun.</span>"
|
||||
projectile_type = /obj/item/projectile/beam/stun
|
||||
modifystate = "energystun"
|
||||
update_icon()
|
||||
if(user.l_hand == src)
|
||||
user.update_inv_l_hand()
|
||||
else
|
||||
user.update_inv_r_hand()
|
||||
|
||||
attack_self(mob/living/user as mob)
|
||||
switch(mode)
|
||||
if(0)
|
||||
mode = 1
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
user << "\red [src.name] is now set to kill."
|
||||
projectile_type = "/obj/item/projectile/beam"
|
||||
modifystate = "energykill"
|
||||
if(1)
|
||||
mode = 0
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
user << "\red [src.name] is now set to stun."
|
||||
projectile_type = "/obj/item/projectile/beam/stun"
|
||||
modifystate = "energystun"
|
||||
update_icon()
|
||||
if(user.l_hand == src)
|
||||
user.update_inv_l_hand()
|
||||
else
|
||||
user.update_inv_r_hand()
|
||||
/obj/item/weapon/gun/energy/gun/mounted
|
||||
self_recharge = 1
|
||||
use_external_power = 1
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear
|
||||
name = "advanced energy gun"
|
||||
desc = "An energy gun with an experimental miniaturized reactor."
|
||||
icon_state = "nucgun"
|
||||
origin_tech = "combat=3;materials=5;powerstorage=3"
|
||||
origin_tech = "combat=3;materials=5;powerstorage=3"
|
||||
slot_flags = SLOT_BELT
|
||||
force = 8 //looks heavier than a pistol
|
||||
self_recharge = 1
|
||||
var/lightfail = 0
|
||||
var/charge_tick = 0
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
//override for failcheck behaviour
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
if((power_supply.charge / power_supply.maxcharge) != 1)
|
||||
if(!failcheck()) return 0
|
||||
power_supply.give(charge_cost)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
|
||||
Del()
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/proc/failcheck()
|
||||
lightfail = 0
|
||||
if (prob(src.reliability)) return 1 //No failure
|
||||
if (prob(src.reliability))
|
||||
for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it
|
||||
if (src in M.contents)
|
||||
M << "<span class='warning'>Your gun feels pleasantly warm for a moment.</span>"
|
||||
else
|
||||
M << "<span class='warning'>You feel a warm sensation.</span>"
|
||||
M.apply_effect(rand(3,120), IRRADIATE)
|
||||
lightfail = 1
|
||||
else
|
||||
for (var/mob/living/M in range(rand(1,4),src)) //Big failure, TIME FOR RADIATION BITCHES
|
||||
if (src in M.contents)
|
||||
M << "<span class='danger'>Your gun's reactor overloads!</span>"
|
||||
M << "<span class='warning'>You feel a wave of heat wash over you.</span>"
|
||||
M.apply_effect(300, IRRADIATE)
|
||||
crit_fail = 1 //break the gun so it stops recharging
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
update_icon()
|
||||
return 0
|
||||
|
||||
|
||||
process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
if((power_supply.charge / power_supply.maxcharge) != 1)
|
||||
if(!failcheck()) return 0
|
||||
power_supply.give(100)
|
||||
update_icon()
|
||||
return 1
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/proc/update_charge()
|
||||
if (crit_fail)
|
||||
overlays += "nucgun-whee"
|
||||
return
|
||||
var/ratio = power_supply.charge / power_supply.maxcharge
|
||||
ratio = round(ratio, 0.25) * 100
|
||||
overlays += "nucgun-[ratio]"
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/proc/update_reactor()
|
||||
if(crit_fail)
|
||||
overlays += "nucgun-crit"
|
||||
return
|
||||
if(lightfail)
|
||||
overlays += "nucgun-medium"
|
||||
else if ((power_supply.charge/power_supply.maxcharge) <= 0.5)
|
||||
overlays += "nucgun-light"
|
||||
else
|
||||
overlays += "nucgun-clean"
|
||||
|
||||
proc
|
||||
failcheck()
|
||||
lightfail = 0
|
||||
if (prob(src.reliability)) return 1 //No failure
|
||||
if (prob(src.reliability))
|
||||
for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it
|
||||
if (src in M.contents)
|
||||
M << "\red Your gun feels pleasantly warm for a moment."
|
||||
else
|
||||
M << "\red You feel a warm sensation."
|
||||
M.apply_effect(rand(3,120), IRRADIATE)
|
||||
lightfail = 1
|
||||
else
|
||||
for (var/mob/living/M in range(rand(1,4),src)) //Big failure, TIME FOR RADIATION BITCHES
|
||||
if (src in M.contents)
|
||||
M << "\red Your gun's reactor overloads!"
|
||||
M << "\red You feel a wave of heat wash over you."
|
||||
M.apply_effect(300, IRRADIATE)
|
||||
crit_fail = 1 //break the gun so it stops recharging
|
||||
processing_objects.Remove(src)
|
||||
update_icon()
|
||||
return 0
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/proc/update_mode()
|
||||
if (mode == 0)
|
||||
overlays += "nucgun-stun"
|
||||
else if (mode == 1)
|
||||
overlays += "nucgun-kill"
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/emp_act(severity)
|
||||
..()
|
||||
reliability -= round(15/severity)
|
||||
|
||||
update_charge()
|
||||
if (crit_fail)
|
||||
overlays += "nucgun-whee"
|
||||
return
|
||||
var/ratio = power_supply.charge / power_supply.maxcharge
|
||||
ratio = round(ratio, 0.25) * 100
|
||||
overlays += "nucgun-[ratio]"
|
||||
|
||||
|
||||
update_reactor()
|
||||
if(crit_fail)
|
||||
overlays += "nucgun-crit"
|
||||
return
|
||||
if(lightfail)
|
||||
overlays += "nucgun-medium"
|
||||
else if ((power_supply.charge/power_supply.maxcharge) <= 0.5)
|
||||
overlays += "nucgun-light"
|
||||
else
|
||||
overlays += "nucgun-clean"
|
||||
|
||||
|
||||
update_mode()
|
||||
if (mode == 0)
|
||||
overlays += "nucgun-stun"
|
||||
else if (mode == 1)
|
||||
overlays += "nucgun-kill"
|
||||
|
||||
|
||||
emp_act(severity)
|
||||
..()
|
||||
reliability -= round(15/severity)
|
||||
|
||||
|
||||
update_icon()
|
||||
overlays.Cut()
|
||||
update_charge()
|
||||
update_reactor()
|
||||
update_mode()
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/update_icon()
|
||||
overlays.Cut()
|
||||
update_charge()
|
||||
update_reactor()
|
||||
update_mode()
|
||||
|
||||
@@ -1,70 +1,57 @@
|
||||
/obj/item/weapon/gun/energy/pulse_rifle
|
||||
name = "pulse rifle"
|
||||
desc = "A heavy-duty, pulse-based energy weapon, preferred by front-line combat personnel."
|
||||
desc = "A weapon that uses advanced pulse-based beam generation technology to emit powerful laser blasts. Because of its complexity and cost, it is rarely seen in use except by specialists."
|
||||
icon_state = "pulse"
|
||||
item_state = null //so the human update icon uses the icon_state instead.
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
force = 10
|
||||
fire_sound = 'sound/weapons/pulse.ogg'
|
||||
charge_cost = 200
|
||||
projectile_type = "/obj/item/projectile/beam/pulse"
|
||||
cell_type = "/obj/item/weapon/cell/super"
|
||||
projectile_type = /obj/item/projectile/beam/pulse
|
||||
cell_type = /obj/item/weapon/cell/super
|
||||
var/mode = 2
|
||||
fire_delay = 25
|
||||
|
||||
attack_self(mob/living/user as mob)
|
||||
switch(mode)
|
||||
if(2)
|
||||
mode = 0
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
user << "\red [src.name] is now set to stun."
|
||||
projectile_type = "/obj/item/projectile/beam/stun"
|
||||
if(0)
|
||||
mode = 1
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
user << "\red [src.name] is now set to kill."
|
||||
projectile_type = "/obj/item/projectile/beam"
|
||||
if(1)
|
||||
mode = 2
|
||||
charge_cost = 200
|
||||
fire_sound = 'sound/weapons/pulse.ogg'
|
||||
user << "\red [src.name] is now set to DESTROY."
|
||||
projectile_type = "/obj/item/projectile/beam/pulse"
|
||||
return
|
||||
|
||||
isHandgun()
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gun/energy/pulse_rifle/cyborg/load_into_chamber()
|
||||
if(in_chamber)
|
||||
return 1
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
if(R && R.cell)
|
||||
R.cell.use(charge_cost)
|
||||
in_chamber = new/obj/item/projectile/beam(src)
|
||||
return 1
|
||||
return 0
|
||||
/obj/item/weapon/gun/energy/pulse_rifle/attack_self(mob/living/user as mob)
|
||||
switch(mode)
|
||||
if(2)
|
||||
mode = 0
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
user << "<span class='warning'>[src.name] is now set to stun.</span>"
|
||||
projectile_type = /obj/item/projectile/beam/stun
|
||||
if(0)
|
||||
mode = 1
|
||||
charge_cost = 100
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
user << "<span class='warning'>[src.name] is now set to kill.</span>"
|
||||
projectile_type = /obj/item/projectile/beam
|
||||
if(1)
|
||||
mode = 2
|
||||
charge_cost = 200
|
||||
fire_sound = 'sound/weapons/pulse.ogg'
|
||||
user << "<span class='warning'>[src.name] is now set to DESTROY.</span>"
|
||||
projectile_type = /obj/item/projectile/beam/pulse
|
||||
|
||||
/obj/item/weapon/gun/energy/pulse_rifle/mounted
|
||||
self_recharge = 1
|
||||
use_external_power = 1
|
||||
|
||||
/obj/item/weapon/gun/energy/pulse_rifle/destroyer
|
||||
name = "pulse destroyer"
|
||||
desc = "A heavy-duty, pulse-based energy weapon."
|
||||
cell_type = "/obj/item/weapon/cell/infinite"
|
||||
desc = "A heavy-duty, pulse-based energy weapon. Because of its complexity and cost, it is rarely seen in use except by specialists."
|
||||
cell_type = /obj/item/weapon/cell/infinite
|
||||
fire_delay = 10
|
||||
|
||||
attack_self(mob/living/user as mob)
|
||||
user << "\red [src.name] has three settings, and they are all DESTROY."
|
||||
|
||||
/obj/item/weapon/gun/energy/pulse_rifle/destroyer/attack_self(mob/living/user as mob)
|
||||
user << "<span class='warning'>[src.name] has three settings, and they are all DESTROY.</span>"
|
||||
|
||||
|
||||
//WHY?
|
||||
/obj/item/weapon/gun/energy/pulse_rifle/M1911
|
||||
name = "\improper M1911-P"
|
||||
desc = "It's not the size of the gun, it's the size of the hole it puts through people."
|
||||
slot_flags = SLOT_BELT|SLOT_HOLSTER
|
||||
icon_state = "m1911-p"
|
||||
cell_type = "/obj/item/weapon/cell/infinite"
|
||||
cell_type = /obj/item/weapon/cell/infinite
|
||||
fire_delay = 10
|
||||
|
||||
isHandgun()
|
||||
return 1
|
||||
|
||||
@@ -5,17 +5,16 @@
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
origin_tech = "combat=2;magnets=4"
|
||||
w_class = 4.0
|
||||
force = 10
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BACK
|
||||
charge_cost = 100
|
||||
projectile_type = "/obj/item/projectile/ion"
|
||||
projectile_type = /obj/item/projectile/ion
|
||||
|
||||
/obj/item/weapon/gun/energy/ionrifle/emp_act(severity)
|
||||
if(severity <= 2)
|
||||
power_supply.use(round(power_supply.maxcharge / severity))
|
||||
update_icon()
|
||||
else
|
||||
return
|
||||
if(severity > 2)
|
||||
return //so it doesn't EMP itself, I guess
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/energy/decloner
|
||||
name = "biological demolecularisor"
|
||||
@@ -24,9 +23,89 @@
|
||||
fire_sound = 'sound/weapons/pulse3.ogg'
|
||||
origin_tech = "combat=5;materials=4;powerstorage=3"
|
||||
charge_cost = 100
|
||||
projectile_type = "/obj/item/projectile/energy/declone"
|
||||
projectile_type = /obj/item/projectile/energy/declone
|
||||
|
||||
obj/item/weapon/gun/energy/staff
|
||||
/obj/item/weapon/gun/energy/floragun
|
||||
name = "floral somatoray"
|
||||
desc = "A tool that discharges controlled radiation which induces mutation in plant cells."
|
||||
icon_state = "floramut100"
|
||||
item_state = "obj/item/gun.dmi"
|
||||
fire_sound = 'sound/effects/stealthoff.ogg'
|
||||
charge_cost = 100
|
||||
projectile_type = /obj/item/projectile/energy/floramut
|
||||
origin_tech = "materials=2;biotech=3;powerstorage=3"
|
||||
modifystate = "floramut"
|
||||
self_recharge = 1
|
||||
var/mode = 0 //0 = mutate, 1 = yield boost
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/attack_self(mob/living/user as mob)
|
||||
switch(mode)
|
||||
if(0)
|
||||
mode = 1
|
||||
charge_cost = 100
|
||||
user << "<span class='warning'>The [src.name] is now set to increase yield.</span>"
|
||||
projectile_type = /obj/item/projectile/energy/florayield
|
||||
modifystate = "florayield"
|
||||
if(1)
|
||||
mode = 0
|
||||
charge_cost = 100
|
||||
user << "<span class='warning'>The [src.name] is now set to induce mutations.</span>"
|
||||
projectile_type = /obj/item/projectile/energy/floramut
|
||||
modifystate = "floramut"
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, adjacent_flag)
|
||||
//allow shooting into adjacent hydrotrays regardless of intent
|
||||
if(adjacent_flag && istype(target,/obj/machinery/portable_atmospherics/hydroponics))
|
||||
user.visible_message("<span class='danger'>\The [user] fires \the [src] into \the [target]!</span>")
|
||||
Fire(target,user)
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/energy/meteorgun
|
||||
name = "meteor gun"
|
||||
desc = "For the love of god, make sure you're aiming this the right way!"
|
||||
icon_state = "riotgun"
|
||||
item_state = "c20r"
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
w_class = 4
|
||||
projectile_type = /obj/item/projectile/meteor
|
||||
charge_cost = 100
|
||||
cell_type = /obj/item/weapon/cell/potato
|
||||
self_recharge = 1
|
||||
recharge_time = 5 //Time it takes for shots to recharge (in ticks)
|
||||
charge_meter = 0
|
||||
|
||||
/obj/item/weapon/gun/energy/meteorgun/pen
|
||||
name = "meteor pen"
|
||||
desc = "The pen is mightier than the sword."
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "pen"
|
||||
item_state = "pen"
|
||||
w_class = 1
|
||||
slot_flags = SLOT_BELT
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/mindflayer
|
||||
name = "mind flayer"
|
||||
desc = "A prototype weapon recovered from the ruins of Research-Station Epsilon."
|
||||
icon_state = "xray"
|
||||
projectile_type = /obj/item/projectile/beam/mindflayer
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
|
||||
/obj/item/weapon/gun/energy/toxgun
|
||||
name = "phoron pistol"
|
||||
desc = "A specialized firearm designed to fire lethal bolts of phoron."
|
||||
icon_state = "toxgun"
|
||||
fire_sound = 'sound/effects/stealthoff.ogg'
|
||||
w_class = 3.0
|
||||
origin_tech = "combat=5;phorontech=4"
|
||||
projectile_type = /obj/item/projectile/energy/phoron
|
||||
|
||||
/* Staves */
|
||||
|
||||
/obj/item/weapon/gun/energy/staff
|
||||
name = "staff of change"
|
||||
desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself"
|
||||
icon = 'icons/obj/gun.dmi'
|
||||
@@ -37,199 +116,91 @@ obj/item/weapon/gun/energy/staff
|
||||
slot_flags = SLOT_BACK
|
||||
w_class = 4.0
|
||||
charge_cost = 200
|
||||
projectile_type = "/obj/item/projectile/change"
|
||||
projectile_type = /obj/item/projectile/change
|
||||
origin_tech = null
|
||||
clumsy_check = 0
|
||||
var/charge_tick = 0
|
||||
self_recharge = 1
|
||||
charge_meter = 0
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
|
||||
process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
power_supply.give(200)
|
||||
return 1
|
||||
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
click_empty(mob/user = null)
|
||||
if (user)
|
||||
user.visible_message("*fizzle*", "\red <b>*fizzle*</b>")
|
||||
else
|
||||
src.visible_message("*fizzle*")
|
||||
playsound(src.loc, 'sound/effects/sparks1.ogg', 100, 1)
|
||||
/obj/item/weapon/gun/energy/staff/handle_click_empty(mob/user = null)
|
||||
if (user)
|
||||
user.visible_message("*fizzle*", "<span class='danger'>*fizzle*</span>")
|
||||
else
|
||||
src.visible_message("*fizzle*")
|
||||
playsound(src.loc, 'sound/effects/sparks1.ogg', 100, 1)
|
||||
|
||||
/obj/item/weapon/gun/energy/staff/animate
|
||||
name = "staff of animation"
|
||||
desc = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines."
|
||||
projectile_type = "/obj/item/projectile/animate"
|
||||
projectile_type = /obj/item/projectile/animate
|
||||
charge_cost = 100
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun
|
||||
name = "floral somatoray"
|
||||
desc = "A tool that discharges controlled radiation which induces mutation in plant cells."
|
||||
icon_state = "floramut100"
|
||||
item_state = "obj/item/gun.dmi"
|
||||
fire_sound = 'sound/effects/stealthoff.ogg'
|
||||
charge_cost = 100
|
||||
projectile_type = "/obj/item/projectile/energy/floramut"
|
||||
origin_tech = "materials=2;biotech=3;powerstorage=3"
|
||||
modifystate = "floramut"
|
||||
var/charge_tick = 0
|
||||
var/mode = 0 //0 = mutate, 1 = yield boost
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
power_supply.give(100)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/attack_self(mob/living/user as mob)
|
||||
switch(mode)
|
||||
if(0)
|
||||
mode = 1
|
||||
charge_cost = 100
|
||||
user << "\red The [src.name] is now set to increase yield."
|
||||
projectile_type = "/obj/item/projectile/energy/florayield"
|
||||
modifystate = "florayield"
|
||||
if(1)
|
||||
mode = 0
|
||||
charge_cost = 100
|
||||
user << "\red The [src.name] is now set to induce mutations."
|
||||
projectile_type = "/obj/item/projectile/energy/floramut"
|
||||
modifystate = "floramut"
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, flag)
|
||||
|
||||
if(flag && istype(target,/obj/machinery/portable_atmospherics/hydroponics))
|
||||
var/obj/machinery/portable_atmospherics/hydroponics/tray = target
|
||||
if(load_into_chamber())
|
||||
user.visible_message("\red <b> \The [user] fires \the [src] into \the [tray]!</b>")
|
||||
Fire(target,user)
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/energy/meteorgun
|
||||
name = "meteor gun"
|
||||
desc = "For the love of god, make sure you're aiming this the right way!"
|
||||
icon_state = "riotgun"
|
||||
item_state = "c20r"
|
||||
w_class = 4
|
||||
projectile_type = "/obj/item/projectile/meteor"
|
||||
charge_cost = 100
|
||||
cell_type = "/obj/item/weapon/cell/potato"
|
||||
clumsy_check = 0 //Admin spawn only, might as well let clowns use it.
|
||||
var/charge_tick = 0
|
||||
var/recharge_time = 5 //Time it takes for shots to recharge (in ticks)
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
process()
|
||||
charge_tick++
|
||||
if(charge_tick < recharge_time) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
power_supply.give(100)
|
||||
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/meteorgun/pen
|
||||
name = "meteor pen"
|
||||
desc = "The pen is mightier than the sword."
|
||||
icon = 'icons/obj/bureaucracy.dmi'
|
||||
icon_state = "pen"
|
||||
item_state = "pen"
|
||||
w_class = 1
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/mindflayer
|
||||
name = "mind flayer"
|
||||
desc = "A prototype weapon recovered from the ruins of Research-Station Epsilon."
|
||||
icon_state = "xray"
|
||||
projectile_type = "/obj/item/projectile/beam/mindflayer"
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
|
||||
obj/item/weapon/gun/energy/staff/focus
|
||||
name = "mental focus"
|
||||
desc = "An artefact that channels the will of the user into destructive bolts of force. If you aren't careful with it, you might poke someone's brain out."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "focus"
|
||||
item_state = "focus"
|
||||
projectile_type = "/obj/item/projectile/forcebolt"
|
||||
slot_flags = SLOT_BACK
|
||||
projectile_type = /obj/item/projectile/forcebolt
|
||||
/*
|
||||
attack_self(mob/living/user as mob)
|
||||
if(projectile_type == "/obj/item/projectile/forcebolt")
|
||||
charge_cost = 200
|
||||
user << "\red The [src.name] will now strike a small area."
|
||||
user << "<span class='warning'>The [src.name] will now strike a small area.</span>"
|
||||
projectile_type = "/obj/item/projectile/forcebolt/strong"
|
||||
else
|
||||
charge_cost = 100
|
||||
user << "\red The [src.name] will now strike only a single person."
|
||||
user << "<span class='warning'>The [src.name] will now strike only a single person.</span>"
|
||||
projectile_type = "/obj/item/projectile/forcebolt"
|
||||
*/
|
||||
|
||||
/obj/item/weapon/gun/energy/toxgun
|
||||
name = "phoron pistol"
|
||||
desc = "A specialized firearm designed to fire lethal bolts of phoron."
|
||||
icon_state = "toxgun"
|
||||
fire_sound = 'sound/effects/stealthoff.ogg'
|
||||
w_class = 3.0
|
||||
origin_tech = "combat=5;phorontech=4"
|
||||
projectile_type = "/obj/item/projectile/energy/phoron"
|
||||
/* Adminbus guns */
|
||||
|
||||
/obj/item/weapon/gun/energy/sniperrifle
|
||||
name = "\improper L.W.A.P. sniper rifle"
|
||||
desc = "A rifle constructed of lightweight materials, fitted with a SMART aiming-system scope."
|
||||
icon = 'icons/obj/gun.dmi'
|
||||
icon_state = "sniper"
|
||||
fire_sound = 'sound/weapons/marauder.ogg'
|
||||
origin_tech = "combat=6;materials=5;powerstorage=4"
|
||||
projectile_type = "/obj/item/projectile/beam/sniper"
|
||||
slot_flags = SLOT_BACK
|
||||
charge_cost = 250
|
||||
fire_delay = 35
|
||||
w_class = 4.0
|
||||
zoomdevicename = "scope"
|
||||
// Serves as a target spotter for the Icarus.
|
||||
/obj/item/weapon/gun/energy/icarus
|
||||
name = "rubber ducky"
|
||||
desc = "It's a cute rubber duck. With an evil gleam in it's eye."
|
||||
projectile_type = /obj/item/projectile/icarus/pointdefense
|
||||
icon = 'icons/obj/watercloset.dmi'
|
||||
icon_state = "rubberducky"
|
||||
item_state = "rubberducky"
|
||||
charge_cost = 0
|
||||
silenced = 1
|
||||
|
||||
/obj/item/weapon/gun/energy/sniperrifle/verb/scope()
|
||||
/obj/item/weapon/gun/energy/icarus/attack_self(mob/living/user as mob)
|
||||
if(projectile_type == /obj/item/projectile/icarus/pointdefense)
|
||||
projectile_type = /obj/item/projectile/icarus/guns
|
||||
user << "You inform the Icarus to switch to the main guns."
|
||||
else
|
||||
projectile_type = /obj/item/projectile/icarus/pointdefense
|
||||
user << "You inform the Icarus to switch to the point-defense lasers."
|
||||
|
||||
. = ..()
|
||||
|
||||
/obj/item/weapon/gun/energy/icarus/update_icon()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/energy/icarus/verb/SetIcarusAngle()
|
||||
set src in usr
|
||||
set name = "Set Firing Angle"
|
||||
set desc = "Sets the angle from which the icarus will fire."
|
||||
set category = "Object"
|
||||
set name = "Use Scope"
|
||||
set popup_menu = 1
|
||||
|
||||
zoom()
|
||||
Icarus_SetPosition(usr)
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/variable
|
||||
name = "abstract weapon"
|
||||
desc = "It seems to shift and flow as you watch."
|
||||
charge_cost = 0
|
||||
silenced = 1
|
||||
|
||||
/obj/item/weapon/gun/energy/variable/update_icon()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/energy/variable/attack_self(mob/living/user as mob)
|
||||
var/type = input(user,"What projectile type?","Projectile", null) as null|anything in typesof(/obj/item/projectile)
|
||||
if(!type)
|
||||
return ..()
|
||||
projectile_type = type
|
||||
. = ..()
|
||||
|
||||
@@ -5,39 +5,16 @@
|
||||
item_state = null //so the human update icon uses the icon_state instead.
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
charge_cost = 100
|
||||
projectile_type = "/obj/item/projectile/beam/stun"
|
||||
cell_type = "/obj/item/weapon/cell/crap"
|
||||
projectile_type = /obj/item/projectile/beam/stun
|
||||
cell_type = /obj/item/weapon/cell/crap
|
||||
|
||||
/obj/item/weapon/gun/energy/taser/cyborg
|
||||
cell_type = "/obj/item/weapon/cell/secborg"
|
||||
var/charge_tick = 0
|
||||
var/recharge_time = 10 //Time it takes for shots to recharge (in ticks)
|
||||
/obj/item/weapon/gun/energy/taser/mounted
|
||||
self_recharge = 1
|
||||
use_external_power = 1
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
process() //Every [recharge_time] ticks, recharge a shot for the cyborg
|
||||
charge_tick++
|
||||
if(charge_tick < recharge_time) return 0
|
||||
charge_tick = 0
|
||||
|
||||
if(!power_supply) return 0 //sanity
|
||||
if(power_supply.charge >= power_supply.maxcharge) return 0 // check if we actually need to recharge
|
||||
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
if(R && R.cell)
|
||||
R.cell.use(charge_cost) //Take power from the borg...
|
||||
power_supply.give(charge_cost) //... to recharge the shot
|
||||
|
||||
update_icon()
|
||||
return 1
|
||||
/obj/item/weapon/gun/energy/taser/mounted/cyborg
|
||||
cell_type = /obj/item/weapon/cell/secborg
|
||||
recharge_time = 10 //Time it takes for shots to recharge (in ticks)
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/stunrevolver
|
||||
@@ -47,9 +24,8 @@
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
origin_tech = "combat=3;materials=3;powerstorage=2"
|
||||
charge_cost = 125
|
||||
projectile_type = "/obj/item/projectile/beam/stun"
|
||||
cell_type = "/obj/item/weapon/cell"
|
||||
|
||||
projectile_type = /obj/item/projectile/beam/stun
|
||||
cell_type = /obj/item/weapon/cell
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/crossbow
|
||||
@@ -60,43 +36,22 @@
|
||||
item_state = "crossbow"
|
||||
matter = list("metal" = 2000)
|
||||
origin_tech = "combat=2;magnets=2;syndicate=5"
|
||||
slot_flags = SLOT_BELT
|
||||
silenced = 1
|
||||
fire_sound = 'sound/weapons/Genhit.ogg'
|
||||
projectile_type = "/obj/item/projectile/energy/bolt"
|
||||
cell_type = "/obj/item/weapon/cell/crap"
|
||||
var/charge_tick = 0
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
|
||||
process()
|
||||
charge_tick++
|
||||
if(charge_tick < 4) return 0
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
power_supply.give(100)
|
||||
return 1
|
||||
|
||||
|
||||
update_icon()
|
||||
return
|
||||
projectile_type = /obj/item/projectile/energy/bolt
|
||||
cell_type = /obj/item/weapon/cell/crap
|
||||
self_recharge = 1
|
||||
charge_meter = 0
|
||||
|
||||
/obj/item/weapon/gun/energy/crossbow/ninja
|
||||
name = "energy dart thrower"
|
||||
projectile_type = "/obj/item/projectile/energy/dart"
|
||||
projectile_type = /obj/item/projectile/energy/dart
|
||||
|
||||
/obj/item/weapon/gun/energy/crossbow/largecrossbow
|
||||
name = "Energy Crossbow"
|
||||
name = "energy crossbow"
|
||||
desc = "A weapon favored by mercenary infiltration teams."
|
||||
w_class = 4.0
|
||||
w_class = 4
|
||||
force = 10
|
||||
matter = list("metal" = 200000)
|
||||
projectile_type = "/obj/item/projectile/energy/bolt/large"
|
||||
projectile_type = /obj/item/projectile/energy/bolt/large
|
||||
|
||||
@@ -7,74 +7,73 @@
|
||||
var/current_temperature = T20C
|
||||
charge_cost = 100
|
||||
origin_tech = "combat=3;materials=4;powerstorage=3;magnets=2"
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
|
||||
projectile_type = "/obj/item/projectile/temp"
|
||||
cell_type = "/obj/item/weapon/cell/crap"
|
||||
projectile_type = /obj/item/projectile/temp
|
||||
cell_type = /obj/item/weapon/cell/crap
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
/obj/item/weapon/gun/energy/temperature/New()
|
||||
..()
|
||||
processing_objects.Add(src)
|
||||
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
/obj/item/weapon/gun/energy/temperature/Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
|
||||
attack_self(mob/living/user as mob)
|
||||
user.set_machine(src)
|
||||
var/temp_text = ""
|
||||
if(temperature > (T0C - 50))
|
||||
temp_text = "<FONT color=black>[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)</FONT>"
|
||||
/obj/item/weapon/gun/energy/temperature/attack_self(mob/living/user as mob)
|
||||
user.set_machine(src)
|
||||
var/temp_text = ""
|
||||
if(temperature > (T0C - 50))
|
||||
temp_text = "<FONT color=black>[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)</FONT>"
|
||||
else
|
||||
temp_text = "<FONT color=blue>[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)</FONT>"
|
||||
|
||||
var/dat = {"<B>Freeze Gun Configuration: </B><BR>
|
||||
Current output temperature: [temp_text]<BR>
|
||||
Target output temperature: <A href='?src=\ref[src];temp=-100'>-</A> <A href='?src=\ref[src];temp=-10'>-</A> <A href='?src=\ref[src];temp=-1'>-</A> [current_temperature] <A href='?src=\ref[src];temp=1'>+</A> <A href='?src=\ref[src];temp=10'>+</A> <A href='?src=\ref[src];temp=100'>+</A><BR>
|
||||
"}
|
||||
|
||||
user << browse(dat, "window=freezegun;size=450x300;can_resize=1;can_close=1;can_minimize=1")
|
||||
onclose(user, "window=freezegun", src)
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/temperature/Topic(href, href_list)
|
||||
if (..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
|
||||
if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
if(amount > 0)
|
||||
src.current_temperature = min(500, src.current_temperature+amount)
|
||||
else
|
||||
temp_text = "<FONT color=blue>[temperature] ([round(temperature-T0C)]°C) ([round(temperature*1.8-459.67)]°F)</FONT>"
|
||||
|
||||
var/dat = {"<B>Freeze Gun Configuration: </B><BR>
|
||||
Current output temperature: [temp_text]<BR>
|
||||
Target output temperature: <A href='?src=\ref[src];temp=-100'>-</A> <A href='?src=\ref[src];temp=-10'>-</A> <A href='?src=\ref[src];temp=-1'>-</A> [current_temperature] <A href='?src=\ref[src];temp=1'>+</A> <A href='?src=\ref[src];temp=10'>+</A> <A href='?src=\ref[src];temp=100'>+</A><BR>
|
||||
"}
|
||||
src.current_temperature = max(0, src.current_temperature+amount)
|
||||
if (istype(src.loc, /mob))
|
||||
attack_self(src.loc)
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
user << browse(dat, "window=freezegun;size=450x300;can_resize=1;can_close=1;can_minimize=1")
|
||||
onclose(user, "window=freezegun", src)
|
||||
/obj/item/weapon/gun/energy/temperature/process()
|
||||
switch(temperature)
|
||||
if(0 to 100) charge_cost = 1000
|
||||
if(100 to 250) charge_cost = 500
|
||||
if(251 to 300) charge_cost = 100
|
||||
if(301 to 400) charge_cost = 500
|
||||
if(401 to 500) charge_cost = 1000
|
||||
|
||||
|
||||
Topic(href, href_list)
|
||||
if (..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
|
||||
if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
if(amount > 0)
|
||||
src.current_temperature = min(500, src.current_temperature+amount)
|
||||
if(current_temperature != temperature)
|
||||
var/difference = abs(current_temperature - temperature)
|
||||
if(difference >= 10)
|
||||
if(current_temperature < temperature)
|
||||
temperature -= 10
|
||||
else
|
||||
src.current_temperature = max(0, src.current_temperature+amount)
|
||||
if (istype(src.loc, /mob))
|
||||
attack_self(src.loc)
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
process()
|
||||
switch(temperature)
|
||||
if(0 to 100) charge_cost = 1000
|
||||
if(100 to 250) charge_cost = 500
|
||||
if(251 to 300) charge_cost = 100
|
||||
if(301 to 400) charge_cost = 500
|
||||
if(401 to 500) charge_cost = 1000
|
||||
|
||||
if(current_temperature != temperature)
|
||||
var/difference = abs(current_temperature - temperature)
|
||||
if(difference >= 10)
|
||||
if(current_temperature < temperature)
|
||||
temperature -= 10
|
||||
else
|
||||
temperature += 10
|
||||
else
|
||||
temperature = current_temperature
|
||||
return
|
||||
temperature += 10
|
||||
else
|
||||
temperature = current_temperature
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/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
|
||||
|
||||
var/release_force = 0
|
||||
var/throw_distance = 10
|
||||
fire_sound_text = "a launcher firing"
|
||||
|
||||
//This normally uses a proc on projectiles and our ammo is not strictly speaking a projectile.
|
||||
/obj/item/weapon/gun/launcher/can_hit(var/mob/living/target as mob, var/mob/living/user as mob)
|
||||
return 1
|
||||
|
||||
//Override this to avoid a runtime with suicide handling.
|
||||
/obj/item/weapon/gun/launcher/handle_suicide(mob/living/user)
|
||||
user << "\red Shooting yourself with \a [src] is pretty tricky. You can't seem to manage it."
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/launcher/proc/update_release_force(obj/item/projectile)
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gun/launcher/process_projectile(obj/item/projectile, mob/user, atom/target, var/target_zone, var/params=null, var/pointblank=0, var/reflex=0)
|
||||
update_release_force(projectile)
|
||||
projectile.loc = get_turf(user)
|
||||
projectile.throw_at(target, throw_distance, release_force, user)
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/launcher/attack_self(mob/living/user as mob)
|
||||
return
|
||||
+50
-47
@@ -51,43 +51,39 @@
|
||||
icon_state = "crossbow"
|
||||
item_state = "crossbow-solid"
|
||||
fire_sound = 'sound/weapons/punchmiss.ogg' // TODO: Decent THWOK noise.
|
||||
ejectshell = 0 // No spent shells.
|
||||
mouthshoot = 1 // No suiciding with this weapon, causes runtimes.
|
||||
fire_sound_text = "a solid thunk"
|
||||
fire_delay = 25
|
||||
slot_flags = SLOT_BACK
|
||||
|
||||
var/obj/item/bolt
|
||||
var/tension = 0 // Current draw on the bow.
|
||||
var/max_tension = 5 // Highest possible tension.
|
||||
var/release_speed = 5 // Speed per unit of tension.
|
||||
var/obj/item/weapon/cell/cell = null // Used for firing superheated rods.
|
||||
var/current_user // Used to check if the crossbow has changed hands since being drawn.
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/emp_act(severity)
|
||||
if(cell && severity)
|
||||
cell.use(100*severity)
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/special_check(user)
|
||||
if(tension <= 0)
|
||||
user << "\red \The [src] is not drawn back!"
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/update_release_force()
|
||||
release_force = tension*release_speed
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
|
||||
/obj/item/weapon/gun/launcher/crossbow/consume_next_projectile(mob/user=null)
|
||||
if(tension <= 0)
|
||||
user << "\red \The [src] is not drawn back!"
|
||||
return null
|
||||
return bolt
|
||||
|
||||
if(!..()) return //Only do this on a successful shot.
|
||||
/obj/item/weapon/gun/launcher/crossbow/handle_post_fire(mob/user, atom/target)
|
||||
bolt = null
|
||||
icon_state = "crossbow"
|
||||
tension = 0
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/attack_self(mob/living/user as mob)
|
||||
if(tension)
|
||||
if(in_chamber && in_chamber.loc == src) //Just in case they click it the tick after firing.
|
||||
user.visible_message("[user] relaxes the tension on [src]'s string and removes [in_chamber].","You relax the tension on [src]'s string and remove [in_chamber].")
|
||||
in_chamber.loc = get_turf(src)
|
||||
var/obj/item/weapon/arrow/A = in_chamber
|
||||
in_chamber = null
|
||||
if(bolt)
|
||||
user.visible_message("[user] relaxes the tension on [src]'s string and removes [bolt].","You relax the tension on [src]'s string and remove [bolt].")
|
||||
bolt.loc = get_turf(src)
|
||||
var/obj/item/weapon/arrow/A = bolt
|
||||
bolt = null
|
||||
A.removed(user)
|
||||
else
|
||||
user.visible_message("[user] relaxes the tension on [src]'s string.","You relax the tension on [src]'s string.")
|
||||
@@ -98,7 +94,7 @@
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/proc/draw(var/mob/user as mob)
|
||||
|
||||
if(!in_chamber)
|
||||
if(!bolt)
|
||||
user << "You don't have anything nocked to [src]."
|
||||
return
|
||||
|
||||
@@ -106,50 +102,57 @@
|
||||
return
|
||||
|
||||
current_user = user
|
||||
user.visible_message("[user] begins to draw back the string of [src].","You begin to draw back the string of [src].")
|
||||
user.visible_message("[user] begins to draw back the string of [src].","<span class='notice'>You begin to draw back the string of [src].</span>")
|
||||
tension = 1
|
||||
spawn(25) increase_tension(user) //TODO: This needs to be changed to something less shit.
|
||||
|
||||
while(bolt && tension && current_user == user)
|
||||
if(!do_after(user, 25)) //crossbow strings don't just magically pull back on their own.
|
||||
user.visible_message("[usr] stops drawing and relaxes the string of [src].","<span class='warning'>You stop drawing back and relax the string of [src].</span>")
|
||||
tension = 0
|
||||
icon_state = "crossbow"
|
||||
return
|
||||
|
||||
tension++
|
||||
icon_state = "crossbow-drawn"
|
||||
|
||||
if(tension >= max_tension)
|
||||
tension = max_tension
|
||||
usr << "[src] clunks as you draw the string to its maximum tension!"
|
||||
return
|
||||
|
||||
user.visible_message("[usr] draws back the string of [src]!","<span class='notice'>You continue drawing back the string of [src]!</span>")
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/proc/increase_tension(var/mob/user as mob)
|
||||
|
||||
if(!in_chamber || !tension || current_user != user) //Arrow has been fired, bow has been relaxed or user has changed.
|
||||
if(!bolt || !tension || current_user != user) //Arrow has been fired, bow has been relaxed or user has changed.
|
||||
return
|
||||
|
||||
tension++
|
||||
icon_state = "crossbow-drawn"
|
||||
|
||||
if(tension>=max_tension)
|
||||
tension = max_tension
|
||||
usr << "[src] clunks as you draw the string to its maximum tension!"
|
||||
else
|
||||
user.visible_message("[usr] draws back the string of [src]!","You continue drawing back the string of [src]!")
|
||||
spawn(25) increase_tension(user)
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(!in_chamber)
|
||||
if(!bolt)
|
||||
if (istype(W,/obj/item/weapon/arrow))
|
||||
user.drop_item()
|
||||
in_chamber = W
|
||||
in_chamber.loc = src
|
||||
user.visible_message("[user] slides [in_chamber] into [src].","You slide [in_chamber] into [src].")
|
||||
bolt = W
|
||||
bolt.loc = src
|
||||
user.visible_message("[user] slides [bolt] into [src].","You slide [bolt] into [src].")
|
||||
icon_state = "crossbow-nocked"
|
||||
return
|
||||
else if(istype(W,/obj/item/stack/rods))
|
||||
var/obj/item/stack/rods/R = W
|
||||
if (R.use(1))
|
||||
in_chamber = new /obj/item/weapon/arrow/rod(src)
|
||||
in_chamber.fingerprintslast = src.fingerprintslast
|
||||
in_chamber.loc = src
|
||||
bolt = new /obj/item/weapon/arrow/rod(src)
|
||||
bolt.fingerprintslast = src.fingerprintslast
|
||||
bolt.loc = src
|
||||
icon_state = "crossbow-nocked"
|
||||
user.visible_message("[user] jams [in_chamber] into [src].","You jam [in_chamber] into [src].")
|
||||
user.visible_message("[user] jams [bolt] into [src].","You jam [bolt] into [src].")
|
||||
superheat_rod(user)
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/cell))
|
||||
if(!cell)
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
cell = W
|
||||
cell.loc = src
|
||||
user << "<span class='notice'>You jam [cell] into [src] and wire it to the firing coil.</span>"
|
||||
superheat_rod(user)
|
||||
else
|
||||
@@ -168,14 +171,14 @@
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/crossbow/proc/superheat_rod(var/mob/user)
|
||||
if(!user || !cell || !in_chamber) return
|
||||
if(!user || !cell || !bolt) return
|
||||
if(cell.charge < 500) return
|
||||
if(in_chamber.throwforce >= 15) return
|
||||
if(!istype(in_chamber,/obj/item/weapon/arrow/rod)) return
|
||||
if(bolt.throwforce >= 15) return
|
||||
if(!istype(bolt,/obj/item/weapon/arrow/rod)) return
|
||||
|
||||
user << "<span class='notice'>[in_chamber] plinks and crackles as it begins to glow red-hot.</span>"
|
||||
in_chamber.throwforce = 15
|
||||
in_chamber.icon_state = "metal-rod-superheated"
|
||||
user << "<span class='notice'>[bolt] plinks and crackles as it begins to glow red-hot.</span>"
|
||||
bolt.throwforce = 15
|
||||
bolt.icon_state = "metal-rod-superheated"
|
||||
cell.use(500)
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/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
|
||||
force = 10
|
||||
|
||||
fire_sound = 'sound/weapons/empty.ogg'
|
||||
fire_sound_text = "a metallic thunk"
|
||||
recoil = 0
|
||||
throw_distance = 7
|
||||
release_force = 5
|
||||
|
||||
var/obj/item/weapon/grenade/chambered
|
||||
var/list/grenades = new/list()
|
||||
var/max_grenades = 4 //holds this + one in the chamber
|
||||
matter = list("metal" = 2000)
|
||||
|
||||
//revolves the magazine, allowing players to choose between multiple grenade types
|
||||
/obj/item/weapon/gun/launcher/grenade/proc/pump(mob/M as mob)
|
||||
playsound(M, 'sound/weapons/shotgunpump.ogg', 60, 1)
|
||||
|
||||
var/obj/item/weapon/grenade/next
|
||||
if(grenades.len)
|
||||
next = grenades[1] //get this first, so that the chambered grenade can still be removed if the grenades list is empty
|
||||
if(chambered)
|
||||
grenades += chambered //rotate the revolving magazine
|
||||
chambered = null
|
||||
if(next)
|
||||
grenades -= next //Remove grenade from loaded list.
|
||||
chambered = next
|
||||
M << "<span class='warning'>You pump [src], loading \a [next] into the chamber.</span>"
|
||||
else
|
||||
M << "<span class='warning'>You pump [src], but the magazine is empty.</span>"
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/gun/launcher/grenade/examine(mob/user)
|
||||
if(..(user, 2))
|
||||
var/grenade_count = grenades.len + (chambered? 1 : 0)
|
||||
user << "Has [grenade_count] grenade\s remaining."
|
||||
if(chambered)
|
||||
user << "\A [chambered] is chambered."
|
||||
|
||||
/obj/item/weapon/gun/launcher/grenade/attack_self(mob/user)
|
||||
pump(user)
|
||||
|
||||
/obj/item/weapon/gun/launcher/grenade/attackby(obj/item/I, mob/user)
|
||||
if((istype(I, /obj/item/weapon/grenade)))
|
||||
if(grenades.len >= max_grenades)
|
||||
user << "<span class='warning'>[src] is full.</span>"
|
||||
return
|
||||
user.remove_from_mob(I)
|
||||
I.loc = src
|
||||
grenades.Insert(1, I) //add to the head of the list, so that it is loaded on the next pump
|
||||
user.visible_message("[user] inserts \a [I] into [src].", "<span class='notice'>You insert \a [I] into [src].</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/grenade/attack_hand(mob/user)
|
||||
if(user.get_inactive_hand() == src)
|
||||
if(grenades.len)
|
||||
var/obj/item/weapon/grenade/G = grenades[grenades.len]
|
||||
grenades.len--
|
||||
user.put_in_hands(G)
|
||||
user.visible_message("[user] removes \a [G] from [src].", "<span class='notice'>You remove \a [G] from [src].</span>")
|
||||
else
|
||||
user << "<span class='warning'>[src] is empty.</span>"
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/grenade/consume_next_projectile()
|
||||
if(chambered)
|
||||
chambered.det_time = 10
|
||||
chambered.activate(null)
|
||||
return chambered
|
||||
|
||||
/obj/item/weapon/gun/launcher/grenade/handle_post_fire(mob/user)
|
||||
message_admins("[key_name_admin(user)] fired a grenade ([chambered.name]) from a grenade launcher ([src.name]).")
|
||||
log_game("[key_name_admin(user)] used a grenade ([chambered.name]).")
|
||||
chambered = null
|
||||
+27
-33
@@ -4,6 +4,7 @@
|
||||
icon = 'icons/obj/gun.dmi'
|
||||
icon_state = "pneumatic"
|
||||
item_state = "pneumatic"
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = 5.0
|
||||
flags = CONDUCT
|
||||
fire_sound_text = "a loud whoosh of moving air"
|
||||
@@ -61,8 +62,7 @@
|
||||
icon_state = "pneumatic-tank"
|
||||
item_state = "pneumatic-tank"
|
||||
user.update_icons()
|
||||
else if(W.w_class <= max_w_class)
|
||||
|
||||
else if(istype(W) && W.w_class <= max_w_class)
|
||||
var/total_stored = 0
|
||||
for(var/obj/item/O in src.contents)
|
||||
total_stored += O.w_class
|
||||
@@ -79,9 +79,6 @@
|
||||
/obj/item/weapon/gun/launcher/pneumatic/attack_self(mob/user as mob)
|
||||
if(contents.len > 0)
|
||||
var/obj/item/removing = contents[contents.len]
|
||||
if(removing == in_chamber)
|
||||
in_chamber = null
|
||||
|
||||
removing.loc = get_turf(src)
|
||||
user.put_in_hands(removing)
|
||||
user << "You remove [removing] from the hopper."
|
||||
@@ -89,12 +86,19 @@
|
||||
user << "There is nothing to remove in \the [src]."
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/launcher/pneumatic/load_into_chamber()
|
||||
/obj/item/weapon/gun/launcher/pneumatic/consume_next_projectile(mob/user=null)
|
||||
if(!contents.len)
|
||||
return 0
|
||||
return null
|
||||
if (!tank)
|
||||
user << "There is no gas tank in [src]!"
|
||||
return null
|
||||
|
||||
in_chamber = contents[1]
|
||||
return !isnull(in_chamber)
|
||||
var/fire_pressure = (tank.air_contents.return_pressure()/100)*pressure_setting
|
||||
if(fire_pressure < minimum_tank_pressure)
|
||||
user << "There isn't enough gas in the tank to fire [src]."
|
||||
return null
|
||||
|
||||
return contents[1]
|
||||
|
||||
/obj/item/weapon/gun/launcher/pneumatic/examine(mob/user)
|
||||
if(!..(user, 2))
|
||||
@@ -105,31 +109,21 @@
|
||||
else
|
||||
user << "Nothing is attached to the tank valve!"
|
||||
|
||||
/obj/item/weapon/gun/launcher/pneumatic/special_check(user)
|
||||
/obj/item/weapon/gun/launcher/pneumatic/update_release_force(obj/item/projectile)
|
||||
if(tank)
|
||||
release_force = ((fire_pressure*tank.volume)/projectile.w_class)/force_divisor //projectile speed.
|
||||
if(release_force > 80) release_force = 80 //damage cap.
|
||||
else
|
||||
release_force = 0
|
||||
|
||||
if (!tank)
|
||||
user << "There is no gas tank in [src]!"
|
||||
return 0
|
||||
|
||||
fire_pressure = (tank.air_contents.return_pressure()/100)*pressure_setting
|
||||
if (fire_pressure < minimum_tank_pressure)
|
||||
user << "There isn't enough gas in the tank to fire [src]."
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/launcher/pneumatic/update_release_force()
|
||||
if(!in_chamber) return
|
||||
release_force = ((fire_pressure*tank.volume)/in_chamber.w_class)/force_divisor //projectile speed.
|
||||
if(release_force >80) release_force = 80 //damage cap.
|
||||
|
||||
/obj/item/weapon/gun/launcher/pneumatic/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
|
||||
|
||||
if(!tank || !..()) return //Only do this on a successful shot.
|
||||
|
||||
var/lost_gas_amount = tank.air_contents.total_moles*(pressure_setting/100)
|
||||
var/datum/gas_mixture/removed = tank.air_contents.remove(lost_gas_amount)
|
||||
user.loc.assume_air(removed)
|
||||
/obj/item/weapon/gun/launcher/pneumatic/handle_post_fire()
|
||||
if(tank)
|
||||
var/lost_gas_amount = tank.air_contents.total_moles*(pressure_setting/100)
|
||||
var/datum/gas_mixture/removed = tank.air_contents.remove(lost_gas_amount)
|
||||
|
||||
var/turf/T = get_turf(src.loc)
|
||||
if(T) T.assume_air(removed)
|
||||
..()
|
||||
|
||||
//Constructable pneumatic cannon.
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/obj/item/weapon/gun/launcher/rocket
|
||||
name = "rocket launcher"
|
||||
desc = "MAGGOT."
|
||||
icon_state = "rocket"
|
||||
item_state = "rocket"
|
||||
w_class = 4.0
|
||||
throw_speed = 2
|
||||
throw_range = 10
|
||||
force = 5.0
|
||||
flags = CONDUCT | USEDELAY
|
||||
slot_flags = 0
|
||||
origin_tech = "combat=8;materials=5"
|
||||
fire_sound = 'sound/effects/bang.ogg'
|
||||
|
||||
release_force = 15
|
||||
throw_distance = 30
|
||||
var/max_rockets = 1
|
||||
var/list/rockets = new/list()
|
||||
|
||||
/obj/item/weapon/gun/launcher/rocket/examine(mob/user)
|
||||
if(!..(user, 2))
|
||||
return
|
||||
user << "\blue [rockets.len] / [max_rockets] rockets."
|
||||
|
||||
/obj/item/weapon/gun/launcher/rocket/attackby(obj/item/I as obj, mob/user as mob)
|
||||
if(istype(I, /obj/item/ammo_casing/rocket))
|
||||
if(rockets.len < max_rockets)
|
||||
user.drop_item()
|
||||
I.loc = src
|
||||
rockets += I
|
||||
user << "\blue You put the rocket in [src]."
|
||||
user << "\blue [rockets.len] / [max_rockets] rockets."
|
||||
else
|
||||
usr << "\red [src] cannot hold more rockets."
|
||||
|
||||
/obj/item/weapon/gun/launcher/rocket/consume_next_projectile()
|
||||
if(rockets.len)
|
||||
var/obj/item/ammo_casing/rocket/I = rockets[1]
|
||||
var/obj/item/missile/M = new (src)
|
||||
M.primed = 1
|
||||
rockets -= I
|
||||
return M
|
||||
return null
|
||||
|
||||
/obj/item/weapon/gun/launcher/rocket/handle_post_fire(mob/user, atom/target)
|
||||
message_admins("[key_name_admin(user)] fired a rocket from a rocket launcher ([src.name]) at [target].")
|
||||
log_game("[key_name_admin(user)] used a rocket launcher ([src.name]) at [target].")
|
||||
..()
|
||||
@@ -0,0 +1,135 @@
|
||||
/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."
|
||||
icon = 'icons/obj/ammo.dmi'
|
||||
icon_state = "syringe-cartridge"
|
||||
var/icon_flight = "syringe-cartridge-flight" //so it doesn't look so weird when shot
|
||||
matter = list("metal" = 125, "glass" = 375)
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BELT
|
||||
throwforce = 3
|
||||
force = 3
|
||||
w_class = 1
|
||||
var/obj/item/weapon/reagent_containers/syringe/syringe
|
||||
|
||||
/obj/item/weapon/syringe_cartridge/update_icon()
|
||||
underlays.Cut()
|
||||
if(syringe)
|
||||
underlays += image(syringe.icon, src, syringe.icon_state)
|
||||
underlays += syringe.filling
|
||||
|
||||
/obj/item/weapon/syringe_cartridge/attackby(obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/weapon/reagent_containers/syringe))
|
||||
syringe = I
|
||||
user << "<span class='notice'>You carefully insert [syringe] into [src].</span>"
|
||||
user.remove_from_mob(syringe)
|
||||
syringe.loc = src
|
||||
sharp = 1
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/syringe_cartridge/attack_self(mob/user)
|
||||
if(syringe)
|
||||
user << "<span class='notice'>You remove [syringe] from [src].</span>"
|
||||
user.put_in_hands(syringe)
|
||||
syringe = null
|
||||
sharp = initial(sharp)
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/syringe_cartridge/proc/prime()
|
||||
//the icon state will revert back when update_icon() is called from throw_impact()
|
||||
icon_state = icon_flight
|
||||
underlays.Cut()
|
||||
|
||||
/obj/item/weapon/syringe_cartridge/throw_impact(atom/hit_atom, var/speed)
|
||||
..() //handles embedding for us. Should have a decent chance if thrown fast enough
|
||||
if(syringe)
|
||||
//check speed to see if we hit hard enough to trigger the rapid injection
|
||||
//incidentally, this means syringe_cartridges can be used with the pneumatic launcher
|
||||
if(speed >= 10 && isliving(hit_atom))
|
||||
var/mob/living/L = hit_atom
|
||||
//unfortuately we don't know where the dart will actually hit, since that's done by the parent.
|
||||
if(L.can_inject())
|
||||
if(syringe.reagents)
|
||||
syringe.reagents.trans_to(L, 15)
|
||||
|
||||
syringe.break_syringe(iscarbon(hit_atom)? hit_atom : null)
|
||||
syringe.update_icon()
|
||||
|
||||
icon_state = initial(icon_state) //reset icon state
|
||||
update_icon()
|
||||
|
||||
/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
|
||||
force = 7
|
||||
matter = list("metal" = 2000)
|
||||
slot_flags = SLOT_BELT
|
||||
|
||||
fire_sound = 'sound/weapons/empty.ogg'
|
||||
fire_sound_text = "a metallic thunk"
|
||||
recoil = 0
|
||||
release_force = 10
|
||||
throw_distance = 10
|
||||
|
||||
var/list/darts = list()
|
||||
var/max_darts = 1
|
||||
var/obj/item/weapon/syringe_cartridge/next
|
||||
|
||||
/obj/item/weapon/gun/launcher/syringe/consume_next_projectile()
|
||||
if(next)
|
||||
next.prime()
|
||||
return next
|
||||
return null
|
||||
|
||||
/obj/item/weapon/gun/launcher/syringe/handle_post_fire()
|
||||
..()
|
||||
darts -= next
|
||||
next = null
|
||||
|
||||
/obj/item/weapon/gun/launcher/syringe/attack_self(mob/living/user as mob)
|
||||
if(next)
|
||||
user.visible_message("[user] unlatches and carefully relaxes the bolt on [src].", "<span class='warning'>You unlatch and carefully relax the bolt on [src], unloading the spring.</span>")
|
||||
next = null
|
||||
else if(darts.len)
|
||||
playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1)
|
||||
user.visible_message("[user] draws back the bolt on [src], clicking it into place.", "<span class='warning'>You draw back the bolt on the [src], loading the spring!</span>")
|
||||
next = darts[1]
|
||||
add_fingerprint(user)
|
||||
|
||||
/obj/item/weapon/gun/launcher/syringe/attack_hand(mob/living/user as mob)
|
||||
if(user.get_inactive_hand() == src)
|
||||
if(!darts.len)
|
||||
user << "<span class='warning'>[src] is empty.</span>"
|
||||
return
|
||||
if(next)
|
||||
user << "<span class='warning'>[src]'s cover is locked shut.</span>"
|
||||
return
|
||||
var/obj/item/weapon/syringe_cartridge/C = darts[1]
|
||||
darts -= C
|
||||
user.put_in_hands(C)
|
||||
user.visible_message("[user] removes \a [C] from [src].", "<span class='notice'>You remove \a [C] from [src].</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/syringe/attackby(var/obj/item/A as obj, mob/user as mob)
|
||||
if(istype(A, /obj/item/weapon/syringe_cartridge))
|
||||
var/obj/item/weapon/syringe_cartridge/C = A
|
||||
if(darts.len >= max_darts)
|
||||
user << "<span class='warning'>[src] is full!</span>"
|
||||
return
|
||||
user.remove_from_mob(C)
|
||||
C.loc = src
|
||||
darts += C //add to the end
|
||||
user.visible_message("[user] inserts \a [C] into [src].", "<span class='notice'>You insert \a [C] into [src].</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/launcher/syringe/rapid
|
||||
name = "syringe gun revolver"
|
||||
desc = "A modification of the syringe gun design, using a rotating cylinder to store up to five syringes. The spring still needs to be drawn between shots."
|
||||
icon_state = "rapidsyringegun"
|
||||
max_darts = 5
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user