Second commits.

This contains the changes to item_attack.dm
Obj/attackby() now follows a similar structure as mob/living/attackby. It calls attack_obj() (like attack() but for obj) which calls attacked_by (just like attack() does)
The use of the NOBLUDGEON flag changes a bit, it is now used to signify the item cannot be used as a melee weapon at all. No attack animation, no attack message. I've given this bitflag to many items that have an afterattack() so as to not both attack and do the special action (among those items: the rcd)

There's also the code changes to attacking machines: attacking any machine now give a proper message and a sound. And with this, I made more machines breakable (using a health var and the very little used BROKEN stat). Most notably, tables can now be attacked when on harm intent and be destroyed.

The newly destroyable machines have a take_damage() proc used by all sorts of attack (weapon, xeno, animal, hulk, mech melee, gun projectile, thrown items).

There's some more stuff in there, see the PR's description and comments.
This commit is contained in:
phil235
2016-04-24 20:37:00 +02:00
parent 0caa59b21a
commit b146131a34
54 changed files with 1480 additions and 1410 deletions
+48 -64
View File
@@ -74,71 +74,55 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis).
/obj/machinery/r_n_d/circuit_imprinter/proc/TotalMaterials()
return g_amount + gold_amount + diamond_amount
/obj/machinery/r_n_d/circuit_imprinter/attackby(obj/item/O, mob/user, params)
if (shocked)
shock(user,50)
if (default_deconstruction_screwdriver(user, "circuit_imprinter_t", "circuit_imprinter", O))
if(linked_console)
linked_console.linked_imprinter = null
linked_console = null
return
//we drop the minerals in the machine onto the ground when deconstructed.
/obj/machinery/r_n_d/circuit_imprinter/deconstruction()
for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
if(g_amount >= MINERAL_MATERIAL_AMOUNT)
var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc)
G.amount = round(g_amount / MINERAL_MATERIAL_AMOUNT)
if(gold_amount >= MINERAL_MATERIAL_AMOUNT)
var/obj/item/stack/sheet/mineral/gold/G = new /obj/item/stack/sheet/mineral/gold(src.loc)
G.amount = round(gold_amount / MINERAL_MATERIAL_AMOUNT)
if(diamond_amount >= MINERAL_MATERIAL_AMOUNT)
var/obj/item/stack/sheet/mineral/diamond/G = new /obj/item/stack/sheet/mineral/diamond(src.loc)
G.amount = round(diamond_amount / MINERAL_MATERIAL_AMOUNT)
..()
if(exchange_parts(user, O))
return
/obj/machinery/r_n_d/circuit_imprinter/Insert_Item(obj/item/O, mob/user)
if (panel_open)
if(istype(O, /obj/item/weapon/crowbar))
for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
if(g_amount >= MINERAL_MATERIAL_AMOUNT)
var/obj/item/stack/sheet/glass/G = new /obj/item/stack/sheet/glass(src.loc)
G.amount = round(g_amount / MINERAL_MATERIAL_AMOUNT)
if(gold_amount >= MINERAL_MATERIAL_AMOUNT)
var/obj/item/stack/sheet/mineral/gold/G = new /obj/item/stack/sheet/mineral/gold(src.loc)
G.amount = round(gold_amount / MINERAL_MATERIAL_AMOUNT)
if(diamond_amount >= MINERAL_MATERIAL_AMOUNT)
var/obj/item/stack/sheet/mineral/diamond/G = new /obj/item/stack/sheet/mineral/diamond(src.loc)
G.amount = round(diamond_amount / MINERAL_MATERIAL_AMOUNT)
default_deconstruction_crowbar(O)
return
else
user << "<span class='warning'>You can't load the [src.name] while it's opened!</span>"
return
if (disabled)
return
if (!linked_console)
user << "<span class='warning'>The [name] must be linked to an R&D console first!</span>"
if (O.is_open_container()) //inserting reagents into the machine
return 1
if (O.is_open_container())
return
if (!istype(O, /obj/item/stack/sheet/glass) && !istype(O, /obj/item/stack/sheet/mineral/gold) && !istype(O, /obj/item/stack/sheet/mineral/diamond))
if (istype(O, /obj/item/stack/sheet/glass) || istype(O, /obj/item/stack/sheet/mineral/gold) || istype(O, /obj/item/stack/sheet/mineral/diamond))
. = 1
if(!is_insertion_ready(user))
return
var/obj/item/stack/sheet/stack = O
if ((TotalMaterials() + stack.perunit) > max_material_amount)
user << "<span class='warning'>The [name] is full! Please remove glass from the protolathe in order to insert more.</span>"
return
var/amount = round(input("How many sheets do you want to add?") as num)
if(amount <= 0 || stack.amount <= 0)
return
if(amount > stack.amount)
amount = min(stack.amount, round((max_material_amount-TotalMaterials())/stack.perunit))
busy = 1
use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount/10)))
user << "<span class='notice'>You add [amount] sheets to the [src.name].</span>"
if(istype(stack, /obj/item/stack/sheet/glass))
g_amount += amount * MINERAL_MATERIAL_AMOUNT
else if(istype(stack, /obj/item/stack/sheet/mineral/gold))
gold_amount += amount * MINERAL_MATERIAL_AMOUNT
else if(istype(stack, /obj/item/stack/sheet/mineral/diamond))
diamond_amount += amount * MINERAL_MATERIAL_AMOUNT
stack.use(amount)
busy = 0
src.updateUsrDialog()
else if(user.a_intent != "harm")
user << "<span class='warning'>You cannot insert this item into the [name]!</span>"
return
if (stat)
return
if (busy)
user << "<span class='warning'>The [name] is busy! Please wait for completion of previous operation.</span>"
return
var/obj/item/stack/sheet/stack = O
if ((TotalMaterials() + stack.perunit) > max_material_amount)
user << "<span class='warning'>The [name] is full! Please remove glass from the protolathe in order to insert more.</span>"
return
var/amount = round(input("How many sheets do you want to add?") as num)
if(amount <= 0 || stack.amount <= 0)
return
if(amount > stack.amount)
amount = min(stack.amount, round((max_material_amount-TotalMaterials())/stack.perunit))
busy = 1
use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount/10)))
user << "<span class='notice'>You add [amount] sheets to the [src.name].</span>"
if(istype(stack, /obj/item/stack/sheet/glass))
g_amount += amount * MINERAL_MATERIAL_AMOUNT
else if(istype(stack, /obj/item/stack/sheet/mineral/gold))
gold_amount += amount * MINERAL_MATERIAL_AMOUNT
else if(istype(stack, /obj/item/stack/sheet/mineral/diamond))
diamond_amount += amount * MINERAL_MATERIAL_AMOUNT
stack.use(amount)
busy = 0
src.updateUsrDialog()
else
return 0
+6 -29
View File
@@ -11,7 +11,6 @@ Note: Must be placed within 3 tiles of the R&D Console
name = "Destructive Analyzer"
desc = "Learn science by destroying things!"
icon_state = "d_analyzer"
var/obj/item/weapon/loaded_item = null
var/decon_mod = 0
/obj/machinery/r_n_d/destructive_analyzer/New()
@@ -36,30 +35,11 @@ Note: Must be placed within 3 tiles of the R&D Console
temp_list[O] = text2num(temp_list[O])
return temp_list
/obj/machinery/r_n_d/destructive_analyzer/attackby(obj/item/O, mob/user, params)
if (shocked)
shock(user,50)
if (default_deconstruction_screwdriver(user, "d_analyzer_t", "d_analyzer", O))
if(linked_console)
linked_console.linked_destroy = null
linked_console = null
return
if(exchange_parts(user, O))
return
default_deconstruction_crowbar(O)
if (disabled)
return
if (!linked_console)
user << "<span class='warning'>The [src.name] must be linked to an R&D console first!</span>"
return
if (busy)
user << "<span class='warning'>The [src.name] is busy right now.</span>"
return
if (istype(O, /obj/item) && !loaded_item)
/obj/machinery/r_n_d/destructive_analyzer/Insert_Item(obj/item/O, mob/user)
if(user.a_intent != "harm")
. = 1
if(!is_insertion_ready(user))
return
if(!O.origin_tech)
user << "<span class='warning'>This doesn't seem to have a tech origin!</span>"
return
@@ -75,7 +55,4 @@ Note: Must be placed within 3 tiles of the R&D Console
O.loc = src
user << "<span class='notice'>You add the [O.name] to the [src.name]!</span>"
flick("d_analyzer_la", src)
spawn(10)
icon_state = "d_analyzer_l"
busy = 0
return
+10 -33
View File
@@ -25,7 +25,6 @@
var/recentlyExperimented = 0
var/mob/trackedIan
var/mob/trackedRuntime
var/obj/item/loaded_item = null
var/badThingCoeff = 0
var/resetTime = 15
var/cloneMode = FALSE
@@ -111,36 +110,14 @@
return FALSE
return TRUE
/obj/machinery/r_n_d/experimentor/attackby(obj/item/O, mob/user, params)
if (shocked)
shock(user,50)
if (default_deconstruction_screwdriver(user, "h_lathe_maint", "h_lathe", O))
if(linked_console)
linked_console.linked_destroy = null
linked_console = null
return
if(exchange_parts(user, O))
return
if(panel_open && istype(O, /obj/item/weapon/crowbar))
default_deconstruction_crowbar(O)
return
if(!checkCircumstances(O))
user << "<span class='warning'>The [O] is not yet valid for the [src] and must be completed!</span>"
return
if (disabled)
return
if (!linked_console)
user << "<span class='warning'>The [src] must be linked to an R&D console first!</span>"
return
if (loaded_item)
user << "<span class='warning'>The [src] is already loaded.</span>"
return
if (istype(O, /obj/item))
/obj/machinery/r_n_d/experimentor/Insert_Item(obj/item/O, mob/user)
if(user.a_intent != "harm")
. = 1
if(!is_insertion_ready(user))
return
if(!checkCircumstances(O))
user << "<span class='warning'>The [O] is not yet valid for the [src] and must be completed!</span>"
return
if(!O.origin_tech)
user << "<span class='warning'>This doesn't seem to have a tech origin!</span>"
return
@@ -158,7 +135,7 @@
user << "<span class='notice'>You add the [O.name] to the machine.</span>"
flick("h_lathe_load", src)
return
/obj/machinery/r_n_d/experimentor/default_deconstruction_crowbar(obj/item/O)
ejectItem()
@@ -640,7 +617,7 @@
spawn(cooldownMax)
cooldown = FALSE
else
user << "<span class='notice'>You aren't quite sure what to do with this yet.</span>"
user << "<span class='notice'>You aren't quite sure what to do with this, yet.</span>"
//////////////// RELIC PROCS /////////////////////////////
+36 -52
View File
@@ -72,61 +72,45 @@ Note: Must be placed west/left of and R&D console to function.
A = A / max(1, (being_built.materials[M]))
return A
/obj/machinery/r_n_d/protolathe/attackby(obj/item/O, mob/user, params)
if (shocked)
shock(user,50)
if (default_deconstruction_screwdriver(user, "protolathe_t", "protolathe", O))
if(linked_console)
linked_console.linked_lathe = null
linked_console = null
return
//we eject the materials upon deconstruction.
/obj/machinery/r_n_d/protolathe/deconstruction()
for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
materials.retrieve_all()
..()
if(exchange_parts(user, O))
return
/obj/machinery/r_n_d/protolathe/Insert_Item(obj/item/O, mob/user)
if (panel_open)
if(istype(O, /obj/item/weapon/crowbar))
for(var/obj/item/weapon/reagent_containers/glass/G in component_parts)
reagents.trans_to(G, G.reagents.maximum_volume)
materials.retrieve_all()
default_deconstruction_crowbar(O)
if(O.is_open_container()) //inserting reagents into the machine
return 1
if(istype(O,/obj/item/stack/sheet))
. = 1
if(!is_insertion_ready(user))
return
if(!materials.has_space( materials.get_item_material_amount(O) ))
user << "<span class='warning'>The [src.name]'s material bin is full! Please remove material before adding more.</span>"
return 1
var/obj/item/stack/sheet/stack = O
var/amount = round(input("How many sheets do you want to add?") as num)//No decimals
if(!in_range(src, stack) || !user.Adjacent(src))
return
var/amount_inserted = materials.insert_stack(O,amount)
if(!amount_inserted)
return 1
else
user << "<span class='warning'>You can't load the [src.name] while it's opened!</span>"
return 1
if (disabled)
return
if (!linked_console)
user << "<span class='warning'>The [src.name] must be linked to an R&D console first!</span>"
return 1
if (busy)
user << "<span class='warning'>The [src.name] is busy! Please wait for completion of previous operation.</span>"
return 1
if (O.is_open_container())
return
if (stat)
return 1
if(!istype(O,/obj/item/stack/sheet))
return 1
var/stack_name = stack.name
busy = 1
use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount_inserted/10)))
user << "<span class='notice'>You add [amount_inserted] sheets to the [src.name].</span>"
overlays += "protolathe_[stack_name]"
sleep(10)
overlays -= "protolathe_[stack_name]"
busy = 0
updateUsrDialog()
if(!materials.has_space( materials.get_item_material_amount(O) ))
user << "<span class='warning'>The [src.name]'s material bin is full! Please remove material before adding more.</span>"
return 1
var/obj/item/stack/sheet/stack = O
var/amount = round(input("How many sheets do you want to add?") as num)//No decimals
if(!in_range(src, stack) || !user.Adjacent(src))
return
var/amount_inserted = materials.insert_stack(O,amount)
if(!amount_inserted)
return 1
else if(user.a_intent != "harm")
user << "<span class='warning'>You cannot insert this item into the [name]!</span>"
else
var/stack_name = stack.name
busy = 1
use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount_inserted/10)))
user << "<span class='notice'>You add [amount_inserted] sheets to the [src.name].</span>"
overlays += "protolathe_[stack_name]"
sleep(10)
overlays -= "protolathe_[stack_name]"
busy = 0
updateUsrDialog()
return 0
+55 -1
View File
@@ -14,6 +14,7 @@
var/disabled = 0
var/shocked = 0
var/obj/machinery/computer/rdconsole/linked_console
var/obj/item/loaded_item = null //the item loaded inside the machine (currently only used by experimentor and destructive analyzer)
/obj/machinery/r_n_d/New()
..()
@@ -39,9 +40,62 @@
/obj/machinery/r_n_d/attack_hand(mob/user)
if(shocked)
shock(user,50)
if(shock(user,50))
return
if(panel_open)
wires.interact(user)
/obj/machinery/r_n_d/attackby(obj/item/O, mob/user, params)
if (shocked)
if(shock(user,50))
return 1
if (default_deconstruction_screwdriver(user, "[initial(icon_state)]_t", initial(icon_state), O))
if(linked_console)
linked_console.linked_lathe = null
linked_console = null
return
if(exchange_parts(user, O))
return
if(default_deconstruction_crowbar(O))
return
if(Insert_Item(O, user))
return 1
else
return ..()
//proc used to handle inserting items or reagents into r_n_d machines
/obj/machinery/r_n_d/proc/Insert_Item(obj/item/I, mob/user)
return
//whether the machine can have an item inserted in its current state.
/obj/machinery/r_n_d/proc/is_insertion_ready(mob/user)
if(panel_open)
user << "<span class='warning'>You can't load the [src.name] while it's opened!</span>"
return
if (disabled)
return
if (!linked_console)
user << "<span class='warning'>The [name] must be linked to an R&D console first!</span>"
return
if (busy)
user << "<span class='warning'>The [src.name] is busy right now.</span>"
return
if(stat & BROKEN)
user << "<span class='warning'>The [src.name] is broken.</span>"
return
if(stat & NOPOWER)
user << "<span class='warning'>The [src.name] has no power.</span>"
return
if(loaded_item)
user << "<span class='warning'>The [src] is already loaded.</span>"
return
return 1
//we eject the loaded item when deconstructing the machine
/obj/machinery/r_n_d/deconstruction()
if(loaded_item)
loaded_item.loc = loc
..()
+5 -16
View File
@@ -124,20 +124,10 @@
env.merge(removed)
air_update_turf()
/obj/machinery/r_n_d/server/attackby(obj/item/O, mob/user, params)
if (disabled)
return
if (shocked)
shock(user,50)
if (default_deconstruction_screwdriver(user, "server_o", "server", O))
return
if(exchange_parts(user, O))
return
if (panel_open)
if(istype(O, /obj/item/weapon/crowbar))
griefProtection()
default_deconstruction_crowbar(O)
return 1
//called when the server is deconstructed.
/obj/machinery/r_n_d/server/deconstruction()
griefProtection()
..()
/obj/machinery/r_n_d/server/attack_hand(mob/user as mob) // I guess only exists to stop ninjas or hell does it even work I dunno. See also ninja gloves.
if (disabled)
@@ -323,9 +313,8 @@
return
/obj/machinery/computer/rdservercontrol/attackby(obj/item/weapon/D, mob/user, params)
..()
. = ..()
src.updateUsrDialog()
return
/obj/machinery/computer/rdservercontrol/emag_act(mob/user)
if(!emagged)