diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 586b2622593..bf5d6352087 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -154,7 +154,6 @@ /mob/proc/DblClickOn(var/atom/A, var/params) ClickOn(A,params) - /* Translates into attack_hand, etc. @@ -168,6 +167,22 @@ /mob/proc/UnarmedAttack(var/atom/A, var/proximity_flag) return +/mob/living/UnarmedAttack(var/atom/A, var/proximity_flag) + + if(!ticker) + src << "You cannot attack people before the game has started." + return 0 + + if (istype(get_area(src), /area/start)) + src << "No attacking people at spawn, you jackass." + return 0 + + if(stat) + return + + if(!proximity_flag) + return 0 + /* Ranged unarmed attack: diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 2d3f3c45dac..5f4d9fc8dfc 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -1,3 +1,6 @@ +// Generic damage proc (slimes and monkeys). +/atom/proc/attack_generic(mob/user as mob) + return /* Humans: Adds an exception for gloves, to allow special glove types like the ninja ones. @@ -5,12 +8,15 @@ Otherwise pretty standard. */ /mob/living/carbon/human/UnarmedAttack(var/atom/A, var/proximity) - var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines + + if(!..()) + return // Special glove functions: // If the gloves do anything, have them return 1 to stop // normal attack_hand() here. - if(proximity && istype(G) && G.Touch(A,1)) + var/obj/item/clothing/gloves/G = gloves // not typecast specifically enough in defines + if(istype(G) && G.Touch(A,1)) return A.attack_hand(src) @@ -42,12 +48,6 @@ return A.attack_tk(src) -/* - Animals & All Unspecified -*/ -/mob/living/UnarmedAttack(var/atom/A) - return - /mob/living/RestrainedClickOn(var/atom/A) return @@ -58,7 +58,13 @@ //TODO: Disease spreading and unarmed damage against mobs. /mob/living/carbon/monkey/UnarmedAttack(var/atom/A, var/proximity) - if(!proximity) + + if(!..()) + return + + if(a_intent == "harm") + A.attack_generic(src,rand(1,3),"bites") + else A.attack_hand(src) /* @@ -104,6 +110,52 @@ /mob/living/carbon/slime/RestrainedClickOn(var/atom/A) return +/mob/living/carbon/slime/UnarmedAttack(var/atom/A, var/proximity) + + if(!..()) + return + + // Eating + if(Victim) + return + + // Basic attack. + A.attack_generic(src, (is_adult ? rand(20,40) : rand(5,25)), "glomps") + + // Handle mob shocks. + var/mob/living/M = A + if(istype(M) && powerlevel > 0 && !istype(A,/mob/living/carbon/slime)) + + if(ishuman(M)) + var/mob/living/carbon/human/H = M + if(H.species.flags & IS_SYNTHETIC || H.species.insulated) + return + + var/power = max(0,min(10,(powerlevel+rand(0,3)))) + + var/stunprob = 10 + switch(power*10) + if(1 to 2) stunprob = 20 + if(3 to 4) stunprob = 30 + if(5 to 6) stunprob = 40 + if(7 to 8) stunprob = 60 + if(9) stunprob = 70 + if(10) stunprob = 95 + + if(prob(stunprob)) + powerlevel = max(0,powerlevel-3) + src.visible_message("\red The [name] has shocked [M]!") + M.Weaken(power) + M.Stun(power) + if (M.stuttering < power) M.stuttering = power + + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, M) + s.start() + + if(prob(stunprob) && powerlevel >= 8) + M.adjustFireLoss(powerlevel * rand(6,10)) + M.updatehealth() /* New Players: Have no reason to click on anything at all. diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 07936e26858..48f2dcab17c 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -338,6 +338,18 @@ spawn(13) del(src) +/obj/machinery/turret/attack_generic(var/mob/user, var/damage, var/attack_message) + if(!damage) + return + if(stat & BROKEN) + user << "That object is useless to you." + return + visible_message("[user] [attack_message] the [src]!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + src.health -= damage + if (src.health <= 0) + src.die() + /obj/structure/turret/gun_turret name = "Gun Turret" density = 1 diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index c8b22dda280..e45fa114e80 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1703,6 +1703,27 @@ icon_state = initial(icon_state) return icon_state +/obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message) + + if(!damage) + return + + src.log_message("Attack by an animal. Attacker - [user].",1) + + if(!prob(src.deflect_chance)) + src.take_damage(damage) + src.check_for_internal_damage(list(MECHA_INT_TEMP_CONTROL,MECHA_INT_TANK_BREACH,MECHA_INT_CONTROL_LOST)) + visible_message("\red [user] [attack_message] [src]!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + else + src.log_append_to_last("Armor saved.") + playsound(src.loc, 'sound/weapons/slash.ogg', 50, 1, -1) + src.occupant_message("\blue The [user]'s attack is stopped by the armor.") + visible_message("\blue The [user] rebounds off [src.name]'s armor!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + return + + ////////////////////////////////////////// //////// Mecha global iterators //////// ////////////////////////////////////////// diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm index 3fedae810b1..b6e9406b51d 100644 --- a/code/game/objects/structures.dm +++ b/code/game/objects/structures.dm @@ -1,5 +1,6 @@ /obj/structure icon = 'icons/obj/structures.dmi' + var/climbable var/breakable var/parts @@ -14,13 +15,12 @@ if(breakable) if(HULK in user.mutations) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) - visible_message("[user] smashes the [src] apart!") - destroy() + attack_generic(user,1,"smashes") else if(istype(user,/mob/living/carbon/human)) var/mob/living/carbon/human/H = user if(H.species.can_shred(user)) - visible_message("[H] slices [src] apart!") - destroy() + attack_generic(user,1,"slices") + return /obj/structure/blob_act() if(prob(50)) @@ -166,4 +166,10 @@ if (issilicon(user)) user << "You need hands for this." return 0 - return 1 \ No newline at end of file + return 1 + +/obj/structure/attack_generic(var/mob/user, var/damage, var/attack_verb, var/wallbreaker) + if(!breakable || !damage || !wallbreaker) + return + visible_message("[user] [attack_verb] the [src] apart!") + destroy() \ No newline at end of file diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 6be83616f6b..33ad8abc15d 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -297,4 +297,11 @@ for (var/atom/A in src) if(istype(A,/obj/)) var/obj/O = A - O.hear_talk(M, text) \ No newline at end of file + O.hear_talk(M, text) + +/obj/structure/closet/attack_generic(var/mob/user, var/damage, var/attack_message = "destroys", var/wallbreaker) + if(!damage || !wallbreaker) + return + visible_message("[user] [attack_message] the [src]!") + dump_contents() + del(src) \ No newline at end of file diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index b8d811efb62..d6628f0023e 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -6,193 +6,198 @@ var/state = 0 var/health = 200 +/obj/structure/girder/attack_generic(var/mob/user, var/damage, var/attack_message = "smashes apart", var/wallbreaker) + if(!damage || !wallbreaker) + return + visible_message("[user] [attack_message] the [src]!") + dismantle() - bullet_act(var/obj/item/projectile/Proj) - if(istype(Proj, /obj/item/projectile/beam)) - health -= Proj.damage - ..() - if(health <= 0) - new /obj/item/stack/sheet/metal(get_turf(src)) - del(src) +/obj/structure/girder/bullet_act(var/obj/item/projectile/Proj) + if(istype(Proj, /obj/item/projectile/beam)) + health -= Proj.damage + ..() + if(health <= 0) + new /obj/item/stack/sheet/metal(get_turf(src)) + del(src) - return + return - attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/wrench) && state == 0) - if(anchored && !istype(src,/obj/structure/girder/displaced)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "\blue Now disassembling the girder" - if(do_after(user,40)) - if(!src) return - user << "\blue You dissasembled the girder!" - dismantle() - else if(!anchored) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "\blue Now securing the girder" - if(get_turf(user, 40)) - user << "\blue You secured the girder!" - new/obj/structure/girder( src.loc ) - del(src) - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - user << "\blue Now slicing apart the girder" - if(do_after(user,30)) +/obj/structure/girder/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/wrench) && state == 0) + if(anchored && !istype(src,/obj/structure/girder/displaced)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "\blue Now disassembling the girder" + if(do_after(user,40)) if(!src) return - user << "\blue You slice apart the girder!" + user << "\blue You dissasembled the girder!" dismantle() - - else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill)) - user << "\blue You drill through the girder!" - dismantle() - - else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 && istype(src,/obj/structure/girder/reinforced)) - playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) - user << "\blue Now unsecuring support struts" - if(do_after(user,40)) - if(!src) return - user << "\blue You unsecured the support struts!" - state = 1 - - else if(istype(W, /obj/item/weapon/wirecutters) && istype(src,/obj/structure/girder/reinforced) && state == 1) - playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) - user << "\blue Now removing support struts" - if(do_after(user,40)) - if(!src) return - user << "\blue You removed the support struts!" + else if(!anchored) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "\blue Now securing the girder" + if(get_turf(user, 40)) + user << "\blue You secured the girder!" new/obj/structure/girder( src.loc ) del(src) - else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored ) - playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) - user << "\blue Now dislodging the girder" - if(do_after(user, 40)) - if(!src) return - user << "\blue You dislodged the girder!" - new/obj/structure/girder/displaced( src.loc ) - del(src) + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + user << "\blue Now slicing apart the girder" + if(do_after(user,30)) + if(!src) return + user << "\blue You slice apart the girder!" + dismantle() - else if(istype(W, /obj/item/stack/sheet)) + else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill)) + user << "\blue You drill through the girder!" + dismantle() - var/obj/item/stack/sheet/S = W - switch(S.type) + else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 && istype(src,/obj/structure/girder/reinforced)) + playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1) + user << "\blue Now unsecuring support struts" + if(do_after(user,40)) + if(!src) return + user << "\blue You unsecured the support struts!" + state = 1 - if(/obj/item/stack/sheet/metal, /obj/item/stack/sheet/metal/cyborg) - if(!anchored) - if(S.use(2)) - user << "You create a false wall! Push on it to open or close the passage." - new /obj/structure/falsewall (src.loc) + else if(istype(W, /obj/item/weapon/wirecutters) && istype(src,/obj/structure/girder/reinforced) && state == 1) + playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) + user << "\blue Now removing support struts" + if(do_after(user,40)) + if(!src) return + user << "\blue You removed the support struts!" + new/obj/structure/girder( src.loc ) + del(src) + + else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored ) + playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1) + user << "\blue Now dislodging the girder" + if(do_after(user, 40)) + if(!src) return + user << "\blue You dislodged the girder!" + new/obj/structure/girder/displaced( src.loc ) + del(src) + + else if(istype(W, /obj/item/stack/sheet)) + + var/obj/item/stack/sheet/S = W + switch(S.type) + + if(/obj/item/stack/sheet/metal, /obj/item/stack/sheet/metal/cyborg) + if(!anchored) + if(S.use(2)) + user << "You create a false wall! Push on it to open or close the passage." + new /obj/structure/falsewall (src.loc) + del(src) + else + if(S.get_amount() < 2) return ..() + user << "Now adding plating..." + if (do_after(user,40)) + if (S.use(2)) + user << "You added the plating!" + var/turf/Tsrc = get_turf(src) + Tsrc.ChangeTurf(/turf/simulated/wall) + for(var/turf/simulated/wall/X in Tsrc.loc) + if(X) X.add_hiddenprint(usr) del(src) - else - if(S.get_amount() < 2) return ..() - user << "Now adding plating..." - if (do_after(user,40)) - if (S.use(2)) - user << "You added the plating!" + return + + if(/obj/item/stack/sheet/plasteel) + if(!anchored) + if(S.use(2)) + user << "\blue You create a false wall! Push on it to open or close the passage." + new /obj/structure/falserwall (src.loc) + del(src) + else + if (src.icon_state == "reinforced") //I cant believe someone would actually write this line of code... + if(S.get_amount() < 1) return ..() + user << "Now finalising reinforced wall." + if(do_after(user, 50)) + if (S.use(1)) + user << "Wall fully reinforced!" var/turf/Tsrc = get_turf(src) - Tsrc.ChangeTurf(/turf/simulated/wall) - for(var/turf/simulated/wall/X in Tsrc.loc) + Tsrc.ChangeTurf(/turf/simulated/wall/r_wall) + for(var/turf/simulated/wall/r_wall/X in Tsrc.loc) if(X) X.add_hiddenprint(usr) del(src) return - - if(/obj/item/stack/sheet/plasteel) - if(!anchored) - if(S.use(2)) - user << "\blue You create a false wall! Push on it to open or close the passage." - new /obj/structure/falserwall (src.loc) - del(src) else - if (src.icon_state == "reinforced") //I cant believe someone would actually write this line of code... - if(S.get_amount() < 1) return ..() - user << "Now finalising reinforced wall." - if(do_after(user, 50)) - if (S.use(1)) - user << "Wall fully reinforced!" - var/turf/Tsrc = get_turf(src) - Tsrc.ChangeTurf(/turf/simulated/wall/r_wall) - for(var/turf/simulated/wall/r_wall/X in Tsrc.loc) - if(X) X.add_hiddenprint(usr) - del(src) - return - else - if(S.get_amount() < 1) return ..() - user << "Now reinforcing girders..." - if (do_after(user,60)) - if(S.use(1)) - user << "Girders reinforced!" - new/obj/structure/girder/reinforced( src.loc ) - del(src) - return + if(S.get_amount() < 1) return ..() + user << "Now reinforcing girders..." + if (do_after(user,60)) + if(S.use(1)) + user << "Girders reinforced!" + new/obj/structure/girder/reinforced( src.loc ) + del(src) + return - if(S.sheettype) - var/M = S.sheettype - if(!anchored) - if(S.amount < 2) return + if(S.sheettype) + var/M = S.sheettype + if(!anchored) + if(S.amount < 2) return + S.use(2) + user << "\blue You create a false wall! Push on it to open or close the passage." + var/F = text2path("/obj/structure/falsewall/[M]") + new F (src.loc) + del(src) + else + if(S.amount < 2) return ..() + user << "\blue Now adding plating..." + if (do_after(user,40)) + if(!src || !S || S.amount < 2) return S.use(2) - user << "\blue You create a false wall! Push on it to open or close the passage." - var/F = text2path("/obj/structure/falsewall/[M]") - new F (src.loc) + user << "\blue You added the plating!" + var/turf/Tsrc = get_turf(src) + Tsrc.ChangeTurf(text2path("/turf/simulated/wall/mineral/[M]")) + for(var/turf/simulated/wall/mineral/X in Tsrc.loc) + if(X) X.add_hiddenprint(usr) del(src) - else - if(S.amount < 2) return ..() - user << "\blue Now adding plating..." - if (do_after(user,40)) - if(!src || !S || S.amount < 2) return - S.use(2) - user << "\blue You added the plating!" - var/turf/Tsrc = get_turf(src) - Tsrc.ChangeTurf(text2path("/turf/simulated/wall/mineral/[M]")) - for(var/turf/simulated/wall/mineral/X in Tsrc.loc) - if(X) X.add_hiddenprint(usr) - del(src) - return + return - add_hiddenprint(usr) + add_hiddenprint(usr) - else if(istype(W, /obj/item/pipe)) - var/obj/item/pipe/P = W - if (P.pipe_type in list(0, 1, 5)) //simple pipes, simple bends, and simple manifolds. - user.drop_item() - P.loc = src.loc - user << "\blue You fit the pipe into the [src]!" - else - ..() + else if(istype(W, /obj/item/pipe)) + var/obj/item/pipe/P = W + if (P.pipe_type in list(0, 1, 5)) //simple pipes, simple bends, and simple manifolds. + user.drop_item() + P.loc = src.loc + user << "\blue You fit the pipe into the [src]!" + else + ..() - proc/dismantle() - new /obj/item/stack/sheet/metal(get_turf(src)) +/obj/structure/girder/proc/dismantle() + new /obj/item/stack/sheet/metal(get_turf(src)) + del(src) + +/obj/structure/girder/attack_hand(mob/user as mob) + if (HULK in user.mutations) + visible_message("[user] smashes [src] apart!") + dismantle() + return + return ..() + +/obj/structure/girder/blob_act() + if(prob(40)) del(src) - attack_hand(mob/user as mob) - if (HULK in user.mutations) - visible_message("[user] smashes [src] apart!") - dismantle() - return - return ..() - blob_act() - if(prob(40)) +/obj/structure/girder/ex_act(severity) + switch(severity) + if(1.0) del(src) - - - ex_act(severity) - switch(severity) - if(1.0) + return + if(2.0) + if (prob(30)) + var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) + new remains(loc) del(src) - return - if(2.0) - if (prob(30)) - var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) - new remains(loc) - del(src) - return - if(3.0) - if (prob(5)) - var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) - new remains(loc) - del(src) - return - else - return + return + if(3.0) + if (prob(5)) + var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal) + new remains(loc) + del(src) + return + else + return /obj/structure/girder/displaced icon_state = "displaced" @@ -212,54 +217,54 @@ layer = 2 var/health = 250 - attackby(obj/item/W as obj, mob/user as mob) - if(istype(W, /obj/item/weapon/wrench)) - playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) - user << "\blue Now disassembling the girder" - if(do_after(user,40)) - user << "\blue You dissasembled the girder!" - new /obj/effect/decal/remains/human(get_turf(src)) - del(src) - - else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) - user << "\blue Now slicing apart the girder" - if(do_after(user,30)) - user << "\blue You slice apart the girder!" +/obj/structure/cultgirder/attackby(obj/item/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/wrench)) + playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1) + user << "\blue Now disassembling the girder" + if(do_after(user,40)) + user << "\blue You dissasembled the girder!" new /obj/effect/decal/remains/human(get_turf(src)) del(src) - else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill)) - user << "\blue You drill through the girder!" - new /obj/effect/decal/remains/human(get_turf(src)) + else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter)) + user << "\blue Now slicing apart the girder" + if(do_after(user,30)) + user << "\blue You slice apart the girder!" + new /obj/effect/decal/remains/human(get_turf(src)) + del(src) + + else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill)) + user << "\blue You drill through the girder!" + new /obj/effect/decal/remains/human(get_turf(src)) + del(src) + +/obj/structure/cultgirder/blob_act() + if(prob(40)) + del(src) + +/obj/structure/cultgirder/bullet_act(var/obj/item/projectile/Proj) //No beam check- How else will you destroy the cult girder with silver bullets????? + health -= Proj.damage + ..() + if(health <= 0) + new /obj/item/stack/sheet/metal(get_turf(src)) + del(src) + + return + +/obj/structure/cultgirder/ex_act(severity) + switch(severity) + if(1.0) del(src) - - blob_act() - if(prob(40)) - del(src) - - bullet_act(var/obj/item/projectile/Proj) //No beam check- How else will you destroy the cult girder with silver bullets????? - health -= Proj.damage - ..() - if(health <= 0) - new /obj/item/stack/sheet/metal(get_turf(src)) - del(src) - - return - - ex_act(severity) - switch(severity) - if(1.0) + return + if(2.0) + if (prob(30)) + new /obj/effect/decal/remains/human(loc) del(src) - return - if(2.0) - if (prob(30)) - new /obj/effect/decal/remains/human(loc) - del(src) - return - if(3.0) - if (prob(5)) - new /obj/effect/decal/remains/human(loc) - del(src) - return - else - return \ No newline at end of file + return + if(3.0) + if (prob(5)) + new /obj/effect/decal/remains/human(loc) + del(src) + return + else + return \ No newline at end of file diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index ce645d6afea..8d8c0469c25 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -30,19 +30,13 @@ playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) - var/damage_dealt + var/damage_dealt = 1 + var/attack_message = "kicks" if(istype(user,/mob/living/carbon/human)) var/mob/living/carbon/human/H = user if(H.species.can_shred(H)) + attack_message = "mangles" damage_dealt = 5 - user.visible_message("[user] mangles [src].", \ - "You mangle [src].", \ - "You hear twisting metal.") - - if(!damage_dealt) - user.visible_message("[user] kicks [src].", \ - "You kick [src].", \ - "You hear twisting metal.") if(shock(user, 70)) return @@ -52,8 +46,7 @@ else damage_dealt += 1 - health -= damage_dealt - healthcheck() + attack_generic(user,damage_dealt,attack_message) /obj/structure/grille/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) if(air_group || (height==0)) return 1 @@ -195,3 +188,8 @@ health -= 1 healthcheck() ..() + +/obj/structure/grille/attack_generic(var/mob/user, var/damage, var/attack_verb) + visible_message("[user] [attack_verb] the [src]!") + health -= damage + healthcheck() \ No newline at end of file diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 06544dfca8e..fad90eebdfc 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -26,112 +26,103 @@ var/health = 50.0 - New(location) - ..() - update_nearby_tiles(need_rebuild=1) +/obj/structure/inflatable/New(location) + ..() + update_nearby_tiles(need_rebuild=1) - Del() - update_nearby_tiles() - ..() +/obj/structure/inflatable/Del() + update_nearby_tiles() + ..() - proc/update_nearby_tiles(need_rebuild) //Copypasta from airlock code - if(!air_master) - return 0 - air_master.mark_for_update(get_turf(src)) - return 1 - - - - CanPass(atom/movable/mover, turf/target, height=0, air_group=0) +/obj/structure/inflatable/proc/update_nearby_tiles(need_rebuild) //Copypasta from airlock code + if(!air_master) return 0 + air_master.mark_for_update(get_turf(src)) + return 1 - bullet_act(var/obj/item/projectile/Proj) - health -= Proj.damage - ..() - if(health <= 0) +/obj/structure/inflatable/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + return 0 + +/obj/structure/inflatable/bullet_act(var/obj/item/projectile/Proj) + health -= Proj.damage + ..() + if(health <= 0) + deflate(1) + return + +/obj/structure/inflatable/ex_act(severity) + switch(severity) + if(1.0) + del(src) + return + if(2.0) deflate(1) - return - - - ex_act(severity) - switch(severity) - if(1.0) - del(src) - return - if(2.0) + return + if(3.0) + if(prob(50)) deflate(1) return - if(3.0) - if(prob(50)) - deflate(1) - return +/obj/structure/inflatable/blob_act() + deflate(1) - blob_act() - deflate(1) +/obj/structure/inflatable/meteorhit() + deflate(1) - - meteorhit() - //world << "glass at [x],[y],[z] Mhit" - deflate(1) - - - attack_hand(mob/user as mob) +/obj/structure/inflatable/attack_hand(mob/user as mob) add_fingerprint(user) return +/obj/structure/inflatable/attackby(obj/item/weapon/W as obj, mob/user as mob) + if(!istype(W)) return - proc/attack_generic(mob/user as mob, damage = 0) //used by attack_animal and attack_slime - health -= damage - if(health <= 0) - user.visible_message("[user] tears open [src]!") - deflate(1) - else //for nicer text~ - user.visible_message("[user] tears at [src]!") + if (can_puncture(W)) + visible_message("\red [user] pierces [src] with [W]!") + deflate(1) + if(W.damtype == BRUTE || W.damtype == BURN) + hit(W.force) + ..() + return - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(!istype(W)) return +/obj/structure/inflatable/proc/hit(var/damage, var/sound_effect = 1) + health = max(0, health - damage) + if(sound_effect) + playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) + if(health <= 0) + deflate(1) - if (can_puncture(W)) - visible_message("\red [user] pierces [src] with [W]!") - deflate(1) - if(W.damtype == BRUTE || W.damtype == BURN) - hit(W.force) - ..() - return - - proc/hit(var/damage, var/sound_effect = 1) - health = max(0, health - damage) - if(sound_effect) - playsound(loc, 'sound/effects/Glasshit.ogg', 75, 1) - if(health <= 0) - deflate(1) - - - proc/deflate(var/violent=0) - playsound(loc, 'sound/machines/hiss.ogg', 75, 1) - if(violent) - visible_message("[src] rapidly deflates!") - var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc) +/obj/structure/inflatable/proc/deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/torn/R = new /obj/item/inflatable/torn(loc) + src.transfer_fingerprints_to(R) + del(src) + else + //user << "\blue You slowly deflate the inflatable wall." + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/R = new /obj/item/inflatable(loc) src.transfer_fingerprints_to(R) del(src) - else - //user << "\blue You slowly deflate the inflatable wall." - visible_message("[src] slowly deflates.") - spawn(50) - var/obj/item/inflatable/R = new /obj/item/inflatable(loc) - src.transfer_fingerprints_to(R) - del(src) - verb/hand_deflate() - set name = "Deflate" - set category = "Object" - set src in oview(1) +/obj/structure/inflatable/verb/hand_deflate() + set name = "Deflate" + set category = "Object" + set src in oview(1) - if(isobserver(usr)) //to stop ghosts from deflating - return + if(isobserver(usr)) //to stop ghosts from deflating + return - deflate() + deflate() + +/obj/structure/inflatable/attack_generic(var/mob/user, var/damage, var/attack_verb) + health -= damage + if(health <= 0) + user.visible_message("[user] [attack_verb] open the [src]!") + deflate(1) + else + user.visible_message("[user] [attack_verb] at [src]!") /obj/item/inflatable/door/ name = "inflatable door" @@ -159,94 +150,84 @@ var/state = 0 //closed, 1 == open var/isSwitchingStates = 0 - //Bumped(atom/user) - // ..() - // if(!state) - // return TryToSwitchState(user) - // return +/obj/structure/inflatable/door/attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral + if(isAI(user)) //so the AI can't open it + return + else if(isrobot(user)) //but cyborgs can + if(get_dist(user,src) <= 1) //not remotely though + return TryToSwitchState(user) - attack_ai(mob/user as mob) //those aren't machinery, they're just big fucking slabs of a mineral - if(isAI(user)) //so the AI can't open it - return - else if(isrobot(user)) //but cyborgs can - if(get_dist(user,src) <= 1) //not remotely though - return TryToSwitchState(user) +/obj/structure/inflatable/door/attack_hand(mob/user as mob) + return TryToSwitchState(user) - attack_hand(mob/user as mob) - return TryToSwitchState(user) +/obj/structure/inflatable/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0) + if(air_group) + return state + if(istype(mover, /obj/effect/beam)) + return !opacity + return !density - CanPass(atom/movable/mover, turf/target, height=0, air_group=0) - if(air_group) - return state - if(istype(mover, /obj/effect/beam)) - return !opacity - return !density - - proc/TryToSwitchState(atom/user) - if(isSwitchingStates) return - if(ismob(user)) - var/mob/M = user - if(world.time - user.last_bumped <= 60) return //NOTE do we really need that? - if(M.client) - if(iscarbon(M)) - var/mob/living/carbon/C = M - if(!C.handcuffed) - SwitchState() - else +/obj/structure/inflatable/door/proc/TryToSwitchState(atom/user) + if(isSwitchingStates) return + if(ismob(user)) + var/mob/M = user + if(world.time - user.last_bumped <= 60) return //NOTE do we really need that? + if(M.client) + if(iscarbon(M)) + var/mob/living/carbon/C = M + if(!C.handcuffed) SwitchState() - else if(istype(user, /obj/mecha)) - SwitchState() + else + SwitchState() + else if(istype(user, /obj/mecha)) + SwitchState() - proc/SwitchState() - if(state) - Close() - else - Open() - update_nearby_tiles() - - proc/Open() - isSwitchingStates = 1 - //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) - flick("door_opening",src) - sleep(10) - density = 0 - opacity = 0 - state = 1 - update_icon() - isSwitchingStates = 0 - - proc/Close() - isSwitchingStates = 1 - //playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 100, 1) - flick("door_closing",src) - sleep(10) - density = 1 - opacity = 0 - state = 0 - update_icon() - isSwitchingStates = 0 +/obj/structure/inflatable/door/proc/SwitchState() + if(state) + Close() + else + Open() + update_nearby_tiles() +/obj/structure/inflatable/door/proc/Open() + isSwitchingStates = 1 + flick("door_opening",src) + sleep(10) + density = 0 + opacity = 0 + state = 1 update_icon() - if(state) - icon_state = "door_open" - else - icon_state = "door_closed" + isSwitchingStates = 0 - deflate(var/violent=0) - playsound(loc, 'sound/machines/hiss.ogg', 75, 1) - if(violent) - visible_message("[src] rapidly deflates!") - var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc) +/obj/structure/inflatable/door/proc/Close() + isSwitchingStates = 1 + flick("door_closing",src) + sleep(10) + density = 1 + opacity = 0 + state = 0 + update_icon() + isSwitchingStates = 0 + +/obj/structure/inflatable/door/update_icon() + if(state) + icon_state = "door_open" + else + icon_state = "door_closed" + +/obj/structure/inflatable/door/deflate(var/violent=0) + playsound(loc, 'sound/machines/hiss.ogg', 75, 1) + if(violent) + visible_message("[src] rapidly deflates!") + var/obj/item/inflatable/door/torn/R = new /obj/item/inflatable/door/torn(loc) + src.transfer_fingerprints_to(R) + del(src) + else + visible_message("[src] slowly deflates.") + spawn(50) + var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc) src.transfer_fingerprints_to(R) del(src) - else - //user << "\blue You slowly deflate the inflatable wall." - visible_message("[src] slowly deflates.") - spawn(50) - var/obj/item/inflatable/door/R = new /obj/item/inflatable/door(loc) - src.transfer_fingerprints_to(R) - del(src) - /obj/item/inflatable/torn name = "torn inflatable wall" diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 83112a0021e..b685c9ed83d 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -8,7 +8,6 @@ anchored = 1 var/shattered = 0 - /obj/structure/mirror/attack_hand(mob/user as mob) if(shattered) return @@ -17,14 +16,10 @@ var/mob/living/carbon/human/H = user if(H.a_intent == "hurt") - if(shattered) - playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) - return if(prob(30) || H.species.can_shred(H)) - user.visible_message("[user] smashes [src]!") - shatter() + attack_generic(user,1) else - user.visible_message("[user] hits [src] and bounces off!") + attack_generic(user) return var/userloc = H.loc @@ -82,7 +77,6 @@ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) ..() - /obj/structure/mirror/attackby(obj/item/I as obj, mob/user as mob) if(shattered) playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) @@ -93,4 +87,16 @@ shatter() else visible_message("[user] hits [src] with [I]!") - playsound(src.loc, 'sound/effects/Glasshit.ogg', 70, 1) \ No newline at end of file + playsound(src.loc, 'sound/effects/Glasshit.ogg', 70, 1) + +/obj/structure/mirror/attack_generic(var/mob/user, var/damage) + + if(shattered) + playsound(src.loc, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1) + return + + if(damage) + user.visible_message("[user] smashes [src]!") + shatter() + else + user.visible_message("[user] hits [src] and bounces off!") diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index 4b39e9d3b61..19001a0ae8b 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -150,7 +150,9 @@ "You hear a knocking sound.") return -/obj/structure/window/proc/attack_generic(mob/user as mob, damage = 0) //used by attack_animal and attack_slime +/obj/structure/window/attack_generic(var/mob/user, var/damage) + if(!damage) + return user.visible_message("[user] smashes into [src]!") take_damage(damage) diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index e960b9720d8..32caff56369 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -248,6 +248,23 @@ src.add_fingerprint(user) return +/turf/simulated/wall/attack_generic(var/mob/user, var/damage, var/wallbreaker) + + if(!damage || !wallbreaker) + user << "You push the wall but nothing happens." + return + + if(istype(src,/turf/simulated/wall/r_wall) && !rotting) + user << "This wall is far too strong for you to destroy." + + if(rotting || prob(40)) + user << "You smash through the wall!" + dismantle_wall(1) + else + user << "You smash against the wall." + take_damage(rand(25,75)) + return + /turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) if (!(istype(user, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey") diff --git a/code/modules/mob/living/carbon/human/human_attackhand.dm b/code/modules/mob/living/carbon/human/human_attackhand.dm index b8030886c3d..5a06c40b879 100644 --- a/code/modules/mob/living/carbon/human/human_attackhand.dm +++ b/code/modules/mob/living/carbon/human/human_attackhand.dm @@ -222,4 +222,19 @@ return /mob/living/carbon/human/proc/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, inrange, params) - return \ No newline at end of file + return + +/mob/living/carbon/human/attack_generic(var/mob/user, var/damage, var/attack_message) + + if(!damage) + return + + user.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] was attacked by [user.name] ([user.ckey])") + src.visible_message("[user] has [attack_message] [src]!") + + var/dam_zone = pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg", "groin") + var/datum/organ/external/affecting = get_organ(ran_zone(dam_zone)) + var/armor_block = run_armor_check(affecting, "melee") + apply_damage(damage, BRUTE, affecting, armor_block) + updatehealth() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/metroid/metroid.dm b/code/modules/mob/living/carbon/metroid/metroid.dm index dbd5faa707c..3b6bd746ff1 100644 --- a/code/modules/mob/living/carbon/metroid/metroid.dm +++ b/code/modules/mob/living/carbon/metroid/metroid.dm @@ -840,10 +840,6 @@ mob/living/carbon/slime/var/temperature_resistance = T0C+75 /mob/living/carbon/slime/has_eyes() return 0 - -/mob/living/carbon/slime/UnarmedAttack(var/atom/A) - return - //////////////////////////////Old shit from metroids/RoRos, and the old cores, would not take much work to re-add them//////////////////////// /* diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 3e895c73c2c..810227ddf7a 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -179,3 +179,14 @@ return 0 // End BS12 momentum-transfer code. + +/mob/living/attack_generic(var/mob/user, var/damage, var/attack_message) + + if(!damage) + return + + adjustBruteLoss(damage) + user.attack_log += text("\[[time_stamp()]\] attacked [src.name] ([src.ckey])") + src.attack_log += text("\[[time_stamp()]\] was attacked by [user.name] ([user.ckey])") + src.visible_message("[user] has [attack_message] [src]!") + updatehealth() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 42259b5fd31..c7abbb3d5a6 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -892,6 +892,10 @@ var/list/robot_verbs_default = list( user << "You remove \the [broken_device]." user.put_in_active_hand(broken_device) +//Robots take half damage from basic attacks. +/mob/living/silicon/robot/attack_generic(var/mob/user, var/damage, var/attack_message) + return ..(user,Floor(damage/2),attack_message) + /mob/living/silicon/robot/proc/allowed(mob/M) //check if it doesn't require any access at all if(check_access(null)) diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index 89e0094daea..2ef60f73938 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -737,3 +737,14 @@ if(!message || stat) return speech_buffer.Add(message) + +/mob/living/simple_animal/parrot/attack_generic(var/mob/user, var/damage, var/attack_message) + ..() + if(client) return + if(parrot_state == PARROT_PERCH) + parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched + if(!damage) + return + parrot_interest = user + parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless + icon_state = "parrot_fly" \ No newline at end of file diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index 168f56e1319..9ad0997f730 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -307,6 +307,16 @@ if(on != on_gs) on_gs = on +/obj/machinery/light/attack_generic(var/mob/user, var/damage) + if(!damage) + return + if(status == LIGHT_EMPTY||status == LIGHT_BROKEN) + user << "That object is useless to you." + return + if(!(status == LIGHT_OK||status == LIGHT_BURNED)) + return + visible_message("[user] smashes the light!") + broken() // attempt to set the light's on/off status // will not switch on if broken/burned/empty diff --git a/code/modules/vehicles/vehicle.dm b/code/modules/vehicles/vehicle.dm index 741393c6566..a07ea901efc 100644 --- a/code/modules/vehicles/vehicle.dm +++ b/code/modules/vehicles/vehicle.dm @@ -346,4 +346,14 @@ // Stat update procs //------------------------------------------------------- /obj/vehicle/proc/update_stats() - return \ No newline at end of file + return + +/obj/vehicle/attack_generic(var/mob/user, var/damage, var/attack_message) + if(!damage) + return + visible_message("[user] [attack_message] the [src]!") + user.attack_log += text("\[[time_stamp()]\] attacked [src.name]") + src.health -= damage + if(prob(10)) + new /obj/effect/decal/cleanable/blood/oil(src.loc) + healthcheck() \ No newline at end of file