Merge and removal of a wild file

Merge branch 'dev' into ofChemistryAndStuff

Conflicts:
	code/modules/reagents/Chemistry-Holder.dm
This commit is contained in:
Kelenius
2015-04-29 14:20:44 +03:00
34 changed files with 788 additions and 517 deletions
+6 -6
View File
@@ -1369,8 +1369,8 @@
var/data = ""
var/obj/item/weapon/paper_bundle/B = fax
for (var/page = 1, page <= B.amount, page++)
var/obj/pageobj = B.contents[page]
for (var/page = 1, page <= B.pages.len, page++)
var/obj/pageobj = B.pages[page]
data += "<A href='?src=\ref[src];AdminFaxViewPage=[page];paper_bundle=\ref[B]'>Page [page] - [pageobj.name]</A><BR>"
usr << browse(data, "window=[B.name]")
@@ -1383,11 +1383,11 @@
if (!bundle) return
if (istype(bundle.contents[page], /obj/item/weapon/paper))
var/obj/item/weapon/paper/P = bundle.contents[page]
if (istype(bundle.pages[page], /obj/item/weapon/paper))
var/obj/item/weapon/paper/P = bundle.pages[page]
P.show_content(src.owner, 1)
else if (istype(bundle.contents[page], /obj/item/weapon/photo))
var/obj/item/weapon/photo/H = bundle.contents[page]
else if (istype(bundle.pages[page], /obj/item/weapon/photo))
var/obj/item/weapon/photo/H = bundle.pages[page]
H.show(src.owner)
return
@@ -1,133 +0,0 @@
/obj/machinery/beehive
name = "beehive"
icon = 'icons/obj/apiary_bees_etc.dmi'
icon_state = "apiary"
density = 1
anchored = 1
var/closed = 0
var/bee_count = 0 // A real hive has 20k - 80k bees... we tone it down
var/smoked = 0
var/honeycombs = 0
var/frames = 0
var/maxFrames = 5
/obj/machinery/beehive/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/crowbar))
closed = !closed
user.visible_message("<span class='notice'>[user] [closed ? "closes" : "opens"] \the [src].</span>", "<span class='notice'>You [closed ? "close" : "open"] \the [src]")
else if(istype(I, /obj/item/weapon/wrench))
anchored = !anchored
user.visible_message("<span class='notice'>[user] [closed ? "wrenches" : "unwrenches"] \the [src].</span>", "<span class='notice'>You [closed ? "wrench" : "unwrench"] \the [src]")
else if(istype(I, /obj/item/bee_smoker))
if(!closed)
user << "<span class='notice'>You need to open \the [src] with a crowbar before smoking the bees.</span>"
return
user.visible_message("<span class='notice'>[user] smokes the bees in \the [src].</span>", "<span class='notice'>You smoke the bees in \the [src].</span>")
smoked = 30
else if(istype(I, /obj/item/honey_frame))
if(closed)
user << "<span class='notice'>You need to open \the [src] with a crowbar before inserting \the [I].</span>"
return
if(frames >= maxFrames)
user << "<span class='notice'>There is no place for an another frame.</span>"
return
var/obj/item/honey_frame/H = I
if(H.honey)
user << "<span class='notice'>\The [I] is full with beeswax and honey, empty it in the extractor first.</span>"
return
++frames
user.visible_message("<span class='notice'>[user] loads \the [I] into \the [src].</span>", "<span class='notice'>You load \the [I] into \the [src].</span>")
qdel(I)
/obj/machinery/beehive/attack_hand(var/mob/user)
if(!closed)
if(honeycombs < 1)
user << "<span class='notice'>There are no filled honeycombs.</span>"
return
user.visible_message("<span class='notice'>[user] starts taking the honeycombs out of \the [src].", "<span class='notice'>You start taking the honeycombs out of \the [src]...")
while(honeycombs > 1 && do_after(user, 30))
new /obj/item/honey_frame/filled(loc)
--honeycombs
--frames
user << "<span class='notice'>You take all filled honeycombs out.</span>"
/obj/machinery/beehive/process()
if(closed && !smoked)
pollinate_flowers()
smoked = max(0, smoked - 1)
/obj/machinery/beehive/proc/pollinate_flowers()
for(var/obj/machinery/portable_atmospherics/hydroponics/H in view(7, src))
if(H.seed && !H.dead)
H.health += 0.05
honeycombs = max(honeycombs + 0.01, frames) // 100/tray amount ticks per frame, each 20 units of honey
/obj/machinery/honey_extractor
name = "honey extractor"
desc = "A machine used to turn honeycombs on the frame into honey and wax."
icon = 'icons/obj/virology.dmi'
icon_state = "centrifuge"
var/processing = 0
var/honey = 0
/obj/machinery/honey_extractor/attackby(var/obj/item/I, var/mob/user)
if(processing)
user << "<span class='notice'>\The [src] is currently spinning, wait until it's finished.</span>"
return
else if(istype(I, /obj/item/honey_frame))
var/obj/item/honey_frame/H = I
if(!H.honey)
user << "<span class='notice'>\The [H] is empty, put it into a beehive.</span>"
return
user.visible_message("<span class='notice'>[user] loads \the [H] into \the [src] and turns it on.</span>", "<span class='notice'>You load \the [H] into \the [src] and turn it on.</span>")
processing = H.honey
qdel(H)
spawn(50)
new /obj/item/honey_frame(loc)
//new /obj/item/stack/wax(loc)
honey += processing
processing = 0
else if(istype(I, /obj/item/weapon/reagent_containers/glass))
var/obj/item/weapon/reagent_containers/glass/G = I
var/transferred = min(G.reagents.maximum_volume - G.reagents.total_volume, honey)
G.reagents.add_reagent("honey", transferred)
honey -= transferred
user.visible_message("<span class='notice'>[user] collects honey from \the [src] into \the [G].</span>", "<span class='notice'>You collect [transferred] units of honey from \the [src] into the [G].</span>")
return 1
/obj/item/bee_smoker
name = "bee smoker"
desc = "A device used to calm down bees before harvesting honey."
icon = 'icons/obj/apiary_bees_etc.dmi'
icon_state = "apiary"
w_class = 2
/obj/item/honey_frame
name = "beehive frame"
desc = "A frame for the beehive that the bees will fill with honeycombs."
icon = 'icons/obj/apiary_bees_etc.dmi'
icon_state = "apiary"
w_class = 2
var/honey = 0
/obj/item/honey_frame/filled
name = "filled beehive frame"
desc = "A frame for the beehive that the bees have filled with honeycombs."
honey = 20
/obj/item/beehive_assembly
name = "beehive assembly"
desc = "Contains everything you need to build a beehive. Cannot be disassembled once deployed."
icon = 'icons/obj/apiary_bees_etc.dmi'
icon_state = "apiary"
/obj/item/beehive_assembly/attack_self(var/mob/user)
new /obj/machinery/beehive(get_turf(user))
qdel(src)
/obj/item/bee_pack
name = "bee pack"
desc = "A stasis-pack that contains a queen bee and some workers. Put it into the beehive to wake them up."
@@ -765,8 +765,8 @@ var/global/list/damage_icon_parts = list()
overlay_icon = rig.mob_icon
else if(back.sprite_sheets && back.sprite_sheets[species.name])
overlay_icon = back.sprite_sheets[species.name]
else if(back.item_icons && (slot_l_hand_str in back.item_icons))
overlay_icon = back.item_icons[slot_l_hand_str]
else if(back.item_icons && (slot_back_str in back.item_icons))
overlay_icon = back.item_icons[slot_back_str]
else
overlay_icon = INV_BACK_DEF_ICON
+4 -4
View File
@@ -90,15 +90,15 @@
/mob/living/default_can_use_topic(var/src_object)
. = shared_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE)
if(. != STATUS_CLOSE)
if(loc)
. = loc.contents_nano_distance(src_object, src)
. = min(., loc.contents_nano_distance(src_object, src))
if(STATUS_INTERACTIVE)
return STATUS_UPDATE
/mob/living/carbon/human/default_can_use_topic(var/src_object)
. = shared_nano_interaction(src_object)
if(. == STATUS_INTERACTIVE)
. = shared_living_nano_distance(src_object)
if(. != STATUS_CLOSE)
. = min(., shared_living_nano_distance(src_object))
if(. == STATUS_UPDATE && (TK in mutations)) // If we have telekinesis and remain close enough, allow interaction.
return STATUS_INTERACTIVE
+18
View File
@@ -0,0 +1,18 @@
/var/global/datum/topic_state/physical/physical_state = new()
/datum/topic_state/physical/can_use_topic(var/src_object, var/mob/user)
. = user.shared_nano_interaction(src_object)
if(. > STATUS_CLOSE)
return min(., user.check_physical_distance(src_object))
/mob/proc/check_physical_distance(var/src_object)
return STATUS_CLOSE
/mob/dead/observer/check_physical_distance(var/src_object)
return default_can_use_topic(src_object)
/mob/living/check_physical_distance(var/src_object)
return shared_living_nano_distance(src_object)
/mob/living/silicon/check_physical_distance(var/src_object)
return max(STATUS_UPDATE, shared_living_nano_distance(src_object))
+15 -3
View File
@@ -68,14 +68,14 @@
//The topmost paper. I don't think there's any way to organise contents in byond, so this is what we're stuck with. -Pete
if(toppaper)
var/obj/item/weapon/paper/P = toppaper
dat += "<A href='?src=\ref[src];write=\ref[P]'>Write</A> <A href='?src=\ref[src];remove=\ref[P]'>Remove</A> - <A href='?src=\ref[src];read=\ref[P]'>[P.name]</A><BR><HR>"
dat += "<A href='?src=\ref[src];write=\ref[P]'>Write</A> <A href='?src=\ref[src];remove=\ref[P]'>Remove</A> <A href='?src=\ref[src];rename=\ref[P]'>Rename</A> - <A href='?src=\ref[src];read=\ref[P]'>[P.name]</A><BR><HR>"
for(var/obj/item/weapon/paper/P in src)
if(P==toppaper)
continue
dat += "<A href='?src=\ref[src];remove=\ref[P]'>Remove</A> - <A href='?src=\ref[src];read=\ref[P]'>[P.name]</A><BR>"
dat += "<A href='?src=\ref[src];remove=\ref[P]'>Remove</A> <A href='?src=\ref[src];rename=\ref[P]'>Rename</A> - <A href='?src=\ref[src];read=\ref[P]'>[P.name]</A><BR>"
for(var/obj/item/weapon/photo/Ph in src)
dat += "<A href='?src=\ref[src];remove=\ref[Ph]'>Remove</A> - <A href='?src=\ref[src];look=\ref[Ph]'>[Ph.name]</A><BR>"
dat += "<A href='?src=\ref[src];remove=\ref[Ph]'>Remove</A> <A href='?src=\ref[src];rename=\ref[Ph]'>Rename</A> - <A href='?src=\ref[src];look=\ref[Ph]'>[Ph.name]</A><BR>"
user << browse(dat, "window=clipboard")
onclose(user, "clipboard")
@@ -129,6 +129,18 @@
toppaper = newtop
else
toppaper = null
else if(href_list["rename"])
var/obj/item/weapon/O = locate(href_list["rename"])
if(O && (O.loc == src))
if(istype(O, /obj/item/weapon/paper))
var/obj/item/weapon/paper/to_rename = O
to_rename.rename()
else if(istype(O, /obj/item/weapon/photo))
var/obj/item/weapon/photo/to_rename = O
to_rename.rename()
else if(href_list["read"])
var/obj/item/weapon/paper/P = locate(href_list["read"])
+1 -1
View File
@@ -189,7 +189,7 @@ var/list/adminfaxes = list() //cache for faxes that have been sent to admins
else if (istype(copyitem, /obj/item/weapon/photo))
rcvdcopy = photocopy(copyitem)
else if (istype(copyitem, /obj/item/weapon/paper_bundle))
rcvdcopy = bundlecopy(copyitem)
rcvdcopy = bundlecopy(copyitem, 0)
else
visible_message("[src] beeps, \"Error transmitting message.\"")
return
+19 -4
View File
@@ -44,11 +44,11 @@
var/dat = "<title>[name]</title>"
for(var/obj/item/weapon/paper/P in src)
dat += "<A href='?src=\ref[src];remove=\ref[P]'>Remove</A> - <A href='?src=\ref[src];read=\ref[P]'>[P.name]</A><BR>"
dat += "<A href='?src=\ref[src];remove=\ref[P]'>Remove</A> <A href='?src=\ref[src];rename=\ref[P]'>Rename</A> - <A href='?src=\ref[src];read=\ref[P]'>[P.name]</A><BR>"
for(var/obj/item/weapon/photo/Ph in src)
dat += "<A href='?src=\ref[src];remove=\ref[Ph]'>Remove</A> - <A href='?src=\ref[src];look=\ref[Ph]'>[Ph.name]</A><BR>"
dat += "<A href='?src=\ref[src];remove=\ref[Ph]'>Remove</A> <A href='?src=\ref[src];rename=\ref[Ph]'>Rename</A> - <A href='?src=\ref[src];look=\ref[Ph]'>[Ph.name]</A><BR>"
for(var/obj/item/weapon/paper_bundle/Pb in src)
dat += "<A href='?src=\ref[src];remove=\ref[Pb]'>Remove</A> - <A href='?src=\ref[src];browse=\ref[Pb]'>[Pb.name]</A><BR>"
dat += "<A href='?src=\ref[src];remove=\ref[Pb]'>Remove</A> <A href='?src=\ref[src];rename=\ref[Pb]'>Rename</A> - <A href='?src=\ref[src];browse=\ref[Pb]'>[Pb.name]</A><BR>"
user << browse(dat, "window=folder")
onclose(user, "folder")
add_fingerprint(usr)
@@ -85,7 +85,22 @@
if(P && (P.loc == src) && istype(P))
P.attack_self(usr)
onclose(usr, "[P.name]")
else if(href_list["rename"])
var/obj/item/weapon/O = locate(href_list["rename"])
if(O && (O.loc == src))
if(istype(O, /obj/item/weapon/paper))
var/obj/item/weapon/paper/to_rename = O
to_rename.rename()
else if(istype(O, /obj/item/weapon/photo))
var/obj/item/weapon/photo/to_rename = O
to_rename.rename()
else if(istype(O, /obj/item/weapon/paper_bundle))
var/obj/item/weapon/paper_bundle/to_rename = O
to_rename.rename()
//Update everything
attack_self(usr)
update_icon()
+12 -7
View File
@@ -95,12 +95,15 @@
usr << "<span class='warning'>You cut yourself on the paper.</span>"
return
var/n_name = sanitizeSafe(input(usr, "What would you like to label the paper?", "Paper Labelling", null) as text, MAX_NAME_LEN)
if((loc == usr && usr.stat == 0))
name = "[(n_name ? text("[n_name]") : initial(name))]"
if(name != "paper")
desc = "This is a paper titled '" + name + "'."
add_fingerprint(usr)
return
// We check loc one level up, so we can rename in clipboards and such. See also: /obj/item/weapon/photo/rename()
if((loc == usr || loc.loc && loc.loc == usr) && usr.stat == 0 && n_name)
name = n_name
if(n_name != "paper")
desc = "This is a paper titled '" + name + "'."
add_fingerprint(usr)
return
/obj/item/weapon/paper/attack_self(mob/living/user as mob)
user.examinate(src)
@@ -447,7 +450,9 @@
user << "<span class='notice'>You clip the [P.name] to [(src.name == "paper") ? "the paper" : src.name].</span>"
src.loc = B
P.loc = B
B.amount++
B.pages.Add(src)
B.pages.Add(P)
B.update_icon()
else if(istype(P, /obj/item/weapon/pen) || istype(P, /obj/item/toy/crayon))
+76 -79
View File
@@ -11,50 +11,35 @@
layer = 4
pressure_resistance = 1
attack_verb = list("bapped")
var/amount = 0 //Amount of items clipped to the paper
var/page = 1
var/screen = 0
var/page = 1 // current page
var/list/pages = list() // Ordered list of pages as they are to be displayed. Can be different order than src.contents.
/obj/item/weapon/paper_bundle/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
var/obj/item/weapon/paper/P
if(istype(W, /obj/item/weapon/paper))
P = W
if (istype(P, /obj/item/weapon/paper/carbon))
var/obj/item/weapon/paper/carbon/C = P
if (!C.iscopy && !C.copied)
user << "<span class='notice'>Take off the carbon copy first.</span>"
add_fingerprint(user)
return
amount++
if(screen == 2)
screen = 1
user << "<span class='notice'>You add [(P.name == "paper") ? "the paper" : P.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].</span>"
user.drop_from_inventory(P)
P.loc = src
if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user
H.update_inv_l_hand()
H.update_inv_r_hand()
else if(istype(W, /obj/item/weapon/photo))
amount++
if(screen == 2)
screen = 1
user << "<span class='notice'>You add [(W.name == "photo") ? "the photo" : W.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].</span>"
user.drop_from_inventory(W)
W.loc = src
if (istype(W, /obj/item/weapon/paper/carbon))
var/obj/item/weapon/paper/carbon/C = W
if (!C.iscopy && !C.copied)
user << "<span class='notice'>Take off the carbon copy first.</span>"
add_fingerprint(user)
return
// adding sheets
if(istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/weapon/photo))
insert_sheet_at(user, pages.len+1, W)
// burning
else if(istype(W, /obj/item/weapon/flame))
burnpaper(W, user)
// merging bundles
else if(istype(W, /obj/item/weapon/paper_bundle))
user.drop_from_inventory(W)
for(var/obj/O in W)
O.loc = src
O.add_fingerprint(usr)
src.amount++
if(screen == 2)
screen = 1
pages.Add(O)
user << "<span class='notice'>You add \the [W.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].</span>"
qdel(W)
else
@@ -62,15 +47,27 @@
return 0
if(istype(W, /obj/item/weapon/pen) || istype(W, /obj/item/toy/crayon))
usr << browse("", "window=[name]") //Closes the dialog
P = src[page]
var/obj/P = pages[page]
P.attackby(W, user)
update_icon()
attack_self(usr) //Update the browsed page.
add_fingerprint(usr)
return
/obj/item/weapon/paper_bundle/proc/insert_sheet_at(mob/user, var/index, obj/item/weapon/sheet)
if(istype(sheet, /obj/item/weapon/paper))
user << "<span class='notice'>You add [(sheet.name == "paper") ? "the paper" : sheet.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].</span>"
else if(istype(sheet, /obj/item/weapon/photo))
user << "<span class='notice'>You add [(sheet.name == "photo") ? "the photo" : sheet.name] to [(src.name == "paper bundle") ? "the paper bundle" : src.name].</span>"
user.drop_from_inventory(sheet)
sheet.loc = src
pages.Insert(index, sheet)
if(index <= page)
page++
/obj/item/weapon/paper_bundle/proc/burnpaper(obj/item/weapon/flame/P, mob/user)
var/class = "<span class='warning'>"
@@ -105,28 +102,32 @@
/obj/item/weapon/paper_bundle/proc/show_content(mob/user as mob)
var/dat
var/obj/item/weapon/W = src[page]
switch(screen)
if(0)
dat+= "<DIV STYLE='float:left; text-align:left; width:33.33333%'></DIV>"
dat+= "<DIV STYLE='float:left; text-align:center; width:33.33333%'><A href='?src=\ref[src];remove=1'>Remove [(istype(W, /obj/item/weapon/paper)) ? "paper" : "photo"]</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:right; width:33.33333%'><A href='?src=\ref[src];next_page=1'>Next Page</A></DIV><BR><HR>"
if(1)
dat+= "<DIV STYLE='float:left; text-align:left; width:33.33333%'><A href='?src=\ref[src];prev_page=1'>Previous Page</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:center; width:33.33333%'><A href='?src=\ref[src];remove=1'>Remove [(istype(W, /obj/item/weapon/paper)) ? "paper" : "photo"]</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:right; width:33.33333%'><A href='?src=\ref[src];next_page=1'>Next Page</A></DIV><BR><HR>"
if(2)
dat+= "<DIV STYLE='float:left; text-align:left; width:33.33333%'><A href='?src=\ref[src];prev_page=1'>Previous Page</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:center; width:33.33333%'><A href='?src=\ref[src];remove=1'>Remove [(istype(W, /obj/item/weapon/paper)) ? "paper" : "photo"]</A></DIV><BR><HR>"
dat+= "<DIV STYLE='float;left; text-align:right; with:33.33333%'></DIV>"
if(istype(src[page], /obj/item/weapon/paper))
var/obj/item/weapon/W = pages[page]
// first
if(page == 1)
dat+= "<DIV STYLE='float:left; text-align:left; width:33.33333%'><A href='?src=\ref[src];prev_page=1'>Front</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:center; width:33.33333%'><A href='?src=\ref[src];remove=1'>Remove [(istype(W, /obj/item/weapon/paper)) ? "paper" : "photo"]</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:right; width:33.33333%'><A href='?src=\ref[src];next_page=1'>Next Page</A></DIV><BR><HR>"
// last
else if(page == pages.len)
dat+= "<DIV STYLE='float:left; text-align:left; width:33.33333%'><A href='?src=\ref[src];prev_page=1'>Previous Page</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:center; width:33.33333%'><A href='?src=\ref[src];remove=1'>Remove [(istype(W, /obj/item/weapon/paper)) ? "paper" : "photo"]</A></DIV>"
dat+= "<DIV STYLE='float;left; text-align:right; with:33.33333%'><A href='?src=\ref[src];next_page=1'>Back</A></DIV><BR><HR>"
// middle pages
else
dat+= "<DIV STYLE='float:left; text-align:left; width:33.33333%'><A href='?src=\ref[src];prev_page=1'>Previous Page</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:center; width:33.33333%'><A href='?src=\ref[src];remove=1'>Remove [(istype(W, /obj/item/weapon/paper)) ? "paper" : "photo"]</A></DIV>"
dat+= "<DIV STYLE='float:left; text-align:right; width:33.33333%'><A href='?src=\ref[src];next_page=1'>Next Page</A></DIV><BR><HR>"
if(istype(pages[page], /obj/item/weapon/paper))
var/obj/item/weapon/paper/P = W
if(!(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/dead/observer) || istype(usr, /mob/living/silicon)))
dat+= "<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[stars(P.info)][P.stamps]</BODY></HTML>"
else
dat+= "<HTML><HEAD><TITLE>[P.name]</TITLE></HEAD><BODY>[P.info][P.stamps]</BODY></HTML>"
user << browse(dat, "window=[name]")
else if(istype(src[page], /obj/item/weapon/photo))
else if(istype(pages[page], /obj/item/weapon/photo))
var/obj/item/weapon/photo/P = W
user << browse_rsc(P.img, "tmp_photo.png")
user << browse(dat + "<html><head><title>[P.name]</title></head>" \
@@ -145,55 +146,51 @@
..()
if((src in usr.contents) || (istype(src.loc, /obj/item/weapon/folder) && (src.loc in usr.contents)))
usr.set_machine(src)
var/obj/item/weapon/in_hand = usr.get_active_hand()
if(href_list["next_page"])
if(page == amount)
screen = 2
else if(page == 1)
screen = 1
else if(page == amount+1)
return
page++
playsound(src.loc, "pageturn", 50, 1)
if(in_hand && (istype(in_hand, /obj/item/weapon/paper) || istype(in_hand, /obj/item/weapon/photo)))
insert_sheet_at(usr, page+1, in_hand)
else if(page != pages.len)
page++
playsound(src.loc, "pageturn", 50, 1)
if(href_list["prev_page"])
if(page == 1)
return
else if(page == 2)
screen = 0
else if(page == amount+1)
screen = 1
page--
playsound(src.loc, "pageturn", 50, 1)
if(in_hand && (istype(in_hand, /obj/item/weapon/paper) || istype(in_hand, /obj/item/weapon/photo)))
insert_sheet_at(usr, page, in_hand)
else if(page > 1)
page--
playsound(src.loc, "pageturn", 50, 1)
if(href_list["remove"])
var/obj/item/weapon/W = src[page]
var/obj/item/weapon/W = pages[page]
usr.put_in_hands(W)
pages.Remove(pages[page])
usr << "<span class='notice'>You remove the [W.name] from the bundle.</span>"
if(amount == 1)
if(pages.len <= 1)
var/obj/item/weapon/paper/P = src[1]
usr.drop_from_inventory(src)
usr.put_in_hands(P)
qdel(src)
else if(page == amount)
screen = 2
else if(page == amount+1)
page--
amount--
return
if(page > pages.len)
page = pages.len
update_icon()
else
usr << "<span class='notice'>You need to hold it in hands!</span>"
if (istype(src.loc, /mob) ||istype(src.loc.loc, /mob))
src.attack_self(src.loc)
src.attack_self(usr)
updateUsrDialog()
/obj/item/weapon/paper_bundle/verb/rename()
set name = "Rename bundle"
set category = "Object"
set src in usr
var/n_name = sanitizeSafe(input(usr, "What would you like to label the bundle?", "Bundle Labelling", null) as text, MAX_NAME_LEN)
if((loc == usr && usr.stat == 0))
if((loc == usr || loc.loc && loc.loc == usr) && usr.stat == 0)
name = "[(n_name ? text("[n_name]") : "paper")]"
add_fingerprint(usr)
return
@@ -215,7 +212,7 @@
/obj/item/weapon/paper_bundle/update_icon()
var/obj/item/weapon/paper/P = src[1]
var/obj/item/weapon/paper/P = pages[1]
icon_state = P.icon_state
overlays = P.overlays
underlays = 0
+4 -4
View File
@@ -56,7 +56,7 @@
sleep(15)
else if (istype(copyitem, /obj/item/weapon/paper_bundle))
var/obj/item/weapon/paper_bundle/B = bundlecopy(copyitem)
sleep(15*B.amount)
sleep(15*B.pages.len)
else
usr << "<span class='warning'>\The [copyitem] can't be copied by \the [src].</span>"
break
@@ -216,7 +216,7 @@
//If need_toner is 0, the copies will still be lightened when low on toner, however it will not be prevented from printing. TODO: Implement print queues for fax machines and get rid of need_toner
/obj/machinery/photocopier/proc/bundlecopy(var/obj/item/weapon/paper_bundle/bundle, var/need_toner=1)
var/obj/item/weapon/paper_bundle/p = new /obj/item/weapon/paper_bundle (src)
for(var/obj/item/weapon/W in bundle)
for(var/obj/item/weapon/W in bundle.pages)
if(toner <= 0 && need_toner)
toner = 0
visible_message("<span class='notice'>A red light on \the [src] flashes, indicating that it is out of toner.</span>")
@@ -227,8 +227,8 @@
else if(istype(W, /obj/item/weapon/photo))
W = photocopy(W)
W.loc = p
p.amount++
//p.amount--
p.pages += W
p.loc = src.loc
p.update_icon()
p.icon_state = "paper_words"
+150 -49
View File
@@ -1,3 +1,33 @@
/*
Defines a firing mode for a gun.
burst number of shots fired when the gun is used
burst_delay tick delay between shots in a burst
fire_delay tick delay after the last shot before the gun may be used again
move_delay tick delay after the last shot before the player may move
dispersion dispersion of each shot in the burst measured in tiles per 7 tiles angle ratio
accuracy accuracy modifier applied to each shot in tiles.
applied on top of the base weapon accuracy.
*/
/datum/firemode
var/name = "default"
var/burst = 1
var/burst_delay = null
var/fire_delay = null
var/move_delay = 1
var/list/accuracy = list(0)
var/list/dispersion = list(0)
//using a list makes defining fire modes for new guns much nicer,
//however we convert the lists to datums in part so that firemodes can be VVed if necessary.
/datum/firemode/New(list/properties = null)
..()
if(!properties) return
for(var/propname in vars)
if(!isnull(properties[propname]))
src.vars[propname] = properties[propname]
//Parent gun type. Guns are weapons that can be aimed at mobs and act over a distance
/obj/item/weapon/gun
name = "gun"
@@ -21,15 +51,20 @@
attack_verb = list("struck", "hit", "bashed")
zoomdevicename = "scope"
var/fire_delay = 6
var/fire_delay = 6 //delay after shooting before the gun can be used again
var/burst_delay = 2 //delay between shots, if firing in bursts
var/fire_sound = 'sound/weapons/Gunshot.ogg'
var/fire_sound_text = "gunshot"
var/recoil = 0 //screen shake
var/silenced = 0
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/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
var/next_fire_time = 0
var/sel_mode = 1 //index of the currently selected mode
var/list/firemodes = list()
var/firemode_type = /datum/firemode //for subtypes that need custom firemode data
//aiming system stuff
var/keep_aim = 1 //1 for keep shooting until aim is lowered
@@ -42,17 +77,15 @@
/obj/item/weapon/gun/New()
..()
if(!firemodes.len)
firemodes += new firemode_type
else
for(var/i in 1 to firemodes.len)
firemodes[i] = new firemode_type(firemodes[i])
if(isnull(scoped_accuracy))
scoped_accuracy = accuracy
//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
//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.
@@ -114,7 +147,7 @@
else
return ..() //Pistolwhippin'
/obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, params, pointblank=0, reflex=0)
/obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, clickparams, pointblank=0, reflex=0)
if(!user || !target) return
add_fingerprint(user)
@@ -122,24 +155,55 @@
if(!special_check(user))
return
if (!ready_to_fire())
if(world.time < next_fire_time)
if (world.time % 3) //to prevent spam
user << "<span class='warning'>[src] is not ready to fire again!"
return
//unpack firemode data
var/datum/firemode/firemode = firemodes[sel_mode]
var/_burst = firemode.burst
var/_burst_delay = isnull(firemode.burst_delay)? src.burst_delay : firemode.burst_delay
var/_fire_delay = isnull(firemode.fire_delay)? src.fire_delay : firemode.fire_delay
var/_move_delay = firemode.move_delay
var/obj/projectile = consume_next_projectile(user)
if(!projectile)
handle_click_empty(user)
return
var/shoot_time = (_burst - 1)*_burst_delay
user.next_move = world.time + shoot_time //no clicking on things while shooting
if(user.client) user.client.move_delay = world.time + shoot_time //no moving while shooting either
next_fire_time = world.time + shoot_time
//actually attempt to shoot
var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed.
for(var/i in 1 to _burst)
var/obj/projectile = consume_next_projectile(user)
if(!projectile)
handle_click_empty(user)
break
var/acc = firemode.accuracy[min(i, firemode.accuracy.len)]
var/disp = firemode.dispersion[min(i, firemode.dispersion.len)]
process_accuracy(projectile, user, target, acc, disp)
if(pointblank)
process_point_blank(projectile, user, target)
if(process_projectile(projectile, user, target, user.zone_sel.selecting, clickparams))
handle_post_fire(user, target, pointblank, reflex)
update_icon()
if(i < _burst)
sleep(_burst_delay)
if(!target)
target = targloc
pointblank = 0
update_held_icon()
//update timing
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()
update_held_icon()
if(user.client) user.client.move_delay = world.time + _move_delay
next_fire_time = world.time + _fire_delay
//obtains the next projectile to fire
/obj/item/weapon/gun/proc/consume_next_projectile()
@@ -186,12 +250,52 @@
shake_camera(user, recoil+1, recoil)
update_icon()
//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))
/obj/item/weapon/gun/proc/process_point_blank(obj/projectile, mob/user, atom/target)
var/obj/item/projectile/P = projectile
if(!istype(P))
return //default behaviour only applies to true projectiles
//default point blank multiplier
var/damage_mult = 1.3
//determine multiplier due to the target being grabbed
if(ismob(target))
var/mob/M = target
if(M.grabbed_by.len)
var/grabstate = 0
for(var/obj/item/weapon/grab/G in M.grabbed_by)
grabstate = max(grabstate, G.state)
if(grabstate >= GRAB_NECK)
damage_mult = 3.0
else if(grabstate >= GRAB_AGGRESSIVE)
damage_mult = 1.5
P.damage *= damage_mult
/obj/item/weapon/gun/proc/process_accuracy(obj/projectile, mob/user, atom/target, acc_mod, dispersion)
var/obj/item/projectile/P = projectile
if(!istype(P))
return //default behaviour only applies to true projectiles
//Accuracy modifiers
P.accuracy = accuracy + acc_mod
P.dispersion = dispersion
//accuracy bonus from aiming
if (aim_targets && (target in aim_targets))
//If you aim at someone beforehead, it'll hit more often.
//Kinda balanced by fact you need like 2 seconds to aim
//As opposed to no-delay pew pew
P.accuracy += 2
//does the actual launching of the projectile
/obj/item/weapon/gun/proc/process_projectile(obj/projectile, mob/user, atom/target, var/target_zone, var/params=null)
var/obj/item/projectile/P = projectile
if(!istype(P))
return 0 //default behaviour only applies to true projectiles
var/obj/item/projectile/P = projectile
if(params)
P.set_clickpoint(params)
//shooting while in shock
var/x_offset = 0
@@ -205,27 +309,6 @@
y_offset = rand(-1,1)
x_offset = rand(-1,1)
//Point blank bonus
if(pointblank)
var/damage_mult = 1.3 //default point blank multiplier
//determine multiplier due to the target being grabbed
if(ismob(target))
var/mob/M = target
if(M.grabbed_by.len)
var/grabstate = 0
for(var/obj/item/weapon/grab/G in M.grabbed_by)
grabstate = max(grabstate, G.state)
if(grabstate >= GRAB_NECK)
damage_mult = 3.0
else if (grabstate >= GRAB_AGGRESSIVE)
damage_mult = 1.5
P.damage *= damage_mult
if(params)
P.set_clickpoint(params)
return !P.launch(target, user, src, target_zone, x_offset, y_offset)
//Suicide handling.
@@ -287,3 +370,21 @@
if(!zoom)
accuracy = initial(accuracy)
recoil = initial(recoil)
/obj/item/weapon/gun/examine(mob/user)
..()
if(firemodes.len > 1)
var/datum/firemode/current_mode = firemodes[sel_mode]
user << "The fire selector is set to [current_mode.name]."
/obj/item/weapon/gun/proc/switch_firemodes(mob/user=null)
sel_mode++
if(sel_mode > firemodes.len)
sel_mode = 1
var/datum/firemode/new_mode = firemodes[sel_mode]
user << "<span class='notice'>\The [src] is now set to [new_mode.name].</span>"
/obj/item/weapon/gun/attack_self(mob/user)
if(firemodes.len > 1)
switch_firemodes(user)
+19
View File
@@ -1,9 +1,16 @@
/datum/firemode/energy
var/projectile_type = null
var/modifystate = null
var/charge_cost = null
var/fire_sound = null
/obj/item/weapon/gun/energy
name = "energy gun"
desc = "A basic energy-based gun."
icon_state = "energy"
fire_sound = 'sound/weapons/Taser.ogg'
fire_sound_text = "laser blast"
firemode_type = /datum/firemode/energy
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
var/charge_cost = 100 //How much energy is needed to fire.
@@ -18,6 +25,18 @@
var/recharge_time = 4
var/charge_tick = 0
/obj/item/weapon/gun/energy/switch_firemodes(mob/user=null)
..()
var/datum/firemode/energy/current_mode = firemodes[sel_mode]
if(istype(current_mode))
projectile_type = isnull(current_mode.projectile_type)? initial(projectile_type) : current_mode.projectile_type
modifystate = isnull(current_mode.modifystate)? initial(modifystate) : current_mode.modifystate
charge_cost = isnull(current_mode.charge_cost)? initial(charge_cost) : current_mode.charge_cost
fire_sound = isnull(current_mode.fire_sound)? initial(fire_sound) : current_mode.fire_sound
update_icon()
update_held_icon()
/obj/item/weapon/gun/energy/emp_act(severity)
..()
update_icon()
+16 -25
View File
@@ -10,26 +10,10 @@
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()
update_held_icon()
firemodes = list(
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, modifystate="energystun", fire_sound='sound/weapons/Taser.ogg'),
list(name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="energykill", fire_sound='sound/weapons/Laser.ogg'),
)
/obj/item/weapon/gun/energy/gun/mounted
name = "mounted energy gun"
@@ -43,7 +27,14 @@
origin_tech = "combat=3;materials=5;powerstorage=3"
slot_flags = SLOT_BELT
force = 8 //looks heavier than a pistol
self_recharge = 1
self_recharge = 1
modifystate = null
firemodes = list(
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg'),
list(name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg'),
)
var/lightfail = 0
//override for failcheck behaviour
@@ -101,10 +92,10 @@
overlays += "nucgun-clean"
/obj/item/weapon/gun/energy/gun/nuclear/proc/update_mode()
if (mode == 0)
overlays += "nucgun-stun"
else if (mode == 1)
overlays += "nucgun-kill"
var/datum/firemode/current_mode = firemodes[sel_mode]
switch(current_mode.name)
if("stun") overlays += "nucgun-stun"
if("lethal") overlays += "nucgun-kill"
/obj/item/weapon/gun/energy/gun/nuclear/emp_act(severity)
..()
+16 -33
View File
@@ -5,33 +5,16 @@
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
var/mode = 2
fire_delay = 25
/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
fire_sound='sound/weapons/Laser.ogg'
charge_cost = 50
projectile_type = /obj/item/projectile/beam
sel_mode = 2
firemodes = list(
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg'),
list(name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg'),
list(name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/pulse.ogg', fire_delay=25, charge_cost=100),
)
/obj/item/weapon/gun/energy/pulse_rifle/mounted
self_recharge = 1
@@ -40,12 +23,13 @@
/obj/item/weapon/gun/energy/pulse_rifle/destroyer
name = "pulse destroyer"
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
cell_type = /obj/item/weapon/cell/super
fire_delay = 25
fire_sound='sound/weapons/pulse.ogg'
projectile_type=/obj/item/projectile/beam/pulse
/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>"
user << "<span class='warning'>[src.name] has three settings, and they are all DESTROY.</span>"
//WHY?
/obj/item/weapon/gun/energy/pulse_rifle/M1911
@@ -53,5 +37,4 @@
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
fire_delay = 10
cell_type = /obj/item/weapon/cell/crap
@@ -43,24 +43,11 @@
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()
update_held_icon()
firemodes = list(
list(name="induce mutations", projectile_type=/obj/item/projectile/energy/floramut, modifystate="floramut"),
list(name="increase yield", projectile_type=/obj/item/projectile/energy/florayield, modifystate="florayield"),
)
/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, adjacent_flag)
//allow shooting into adjacent hydrotrays regardless of intent
@@ -26,6 +26,3 @@
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
+17 -2
View File
@@ -165,7 +165,10 @@
load_ammo(A, user)
/obj/item/weapon/gun/projectile/attack_self(mob/user as mob)
unload_ammo(user)
if(firemodes.len > 1)
switch_firemodes(user)
else
unload_ammo(user)
/obj/item/weapon/gun/projectile/attack_hand(mob/user as mob)
if(user.get_inactive_hand() == src)
@@ -189,9 +192,9 @@
/obj/item/weapon/gun/projectile/examine(mob/user)
..(user)
user << "Has [getAmmo()] round\s remaining."
if(ammo_magazine)
user << "It has \a [ammo_magazine] loaded."
user << "Has [getAmmo()] round\s remaining."
return
/obj/item/weapon/gun/projectile/proc/getAmmo()
@@ -203,3 +206,15 @@
if(chambered)
bullets += 1
return bullets
/* Unneeded -- so far.
//in case the weapon has firemodes and can't unload using attack_hand()
/obj/item/weapon/gun/projectile/verb/unload_gun()
set name = "Unload Ammo"
set category = "Object"
set src in usr
if(usr.stat || usr.restrained()) return
unload_ammo(usr)
*/
@@ -10,7 +10,12 @@
slot_flags = SLOT_BELT
ammo_type = /obj/item/ammo_casing/c9mm
multi_aim = 1
fire_delay = 0
firemodes = list(
list(name="semiauto", burst=1, fire_delay=0),
list(name="3-round bursts", burst=3, move_delay=4, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 1.0)),
list(name="short bursts", burst=5, move_delay=4, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
)
/obj/item/weapon/gun/projectile/automatic/mini_uzi
name = "\improper Uzi"
@@ -59,6 +64,12 @@
slot_flags = SLOT_BACK
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/c762
firemodes = list(
list(name="semiauto", burst=1, fire_delay=0),
list(name="3-round bursts", burst=3, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 0.6)),
list(name="short bursts", burst=5, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
)
/obj/item/weapon/gun/projectile/automatic/sts35/update_icon()
..()
@@ -87,6 +98,9 @@
icon_state = "wt550"
return
/datum/firemode/z8
var/use_launcher = 0
/obj/item/weapon/gun/projectile/automatic/z8
name = "\improper Z8 Bulldog"
desc = "An older model bullpup carbine, made by the now defunct Zendai Foundries. Uses armor piercing 5.56mm rounds. Makes you feel like a space marine when you hold it."
@@ -104,17 +118,20 @@
auto_eject = 1
auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg'
var/use_launcher = 0
burst_delay = 4
firemode_type = /datum/firemode/z8
firemodes = list(
list(name="semiauto", burst=1, fire_delay=0),
list(name="3-round bursts", burst=3, move_delay=6, accuracy = list(0,-1,-1), dispersion = list(0.0, 0.6, 0.6)),
list(name="fire grenades", use_launcher=1)
)
var/obj/item/weapon/gun/launcher/grenade/underslung/launcher
/obj/item/weapon/gun/projectile/automatic/z8/New()
..()
launcher = new(src)
/obj/item/weapon/gun/projectile/automatic/z8/attack_self(mob/user)
use_launcher = !use_launcher
user << "<span class='notice'>You switch to [use_launcher? "\the [launcher]" : "firing normally"].</span>"
/obj/item/weapon/gun/projectile/automatic/z8/attackby(obj/item/I, mob/user)
if((istype(I, /obj/item/weapon/grenade)))
launcher.load(I, user)
@@ -122,16 +139,18 @@
..()
/obj/item/weapon/gun/projectile/automatic/z8/attack_hand(mob/user)
if(user.get_inactive_hand() == src && use_launcher)
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
if(user.get_inactive_hand() == src && current_mode.use_launcher)
launcher.unload(user)
else
..()
/obj/item/weapon/gun/projectile/automatic/z8/Fire(atom/target, mob/living/user, params, pointblank=0, reflex=0)
if(use_launcher)
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
if(current_mode.use_launcher)
launcher.Fire(target, user, params, pointblank, reflex)
if(!launcher.chambered)
use_launcher = 0 //switch back automatically
switch_firemodes() //switch back automatically
else
..()
@@ -166,22 +185,40 @@
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/a762
firemodes = list(
list(name="short bursts", burst=5, move_delay=6, accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
list(name="long bursts", burst=8, move_delay=8, accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(1.0, 1.0, 1.0, 1.0, 1.2)),
)
var/cover_open = 0
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob)
cover_open = !cover_open
user << "<span class='notice'>You [cover_open ? "open" : "close"] [src]'s cover.</span>"
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(ammo_magazine.stored_ammo.len, 25) : "-empty"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/special_check(mob/user)
if(cover_open)
user << "<span class='warning'>[src]'s cover is open! Close it before firing!</span>"
return 0
return ..()
/obj/item/weapon/gun/projectile/automatic/l6_saw/proc/toggle_cover(mob/user)
cover_open = !cover_open
user << "<span class='notice'>You [cover_open ? "open" : "close"] [src]'s cover.</span>"
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob)
if(cover_open)
toggle_cover(user) //close the cover
else
return ..() //once closed, behave like normal
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_hand(mob/user as mob)
if(!cover_open && user.get_inactive_hand() == src)
toggle_cover(user) //open the cover
else
return ..() //once open, behave like normal
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(ammo_magazine.stored_ammo.len, 25) : "-empty"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/load_ammo(var/obj/item/A, mob/user)
if(!cover_open)
user << "<span class='warning'>You need to open the cover to load [src].</span>"
@@ -190,5 +227,6 @@
/obj/item/weapon/gun/projectile/automatic/l6_saw/unload_ammo(mob/user, var/allow_dump=1)
if(!cover_open)
user << "<span class='warning'>You need to open the cover to unload [src].</span>"
return
..()
@@ -65,12 +65,24 @@
caliber = "shotgun"
origin_tech = "combat=3;materials=1"
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
burst_delay = 0
firemodes = list(
list(name="fire one barrel at a time", burst=1),
list(name="fire both barrels at once", burst=2),
)
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet
ammo_type = /obj/item/ammo_casing/shotgun/pellet
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/flare
name = "signal shotgun"
desc = "A double-barreled shotgun meant to fire signal flash shells."
ammo_type = /obj/item/ammo_casing/shotgun/flash
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/unload_ammo(user, allow_dump)
..(user, allow_dump=1)
//this is largely hacky and bad :( -Pete
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter))
+19 -13
View File
@@ -33,6 +33,9 @@
var/p_x = 16
var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center
var/accuracy = 0
var/dispersion = 0.0
var/damage = 10
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
@@ -100,6 +103,12 @@
p_x = text2num(mouse_control["icon-x"])
if(mouse_control["icon-y"])
p_y = text2num(mouse_control["icon-y"])
//randomize clickpoint a bit based on dispersion
if(dispersion)
var/radius = round((dispersion*0.443)*world.icon_size*0.8) //0.443 = sqrt(pi)/4 = 2a, where a is the side length of a square that shares the same area as a circle with diameter = dispersion
p_x = between(0, p_x + rand(-radius, radius), world.icon_size)
p_y = between(0, p_y + rand(-radius, radius), world.icon_size)
//called to launch a projectile from a gun
/obj/item/projectile/proc/launch(atom/target, mob/user, obj/item/weapon/gun/launcher, var/target_zone, var/x_offset=0, var/y_offset=0)
@@ -147,24 +156,15 @@
yo = new_y - starting_loc.y
xo = new_x - starting_loc.x
setup_trajectory()
//Called when the projectile intercepts a mob. Returns 1 if the projectile hit the mob, 0 if it missed and should keep flying.
/obj/item/projectile/proc/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier=0)
if(!istype(target_mob))
return
//accuracy bonus from aiming
if (istype(shot_from, /obj/item/weapon/gun))
var/obj/item/weapon/gun/daddy = shot_from
miss_modifier -= round(15*daddy.accuracy)
//If you aim at someone beforehead, it'll hit more often.
//Kinda balanced by fact you need like 2 seconds to aim
//As opposed to no-delay pew pew
if (daddy.aim_targets && original in daddy.aim_targets)
miss_modifier += -30
//roll to-hit
miss_modifier = max(miss_modifier + 15*(distance-2), 0)
miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier, 0)
var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1))
if(!hit_zone)
visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
@@ -316,10 +316,16 @@
/obj/item/projectile/proc/before_move()
/obj/item/projectile/proc/setup_trajectory()
// trajectory dispersion
var/offset = 0
if(dispersion)
var/radius = round(dispersion*9, 1)
offset = rand(-radius, radius)
// plot the initial trajectory
trajectory = new()
trajectory.setup(starting, original, pixel_x, pixel_y)
trajectory.setup(starting, original, pixel_x, pixel_y, angle_offset=offset)
// generate this now since all visual effects the projectile makes can use it
effect_transform = new()
effect_transform.Scale(trajectory.return_hypotenuse(), 1)
@@ -148,6 +148,7 @@
stun = 3
weaken = 3
penetrating = 5
hitscan = 1 //so the PTR isn't useless as a sniper weapon
/obj/item/projectile/bullet/rifle/a556
damage = 40
-4
View File
@@ -16,10 +16,6 @@
stop_aim()
usr.visible_message("<span class='notice'> \The [usr] lowers \the [src]...</span>")
//Clicking gun will still lower aim for guns that don't overwrite this
/obj/item/weapon/gun/attack_self()
lower_aim()
//Removing the lock and the buttons.
/obj/item/weapon/gun/dropped(mob/user as mob)
stop_aim()
+6 -6
View File
@@ -6,14 +6,14 @@
var/reacting = 0 // Reacting right now
/datum/reagents/New(var/max = 100)
maximum_volume = max
maximum_volume = max
//I dislike having these here but map-objects are initialised before world/New() is called. >_>
if(!chemical_reagents_list)
//Chemical Reagents - Initialises all /datum/reagent into a list indexed by reagent id
var/paths = typesof(/datum/reagent) - /datum/reagent
chemical_reagents_list = list()
for(var/path in paths)
var/datum/reagent/D = new path()
var/datum/reagent/D = new path()
if(!D.name)
continue
chemical_reagents_list[D.id] = D
@@ -40,7 +40,7 @@
for(var/id in reaction_ids)
if(!chemical_reactions_list[id])
chemical_reactions_list[id] = list()
chemical_reactions_list[id] += D
chemical_reactions_list[id] += D
break // Don't bother adding ourselves to other reagent ids, it is redundant.
/datum/reagents/Destroy()
@@ -254,10 +254,10 @@
amount = min(amount, total_volume)
if(!amount)
return
return
var/part = amount / total_volume
for(var/datum/reagent/current in reagent_list)
var/amount_to_remove = current.volume * part
remove_reagent(current.id, amount_to_remove, 1)
@@ -432,4 +432,4 @@
/atom/proc/create_reagents(var/max_vol)
reagents = new/datum/reagents(max_vol)
reagents.my_atom = src
reagents.my_atom = src