diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm index bb9bc75d25..b4abf9b535 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_ash_walker1.dmm @@ -266,7 +266,7 @@ /turf/open/indestructible/boss, /area/ruin/unpowered/ash_walkers) "aH" = ( -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker, +/obj/structure/lavaland/ash_walker, /turf/open/lava/smooth{ initial_gas_mix = "o2=14;n2=23;TEMP=300" }, diff --git a/_maps/RandomZLevels/VR/snowdin_VR.dmm b/_maps/RandomZLevels/VR/snowdin_VR.dmm index bae0b05e3d..222615619e 100644 --- a/_maps/RandomZLevels/VR/snowdin_VR.dmm +++ b/_maps/RandomZLevels/VR/snowdin_VR.dmm @@ -3675,7 +3675,7 @@ /area/awaymission/snowdin/cave/cavern) "im" = ( /obj/effect/decal/cleanable/blood/old, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 5 }, /turf/open/floor/engine/cult{ @@ -8278,7 +8278,7 @@ /turf/open/floor/engine/cult, /area/awaymission/snowdin/post/cavern2) "sb" = ( -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, @@ -10179,7 +10179,7 @@ /obj/structure/cable/yellow{ icon_state = "2-8" }, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm index 96c1a08b1f..913de0817c 100644 --- a/_maps/RandomZLevels/caves.dmm +++ b/_maps/RandomZLevels/caves.dmm @@ -103,7 +103,7 @@ }, /area/awaymission/caves/BMP_asteroid/level_four) "at" = ( -/mob/living/simple_animal/hostile/spawner/skeleton, +/obj/structure/spawner/skeleton, /turf/open/floor/plating/asteroid/basalt/lava{ initial_gas_mix = "n2=23;o2=14" }, @@ -164,7 +164,7 @@ }, /area/awaymission/caves/BMP_asteroid/level_four) "aB" = ( -/mob/living/simple_animal/hostile/spawner/skeleton, +/obj/structure/spawner/skeleton, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -374,7 +374,7 @@ }, /area/awaymission/caves/BMP_asteroid/level_three) "be" = ( -/mob/living/simple_animal/hostile/spawner/mining/goliath, +/obj/structure/spawner/mining/goliath, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -504,7 +504,7 @@ /area/awaymission/caves/BMP_asteroid/level_three) "bw" = ( /obj/effect/decal/cleanable/blood, -/mob/living/simple_animal/hostile/spawner/skeleton, +/obj/structure/spawner/skeleton, /turf/open/floor/engine/cult{ initial_gas_mix = "n2=23;o2=14" }, @@ -930,7 +930,7 @@ /turf/closed/wall, /area/awaymission/caves/BMP_asteroid/level_two) "cL" = ( -/mob/living/simple_animal/hostile/spawner/mining/basilisk, +/obj/structure/spawner/mining/basilisk, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -1644,7 +1644,7 @@ /turf/open/floor/plasteel, /area/awaymission/caves/listeningpost) "fb" = ( -/mob/living/simple_animal/hostile/spawner/mining/hivelord, +/obj/structure/spawner/mining/hivelord, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -2133,7 +2133,7 @@ /turf/open/floor/plasteel/recharge_floor, /area/awaymission/caves/BMP_asteroid) "gD" = ( -/mob/living/simple_animal/hostile/spawner/mining/hivelord, +/obj/structure/spawner/mining/hivelord, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, @@ -2206,7 +2206,7 @@ }, /area/awaymission/caves/BMP_asteroid) "gQ" = ( -/mob/living/simple_animal/hostile/spawner/mining/basilisk, +/obj/structure/spawner/mining/basilisk, /turf/open/floor/plating/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14" }, diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index 57e03061dd..c24bf45f81 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -3670,7 +3670,7 @@ /area/awaymission/snowdin/cave/cavern) "im" = ( /obj/effect/decal/cleanable/blood/old, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 5 }, /turf/open/floor/engine/cult{ @@ -8333,7 +8333,7 @@ /turf/open/floor/engine/cult, /area/awaymission/snowdin/post/cavern2) "sb" = ( -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, @@ -10243,7 +10243,7 @@ /obj/structure/cable/yellow{ icon_state = "2-8" }, -/mob/living/simple_animal/hostile/spawner/nether{ +/obj/structure/spawner/nether{ max_mobs = 4; name = "weak netherworld link" }, diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 9a94fd3f61..ee4288d7fc 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -7891,6 +7891,10 @@ }, /turf/open/floor/engine/cult, /area/wizard_station) +"sa" = ( +/obj/item/hilbertshotel/ghostdojo, +/turf/open/indestructible/hotelwood, +/area/centcom/holding) "sc" = ( /obj/docking_port/stationary{ area_type = /area/syndicate_mothership/control; @@ -47751,7 +47755,7 @@ Of QF Nd Sd -Sd +sa Nd WN Ur diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index 2756be76fb..f4954f8f05 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -110,6 +110,7 @@ #define HIDENECK (1<<10) #define HIDETAUR (1<<11) //gotta hide that snowflake #define HIDESNOUT (1<<12) //or do we actually hide our snoots +#define HIDEACCESSORY (1<<13) //hides the jumpsuit accessory. //bitflags for clothing coverage - also used for limbs #define HEAD (1<<0) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index d68fb9b490..e2d93aebf5 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -25,30 +25,6 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s #define NOT_IMPLEMENTED "NOT_IMPLEMENTED" -#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day - -#define JANUARY 1 -#define FEBRUARY 2 -#define MARCH 3 -#define APRIL 4 -#define MAY 5 -#define JUNE 6 -#define JULY 7 -#define AUGUST 8 -#define SEPTEMBER 9 -#define OCTOBER 10 -#define NOVEMBER 11 -#define DECEMBER 12 - -//Select holiday names -- If you test for a holiday in the code, make the holiday's name a define and test for that instead -#define NEW_YEAR "New Year" -#define VALENTINES "Valentine's Day" -#define APRIL_FOOLS "April Fool's Day" -#define EASTER "Easter" -#define HALLOWEEN "Halloween" -#define CHRISTMAS "Christmas" -#define FESTIVE_SEASON "Festive Season" - //Human Overlays Indexes///////// //LOTS OF CIT CHANGES HERE. BE CAREFUL WHEN UPSTREAM ADDS MORE LAYERS #define MUTATIONS_LAYER 32 //mutations. Tk headglows, cold resistance glow, etc diff --git a/code/__DEFINES/move_force.dm b/code/__DEFINES/move_force.dm new file mode 100644 index 0000000000..ec31388c72 --- /dev/null +++ b/code/__DEFINES/move_force.dm @@ -0,0 +1,20 @@ +//Defaults +#define MOVE_FORCE_DEFAULT 1000 +#define MOVE_RESIST_DEFAULT 1000 +#define PULL_FORCE_DEFAULT 1000 + +//Factors/modifiers +#define MOVE_FORCE_PULL_RATIO 1 //Same move force to pull objects +#define MOVE_FORCE_PUSH_RATIO 1 //Same move force to normally push +#define MOVE_FORCE_FORCEPUSH_RATIO 2 //2x move force to forcefully push +#define MOVE_FORCE_CRUSH_RATIO 3 //3x move force to do things like crush objects +#define MOVE_FORCE_THROW_RATIO 1 //Same force throw as resist to throw objects + +#define MOVE_FORCE_OVERPOWERING (MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO * 10) +#define MOVE_FORCE_EXTREMELY_STRONG (MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO * 3) +#define MOVE_FORCE_VERY_STRONG ((MOVE_FORCE_DEFAULT * MOVE_FORCE_CRUSH_RATIO) - 1) +#define MOVE_FORCE_STRONG (MOVE_FORCE_DEFAULT * 2) +#define MOVE_FORCE_NORMAL MOVE_FORCE_DEFAULT +#define MOVE_FORCE_WEAK (MOVE_FORCE_DEFAULT / 2) +#define MOVE_FORCE_VERY_WEAK ((MOVE_FORCE_DEFAULT / MOVE_FORCE_CRUSH_RATIO) + 1) +#define MOVE_FORCE_EXTREMELY_WEAK (MOVE_FORCE_DEFAULT / (MOVE_FORCE_CRUSH_RATIO * 3)) \ No newline at end of file diff --git a/code/__DEFINES/time.dm b/code/__DEFINES/time.dm index f13f13510b..e1fff1879e 100644 --- a/code/__DEFINES/time.dm +++ b/code/__DEFINES/time.dm @@ -1,3 +1,27 @@ +#define MIDNIGHT_ROLLOVER 864000 //number of deciseconds in a day + +#define JANUARY 1 +#define FEBRUARY 2 +#define MARCH 3 +#define APRIL 4 +#define MAY 5 +#define JUNE 6 +#define JULY 7 +#define AUGUST 8 +#define SEPTEMBER 9 +#define OCTOBER 10 +#define NOVEMBER 11 +#define DECEMBER 12 + +//Select holiday names -- If you test for a holiday in the code, make the holiday's name a define and test for that instead +#define NEW_YEAR "New Year" +#define VALENTINES "Valentine's Day" +#define APRIL_FOOLS "April Fool's Day" +#define EASTER "Easter" +#define HALLOWEEN "Halloween" +#define CHRISTMAS "Christmas" +#define FESTIVE_SEASON "Festive Season" + /* Days of the week to make it easier to reference them. diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index e48eea451d..033636017d 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -173,6 +173,7 @@ #define TRAIT_AUTO_CATCH_ITEM "auto_catch_item" #define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman. #define TRAIT_FREESPRINT "free_sprinting" +#define TRAIT_NO_TELEPORT "no-teleport" //you just can't #define TRAIT_NO_ALCOHOL "alcohol_intolerance" // common trait sources @@ -234,4 +235,5 @@ #define NUKEOP_ANTAGONIST "nukeop-antagonist" #define MADE_UNCLONEABLE "made-uncloneable" #define NUKEOP_TRAIT "nuke-op" +#define MEGAFAUNA_TRAIT "megafauna" #define DEATHSQUAD_TRAIT "deathsquad" diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 49825bcb50..19ee2b2a5a 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -178,7 +178,7 @@ if(!C.credits) C.RollCredits() C.playtitlemusic(40) - + CONFIG_SET(flag/suicide_allowed,TRUE) // EORG suicides allowed var/popcount = gather_roundend_feedback() display_report(popcount) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index e64ed8fd55..e916b2532a 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1276,7 +1276,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) invisibility = 101 density = FALSE see_in_dark = 1e6 - anchored = TRUE + move_resist = INFINITY var/ready_to_die = FALSE /mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index aeca31ebd2..6efc9eab12 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -408,3 +408,5 @@ /datum/config_entry/number/dropped_modes config_entry_value = 3 + +/datum/config_entry/flag/suicide_allowed diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index 48da15f67e..d757b00493 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -55,6 +55,7 @@ SUBSYSTEM_DEF(throwing) var/dist_y var/dx var/dy + var/force = MOVE_FORCE_DEFAULT var/pure_diagonal var/diagonal_error var/datum/callback/callback diff --git a/code/datums/action.dm b/code/datums/action.dm index cb56c26b91..8659a9e7c4 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -544,6 +544,9 @@ cooldown = world.time owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) +/datum/action/item_action/flash + name = "Flash" + //Preset for spells /datum/action/spell_action check_flags = 0 diff --git a/code/datums/components/spawner.dm b/code/datums/components/spawner.dm new file mode 100644 index 0000000000..fe86b60375 --- /dev/null +++ b/code/datums/components/spawner.dm @@ -0,0 +1,49 @@ +/datum/component/spawner + var/mob_types = list(/mob/living/simple_animal/hostile/carp) + var/spawn_time = 300 //30 seconds default + var/list/spawned_mobs = list() + var/spawn_delay = 0 + var/max_mobs = 5 + var/spawn_text = "emerges from" + var/list/faction = list("mining") + +/datum/component/spawner/Initialize(_mob_types, _spawn_time, _faction, _spawn_text, _max_mobs) + if(_spawn_time) + spawn_time=_spawn_time + if(_mob_types) + mob_types=_mob_types + if(_faction) + faction=_faction + if(_spawn_text) + spawn_text=_spawn_text + if(_max_mobs) + max_mobs=_max_mobs + + RegisterSignal(parent, list(COMSIG_PARENT_QDELETING), .proc/stop_spawning) + START_PROCESSING(SSprocessing, src) + +/datum/component/spawner/process() + try_spawn_mob() + + +/datum/component/spawner/proc/stop_spawning(force, hint) + STOP_PROCESSING(SSprocessing, src) + for(var/mob/living/simple_animal/L in spawned_mobs) + if(L.nest == src) + L.nest = null + spawned_mobs = null + +/datum/component/spawner/proc/try_spawn_mob() + var/atom/P = parent + if(spawned_mobs.len >= max_mobs) + return 0 + if(spawn_delay > world.time) + return 0 + spawn_delay = world.time + spawn_time + var/chosen_mob_type = pick(mob_types) + var/mob/living/simple_animal/L = new chosen_mob_type(P.loc) + L.flags_1 |= (P.flags_1 & ADMIN_SPAWNED_1) + spawned_mobs += L + L.nest = src + L.faction = src.faction + P.visible_message("[L] [spawn_text] [P].") \ No newline at end of file diff --git a/code/datums/elements/dusts_on_catatonia.dm b/code/datums/elements/dusts_on_catatonia.dm new file mode 100644 index 0000000000..f5ca5722c4 --- /dev/null +++ b/code/datums/elements/dusts_on_catatonia.dm @@ -0,0 +1,26 @@ +/datum/element/dusts_on_catatonia + element_flags = ELEMENT_DETACH + var/list/mob/attached_mobs = list() + +/datum/element/dusts_on_catatonia/Attach(datum/target,penalize = FALSE) + . = ..() + if(!ismob(target)) + return ELEMENT_INCOMPATIBLE + var/mob/M = target + if(!(M in attached_mobs)) + attached_mobs += M + START_PROCESSING(SSprocessing,src) + +/datum/element/dusts_on_catatonia/Detach(mob/M) + . = ..() + if(M in attached_mobs) + attached_mobs -= M + if(!attached_mobs.len) + STOP_PROCESSING(SSprocessing,src) + +/datum/element/dusts_on_catatonia/process() + for(var/m in attached_mobs) + var/mob/M = m + if(!M.key && !M.get_ghost()) + M.dust(force = TRUE) + Detach(M) diff --git a/code/datums/elements/ghost_role_eligibility.dm b/code/datums/elements/ghost_role_eligibility.dm index 8ecb579bc8..e57aaddd5a 100644 --- a/code/datums/elements/ghost_role_eligibility.dm +++ b/code/datums/elements/ghost_role_eligibility.dm @@ -22,6 +22,8 @@ if(!(M.ckey in timeouts)) timeouts += M.ckey timeouts[M.ckey] = 0 + else if(timeouts[M.ckey] == CANT_REENTER_ROUND) + return timeouts[M.ckey] = max(timeouts[M.ckey],penalty) /datum/element/ghost_role_eligibility/Detach(mob/M) diff --git a/code/datums/helper_datums/teleport.dm b/code/datums/helper_datums/teleport.dm index 1c2ce851fe..6b0981665d 100644 --- a/code/datums/helper_datums/teleport.dm +++ b/code/datums/helper_datums/teleport.dm @@ -66,7 +66,7 @@ var/area/A = get_area(curturf) var/area/B = get_area(destturf) - if(!forced && (A.noteleport || B.noteleport)) + if(!forced && (HAS_TRAIT(teleatom, TRAIT_NO_TELEPORT) || A.noteleport || B.noteleport)) return FALSE if(SEND_SIGNAL(destturf, COMSIG_ATOM_INTERCEPT_TELEPORT, channel, curturf, destturf)) diff --git a/code/datums/martial/psychotic_brawl.dm b/code/datums/martial/psychotic_brawl.dm index 45d73353f9..f0ad7aedfd 100644 --- a/code/datums/martial/psychotic_brawl.dm +++ b/code/datums/martial/psychotic_brawl.dm @@ -26,7 +26,7 @@ if(A.grab_state >= GRAB_AGGRESSIVE) D.grabbedby(A, 1) else - A.start_pulling(D, 1) + A.start_pulling(D, supress_message = TRUE) if(A.pulling) D.drop_all_held_items() D.stop_pulling() diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 751f5faa94..2e46046a7e 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -615,7 +615,7 @@ if(do_after(mob_viewer, 35, null, mob_viewer)) if(isliving(mob_viewer)) var/mob/living/L = mob_viewer - to_chat(mob_viewer, "You succesfuly remove the durathread strand.") + to_chat(mob_viewer, "You successfully remove the durathread strand.") L.remove_status_effect(STATUS_EFFECT_CHOKINGSTRAND) diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 9a6d992991..1f62be8a24 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -360,7 +360,7 @@ SEND_SIGNAL(src, COMSIG_ATOM_FIRE_ACT, exposed_temperature, exposed_volume) return -/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked) +/atom/proc/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(density && !has_gravity(AM)) //thrown stuff bounces off dense stuff in no grav, unless the thrown stuff ends up inside what it hit(embedding, bola, etc...). addtimer(CALLBACK(src, .proc/hitby_react, AM), 2) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 00a08d62b2..829b66a060 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -3,6 +3,9 @@ var/last_move = null var/last_move_time = 0 var/anchored = FALSE + var/move_resist = MOVE_RESIST_DEFAULT + var/move_force = MOVE_FORCE_DEFAULT + var/pull_force = PULL_FORCE_DEFAULT var/datum/thrownthing/throwing = null var/throw_speed = 2 //How many tiles to move per ds when being thrown. Float values are fully supported var/throw_range = 7 @@ -115,20 +118,20 @@ return FALSE return ..() -/atom/movable/proc/start_pulling(atom/movable/AM,gs) +/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) if(QDELETED(AM)) return FALSE - if(!(AM.can_be_pulled(src))) + if(!(AM.can_be_pulled(src, state, force))) return FALSE // If we're pulling something then drop what we're currently pulling and pull this instead. if(pulling) - if(gs==0) + if(state == 0) stop_pulling() return FALSE // Are we trying to pull something we are already pulling? Then enter grab cycle and end. if(AM == pulling) - grab_state = gs + grab_state = state if(istype(AM,/mob/living)) var/mob/living/AMob = AM AMob.grabbedby(src) @@ -139,11 +142,12 @@ AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = AM AM.pulledby = src - grab_state = gs + grab_state = state if(ismob(AM)) var/mob/M = AM log_combat(src, M, "grabbed", addition="passive grab") - visible_message("[src] has grabbed [M] passively!") + if(!supress_message) + visible_message("[src] has grabbed [M] passively!") return TRUE /atom/movable/proc/stop_pulling() @@ -508,17 +512,19 @@ /atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) set waitfor = 0 SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) - return hit_atom.hitby(src) + return hit_atom.hitby(src, throwingdatum=throwingdatum) -/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked) - if(!anchored && hitpush) +/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum) + if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO)))) step(src, AM.dir) ..() -/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) - return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, messy_throw) +/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE) + if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY)) + return + return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, messy_throw) -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback, messy_throw = TRUE) //If this returns FALSE then callback will not be called. +/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE) //If this returns FALSE then callback will not be called. . = FALSE if (!target || speed <= 0) return @@ -564,6 +570,7 @@ TT.speed = speed TT.thrower = thrower TT.diagonals_first = diagonals_first + TT.force = force TT.callback = callback if(!QDELETED(thrower)) TT.target_zone = thrower.zone_selected @@ -614,6 +621,22 @@ return 0 return 1 +/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return FALSE + +/atom/movable/proc/force_push(atom/movable/AM, force = move_force, direction, silent = FALSE) + . = AM.force_pushed(src, force, direction) + if(!silent && .) + visible_message("[src] forcefully pushes against [AM]!", "You forcefully push against [AM]!") + +/atom/movable/proc/move_crush(atom/movable/AM, force = move_force, direction, silent = FALSE) + . = AM.move_crushed(src, force, direction) + if(!silent && .) + visible_message("[src] crushes past [AM]!", "You crush [AM]!") + +/atom/movable/proc/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return FALSE + /atom/movable/CanPass(atom/movable/mover, turf/target) if(mover in buckled_mobs) return 1 @@ -833,14 +856,15 @@ /atom/movable/proc/get_cell() return -/atom/movable/proc/can_be_pulled(user) +/atom/movable/proc/can_be_pulled(user, grab_state, force) if(src == user || !isturf(loc)) return FALSE if(anchored || throwing) return FALSE + if(force < (move_resist * MOVE_FORCE_PULL_RATIO)) + return FALSE return TRUE - /obj/item/proc/do_pickup_animation(atom/target) set waitfor = FALSE if(!istype(loc, /turf)) diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index 0945875ac9..e443d6ad37 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -145,9 +145,9 @@ C.throw_mode_on() //so they can catch it on the return. return ..() -/obj/item/shield/energy/bananium/throw_impact(atom/hit_atom) +/obj/item/shield/energy/bananium/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(active) - var/caught = hit_atom.hitby(src, 0, 0) + var/caught = hit_atom.hitby(src, FALSE, FALSE, throwingdatum=throwingdatum) if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) slipper.Slip(hit_atom) diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 016f226399..495e90d305 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -220,6 +220,12 @@ T -= M.rating*0.2 prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4 +/obj/machinery/autolathe/examine(mob/user) + . += ..() + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Storing up to [materials.max_amount] material units.
Material consumption at [prod_coeff*100]%.
" + /obj/machinery/autolathe/proc/main_win(mob/user) var/dat = "

Autolathe Menu:


" dat += materials_printout() @@ -380,4 +386,4 @@ //Called when the object is constructed by an autolathe //Has a reference to the autolathe so you can do !!FUN!! things with hacked lathes /obj/item/proc/autolathe_crafted(obj/machinery/autolathe/A) - return \ No newline at end of file + return diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm index a982411692..fc6cac785a 100644 --- a/code/game/machinery/cell_charger.dm +++ b/code/game/machinery/cell_charger.dm @@ -28,6 +28,8 @@ . += "There's [charging ? "a" : "no"] cell in the charger." if(charging) . += "Current charge: [round(charging.percent(), 1)]%." + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Charge rate at [charge_rate]J per cycle." /obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/stock_parts/cell) && !panel_open) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index 413621d8b9..711b221c54 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -102,8 +102,13 @@ /obj/machinery/clonepod/examine(mob/user) . = ..() var/mob/living/mob_occupant = occupant + . += "The linking device can be scanned with a multitool." if(mess) . += "It's filled with blood and viscera. You swear you can see it moving..." + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Cloning speed at [speed_coeff*50]%.
Predicted amount of cellular damage: [100-heal_level]%.
" + if(efficiency > 5) + to_chat(user, "Pod has been upgraded to support autoprocessing.") if(is_operational() && mob_occupant) if(mob_occupant.stat != DEAD) . += "Current clone cycle is [round(get_completion())]% complete." diff --git a/code/game/machinery/computer/teleporter.dm b/code/game/machinery/computer/teleporter.dm index 21fb70c38c..c52cf29660 100644 --- a/code/game/machinery/computer/teleporter.dm +++ b/code/game/machinery/computer/teleporter.dm @@ -44,7 +44,7 @@ data += "Current target: [(!target) ? "None" : "[get_area(target)] [(regime_set != "Gate") ? "" : "Teleporter"]"]
" if(calibrating) data += "Calibration: In Progress" - else if(power_station.teleporter_hub.calibrated || power_station.teleporter_hub.accurate >= 3) + else if(power_station.teleporter_hub.calibrated || power_station.efficiency >= 3) data += "Calibration: Optimal" else data += "Calibration: Sub-Optimal" @@ -84,14 +84,14 @@ if(!target) say("Error: No target set to calibrate to.") return - if(power_station.teleporter_hub.calibrated || power_station.teleporter_hub.accurate >= 3) + if(power_station.teleporter_hub.calibrated || power_station.efficiency >= 3) say("Hub is already calibrated!") return say("Processing hub calibration to target...") calibrating = 1 power_station.update_icon() - spawn(50 * (3 - power_station.teleporter_hub.accurate)) //Better parts mean faster calibration + spawn(50 * (3 - power_station.efficiency)) //Better parts mean faster calibration calibrating = 0 if(check_hub_connection()) power_station.teleporter_hub.calibrated = 1 diff --git a/code/game/machinery/dna_scanner.dm b/code/game/machinery/dna_scanner.dm index f62dceff6c..cff2e361bd 100644 --- a/code/game/machinery/dna_scanner.dm +++ b/code/game/machinery/dna_scanner.dm @@ -27,6 +27,13 @@ for(var/obj/item/stock_parts/micro_laser/P in component_parts) damage_coeff = P.rating +/obj/machinery/dna_scannernew/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Radiation pulse accuracy increased by factor [precision_coeff**2].
Radiation pulse damage decreased by factor [damage_coeff**2].
" + if(scan_level >= 3) + . += "Scanner has been upgraded to support autoprocessing." + /obj/machinery/dna_scannernew/update_icon() //no power or maintenance diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 2e43670624..ad0f372530 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -5,6 +5,7 @@ icon_state = "door1" opacity = 1 density = TRUE + move_resist = MOVE_FORCE_VERY_STRONG layer = OPEN_DOOR_LAYER power_channel = ENVIRON max_integrity = 350 diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index 0429db5792..f5bf8c8a1b 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -32,7 +32,7 @@ CalculateAffectingAreas() /obj/machinery/door/firedoor/examine(mob/user) - ..() + . = ..() if(!density) . += "It is open, but could be pried closed." else if(!welded) diff --git a/code/game/machinery/harvester.dm b/code/game/machinery/harvester.dm index e1f9824524..40430b37b7 100644 --- a/code/game/machinery/harvester.dm +++ b/code/game/machinery/harvester.dm @@ -129,7 +129,7 @@ /obj/machinery/harvester/proc/end_harvesting() harvesting = FALSE open_machine() - say("Subject has been succesfuly harvested.") + say("Subject has been successfully harvested.") playsound(src, 'sound/machines/microwave/microwave-end.ogg', 100, 0) /obj/machinery/harvester/screwdriver_act(mob/living/user, obj/item/I) @@ -191,4 +191,6 @@ if(state_open) . += "[src] must be closed before harvesting." else if(!harvesting) - . += "Alt-click [src] to start harvesting." \ No newline at end of file + . += "Alt-click [src] to start harvesting." + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Harvest speed at [interval*0.1] seconds per organ." diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 40fc52d6a1..f3e446c686 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -143,6 +143,11 @@ GLOBAL_LIST_EMPTY(network_holopads) holograph_range += 1 * B.rating holo_range = holograph_range +/obj/machinery/holopad/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Current projection range: [holo_range] units." + /obj/machinery/holopad/attackby(obj/item/P, mob/user, params) if(default_deconstruction_screwdriver(user, "holopad_open", "holopad0", P)) return diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index 5418dcdb97..b4a9584368 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -23,6 +23,11 @@ E += M.rating*15 range = E +/obj/machinery/launchpad/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Maximum range: [range] units." + /obj/machinery/launchpad/attackby(obj/item/I, mob/user, params) if(stationary) if(default_deconstruction_screwdriver(user, "lpad-idle-o", "lpad-idle", I)) diff --git a/code/game/machinery/limbgrower.dm b/code/game/machinery/limbgrower.dm index bf9400219b..28afea817b 100644 --- a/code/game/machinery/limbgrower.dm +++ b/code/game/machinery/limbgrower.dm @@ -144,7 +144,7 @@ // Set this limb up using the specias name and body zone limb.icon_state = "[selected_category]_[limb.body_zone]" limb.name = "\improper synthetic [selected_category] [parse_zone(limb.body_zone)]" - limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]" + limb.desc = "A synthetic [selected_category] limb that will morph on its first use in surgery. This one is for the [parse_zone(limb.body_zone)]." limb.species_id = selected_category limb.update_icon_dropped() @@ -158,6 +158,11 @@ T -= M.rating*0.2 prod_coeff = min(1,max(0,T)) // Coeff going 1 -> 0,8 -> 0,6 -> 0,4 +/obj/machinery/limbgrower/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Storing up to [reagents.maximum_volume]u of synthflesh.
Synthflesh consumption at [prod_coeff*100]%." + /obj/machinery/limbgrower/proc/main_win(mob/user) var/dat = "

Limb Grower Menu:


" dat += "Chemical Storage" diff --git a/code/game/machinery/recharger.dm b/code/game/machinery/recharger.dm index a581981746..2211397f3e 100755 --- a/code/game/machinery/recharger.dm +++ b/code/game/machinery/recharger.dm @@ -23,6 +23,23 @@ for(var/obj/item/stock_parts/capacitor/C in component_parts) recharge_coeff = C.rating +/obj/machinery/recharger/examine(mob/user) + . = ..() + if(!in_range(user, src) && !issilicon(user) && !isobserver(user)) + . += "You're too far away to examine [src]'s contents and display!" + return + + if(charging) + . += {"\The [src] contains: + - \A [charging]."} + + if(!(stat & (NOPOWER|BROKEN))) + . += "The status display reads:" + . += "- Recharging [recharge_coeff*10]% cell charge per cycle." + if(charging) + var/obj/item/stock_parts/cell/C = charging.get_cell() + . += "- \The [charging]'s cell is at [C.percent()]%." + /obj/machinery/recharger/proc/setCharging(new_charging) charging = new_charging if (new_charging) diff --git a/code/game/machinery/rechargestation.dm b/code/game/machinery/rechargestation.dm index cd5f7ad6bf..374c0c71b9 100644 --- a/code/game/machinery/rechargestation.dm +++ b/code/game/machinery/rechargestation.dm @@ -50,6 +50,13 @@ for(var/obj/item/stock_parts/cell/C in component_parts) recharge_speed *= C.maxcharge / 10000 +/obj/machinery/recharge_station/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Recharging [recharge_speed]J per cycle." + if(repairs) + to_chat(user, "[src] has been upgraded to support automatic repairs.") + /obj/machinery/recharge_station/process() if(!is_operational()) return diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index c879ca73e8..538017eaef 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -41,9 +41,10 @@ /obj/machinery/recycler/examine(mob/user) . = ..() - . += "The power light is [(stat & NOPOWER) ? "off" : "on"]." - . += "The safety-mode light is [safety_mode ? "on" : "off"]." - . += "The safety-sensors status light is [obj_flags & EMAGGED ? "off" : "on"]." + . += "Reclaiming [amount_produced]% of materials salvaged." + . += {"The power light is [(stat & NOPOWER) ? "off" : "on"]. + The safety-mode light is [safety_mode ? "on" : "off"]. + The safety-sensors status light is [obj_flags & EMAGGED ? "off" : "on"]."} /obj/machinery/recycler/power_change() ..() diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index fc6577a4f1..16016b8e18 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -4,6 +4,7 @@ icon = 'icons/effects/effects.dmi' icon_state = "shield-old" density = TRUE + move_resist = INFINITY opacity = 0 anchored = TRUE resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF @@ -93,6 +94,7 @@ /obj/machinery/shieldgen/proc/shields_up() active = TRUE update_icon() + move_resist = INFINITY for(var/turf/target_tile in range(shield_range, src)) if(isspaceturf(target_tile) && !(locate(/obj/structure/emergency_shield) in target_tile)) @@ -101,6 +103,7 @@ /obj/machinery/shieldgen/proc/shields_down() active = FALSE + move_resist = initial(move_resist) update_icon() QDEL_LIST(deployed_shields) diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm index 984a911d32..6eca52aa0e 100644 --- a/code/game/machinery/spaceheater.dm +++ b/code/game/machinery/spaceheater.dm @@ -52,6 +52,8 @@ . += "The charge meter reads [cell ? round(cell.percent(), 1) : 0]%." else . += "There is no power cell installed." + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Temperature range at [settableTemperatureRange]°C.
Heating power at [heatingPower*0.001]kJ.
Power consumption at [(efficiency*-0.0025)+150]%." //100%, 75%, 50%, 25% /obj/machinery/space_heater/update_icon() if(on) diff --git a/code/game/machinery/teleporter.dm b/code/game/machinery/teleporter.dm index ae71a0b844..3cc71df0f1 100644 --- a/code/game/machinery/teleporter.dm +++ b/code/game/machinery/teleporter.dm @@ -11,7 +11,7 @@ idle_power_usage = 10 active_power_usage = 2000 circuit = /obj/item/circuitboard/machine/teleporter_hub - var/accurate = FALSE + var/accuracy = 0 var/obj/machinery/teleport/station/power_station var/calibrated //Calibration prevents mutation @@ -29,7 +29,12 @@ var/A = 0 for(var/obj/item/stock_parts/matter_bin/M in component_parts) A += M.rating - accurate = A + accuracy = A + +/obj/machinery/teleport/hub/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Probability of malfunction decreased by [(accuracy*25)-25]%." /obj/machinery/teleport/hub/proc/link_power_station() if(power_station) @@ -69,13 +74,13 @@ if(do_teleport(M, com.target, channel = TELEPORT_CHANNEL_BLUESPACE)) use_power(5000) - if(!calibrated && iscarbon(M) && prob(30 - ((accurate) * 10))) //oh dear a problem + if(!calibrated && iscarbon(M) && prob(30 - ((accuracy) * 10))) //oh dear a problem var/mob/living/carbon/C = M if(C.dna?.species && C.dna.species.id != "fly" && !HAS_TRAIT(C, TRAIT_RADIMMUNE)) to_chat(C, "You hear a buzzing in your ears.") C.set_species(/datum/species/fly) log_game("[C] ([key_name(C)]) was turned into a fly person") - C.apply_effect((rand(120 - accurate * 40, 180 - accurate * 60)), EFFECT_IRRADIATE, 0) + C.apply_effect((rand(120 - accuracy * 40, 180 - accuracy * 60)), EFFECT_IRRADIATE, 0) calibrated = FALSE return @@ -102,7 +107,7 @@ /obj/machinery/teleport/station - name = "station" + name = "teleporter station" desc = "The power control station for a bluespace teleporter. Used for toggling power, and can activate a test-fire to prevent malfunctions." icon_state = "controller" use_power = IDLE_POWER_USE @@ -125,6 +130,15 @@ E += C.rating efficiency = E - 1 +/obj/machinery/teleport/station/examine(mob/user) + . = ..() + if(!panel_open) + . += "The panel is screwed in, obstructing the linking device and wiring panel." + else + . += "The linking device is now able to be scanned with a multitool.
The wiring can be connected to a nearby console and hub with a pair of wirecutters.
" + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: This station can be linked to [efficiency] other station(s)." + /obj/machinery/teleport/station/proc/link_console_and_hub() for(var/direction in GLOB.cardinals) teleporter_hub = locate(/obj/machinery/teleport/hub, get_step(src, direction)) diff --git a/code/game/mecha/equipment/tools/other_tools.dm b/code/game/mecha/equipment/tools/other_tools.dm index a8ba9850ff..fdb620cc67 100644 --- a/code/game/mecha/equipment/tools/other_tools.dm +++ b/code/game/mecha/equipment/tools/other_tools.dm @@ -84,7 +84,7 @@ switch(mode) if(1) if(!locked) - if(!istype(target) || target.anchored) + if(!istype(target) || target.anchored || target.move_resist >= MOVE_FORCE_EXTREMELY_STRONG) occupant_message("Unable to lock on [target]") return locked = target @@ -110,7 +110,7 @@ else atoms = orange(3, target) for(var/atom/movable/A in atoms) - if(A.anchored) + if(A.anchored || A.move_resist >= MOVE_FORCE_EXTREMELY_STRONG) continue spawn(0) var/iter = 5-get_dist(A,target) diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm index 95fc96e119..2e93fc3a49 100644 --- a/code/game/mecha/equipment/weapons/weapons.dm +++ b/code/game/mecha/equipment/weapons/weapons.dm @@ -436,7 +436,7 @@ throwforce = 35 icon_state = "punching_glove" -/obj/item/punching_glove/throw_impact(atom/hit_atom) +/obj/item/punching_glove/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) if(ismovableatom(hit_atom)) var/atom/movable/AM = hit_atom diff --git a/code/game/mecha/mech_bay.dm b/code/game/mecha/mech_bay.dm index bc8a675085..90f037c279 100644 --- a/code/game/mecha/mech_bay.dm +++ b/code/game/mecha/mech_bay.dm @@ -36,6 +36,11 @@ MC += C.rating max_charge = MC * 25 +/obj/machinery/mech_bay_recharge_port/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Base recharge rate at [max_charge]J per cycle." + /obj/machinery/mech_bay_recharge_port/process() if(stat & NOPOWER || !recharge_console) return diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 61c0a8bd37..98e4eb4258 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -62,6 +62,11 @@ T += Ml.rating time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) +/obj/machinery/mecha_part_fabricator/examine(mob/user) + . = ..() + var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Storing up to [materials.max_amount] material units.
Material consumption at [component_coeff*100]%.
Build time reduced by [100-time_coeff*100]%.
" /obj/machinery/mecha_part_fabricator/emag_act() . = ..() diff --git a/code/game/mecha/mecha_defense.dm b/code/game/mecha/mecha_defense.dm index dd335e8b37..e5e578b0e8 100644 --- a/code/game/mecha/mecha_defense.dm +++ b/code/game/mecha/mecha_defense.dm @@ -108,8 +108,8 @@ /obj/mecha/attack_tk() return -/obj/mecha/hitby(atom/movable/A as mob|obj) //wrapper - log_message("Hit by [A].", color="red") +/obj/mecha/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) //wrapper + log_message("Hit by [AM].", color="red") . = ..() diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm index d48013d472..6057d1b418 100644 --- a/code/game/objects/effects/effects.dm +++ b/code/game/objects/effects/effects.dm @@ -4,6 +4,7 @@ /obj/effect icon = 'icons/effects/effects.dmi' resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | FREEZE_PROOF + move_resist = INFINITY obj_flags = 0 /obj/effect/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 78dde8d206..aa4e45dee6 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -568,21 +568,21 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) else return -/obj/item/throw_impact(atom/A, datum/thrownthing/throwingdatum) - if(A && !QDELETED(A)) - SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, A, throwingdatum) - if(get_temperature() && isliving(A)) - var/mob/living/L = A +/obj/item/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + if(hit_atom && !QDELETED(hit_atom)) + SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) + if(get_temperature() && isliving(hit_atom)) + var/mob/living/L = hit_atom L.IgniteMob() var/itempush = 1 if(w_class < 4) itempush = 0 //too light to push anything - return A.hitby(src, 0, itempush) + return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum) -/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, messy_throw = TRUE) +/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE) thrownby = thrower callback = CALLBACK(src, .proc/after_throw, callback, (spin && messy_throw)) //replace their callback with our own - . = ..(target, range, speed, thrower, spin, diagonals_first, callback) + . = ..(target, range, speed, thrower, spin, diagonals_first, callback, force) /obj/item/proc/after_throw(datum/callback/callback, messy_throw) if (callback) //call the original callback @@ -674,7 +674,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) else . = "" -/obj/item/hitby(atom/movable/AM) +/obj/item/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) return /obj/item/attack_hulk(mob/living/carbon/human/user) diff --git a/code/game/objects/items/devices/laserpointer.dm b/code/game/objects/items/devices/laserpointer.dm index cc470466df..1f2f1ddda2 100644 --- a/code/game/objects/items/devices/laserpointer.dm +++ b/code/game/objects/items/devices/laserpointer.dm @@ -56,6 +56,14 @@ else return ..() +/obj/item/laser_pointer/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + if(!diode) + . += "The diode is missing." + else + . += "A class [diode.rating] laser diode is installed. It is screwed in place." + /obj/item/laser_pointer/afterattack(atom/target, mob/living/user, flag, params) . = ..() laser_act(target, user, params) diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index f27884d3ae..b1dd9be376 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -160,7 +160,7 @@ /obj/item/dice/attack_self(mob/user) diceroll(user) -/obj/item/dice/throw_impact(atom/target) +/obj/item/dice/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) diceroll(thrownby) . = ..() diff --git a/code/game/objects/items/grenades/grenade.dm b/code/game/objects/items/grenades/grenade.dm index 033ea9e791..16a5e6d1d3 100644 --- a/code/game/objects/items/grenades/grenade.dm +++ b/code/game/objects/items/grenades/grenade.dm @@ -93,9 +93,8 @@ var/obj/item/I = loc I.grenade_prime_react(src) - -/obj/item/grenade/attackby(obj/item/W, mob/user, params) - if(istype(W, /obj/item/screwdriver)) +/obj/item/grenade/tool_act(mob/living/user, obj/item/I, tool_behaviour) + if(tool_behaviour == TOOL_SCREWDRIVER) switch(det_time) if ("1") det_time = 10 diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index 849e14b476..f6f14554ed 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -340,7 +340,7 @@ return playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1) -/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom) +/obj/item/restraints/legcuffs/bola/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(..() || !iscarbon(hit_atom))//if it gets caught or the target can't be cuffed, return//abort var/mob/living/carbon/C = hit_atom @@ -368,7 +368,7 @@ w_class = WEIGHT_CLASS_SMALL breakouttime = 60 -/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom) +/obj/item/restraints/legcuffs/bola/energy/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(iscarbon(hit_atom)) var/obj/item/restraints/legcuffs/beartrap/B = new /obj/item/restraints/legcuffs/beartrap/energy/cyborg(get_turf(hit_atom)) B.Crossed(hit_atom) diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index fde14a85d9..4b071d6a34 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -333,13 +333,13 @@ if(proximity_flag) consume_everything(target) -/obj/item/melee/supermatter_sword/throw_impact(target) +/obj/item/melee/supermatter_sword/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() - if(ismob(target)) - var/mob/M + if(ismob(hit_atom)) + var/mob/M = hit_atom if(src.loc == M) M.dropItemToGround(src) - consume_everything(target) + consume_everything(hit_atom) /obj/item/melee/supermatter_sword/pickup(user) ..() diff --git a/code/game/objects/items/singularityhammer.dm b/code/game/objects/items/singularityhammer.dm index f55dae67db..86f0ad4936 100644 --- a/code/game/objects/items/singularityhammer.dm +++ b/code/game/objects/items/singularityhammer.dm @@ -105,10 +105,10 @@ playsound(src.loc, "sparks", 50, 1) shock(M) -/obj/item/twohanded/mjollnir/throw_impact(atom/target) +/obj/item/twohanded/mjollnir/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() - if(isliving(target)) - shock(target) + if(isliving(hit_atom)) + shock(hit_atom) /obj/item/twohanded/mjollnir/update_icon() //Currently only here to fuck with the on-mob icons. icon_state = "mjollnir[wielded]" diff --git a/code/game/objects/items/stacks/bscrystal.dm b/code/game/objects/items/stacks/bscrystal.dm index bb1a475f1f..e2357e8f6d 100644 --- a/code/game/objects/items/stacks/bscrystal.dm +++ b/code/game/objects/items/stacks/bscrystal.dm @@ -35,7 +35,7 @@ /obj/item/stack/ore/bluespace_crystal/proc/blink_mob(mob/living/L) do_teleport(L, get_turf(L), blink_range, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) -/obj/item/stack/ore/bluespace_crystal/throw_impact(atom/hit_atom) +/obj/item/stack/ore/bluespace_crystal/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) // not caught in mid-air visible_message("[src] fizzles and disappears upon impact!") var/turf/T = get_turf(hit_atom) diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 8065cd5723..324b40ac7f 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -342,7 +342,7 @@ merge(o) . = ..() -/obj/item/stack/hitby(atom/movable/AM, skip, hitpush) +/obj/item/stack/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(istype(AM, merge_type)) merge(AM) . = ..() diff --git a/code/game/objects/items/stunbaton.dm b/code/game/objects/items/stunbaton.dm index f34fc6a9a3..946eb1eb7b 100644 --- a/code/game/objects/items/stunbaton.dm +++ b/code/game/objects/items/stunbaton.dm @@ -41,7 +41,7 @@ cell = new preload_cell_type(src) update_icon() -/obj/item/melee/baton/throw_impact(atom/hit_atom) +/obj/item/melee/baton/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() //Only mob/living types have stun handling if(status && prob(throw_hit_chance) && iscarbon(hit_atom)) diff --git a/code/game/objects/items/theft_tools.dm b/code/game/objects/items/theft_tools.dm index d52c280f1b..9b9fae7c8f 100644 --- a/code/game/objects/items/theft_tools.dm +++ b/code/game/objects/items/theft_tools.dm @@ -259,7 +259,7 @@ if(proximity && ismovableatom(O) && O != sliver) Consume(O, user) -/obj/item/hemostat/supermatter/throw_impact(atom/hit_atom) // no instakill supermatter javelins +/obj/item/hemostat/supermatter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) // no instakill supermatter javelins if(sliver) sliver.forceMove(loc) to_chat(usr, "\The [sliver] falls out of \the [src] as you throw them.") diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index cf891f5a47..92798528ae 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -84,7 +84,7 @@ else return ..() -/obj/item/toy/balloon/throw_impact(atom/hit_atom) +/obj/item/toy/balloon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? balloon_burst(hit_atom) @@ -531,7 +531,7 @@ /obj/item/toy/snappop/fire_act(exposed_temperature, exposed_volume) pop_burst() -/obj/item/toy/snappop/throw_impact(atom/hit_atom) +/obj/item/toy/snappop/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) pop_burst() @@ -1152,7 +1152,7 @@ icon_state = "minimeteor" w_class = WEIGHT_CLASS_SMALL -/obj/item/toy/minimeteor/throw_impact(atom/hit_atom) +/obj/item/toy/minimeteor/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) playsound(src, 'sound/effects/meteorimpact.ogg', 40, 1) for(var/mob/M in urange(10, src)) @@ -1201,7 +1201,7 @@ if(user.dropItemToGround(src)) throw_at(target, throw_range, throw_speed) -/obj/item/toy/snowball/throw_impact(atom/hit_atom) +/obj/item/toy/snowball/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) playsound(src, 'sound/effects/pop.ogg', 20, 1) qdel(src) diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 70a05a8d40..2d99f0e073 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -46,7 +46,7 @@ if(BURN) playsound(src.loc, 'sound/items/welder.ogg', 100, 1) -/obj/hitby(atom/movable/AM) +/obj/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) ..() var/throwdamage = AM.throwforce if(isobj(AM)) @@ -126,6 +126,17 @@ if(. && !play_soundeffect) playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) +/obj/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + return TRUE + +/obj/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + collision_damage(pusher, force, direction) + return TRUE + +/obj/proc/collision_damage(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) + var/amt = max(0, ((force - (move_resist * MOVE_FORCE_CRUSH_RATIO)) / (move_resist * MOVE_FORCE_CRUSH_RATIO)) * 10) + take_damage(amt, BRUTE) + /obj/attack_slime(mob/living/simple_animal/slime/user) if(!user.is_adult) return diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 8899f2f79f..5f3fc48eb7 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -80,7 +80,7 @@ SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue) anchored = anchorvalue -/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, messy_throw) +/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, messy_throw = TRUE) . = ..() if(obj_flags & FROZEN) visible_message("[src] shatters into a million pieces!") diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 0cce1de41b..92fb13c947 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -46,6 +46,7 @@ roundstart = FALSE death = FALSE anchored = FALSE + move_resist = MOVE_FORCE_NORMAL density = FALSE flavour_text = "You are an ash walker. Your tribe worships the Necropolis. The wastes are sacred ground, its monsters a blessed bounty. You would never leave its beautiful expanse. \ You have seen lights in the distance... they foreshadow the arrival of outsiders that seek to tear apart the Necropolis and its domain. Fresh sacrifices for your nest." @@ -120,6 +121,7 @@ roundstart = FALSE death = FALSE anchored = FALSE + move_resist = MOVE_FORCE_NORMAL density = FALSE var/has_owner = FALSE var/can_transfer = TRUE //if golems can switch bodies to this new shell @@ -645,6 +647,7 @@ SSjob.equip_loadout(null, new_spawn, FALSE) SSquirks.AssignQuirks(new_spawn, new_spawn.client, TRUE, TRUE, null, FALSE, new_spawn) new_spawn.AddElement(/datum/element/ghost_role_eligibility) + new_spawn.AddElement(/datum/element/dusts_on_catatonia) ADD_TRAIT(new_spawn, TRAIT_SIXTHSENSE, GHOSTROLE_TRAIT) ADD_TRAIT(new_spawn,TRAIT_EXEMPT_HEALTH_EVENTS,GHOSTROLE_TRAIT) ADD_TRAIT(new_spawn,TRAIT_PACIFISM,GHOSTROLE_TRAIT) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 205e87329b..0d4444303e 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -258,7 +258,7 @@ take_damage(1, BURN, 0, 0) ..() -/obj/structure/grille/hitby(AM as mob|obj) +/obj/structure/grille/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(isobj(AM)) if(prob(50) && anchored && !broken) var/obj/O = AM diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm b/code/game/objects/structures/lavaland/necropolis_tendril.dm similarity index 71% rename from code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm rename to code/game/objects/structures/lavaland/necropolis_tendril.dm index 27ebb71c0e..6ce0228f54 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/necropolis_tendril.dm +++ b/code/game/objects/structures/lavaland/necropolis_tendril.dm @@ -1,39 +1,32 @@ //Necropolis Tendrils, which spawn lavaland monsters and break into a chasm when killed -/obj/effect/light_emitter/tendril - set_luminosity = 4 - set_cap = 2.5 - light_color = LIGHT_COLOR_LAVA - -/mob/living/simple_animal/hostile/spawner/lavaland +/obj/structure/spawner/lavaland name = "necropolis tendril" desc = "A vile tendril of corruption, originating deep underground. Terrible monsters are pouring out of it." + icon = 'icons/mob/nest.dmi' icon_state = "tendril" - icon_living = "tendril" - icon_dead = "tendril" + faction = list("mining") - weather_immunities = list("lava","ash") - health = 250 - maxHealth = 250 max_mobs = 3 - spawn_time = 300 //30 seconds default + max_integrity = 250 mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/tendril) - spawn_text = "emerges from" - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = INFINITY - loot = list(/obj/effect/collapse, /obj/structure/closet/crate/necropolis/tendril) - del_on_death = 1 + + move_resist=INFINITY // just killing it tears a massive hole in the ground, let's not move it + anchored = TRUE + resistance_flags = FIRE_PROOF | LAVA_PROOF + var/gps = null var/obj/effect/light_emitter/tendril/emitted_light -/mob/living/simple_animal/hostile/spawner/lavaland/goliath + +/obj/structure/spawner/lavaland/goliath mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/tendril) -/mob/living/simple_animal/hostile/spawner/lavaland/legion +/obj/structure/spawner/lavaland/legion mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril) -/mob/living/simple_animal/hostile/spawner/lavaland/Initialize() +GLOBAL_LIST_INIT(tendrils, list()) +/obj/structure/spawner/lavaland/Initialize() . = ..() emitted_light = new(loc) for(var/F in RANGE_TURFS(1, src)) @@ -41,18 +34,19 @@ var/turf/closed/mineral/M = F M.ScrapeAway(null, CHANGETURF_IGNORE_AIR) gps = new /obj/item/gps/internal(src) + GLOB.tendrils += src -/mob/living/simple_animal/hostile/spawner/lavaland/Destroy() - QDEL_NULL(emitted_light) - QDEL_NULL(gps) +/obj/structure/spawner/lavaland/deconstruct(disassembled) + new /obj/effect/collapse(loc) + new /obj/structure/closet/crate/necropolis/tendril(loc) return ..() -/mob/living/simple_animal/hostile/spawner/lavaland/death() + +/obj/structure/spawner/lavaland/Destroy() var/last_tendril = TRUE - for(var/mob/living/simple_animal/hostile/spawner/lavaland/other in GLOB.mob_living_list) - if(other != src) - last_tendril = FALSE - break + if(GLOB.tendrils.len>1) + last_tendril = FALSE + if(last_tendril && !(flags_1 & ADMIN_SPAWNED_1)) if(SSmedals.hub_enabled) for(var/mob/living/L in view(7,src)) @@ -60,7 +54,15 @@ continue SSmedals.UnlockMedal("[BOSS_MEDAL_TENDRIL] [ALL_KILL_MEDAL]", L.client) SSmedals.SetScore(TENDRIL_CLEAR_SCORE, L.client, 1) - ..() + GLOB.tendrils -= src + QDEL_NULL(emitted_light) + QDEL_NULL(gps) + return ..() + +/obj/effect/light_emitter/tendril + set_luminosity = 4 + set_cap = 2.5 + light_color = LIGHT_COLOR_LAVA /obj/effect/collapse name = "collapsing necropolis tendril" @@ -92,4 +94,4 @@ for(var/turf/T in range(2,src)) if(!T.density) T.TerraformTurf(/turf/open/chasm/lavaland, /turf/open/chasm/lavaland, flags = CHANGETURF_INHERIT_AIR) - qdel(src) + qdel(src) \ No newline at end of file diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm new file mode 100644 index 0000000000..e67ef7af60 --- /dev/null +++ b/code/game/objects/structures/spawner.dm @@ -0,0 +1,75 @@ +/obj/structure/spawner + name = "monster nest" + icon = 'icons/mob/animal.dmi' + icon_state = "hole" + max_integrity = 100 + + move_resist = MOVE_FORCE_EXTREMELY_STRONG + anchored = TRUE + density = TRUE + + var/max_mobs = 5 + var/spawn_time = 300 //30 seconds default + var/mob_types = list(/mob/living/simple_animal/hostile/carp) + var/spawn_text = "emerges from" + var/faction = list("hostile") + +/obj/structure/spawner/Initialize() + . = ..() + AddComponent(/datum/component/spawner, mob_types, spawn_time, faction, spawn_text, max_mobs) + +/obj/structure/spawner/syndicate + name = "warp beacon" + icon = 'icons/obj/device.dmi' + icon_state = "syndbeacon" + spawn_text = "warps in from" + mob_types = list(/mob/living/simple_animal/hostile/syndicate/ranged) + faction = list(ROLE_SYNDICATE) + +/obj/structure/spawner/skeleton + name = "bone pit" + desc = "A pit full of bones, and some still seem to be moving..." + icon_state = "hole" + icon = 'icons/mob/nest.dmi' + max_integrity = 150 + max_mobs = 15 + spawn_time = 150 + mob_types = list(/mob/living/simple_animal/hostile/skeleton) + spawn_text = "climbs out of" + faction = list("skeleton") + +/obj/structure/spawner/mining + name = "monster den" + desc = "A hole dug into the ground, harboring all kinds of monsters found within most caves or mining asteroids." + icon_state = "hole" + max_integrity = 200 + max_mobs = 3 + icon = 'icons/mob/nest.dmi' + spawn_text = "crawls out of" + mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/hivelord, /mob/living/simple_animal/hostile/asteroid/basilisk, /mob/living/simple_animal/hostile/asteroid/fugu) + faction = list("mining") + +/obj/structure/spawner/mining/goldgrub + name = "goldgrub den" + desc = "A den housing a nest of goldgrubs, annoying but arguably much better than anything else you'll find in a nest." + mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub) + +/obj/structure/spawner/mining/goliath + name = "goliath den" + desc = "A den housing a nest of goliaths, oh god why?" + mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath) + +/obj/structure/spawner/mining/hivelord + name = "hivelord den" + desc = "A den housing a nest of hivelords." + mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord) + +/obj/structure/spawner/mining/basilisk + name = "basilisk den" + desc = "A den housing a nest of basilisks, bring a coat." + mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk) + +/obj/structure/spawner/mining/wumborian + name = "wumborian fugu den" + desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?" + mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu) \ No newline at end of file diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index ecc8ee5e8d..053b18d8d2 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -151,9 +151,9 @@ has_data = TRUE /turf/open/floor/plating/asteroid/airless/cave/volcanic - mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /mob/living/simple_animal/hostile/spawner/lavaland/goliath = 3, \ - /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40, /mob/living/simple_animal/hostile/spawner/lavaland = 2, \ - /mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30, /mob/living/simple_animal/hostile/spawner/lavaland/legion = 3, \ + mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /obj/structure/spawner/lavaland/goliath = 3, \ + /mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40, /obj/structure/spawner/lavaland = 2, \ + /mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30, /obj/structure/spawner/lavaland/legion = 3, \ SPAWN_MEGAFAUNA = 6, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10) data_having_type = /turf/open/floor/plating/asteroid/airless/cave/volcanic/has_data @@ -274,7 +274,7 @@ return //if there's a megafauna within standard view don't spawn anything at all if(ispath(randumb, /mob/living/simple_animal/hostile/asteroid) || istype(H, /mob/living/simple_animal/hostile/asteroid)) return //if the random is a standard mob, avoid spawning if there's another one within 12 tiles - if((ispath(randumb, /mob/living/simple_animal/hostile/spawner/lavaland) || istype(H, /mob/living/simple_animal/hostile/spawner/lavaland)) && get_dist(src, H) <= 2) + if((ispath(randumb, /obj/structure/spawner/lavaland) || istype(H, /obj/structure/spawner/lavaland)) && get_dist(src, H) <= 2) return //prevents tendrils spawning in each other's collapse range new randumb(T) diff --git a/code/game/turfs/simulated/lava.dm b/code/game/turfs/simulated/lava.dm index 2f8ae0cb93..3a474f339c 100644 --- a/code/game/turfs/simulated/lava.dm +++ b/code/game/turfs/simulated/lava.dm @@ -36,7 +36,7 @@ if(burn_stuff(AM)) START_PROCESSING(SSobj, src) -/turf/open/lava/hitby(atom/movable/AM) +/turf/open/lava/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if(burn_stuff(AM)) START_PROCESSING(SSobj, src) diff --git a/code/game/turfs/simulated/wall/misc_walls.dm b/code/game/turfs/simulated/wall/misc_walls.dm index 8b63d60939..d445be91cb 100644 --- a/code/game/turfs/simulated/wall/misc_walls.dm +++ b/code/game/turfs/simulated/wall/misc_walls.dm @@ -25,7 +25,7 @@ if(stored_pulling) stored_pulling.setDir(get_dir(stored_pulling.loc, newloc)) stored_pulling.forceMove(src) - H.start_pulling(stored_pulling, TRUE) + H.start_pulling(stored_pulling, supress_message = TRUE) /turf/closed/wall/mineral/cult/ratvar_act() . = ..() diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 88e68158ed..372902e8d6 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -185,7 +185,6 @@ body += "Shade" body += "
" - if (M.client) body += "

" body += "Other actions:" body += "
" @@ -194,9 +193,9 @@ body += "Thunderdome 2 | " body += "Thunderdome Admin | " body += "Thunderdome Observer | " - - body += usr.client.citaPPoptions(M) // CITADEL - + body += "Make mentor | " + body += "Remove mentor" + body += "Allow reentering round" body += "
" body += "" @@ -1009,3 +1008,36 @@ "Admin login: [key_name(src)]") if(string) message_admins("[string]") + +/client/proc/cmd_admin_man_up(mob/M in GLOB.mob_list) + set category = "Special Verbs" + set name = "Man Up" + + if(!M) + return + if(!check_rights(R_ADMIN)) + return + + to_chat(M, "Man up, and deal with it.
Move on.") + M.playsound_local(M, 'sound/voice/manup.ogg', 50, FALSE, pressure_affected = FALSE) + + log_admin("Man up: [key_name(usr)] told [key_name(M)] to man up") + var/message = "[key_name_admin(usr)] told [key_name_admin(M)] to man up." + message_admins(message) + admin_ticket_log(M, message) + SSblackbox.record_feedback("tally", "admin_verb", 1, "Man Up") + +/client/proc/cmd_admin_man_up_global() + set category = "Special Verbs" + set name = "Man Up Global" + + if(!check_rights(R_ADMIN)) + return + + to_chat(world, "Man up, and deal with it.
Move on.") + for(var/mob/M in GLOB.player_list) + M.playsound_local(M, 'sound/voice/manup.ogg', 50, FALSE, pressure_affected = FALSE) + + log_admin("Man up global: [key_name(usr)] told everybody to man up") + message_admins("[key_name_admin(usr)] told everybody to man up.") + SSblackbox.record_feedback("tally", "admin_verb", 1, "Man Up Global") diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 88d4105124..c66927b856 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -22,7 +22,10 @@ if(!CheckAdminHref(href, href_list)) return - citaTopic(href, href_list) //CITADEL EDIT, MENTORS + if(href_list["makementor"]) + makeMentor(href_list["makementor"]) + else if(href_list["removementor"]) + removeMentor(href_list["removementor"]) if(href_list["ahelp"]) if(!check_rights(R_ADMIN, TRUE)) @@ -907,12 +910,16 @@ dat += "Alien" else dat += "Alien" - //Gang if(jobban_isbanned(M, ROLE_GANG) || isbanned_dept) dat += "Gang" else dat += "Gang" + //Bloodsucker + if(jobban_isbanned(M, ROLE_BLOODSUCKER) || isbanned_dept) + dat += "Bloodsucker" + else + dat += "Bloodsucker" //Other Roles (black) @@ -1715,6 +1722,16 @@ log_admin("[key_name(usr)] forced [key_name(M)] to say: [speech]") message_admins("[key_name_admin(usr)] forced [key_name_admin(M)] to say: [speech]") + else if(href_list["makeeligible"]) + if(!check_rights(R_ADMIN)) + return + var/mob/M = locate(href_list["makeeligible"]) + if(!ismob(M)) + to_chat(usr, "this can only be used on instances of type /mob.") + var/datum/element/ghost_role_eligibility/eli = SSdcs.GetElement(/datum/element/ghost_role_eligibility) + if(M.ckey in eli.timeouts) + eli.timeouts -= M.ckey + else if(href_list["sendtoprison"]) if(!check_rights(R_ADMIN)) return @@ -2846,3 +2863,57 @@ dat += {"Random (default)
"} dat += {"Now: [GLOB.secret_force_mode]"} usr << browse(dat, "window=f_secret") + +/datum/admins/proc/makeMentor(ckey) + if(!usr.client) + return + if (!check_rights(0)) + return + if(!ckey) + return + var/client/C = GLOB.directory[ckey] + if(C) + if(check_rights_for(C, R_ADMIN,0)) + to_chat(usr, "The client chosen is an admin! Cannot mentorize.") + return + if(SSdbcore.Connect()) + var/datum/DBQuery/query_get_mentor = SSdbcore.NewQuery("SELECT id FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") + if(query_get_mentor.NextRow()) + to_chat(usr, "[ckey] is already a mentor.") + return + var/datum/DBQuery/query_add_mentor = SSdbcore.NewQuery("INSERT INTO `[format_table_name("mentor")]` (`id`, `ckey`) VALUES (null, '[ckey]')") + if(!query_add_mentor.warn_execute()) + return + var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new mentor [ckey]');") + if(!query_add_admin_log.warn_execute()) + return + else + to_chat(usr, "Failed to establish database connection. The changes will last only for the current round.") + new /datum/mentors(ckey) + to_chat(usr, "New mentor added.") + +/datum/admins/proc/removeMentor(ckey) + if(!usr.client) + return + if (!check_rights(0)) + return + if(!ckey) + return + var/client/C = GLOB.directory[ckey] + if(C) + if(check_rights_for(C, R_ADMIN,0)) + to_chat(usr, "The client chosen is an admin, not a mentor! Cannot de-mentorize.") + return + C.remove_mentor_verbs() + C.mentor_datum = null + GLOB.mentors -= C + if(SSdbcore.Connect()) + var/datum/DBQuery/query_remove_mentor = SSdbcore.NewQuery("DELETE FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") + if(!query_remove_mentor.warn_execute()) + return + var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed mentor [ckey]');") + if(!query_add_admin_log.warn_execute()) + return + else + to_chat(usr, "Failed to establish database connection. The changes will last only for the current round.") + to_chat(usr, "Mentor removed.") diff --git a/code/modules/antagonists/abductor/machinery/console.dm b/code/modules/antagonists/abductor/machinery/console.dm index 47294bc766..b8d5b1bf6d 100644 --- a/code/modules/antagonists/abductor/machinery/console.dm +++ b/code/modules/antagonists/abductor/machinery/console.dm @@ -46,7 +46,6 @@ dat += "Advanced Baton (2 Credits)
" dat += "Mental Interface Device (2 Credits)
" dat += "Reagent Synthesizer (2 Credits)
" - dat += "Shrink Ray Blaster (2 Credits)
" dat += "Agent Helmet (1 Credit)
" dat += "Agent Vest (1 Credit)
" dat += "Radio Silencer (1 Credit)
" @@ -119,8 +118,6 @@ Dispense(/obj/item/abductor_machine_beacon/chem_dispenser,cost=2) if("tongue") Dispense(/obj/item/organ/tongue/abductor) - if("shrink_ray") - Dispense(/obj/item/gun/energy/shrink_ray,cost=2) updateUsrDialog() /obj/machinery/abductor/console/proc/TeleporterRetrieve() @@ -245,4 +242,4 @@ new item(drop_location) else - say("Insufficent data!") \ No newline at end of file + say("Insufficent data!") diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm index 7534f7c043..05516cc6a2 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm @@ -45,10 +45,10 @@ bonus_damage *= 3 //total 30 damage on cultists, 50 with ratvar GLOB.clockwork_vitality += target.adjustFireLoss(bonus_damage) //adds the damage done to existing vitality -/obj/item/clockwork/weapon/ratvarian_spear/throw_impact(atom/target) - var/turf/T = get_turf(target) - if(isliving(target)) - var/mob/living/L = target +/obj/item/clockwork/weapon/ratvarian_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + var/turf/T = get_turf(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(is_servant_of_ratvar(L)) if(L.put_in_active_hand(src)) L.visible_message("[L] catches [src] out of the air!") diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index f5be94a0e7..f14aeede9a 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -265,7 +265,7 @@ to_chat(user, "The bola seems to take on a life of its own!") throw_impact(user) -/obj/item/restraints/legcuffs/bola/cult/throw_impact(atom/hit_atom) +/obj/item/restraints/legcuffs/bola/cult/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(iscultist(hit_atom)) return . = ..() @@ -690,10 +690,10 @@ /obj/item/twohanded/cult_spear/update_icon() icon_state = "bloodspear[wielded]" -/obj/item/twohanded/cult_spear/throw_impact(atom/target) - var/turf/T = get_turf(target) - if(isliving(target)) - var/mob/living/L = target +/obj/item/twohanded/cult_spear/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + var/turf/T = get_turf(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(iscultist(L)) playsound(src, 'sound/weapons/throwtap.ogg', 50) if(L.put_in_active_hand(src)) @@ -987,11 +987,11 @@ return TRUE return FALSE -/obj/item/shield/mirror/throw_impact(atom/target, throwingdatum) - var/turf/T = get_turf(target) +/obj/item/shield/mirror/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + var/turf/T = get_turf(hit_atom) var/datum/thrownthing/D = throwingdatum - if(isliving(target)) - var/mob/living/L = target + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(iscultist(L)) playsound(src, 'sound/weapons/throwtap.ogg', 50) if(L.put_in_active_hand(src)) diff --git a/code/modules/antagonists/revenant/revenant.dm b/code/modules/antagonists/revenant/revenant.dm index 1d6a31b072..9754d146c3 100644 --- a/code/modules/antagonists/revenant/revenant.dm +++ b/code/modules/antagonists/revenant/revenant.dm @@ -44,7 +44,7 @@ wander = FALSE density = FALSE movement_type = FLYING - anchored = TRUE + move_resist = MOVE_FORCE_OVERPOWERING mob_size = MOB_SIZE_TINY pass_flags = PASSTABLE | PASSGRILLE | PASSMOB speed = 1 @@ -361,7 +361,7 @@ user.dropItemToGround(src) scatter() -/obj/item/ectoplasm/revenant/throw_impact(atom/hit_atom) +/obj/item/ectoplasm/revenant/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(inert) return diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index 9079b79c3d..b223992d2c 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -142,7 +142,7 @@ . = ..() olddir = dir -/obj/item/assembly/infra/throw_impact() +/obj/item/assembly/infra/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(!olddir) return diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index a42fad82c0..c67b79478e 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -130,10 +130,10 @@ return FALSE -/obj/item/assembly/mousetrap/hitby(A as mob|obj) +/obj/item/assembly/mousetrap/hitby(atom/hit_atom, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(!armed) return ..() - visible_message("[src] is triggered by [A].") + visible_message("[src] is triggered by [hit_atom].") triggered(null) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index 389f1a69f3..632542f605 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -267,12 +267,13 @@ /atom/movable/proc/experience_pressure_difference(pressure_difference, direction, pressure_resistance_prob_delta = 0) var/const/PROBABILITY_OFFSET = 25 var/const/PROBABILITY_BASE_PRECENT = 75 + var/max_force = sqrt(pressure_difference)*(MOVE_FORCE_DEFAULT / 5) set waitfor = 0 var/move_prob = 100 if (pressure_resistance > 0) move_prob = (pressure_difference/pressure_resistance*PROBABILITY_BASE_PRECENT)-PROBABILITY_OFFSET move_prob += pressure_resistance_prob_delta - if (move_prob > PROBABILITY_OFFSET && prob(move_prob)) + if (move_prob > PROBABILITY_OFFSET && prob(move_prob) && (move_resist != INFINITY) && (!anchored && (max_force >= (move_resist * MOVE_FORCE_PUSH_RATIO))) || (anchored && (max_force >= (move_resist * MOVE_FORCE_FORCEPUSH_RATIO)))) step(src, direction) last_high_pressure_movement_air_cycle = SSair.times_fired diff --git a/code/modules/atmospherics/machinery/atmosmachinery.dm b/code/modules/atmospherics/machinery/atmosmachinery.dm index 0450e7e8dd..7edea275b6 100644 --- a/code/modules/atmospherics/machinery/atmosmachinery.dm +++ b/code/modules/atmospherics/machinery/atmosmachinery.dm @@ -14,6 +14,7 @@ Pipelines + Other Objects -> Pipe network /obj/machinery/atmospherics anchored = TRUE + move_resist = INFINITY //Moving a connected machine without actually doing the normal (dis)connection things will probably cause a LOT of issues. idle_power_usage = 0 active_power_usage = 0 power_channel = ENVIRON diff --git a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm index 4e91ee50c3..539b5ce57a 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/cryo.dm @@ -57,6 +57,11 @@ heat_capacity = initial(heat_capacity) / C conduction_coefficient = initial(conduction_coefficient) * C +/obj/machinery/atmospherics/components/unary/cryo_cell/examine(mob/user) //this is leaving out everything but efficiency since they follow the same idea of "better matter bin, better results" + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Efficiency at [efficiency*100]%." + /obj/machinery/atmospherics/components/unary/cryo_cell/Destroy() QDEL_NULL(radio) QDEL_NULL(beaker) diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index 2e643cc05d..255a5a2eec 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -207,6 +207,9 @@ message_admins("[key_name(src)] (job: [src.job ? "[src.job]" : "None"]) [is_special_character(src) ? "(ANTAG!) " : ""][ghosting ? "ghosted" : "committed suicide"] at [AREACOORD(src)].") /mob/living/proc/canSuicide() + if(!CONFIG_GET(flag/suicide_allowed)) + to_chat(src, "Suicide is not enabled in the config.") + return FALSE switch(stat) if(CONSCIOUS) return TRUE diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 69c50c5461..7df10b56f7 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -250,6 +250,36 @@ throwforce = 12 glass_colour_type = /datum/client_colour/glass_colour/red +/obj/item/clothing/glasses/sunglasses/stunglasses + name = "stunglasses" + desc = "Sunglasses with inbuilt flashes. Made for those who prefer to walk around in style, who needs clumsy flashes anyway?" + actions_types = list(/datum/action/item_action/flash) + var/obj/item/assembly/flash/installed + +/obj/item/clothing/glasses/sunglasses/stunglasses/Initialize() + . = ..() + if (!installed) + installed = new(src) + +/obj/item/clothing/glasses/sunglasses/stunglasses/ui_action_click(mob/user) + if (installed && !installed.crit_fail) + installed.attack_self(user) + else + to_chat(user, "Install a new flash in [src]!") + +/obj/item/clothing/glasses/sunglasses/stunglasses/attackby(obj/item/W,mob/user) + if (istype(W,/obj/item/screwdriver)) + if (installed) + installed.forceMove(get_turf(src)) + to_chat(user, "You remove [installed] from [src].") + installed = null + if (istype(W,/obj/item/assembly/flash)) + if (!installed) + W.forceMove(src) + to_chat(user, "You install [W] into [src].") + installed = W + . = ..() + /obj/item/clothing/glasses/welding name = "welding goggles" desc = "Protects the eyes from welders; approved by the mad scientist association." @@ -458,4 +488,4 @@ if(client && client.prefs.uses_glasses_colour && glasses_equipped) add_client_colour(G.glass_colour_type) else - remove_client_colour(G.glass_colour_type) + remove_client_colour(G.glass_colour_type) \ No newline at end of file diff --git a/code/modules/clothing/under/_under.dm b/code/modules/clothing/under/_under.dm index 8424ea962c..63e3a63968 100644 --- a/code/modules/clothing/under/_under.dm +++ b/code/modules/clothing/under/_under.dm @@ -91,6 +91,9 @@ if(user && notifyAttach) to_chat(user, "You attach [I] to [src].") + if((flags_inv & HIDEACCESSORY) || (A.flags_inv & HIDEACCESSORY)) + return TRUE + var/accessory_color = attached_accessory.item_color if(!accessory_color) accessory_color = attached_accessory.icon_state diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index a4d2c17fd6..86d2b40d0f 100644 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -370,22 +370,25 @@ ///////////////////// /obj/item/clothing/accessory/padding - name = "soft padding" - desc = "Some long sheets of padding to help soften the blows of a physical attacks." + name = "protective padding" + desc = "A soft padding meant to cushion the wearer from melee harm." icon_state = "padding" item_color = "nothing" - armor = list("melee" = 15, "bullet" = 10, "laser" = 0, "energy" = 0, "bomb" = 5, "bio" = 0, "rad" = 0, "fire" = -20, "acid" = 45) + armor = list("melee" = 20, "bullet" = 10, "laser" = 0, "energy" = 0, "bomb" = 5, "bio" = 0, "rad" = 0, "fire" = -20, "acid" = 45) + flags_inv = HIDEACCESSORY //hidden from indiscrete mob examines. /obj/item/clothing/accessory/kevlar - name = "kevlar sheets" - desc = "Long thin sheets of kevlar to help resist bullets and some physical attacks." + name = "kevlar padding" + desc = "A layered kevlar padding meant to cushion the wearer from ballistic harm." icon_state = "padding" item_color = "nothing" armor = list("melee" = 10, "bullet" = 20, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 25) + flags_inv = HIDEACCESSORY /obj/item/clothing/accessory/plastics - name = "underling plastic sheet" - desc = "A full body sheet of white plastic to help defuse lasers and energy based weapons." + name = "ablative padding" + desc = "A thin ultra-refractory composite padding meant to cushion the wearer from energy lasers harm." icon_state = "plastics" item_color = "nothing" - armor = list("melee" = 0, "bullet" = 0, "laser" = 20, "energy" = 10, "bomb" = 0, "bio" = 30, "rad" = 0, "fire" = 0, "acid" = -40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 20, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 20, "acid" = -40) + flags_inv = HIDEACCESSORY diff --git a/code/modules/crafting/recipes/recipes_clothing.dm b/code/modules/crafting/recipes/recipes_clothing.dm index 26de5f380d..3e036c7b29 100644 --- a/code/modules/crafting/recipes/recipes_clothing.dm +++ b/code/modules/crafting/recipes/recipes_clothing.dm @@ -86,7 +86,17 @@ tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) reqs = list(/obj/item/clothing/glasses/sunglasses/reagent = 1) category = CAT_CLOTHING - +/* //Kevinz doesn't want it as a recipe for now, leaving it in if anything ever changes to let it in +/datum/crafting_recipe/stunglasses + name = "Stunglasses" + result = /obj/item/clothing/glasses/sunglasses/stunglasses + time = 60 + tools = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER) + reqs = list(/obj/item/assembly/flash = 1, + /obj/item/clothing/glasses/sunglasses = 1, + /obj/item/stack/cable_coil = 5) + category = CAT_CLOTHING +*/ /datum/crafting_recipe/ghostsheet name = "Ghost Sheet" result = /obj/item/clothing/suit/ghost_sheet diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index 65d4af56bd..d4f51e995e 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -43,6 +43,9 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 icon = 'icons/obj/objects.dmi' icon_state = "immrod" throwforce = 100 + move_force = INFINITY + move_resist = INFINITY + pull_force = INFINITY density = TRUE anchored = TRUE flags_1 = PREVENT_CONTENTS_EXPLOSION_1 diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index f5262742e2..83dbad0246 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -214,9 +214,9 @@ GLOBAL_LIST_INIT(hallucination_list, list( . = ..() name = "alien hunter ([rand(1, 1000)])" -/obj/effect/hallucination/simple/xeno/throw_impact(A) +/obj/effect/hallucination/simple/xeno/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) update_icon("alienh_pounce") - if(A == target && target.stat!=DEAD) + if(hit_atom == target && target.stat!=DEAD) target.Knockdown(100) target.visible_message("[target] flails around wildly.","[name] pounces on you!") diff --git a/code/modules/food_and_drinks/drinks/drinks.dm b/code/modules/food_and_drinks/drinks/drinks.dm index 7111ae416b..cd5c9d850b 100644 --- a/code/modules/food_and_drinks/drinks/drinks.dm +++ b/code/modules/food_and_drinks/drinks/drinks.dm @@ -101,10 +101,10 @@ to_chat(user, "You heat [name] with [I]!") ..() -/obj/item/reagent_containers/food/drinks/throw_impact(atom/target, datum/thrownthing/throwinfo) +/obj/item/reagent_containers/food/drinks/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(!.) //if the bottle wasn't caught - smash(target, throwinfo.thrower, TRUE) + smash(hit_atom, throwingdatum?.thrower, TRUE) /obj/item/reagent_containers/food/drinks/proc/smash(atom/target, mob/thrower, ranged = FALSE) if(!isGlass) diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index 757af11b62..7f2b24ca11 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -505,7 +505,7 @@ isGlass = FALSE return -/obj/item/reagent_containers/food/drinks/bottle/molotov/throw_impact(atom/target,datum/thrownthing/throwdata) +/obj/item/reagent_containers/food/drinks/bottle/molotov/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) var/firestarter = 0 for(var/datum/reagent/R in reagents.reagent_list) for(var/A in accelerants) @@ -513,8 +513,8 @@ firestarter = 1 break if(firestarter && active) - target.fire_act() - new /obj/effect/hotspot(get_turf(target)) + hit_atom.fire_act() + new /obj/effect/hotspot(get_turf(hit_atom)) ..() /obj/item/reagent_containers/food/drinks/bottle/molotov/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/food_and_drinks/food/snacks_egg.dm b/code/modules/food_and_drinks/food/snacks_egg.dm index 183e64ff7e..f01966a0ff 100644 --- a/code/modules/food_and_drinks/food/snacks_egg.dm +++ b/code/modules/food_and_drinks/food/snacks_egg.dm @@ -31,7 +31,7 @@ var/color = mix_color_from_reagents(reagents.reagent_list) add_atom_colour(color, FIXED_COLOUR_PRIORITY) -/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom) +/obj/item/reagent_containers/food/snacks/egg/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? var/turf/T = get_turf(hit_atom) new/obj/effect/decal/cleanable/egg_smudge(T) diff --git a/code/modules/food_and_drinks/food/snacks_other.dm b/code/modules/food_and_drinks/food/snacks_other.dm index 0c17814c98..41b08e8c7f 100644 --- a/code/modules/food_and_drinks/food/snacks_other.dm +++ b/code/modules/food_and_drinks/food/snacks_other.dm @@ -443,8 +443,8 @@ head.color = C add_overlay(head) -/obj/item/reagent_containers/food/snacks/lollipop/throw_impact(atom/A) - ..(A) +/obj/item/reagent_containers/food/snacks/lollipop/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + ..(hit_atom) throw_speed = 1 throwforce = 0 diff --git a/code/modules/food_and_drinks/food/snacks_pie.dm b/code/modules/food_and_drinks/food/snacks_pie.dm index 357a921c66..0c3623efda 100644 --- a/code/modules/food_and_drinks/food/snacks_pie.dm +++ b/code/modules/food_and_drinks/food/snacks_pie.dm @@ -29,7 +29,7 @@ foodtype = GRAIN | DAIRY | SUGAR var/stunning = TRUE -/obj/item/reagent_containers/food/snacks/pie/cream/throw_impact(atom/hit_atom) +/obj/item/reagent_containers/food/snacks/pie/cream/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(!.) //if we're not being caught splat(hit_atom) diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm index 27ee54815f..f3b8e466f3 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm @@ -66,10 +66,12 @@ God bless America. oil_use = initial(oil_use) - (oil_efficiency * 0.0095) fry_speed = oil_efficiency -/obj/machinery/deepfryer/examine() +/obj/machinery/deepfryer/examine(mob/user) . = ..() if(frying) . += "You can make out \a [frying] in the oil." + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Frying at [fry_speed*100]% speed.
Using [oil_use*10] units of oil per second.
" /obj/machinery/deepfryer/attackby(obj/item/I, mob/user) if(istype(I, /obj/item/reagent_containers/pill)) diff --git a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm index e5c5a4f933..4406491f10 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/gibber.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/gibber.dm @@ -30,6 +30,14 @@ if(M.rating >= 2) ignore_clothing = TRUE +/obj/machinery/gibber/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Outputting [meat_produced] meat slab(s) after [gibtime*0.1] seconds of processing." + for(var/obj/item/stock_parts/manipulator/M in component_parts) + if(M.rating >= 2) + . += "Gibber has been upgraded to process inorganic materials." + /obj/machinery/gibber/update_icon() cut_overlays() if (dirty) diff --git a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm index c25cb2288f..3d7341308b 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/monkeyrecycler.dm @@ -1,6 +1,6 @@ /obj/machinery/monkey_recycler name = "monkey recycler" - desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces 1 cube for every 5 monkeys inserted." // except it literally never does + desc = "A machine used for recycling dead monkeys into monkey cubes." // except it literally never does icon = 'icons/obj/kitchen.dmi' icon_state = "grinder" layer = BELOW_OBJ_LAYER @@ -22,7 +22,11 @@ cubes_made = M.rating cube_production = cubes_made required_grind = req_grind - src.desc = "A machine used for recycling dead monkeys into monkey cubes. It currently produces [cubes_made] cube(s) for every [required_grind] monkey(s) inserted." + +/obj/machinery/monkey_recycler/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Producing [cube_production] cubes for every monkey inserted." /obj/machinery/monkey_recycler/attackby(obj/item/O, mob/user, params) if(default_deconstruction_screwdriver(user, "grinder_open", "grinder", O)) diff --git a/code/modules/food_and_drinks/kitchen_machinery/processor.dm b/code/modules/food_and_drinks/kitchen_machinery/processor.dm index 35ce25bbaf..b81c127523 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/processor.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/processor.dm @@ -21,6 +21,11 @@ for(var/obj/item/stock_parts/manipulator/M in component_parts) rating_speed = M.rating +/obj/machinery/processor/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Outputting [rating_amount] item(s) at [rating_speed*100]% speed." + /obj/machinery/processor/proc/process_food(datum/food_processor_process/recipe, atom/movable/what) if (recipe.output && loc && !QDELETED(src)) for(var/i = 0, i < rating_amount, i++) diff --git a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm index 893a53ede7..7619f68448 100644 --- a/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/kitchen_machinery/smartfridge.dm @@ -33,6 +33,11 @@ for(var/obj/item/stock_parts/matter_bin/B in component_parts) max_n_of_items = 1500 * B.rating +/obj/machinery/smartfridge/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: This unit can hold a maximum of [max_n_of_items] items." + /obj/machinery/smartfridge/power_change() ..() update_icon() diff --git a/code/modules/food_and_drinks/pizzabox.dm b/code/modules/food_and_drinks/pizzabox.dm index 351495b97a..bd556b8397 100644 --- a/code/modules/food_and_drinks/pizzabox.dm +++ b/code/modules/food_and_drinks/pizzabox.dm @@ -231,7 +231,7 @@ if(boxes.len >= 3 && prob(25 * boxes.len)) disperse_pizzas() -/obj/item/pizzabox/throw_impact(atom/movable/AM) +/obj/item/pizzabox/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(boxes.len >= 2 && prob(20 * boxes.len)) disperse_pizzas() diff --git a/code/modules/holiday/halloween/halloween.dm b/code/modules/holiday/halloween/halloween.dm index 24225c1a20..d3b9b92b4f 100644 --- a/code/modules/holiday/halloween/halloween.dm +++ b/code/modules/holiday/halloween/halloween.dm @@ -132,7 +132,7 @@ speak_emote = list("howls") emote_hear = list("wails","screeches") density = FALSE - anchored = TRUE + move_resist = MOVE_FORCE_OVERPOWERING incorporeal_move = 1 layer = 4 var/timer = 0 diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index bd4c26e0f2..2b116bbfd3 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -450,7 +450,7 @@ reagents.add_reagent(R, 30) name = "[R] Potion" -/obj/item/reagent_containers/potion_container/throw_impact(atom/target) +/obj/item/reagent_containers/potion_container/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() sleep(20) var/datum/effect_system/smoke_spread/chem/s = new() diff --git a/code/modules/holodeck/items.dm b/code/modules/holodeck/items.dm index 7bd2ac689b..206a5c14a3 100644 --- a/code/modules/holodeck/items.dm +++ b/code/modules/holodeck/items.dm @@ -80,7 +80,7 @@ item_state = "dodgeball" desc = "Used for playing the most violent and degrading of childhood games." -/obj/item/toy/beach_ball/holoball/dodgeball/throw_impact(atom/hit_atom) +/obj/item/toy/beach_ball/holoball/dodgeball/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if((ishuman(hit_atom))) var/mob/living/carbon/M = hit_atom @@ -123,7 +123,7 @@ else ..() -/obj/structure/holohoop/hitby(atom/movable/AM) +/obj/structure/holohoop/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) if (isitem(AM) && !istype(AM,/obj/item/projectile)) if(prob(50)) AM.forceMove(get_turf(src)) diff --git a/code/modules/hydroponics/biogenerator.dm b/code/modules/hydroponics/biogenerator.dm index e946973ded..2376010408 100644 --- a/code/modules/hydroponics/biogenerator.dm +++ b/code/modules/hydroponics/biogenerator.dm @@ -52,6 +52,12 @@ productivity = P max_items = max_storage + +/obj/machinery/biogenerator/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Productivity at [productivity*100]%.
Matter consumption reduced by [(efficiency*25)-25]%.
Machine can hold up to [max_items] pieces of produce.
" + /obj/machinery/biogenerator/on_reagent_change(changetype) //When the reagents change, change the icon as well. update_icon() diff --git a/code/modules/hydroponics/grown.dm b/code/modules/hydroponics/grown.dm index bb751c993a..f99cfde92d 100644 --- a/code/modules/hydroponics/grown.dm +++ b/code/modules/hydroponics/grown.dm @@ -91,7 +91,7 @@ squash(user) ..() -/obj/item/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom) +/obj/item/reagent_containers/food/snacks/grown/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? if(seed) for(var/datum/plant_gene/trait/T in seed.genes) diff --git a/code/modules/hydroponics/growninedible.dm b/code/modules/hydroponics/growninedible.dm index bdbf999f7a..ef925e3965 100644 --- a/code/modules/hydroponics/growninedible.dm +++ b/code/modules/hydroponics/growninedible.dm @@ -48,7 +48,7 @@ return 1 return 0 -/obj/item/grown/throw_impact(atom/hit_atom) +/obj/item/grown/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //was it caught by a mob? if(seed) for(var/datum/plant_gene/trait/T in seed.genes) diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 2d0d2c5282..1cd63db6da 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -46,6 +46,11 @@ maxwater = tmp_capacity * 50 // Up to 300 maxnutri = tmp_capacity * 5 // Up to 30 +/obj/machinery/hydroponics/constructable/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Tray efficiency at [rating*100]%." + /obj/machinery/hydroponics/Destroy() if(myseed) qdel(myseed) diff --git a/code/modules/hydroponics/seed_extractor.dm b/code/modules/hydroponics/seed_extractor.dm index 5af19b8431..617b980654 100644 --- a/code/modules/hydroponics/seed_extractor.dm +++ b/code/modules/hydroponics/seed_extractor.dm @@ -56,6 +56,11 @@ for(var/obj/item/stock_parts/manipulator/M in component_parts) seed_multiplier = M.rating +/obj/machinery/seed_extractor/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Extracting [seed_multiplier] seed(s) per piece of produce.
Machine can store up to [max_seeds]% seeds.
" + /obj/machinery/seed_extractor/attackby(obj/item/O, mob/user, params) if(default_deconstruction_screwdriver(user, "sextractor_open", "sextractor", O)) diff --git a/code/modules/mapping/ruins.dm b/code/modules/mapping/ruins.dm index 9c578badb1..34ce6ef35c 100644 --- a/code/modules/mapping/ruins.dm +++ b/code/modules/mapping/ruins.dm @@ -22,6 +22,8 @@ for(var/i in get_affected_turfs(central_turf, 1)) var/turf/T = i + for(var/obj/structure/spawner/nest in T) + qdel(nest) for(var/mob/living/simple_animal/monster in T) qdel(monster) for(var/obj/structure/flora/ash/plant in T) diff --git a/code/modules/mining/fulton.dm b/code/modules/mining/fulton.dm index f46f4f785c..fd366670f0 100644 --- a/code/modules/mining/fulton.dm +++ b/code/modules/mining/fulton.dm @@ -11,6 +11,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) var/uses_left = 3 var/can_use_indoors var/safe_for_living_creatures = 1 + var/max_force_fulton = MOVE_FORCE_STRONG /obj/item/extraction_pack/examine() . = ..() @@ -57,7 +58,7 @@ GLOBAL_LIST_EMPTY(total_extraction_beacons) return if(!isturf(A.loc)) // no extracting stuff inside other stuff return - if(A.anchored) + if(A.anchored || (A.move_resist > max_force_fulton)) return to_chat(user, "You start attaching the pack to [A]...") if(do_after(user,50,target=A)) diff --git a/code/modules/mining/ores_coins.dm b/code/modules/mining/ores_coins.dm index 1c83c70d95..7765bf8713 100644 --- a/code/modules/mining/ores_coins.dm +++ b/code/modules/mining/ores_coins.dm @@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(sand_recipes, list(\ recipes = GLOB.sand_recipes . = ..() -/obj/item/stack/ore/glass/throw_impact(atom/hit_atom) +/obj/item/stack/ore/glass/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(..() || !ishuman(hit_atom)) return var/mob/living/carbon/human/C = hit_atom diff --git a/code/modules/mob/camera/camera.dm b/code/modules/mob/camera/camera.dm index a1f46c0a64..ff1d9231f7 100644 --- a/code/modules/mob/camera/camera.dm +++ b/code/modules/mob/camera/camera.dm @@ -3,7 +3,8 @@ /mob/camera name = "camera mob" density = FALSE - anchored = TRUE + move_force = INFINITY + move_resist = INFINITY status_flags = GODMODE // You can't damage it. mouse_opacity = MOUSE_OPACITY_TRANSPARENT see_in_dark = 7 diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index 90e16649c9..0c50cb0468 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -4,6 +4,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) /mob/dead sight = SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF + move_resist = INFINITY throwforce = 0 /mob/dead/Initialize() diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm index ae635fa371..0418b281e6 100644 --- a/code/modules/mob/dead/new_player/new_player.dm +++ b/code/modules/mob/dead/new_player/new_player.dm @@ -12,8 +12,6 @@ stat = DEAD canmove = FALSE - anchored = TRUE // don't get pushed around - var/mob/living/new_character //for instant transfer once the round is set up //Used to make sure someone doesn't get spammed with messages if they're ineligible for roles diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index d234aafca6..3d07649e2f 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -12,7 +12,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) stat = DEAD density = FALSE canmove = 0 - anchored = TRUE // don't get pushed around see_invisible = SEE_INVISIBLE_OBSERVER see_in_dark = 100 invisibility = INVISIBILITY_OBSERVER @@ -664,10 +663,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(src, "This creature is too powerful for you to possess!") return 0 - if(istype (target, /mob/living/simple_animal/hostile/spawner)) - to_chat(src, "This isn't really a creature, now is it!") - return 0 - if(can_reenter_corpse && mind && mind.current) if(alert(src, "Your soul is still tied to your former life as [mind.current.name], if you go forward there is no going back to that life. Are you sure you wish to continue?", "Move On", "Yes", "No") == "No") return 0 diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index d830957056..8de60cba2f 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -5,7 +5,7 @@ /mob/living/carbon/alien/get_ear_protection() return 2 //no ears -/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush) +/mob/living/carbon/alien/hitby(atom/movable/AM, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum) return ..(AM, skipcatch = TRUE, hitpush = FALSE) /mob/living/carbon/alien/can_embed(obj/item/I) diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 3babab4586..b20383301d 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -54,15 +54,15 @@ weather_immunities -= "lava" update_icons() -/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/A) +/mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!leaping) return ..() pounce_cooldown = world.time + pounce_cooldown_time - if(A) - if(isliving(A)) - var/mob/living/L = A + if(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(!L.check_shields(src, 0, "the [name]", attack_type = LEAP_ATTACK)) L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") L.Knockdown(100) @@ -72,8 +72,8 @@ Knockdown(40, 1, 1) toggle_leap(0) - else if(A.density && !A.CanPass(src)) - visible_message("[src] smashes into [A]!", "[src] smashes into [A]!") + else if(hit_atom.density && !hit_atom.CanPass(src)) + visible_message("[src] smashes into [hit_atom]!", "[src] smashes into [hit_atom]!") Knockdown(40, 1, 1) if(leaping) diff --git a/code/modules/mob/living/carbon/alien/larva/larva.dm b/code/modules/mob/living/carbon/alien/larva/larva.dm index 8e1e5aab8d..fb26a40350 100644 --- a/code/modules/mob/living/carbon/alien/larva/larva.dm +++ b/code/modules/mob/living/carbon/alien/larva/larva.dm @@ -56,7 +56,7 @@ /mob/living/carbon/alien/larva/toggle_throw_mode() return -/mob/living/carbon/alien/larva/start_pulling() +/mob/living/carbon/alien/larva/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) return /mob/living/carbon/alien/larva/stripPanelUnequip(obj/item/what, mob/who) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 0f6fc7e944..8e5e327f39 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -115,7 +115,7 @@ if(icon_state == "[initial(icon_state)]_thrown") icon_state = "[initial(icon_state)]" -/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom) +/obj/item/clothing/mask/facehugger/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(stat == CONSCIOUS) icon_state = "[initial(icon_state)]" diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index e8f42b707c..6123c5b60f 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -94,15 +94,13 @@ return 1 return ..() -/mob/living/carbon/throw_impact(atom/hit_atom, throwingdatum) +/mob/living/carbon/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() var/hurt = TRUE - if(istype(throwingdatum, /datum/thrownthing)) - var/datum/thrownthing/D = throwingdatum - if(iscyborg(D.thrower)) - var/mob/living/silicon/robot/R = D.thrower - if(!R.emagged) - hurt = FALSE + if(throwingdatum?.thrower && iscyborg(throwingdatum.thrower)) + var/mob/living/silicon/robot/R = throwingdatum.thrower + if(!R.emagged) + hurt = FALSE if(hit_atom.density && isturf(hit_atom)) if(hurt) Knockdown(20) @@ -160,7 +158,7 @@ var/random_turn = a_intent == INTENT_HARM //END OF CIT CHANGES - var/obj/item/I = src.get_active_held_item() + var/obj/item/I = get_active_held_item() var/atom/movable/thrown_thing var/mob/living/throwable_mob @@ -201,11 +199,11 @@ if(thrown_thing) visible_message("[src] has thrown [thrown_thing].") - src.log_message("has thrown [thrown_thing]", LOG_ATTACK) + log_message("has thrown [thrown_thing]", LOG_ATTACK) do_attack_animation(target, no_effect = 1) playsound(loc, 'sound/weapons/punchmiss.ogg', 50, 1, -1) newtonian_move(get_dir(target, src)) - thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, random_turn) + thrown_thing.safe_throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src, null, null, null, move_force, random_turn) @@ -463,7 +461,7 @@ I.throw_at(target,I.throw_range,I.throw_speed,src) if(61 to 90) //throw it down to the floor var/turf/target = get_turf(loc) - I.throw_at(target,I.throw_range,I.throw_speed,src) + I.safe_throw_at(target,I.throw_range,I.throw_speed,src, force = move_force) /mob/living/carbon/Stat() ..() diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index e212e0e713..8edd5847de 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -41,7 +41,7 @@ var/accessory_msg if(istype(w_uniform, /obj/item/clothing/under)) var/obj/item/clothing/under/U = w_uniform - if(U.attached_accessory) + if(U.attached_accessory && !(U.attached_accessory.flags_inv & HIDEACCESSORY) && !(U.flags_inv & HIDEACCESSORY)) accessory_msg += " with [icon2html(U.attached_accessory, user)] \a [U.attached_accessory]" . += "[t_He] [t_is] wearing [w_uniform.get_examine_string(user)][accessory_msg]." diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 2fc4cd8805..934e0f08dc 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -102,7 +102,7 @@ return TRUE return FALSE -/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) +/mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) return dna?.species?.spec_hitby(AM, src) || ..() /mob/living/carbon/human/grabbedby(mob/living/carbon/user, supress_message = 0) diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm index 6eb4868202..3277c57b75 100644 --- a/code/modules/mob/living/carbon/monkey/combat.dm +++ b/code/modules/mob/living/carbon/monkey/combat.dm @@ -405,7 +405,7 @@ retaliate(Proj.firer) return ..() -/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) +/mob/living/carbon/monkey/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) var/obj/item/I = AM if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index c2a307950c..72b7b580f7 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -75,7 +75,7 @@ return if(ismovableatom(A)) var/atom/movable/AM = A - if(PushAM(AM)) + if(PushAM(AM, move_force)) return /mob/living/Bumped(atom/movable/AM) @@ -218,36 +218,46 @@ return //Called when we want to push an atom/movable -/mob/living/proc/PushAM(atom/movable/AM) +/mob/living/proc/PushAM(atom/movable/AM, force = move_force) if(now_pushing) - return 1 + return TRUE if(moving_diagonally)// no pushing during diagonal moves. - return 1 + return TRUE if(!client && (mob_size < MOB_SIZE_SMALL)) return - if(!AM.anchored) - now_pushing = 1 - var/t = get_dir(src, AM) - if (istype(AM, /obj/structure/window)) - var/obj/structure/window/W = AM - if(W.fulltile) - for(var/obj/structure/window/win in get_step(W,t)) - now_pushing = 0 - return - if(pulling == AM) - stop_pulling() - var/current_dir - if(isliving(AM)) - current_dir = AM.dir - step(AM, t) - if(current_dir) - AM.setDir(current_dir) - now_pushing = 0 + now_pushing = TRUE + var/t = get_dir(src, AM) + var/push_anchored = FALSE + if((AM.move_resist * MOVE_FORCE_CRUSH_RATIO) <= force) + if(move_crush(AM, move_force, t)) + push_anchored = TRUE + if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally + if(force_push(AM, move_force, t, push_anchored)) + push_anchored = TRUE + if((AM.anchored && !push_anchored) || (force < (AM.move_resist * MOVE_FORCE_PUSH_RATIO))) + now_pushing = FALSE + return + if (istype(AM, /obj/structure/window)) + var/obj/structure/window/W = AM + if(W.fulltile) + for(var/obj/structure/window/win in get_step(W,t)) + now_pushing = FALSE + return + if(pulling == AM) + stop_pulling() + var/current_dir + if(isliving(AM)) + current_dir = AM.dir + if(step(AM, t)) + step(src, t) + if(current_dir) + AM.setDir(current_dir) + now_pushing = FALSE -/mob/living/start_pulling(atom/movable/AM, supress_message = 0) +/mob/living/start_pulling(atom/movable/AM, state, force = pull_force, supress_message = FALSE) if(!AM || !src) return FALSE - if(!(AM.can_be_pulled(src))) + if(!(AM.can_be_pulled(src, state, force))) return FALSE if(throwing || incapacitated()) return FALSE diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index fbb483fadb..6a14cce4af 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -107,7 +107,7 @@ /mob/living/proc/can_embed(obj/item/I) return FALSE -/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE) +/mob/living/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) var/obj/item/I var/throwpower = 30 if(isitem(AM)) @@ -189,7 +189,7 @@ adjust_fire_stacks(3) IgniteMob() -/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = 0) +/mob/living/proc/grabbedby(mob/living/carbon/user, supress_message = FALSE) if(user == anchored || !isturf(user.loc)) return FALSE @@ -215,7 +215,7 @@ return FALSE if(!user.pulling || user.pulling != src) - user.start_pulling(src, supress_message) + user.start_pulling(src, supress_message = supress_message) return if(!(status_flags & CANPUSH) || HAS_TRAIT(src, TRAIT_PUSHIMMUNE)) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 5ae649c87e..33cbdb7cc9 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -16,7 +16,7 @@ name = "AI" icon = 'icons/mob/ai.dmi' icon_state = "ai" - anchored = TRUE + move_resist = MOVE_FORCE_OVERPOWERING density = TRUE canmove = FALSE status_flags = CANSTUN|CANPUSH @@ -101,6 +101,7 @@ new/obj/structure/AIcore/deactivated(loc) //New empty terminal. return INITIALIZE_HINT_QDEL //Delete AI. + ADD_TRAIT(src, TRAIT_NO_TELEPORT, src) if(L && istype(L, /datum/ai_laws)) laws = L laws.associate(src) @@ -311,9 +312,16 @@ return // stop if(incapacitated()) return - anchored = !anchored // Toggles the anchor + var/is_anchored = FALSE + if(move_resist == MOVE_FORCE_OVERPOWERING) + move_resist = MOVE_FORCE_NORMAL + else + is_anchored = TRUE + move_resist = MOVE_FORCE_OVERPOWERING + REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src) + ADD_TRAIT(src, TRAIT_NO_TELEPORT, src) - to_chat(src, "You are now [anchored ? "" : "un"]anchored.") + to_chat(src, "You are now [is_anchored ? "" : "un"]anchored.") // the message in the [] will change depending whether or not the AI is anchored /mob/living/silicon/ai/update_canmove() //If the AI dies, mobs won't go through it anymore diff --git a/code/modules/mob/living/silicon/ai/death.dm b/code/modules/mob/living/silicon/ai/death.dm index 6ff744e0da..f978b7b697 100644 --- a/code/modules/mob/living/silicon/ai/death.dm +++ b/code/modules/mob/living/silicon/ai/death.dm @@ -14,7 +14,7 @@ cameraFollow = null - anchored = FALSE //unbolt floorbolts + move_resist = MOVE_FORCE_NORMAL update_canmove() if(eyeobj) eyeobj.setLoc(get_turf(src)) diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm index 6577c26402..bb02bf172d 100644 --- a/code/modules/mob/living/silicon/pai/pai_shell.dm +++ b/code/modules/mob/living/silicon/pai/pai_shell.dm @@ -104,7 +104,7 @@ visible_message("[src] [resting? "lays down for a moment..." : "perks up from the ground"]") update_icon() -/mob/living/silicon/pai/start_pulling(atom/movable/AM, gs) +/mob/living/silicon/pai/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) if(ispAI(AM)) return ..() return FALSE diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index af9e0a3873..d844237a61 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -156,7 +156,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, bike_horn(A) -/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0) +/mob/living/simple_animal/bot/honkbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) playsound(src, honksound, 50, TRUE, -1) var/obj/item/I = AM diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index eba5b51f47..48cf93210e 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -13,8 +13,8 @@ desc = "A Multiple Utility Load Effector bot." icon_state = "mulebot0" density = TRUE - anchored = TRUE - animate_movement=1 + move_resist = MOVE_FORCE_STRONG + animate_movement = 1 health = 50 maxHealth = 50 damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 8d815b302d..8302346a00 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -221,7 +221,7 @@ Auto Patrol: []"}, ..() -/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE) +/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) var/obj/item/I = AM if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby)) diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index ed9c94a534..fbdc32f2c1 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -334,7 +334,7 @@ stored_pulling.forceMove(loc) forceMove(AM) if(stored_pulling) - start_pulling(stored_pulling, TRUE) //drag anything we're pulling through the wall with us by magic + start_pulling(stored_pulling, supress_message = TRUE) //drag anything we're pulling through the wall with us by magic /mob/living/simple_animal/hostile/construct/harvester/AttackingTarget() if(iscarbon(target)) diff --git a/code/modules/mob/living/simple_animal/guardian/types/charger.dm b/code/modules/mob/living/simple_animal/guardian/types/charger.dm index 914d38022f..237ab9d919 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/charger.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/charger.dm @@ -44,15 +44,15 @@ if(!charging) ..() -/mob/living/simple_animal/hostile/guardian/charger/throw_impact(atom/A) +/mob/living/simple_animal/hostile/guardian/charger/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!charging) return ..() - else if(A) - if(isliving(A) && A != summoner) - var/mob/living/L = A + else if(hit_atom) + if(isliving(hit_atom) && hit_atom != summoner) + var/mob/living/L = hit_atom var/blocked = FALSE - if(hasmatchingsummoner(A)) //if the summoner matches don't hurt them + if(hasmatchingsummoner(hit_atom)) //if the summoner matches don't hurt them blocked = TRUE if(L.check_shields(src, 90, "[name]", attack_type = THROWN_PROJECTILE_ATTACK)) blocked = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm index 34903a477b..deb88d677b 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -248,7 +248,7 @@ /mob/living/simple_animal/hostile/jungle/leaper/Goto() return -/mob/living/simple_animal/hostile/jungle/leaper/throw_impact() +/mob/living/simple_animal/hostile/jungle/leaper/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) return /mob/living/simple_animal/hostile/jungle/leaper/update_icons() diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm index 29f48c7295..b786637592 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm @@ -147,7 +147,7 @@ update_icons() Goto(target, move_to_delay, minimum_distance) -/mob/living/simple_animal/hostile/jungle/mook/throw_impact(atom/hit_atom, throwingdatum) +/mob/living/simple_animal/hostile/jungle/mook/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() if(isliving(hit_atom) && attack_state == MOOK_ATTACK_ACTIVE) var/mob/living/L = hit_atom diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm index 38dd17a09b..7565a686bf 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/seedling.dm @@ -29,7 +29,7 @@ projectilesound = 'sound/weapons/pierce.ogg' robust_searching = TRUE stat_attack = UNCONSCIOUS - anchored = TRUE + move_resist = MOVE_FORCE_EXTREMELY_STRONG blood_volume = 0 var/combatant_state = SEEDLING_STATE_NEUTRAL var/obj/seedling_weakpoint/weak_point diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 45745bd84e..83abde2fca 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -158,12 +158,12 @@ Difficulty: Hard DestroySurroundings() ..() -/mob/living/simple_animal/hostile/megafauna/bubblegum/throw_impact(atom/A) +/mob/living/simple_animal/hostile/megafauna/bubblegum/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!charging) return ..() - else if(isliving(A)) - var/mob/living/L = A + else if(isliving(hit_atom)) + var/mob/living/L = hit_atom L.visible_message("[src] slams into [L]!", "[src] slams into you!") L.apply_damage(40, BRUTE) playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, 1) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index af3014cb18..d7c52efe1d 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -21,7 +21,9 @@ maxbodytemp = INFINITY vision_range = 4 aggro_vision_range = 15 - anchored = TRUE + move_force = MOVE_FORCE_OVERPOWERING + move_resist = MOVE_FORCE_OVERPOWERING + pull_force = MOVE_FORCE_OVERPOWERING mob_size = MOB_SIZE_LARGE layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway @@ -37,6 +39,7 @@ /mob/living/simple_animal/hostile/megafauna/Initialize(mapload) . = ..() apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING) + ADD_TRAIT(src, TRAIT_NO_TELEPORT, MEGAFAUNA_TRAIT) /mob/living/simple_animal/hostile/megafauna/Destroy() QDEL_NULL(internal) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index 786d7a9775..c7d90f9556 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -54,7 +54,6 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa weather_immunities = list("lava","ash") stop_automated_movement = TRUE wander = FALSE - anchored = TRUE layer = BELOW_MOB_LAYER AIStatus = AI_OFF var/swarmer_spawn_cooldown = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm index 15f2a0a834..c17e98a7db 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/goliath.dm @@ -27,7 +27,9 @@ throw_message = "does nothing to the rocky hide of the" vision_range = 4 aggro_vision_range = 7 - anchored = TRUE //Stays anchored until death as to be unpullable + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_VERY_STRONG + pull_force = MOVE_FORCE_VERY_STRONG var/pre_attack = 0 var/pre_attack_icon = "Goliath_preattack" loot = list(/obj/item/stack/sheet/animalhide/goliath_hide) @@ -51,7 +53,9 @@ . = 1 /mob/living/simple_animal/hostile/asteroid/goliath/death(gibbed) - anchored = FALSE + move_force = MOVE_FORCE_DEFAULT + move_resist = MOVE_RESIST_DEFAULT + pull_force = PULL_FORCE_DEFAULT ..(gibbed) /mob/living/simple_animal/hostile/asteroid/goliath/OpenFire() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm index 82f85766c2..9e398ce0da 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm @@ -217,7 +217,7 @@ can_infest_dead = TRUE //Legion that spawns Legions -/mob/living/simple_animal/hostile/spawner/legion +/mob/living/simple_animal/hostile/big_legion name = "legion" desc = "One of many." icon = 'icons/mob/lavaland/64x64megafauna.dmi' @@ -226,10 +226,6 @@ icon_dead = "legion" health = 450 maxHealth = 450 - max_mobs = 3 - spawn_time = 200 - spawn_text = "peels itself off from" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion) melee_damage_lower = 20 melee_damage_upper = 20 anchored = FALSE @@ -252,6 +248,10 @@ see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE +/mob/living/simple_animal/hostile/big_legion/Initialize() + .=..() + AddComponent(/datum/component/spawner, list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion), 200, faction, "peels itself off from", 3) + //Tendril-spawned Legion remains, the charred skeletons of those whose bodies sank into laval or fell into chasms. /obj/effect/mob_spawn/human/corpse/charredskeleton name = "charred skeletal remains" diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm index f40e1c0093..0cd788325a 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm @@ -45,7 +45,7 @@ visible_message("[P] has a reduced effect on [src]!") return ..() -/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM)//No floor tiling them to death, wiseguy +/mob/living/simple_animal/hostile/asteroid/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum)//No floor tiling them to death, wiseguy if(istype(AM, /obj/item)) var/obj/item/T = AM if(!stat) diff --git a/code/modules/mob/living/simple_animal/hostile/mushroom.dm b/code/modules/mob/living/simple_animal/hostile/mushroom.dm index 991baee7d8..d023cf0dd8 100644 --- a/code/modules/mob/living/simple_animal/hostile/mushroom.dm +++ b/code/modules/mob/living/simple_animal/hostile/mushroom.dm @@ -172,7 +172,7 @@ if(M.a_intent == INTENT_HARM) Bruise() -/mob/living/simple_animal/hostile/mushroom/hitby(atom/movable/AM) +/mob/living/simple_animal/hostile/mushroom/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) ..() if(istype(AM, /obj/item)) var/obj/item/T = AM diff --git a/code/modules/mob/living/simple_animal/hostile/netherworld.dm b/code/modules/mob/living/simple_animal/hostile/netherworld.dm index 903372b05c..918a2d8acc 100644 --- a/code/modules/mob/living/simple_animal/hostile/netherworld.dm +++ b/code/modules/mob/living/simple_animal/hostile/netherworld.dm @@ -65,33 +65,30 @@ attacktext = "punches" deathmessage = "falls apart into a fine dust." -/mob/living/simple_animal/hostile/spawner/nether +/obj/structure/spawner/nether name = "netherworld link" desc = "A direct link to another dimension full of creatures not very happy to see you. Entering the link would be a very bad idea." icon_state = "nether" - icon_living = "nether" - health = 50 - maxHealth = 50 + max_integrity = 50 spawn_time = 600 //1 minute max_mobs = 15 - mob_biotypes = list(MOB_INORGANIC) icon = 'icons/mob/nest.dmi' spawn_text = "crawls through" mob_types = list(/mob/living/simple_animal/hostile/netherworld/migo, /mob/living/simple_animal/hostile/netherworld, /mob/living/simple_animal/hostile/netherworld/blankbody) - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) faction = list("nether") - deathmessage = "shatters into oblivion." - del_on_death = TRUE -/mob/living/simple_animal/hostile/spawner/nether/attack_hand(mob/user) +/obj/structure/spawner/nether/Initialize() + .=..() + START_PROCESSING(SSprocessing, src) + +/obj/structure/spawner/nether/attack_hand(mob/user) user.visible_message("[user] is violently pulled into the link!", \ "Touching the portal, you are quickly pulled through into a world of unimaginable horror!") contents.Add(user) -/mob/living/simple_animal/hostile/spawner/nether/Life() - ..() - var/list/C = src.get_contents() - for(var/mob/living/M in C) + +/obj/structure/spawner/nether/process() + for(var/mob/living/M in contents) if(M) playsound(src, 'sound/magic/demon_consume.ogg', 50, 1) M.adjustBruteLoss(60) diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm index da423f3788..1e1fa9d41b 100644 --- a/code/modules/mob/living/simple_animal/hostile/statue.dm +++ b/code/modules/mob/living/simple_animal/hostile/statue.dm @@ -44,7 +44,10 @@ search_objects = 1 // So that it can see through walls sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS - anchored = TRUE + + move_force = MOVE_FORCE_EXTREMELY_STRONG + move_resist = MOVE_FORCE_EXTREMELY_STRONG + pull_force = MOVE_FORCE_EXTREMELY_STRONG var/cannot_be_seen = 1 var/mob/living/creator = null diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 0d146df04c..6082bdf705 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -66,7 +66,7 @@ var/buffed = 0 //In the event that you want to have a buffing effect on the mob, but don't want it to stack with other effects, any outside force that applies a buff to a simple mob should at least set this to 1, so we have something to check against var/gold_core_spawnable = NO_SPAWN //If the mob can be spawned with a gold slime core. HOSTILE_SPAWN are spawned with plasma, FRIENDLY_SPAWN are spawned with blood - var/mob/living/simple_animal/hostile/spawner/nest + var/datum/component/spawner/nest var/sentience_type = SENTIENCE_ORGANIC // Sentience type, for slime potions diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index 63d776d6e4..5a1a794d4e 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -243,7 +243,7 @@ /mob/living/simple_animal/slime/doUnEquip(obj/item/W) return -/mob/living/simple_animal/slime/start_pulling(atom/movable/AM) +/mob/living/simple_animal/slime/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) return /mob/living/simple_animal/slime/attack_ui(slot) diff --git a/code/modules/mob/living/simple_animal/spawner.dm b/code/modules/mob/living/simple_animal/spawner.dm deleted file mode 100644 index 0b97a940e4..0000000000 --- a/code/modules/mob/living/simple_animal/spawner.dm +++ /dev/null @@ -1,113 +0,0 @@ -/mob/living/simple_animal/hostile/spawner - name = "monster nest" - icon = 'icons/mob/animal.dmi' - health = 100 - maxHealth = 100 - gender = NEUTER - var/list/spawned_mobs = list() - var/max_mobs = 5 - var/spawn_delay = 0 - var/spawn_time = 300 //30 seconds default - var/mob_types = list(/mob/living/simple_animal/hostile/carp) - var/spawn_text = "emerges from" - status_flags = 0 - anchored = TRUE - AIStatus = AI_OFF - a_intent = INTENT_HARM - stop_automated_movement = 1 - wander = 0 - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 0 - maxbodytemp = 350 - layer = BELOW_MOB_LAYER - sentience_type = SENTIENCE_BOSS - - -/mob/living/simple_animal/hostile/spawner/Destroy() - for(var/mob/living/simple_animal/L in spawned_mobs) - if(L.nest == src) - L.nest = null - spawned_mobs = null - return ..() - -/mob/living/simple_animal/hostile/spawner/Life() - . = ..() - if(!.) // dead - return - spawn_mob() - -/mob/living/simple_animal/hostile/spawner/proc/spawn_mob() - if(spawned_mobs.len >= max_mobs) - return 0 - if(spawn_delay > world.time) - return 0 - spawn_delay = world.time + spawn_time - var/chosen_mob_type = pick(mob_types) - var/mob/living/simple_animal/L = new chosen_mob_type(src.loc) - L.flags_1 |= (flags_1 & ADMIN_SPAWNED_1) //If we were admin spawned, lets have our children count as that as well. - spawned_mobs += L - L.nest = src - L.faction = src.faction - visible_message("[L] [spawn_text] [src].") - -/mob/living/simple_animal/hostile/spawner/syndicate - name = "warp beacon" - icon = 'icons/obj/device.dmi' - icon_state = "syndbeacon" - spawn_text = "warps in from" - mob_types = list(/mob/living/simple_animal/hostile/syndicate/ranged) - faction = list(ROLE_SYNDICATE) - -/mob/living/simple_animal/hostile/spawner/skeleton - name = "bone pit" - desc = "A pit full of bones, and some still seem to be moving..." - icon_state = "hole" - icon_living = "hole" - icon = 'icons/mob/nest.dmi' - health = 150 - maxHealth = 150 - max_mobs = 15 - spawn_time = 150 - mob_types = list(/mob/living/simple_animal/hostile/skeleton) - spawn_text = "climbs out of" - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - faction = list("skeleton") - -/mob/living/simple_animal/hostile/spawner/mining - name = "monster den" - desc = "A hole dug into the ground, harboring all kinds of monsters found within most caves or mining asteroids." - icon_state = "hole" - icon_living = "hole" - health = 200 - maxHealth = 200 - max_mobs = 3 - icon = 'icons/mob/nest.dmi' - spawn_text = "crawls out of" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/hivelord, /mob/living/simple_animal/hostile/asteroid/basilisk, /mob/living/simple_animal/hostile/asteroid/fugu) - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - faction = list("mining") - -/mob/living/simple_animal/hostile/spawner/mining/goldgrub - name = "goldgrub den" - desc = "A den housing a nest of goldgrubs, annoying but arguably much better than anything else you'll find in a nest." - mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub) - -/mob/living/simple_animal/hostile/spawner/mining/goliath - name = "goliath den" - desc = "A den housing a nest of goliaths, oh god why?" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/goliath) - -/mob/living/simple_animal/hostile/spawner/mining/hivelord - name = "hivelord den" - desc = "A den housing a nest of hivelords." - mob_types = list(/mob/living/simple_animal/hostile/asteroid/hivelord) - -/mob/living/simple_animal/hostile/spawner/mining/basilisk - name = "basilisk den" - desc = "A den housing a nest of basilisks, bring a coat." - mob_types = list(/mob/living/simple_animal/hostile/asteroid/basilisk) - -/mob/living/simple_animal/hostile/spawner/mining/wumborian - name = "wumborian fugu den" - desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu) diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 41aaaac1c9..a1feb899c6 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -96,8 +96,7 @@ if((direct & (direct - 1)) && mob.loc == n) //moved diagonally successfully add_delay *= 2 - if(mob.loc != oldloc) - move_delay += add_delay + move_delay += add_delay if(.) // If mob is null here, we deserve the runtime if(mob.throwing) mob.throwing.finalize(FALSE) diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index 97c41faf12..e6d53d914f 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -56,7 +56,7 @@ //If we hit the Ninja who owns this Katana, they catch it. //Works for if the Ninja throws it or it throws itself or someone tries //To throw it at the ninja -/obj/item/energy_katana/throw_impact(atom/hit_atom) +/obj/item/energy_katana/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(ishuman(hit_atom)) var/mob/living/carbon/human/H = hit_atom if(istype(H.wear_suit, /obj/item/clothing/suit/space/space_ninja)) diff --git a/code/modules/paperwork/paperplane.dm b/code/modules/paperwork/paperplane.dm index f3f7e45378..cfd028c4df 100644 --- a/code/modules/paperwork/paperplane.dm +++ b/code/modules/paperwork/paperplane.dm @@ -99,7 +99,7 @@ /obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback) . = ..(target, range, speed, thrower, FALSE, diagonals_first, callback) -/obj/item/paperplane/throw_impact(atom/hit_atom) +/obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(iscarbon(hit_atom)) var/mob/living/carbon/C = hit_atom if(!C.get_active_held_item() && !C.restrained()) diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 74f78825a8..3f7fdc45d9 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -23,6 +23,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne desc = "A device which produces a graviton field when set up." icon = 'icons/obj/machines/gravity_generator.dmi' density = TRUE + move_resist = INFINITY use_power = NO_POWER_USE resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF var/sprite_number = 0 diff --git a/code/modules/power/lighting.dm b/code/modules/power/lighting.dm index e50b11ea35..903f63e22c 100644 --- a/code/modules/power/lighting.dm +++ b/code/modules/power/lighting.dm @@ -756,7 +756,7 @@ /obj/item/light/bulb/broken status = LIGHT_BROKEN -/obj/item/light/throw_impact(atom/hit_atom) +/obj/item/light/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) //not caught by a mob shatter() diff --git a/code/modules/power/port_gen.dm b/code/modules/power/port_gen.dm index 9ae6c69847..3a6a98d681 100644 --- a/code/modules/power/port_gen.dm +++ b/code/modules/power/port_gen.dm @@ -103,6 +103,8 @@ . += "The generator has [sheets] units of [sheet_name] fuel left, producing [power_gen] per cycle." if(crit_fail) . += "The generator seems to have broken down." + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Fuel efficiency increased by [(consumption*100)-100]%." /obj/machinery/power/port_gen/pacman/HasFuel() if(sheets >= 1 / (time_per_sheet / power_output) - sheet_left) diff --git a/code/modules/power/rtg.dm b/code/modules/power/rtg.dm index 45d1c0fc00..afbeef30a1 100644 --- a/code/modules/power/rtg.dm +++ b/code/modules/power/rtg.dm @@ -36,6 +36,11 @@ power_gen = initial(power_gen) * part_level +/obj/machinery/power/rtg/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Power generation now at [power_gen*0.001]kW." + /obj/machinery/power/rtg/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, "[initial(icon_state)]-open", initial(icon_state), I)) return diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index e007b72c88..31e0c479ed 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -6,6 +6,7 @@ icon = 'icons/obj/singularity.dmi' icon_state = "Contain_F" density = FALSE + move_resist = INFINITY resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF use_power = NO_POWER_USE interaction_flags_atom = NONE diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index d6f51497cd..d8b0ede3a2 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -68,6 +68,11 @@ sparks.attach(src) sparks.set_up(1, TRUE, src) +/obj/machinery/power/emitter/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Emitting one beam each [fire_delay*0.1] seconds.
Power consumption at [active_power_usage]W.
" + /obj/machinery/power/emitter/ComponentInitialize() . = ..() AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) diff --git a/code/modules/power/singularity/field_generator.dm b/code/modules/power/singularity/field_generator.dm index 595d87697d..54aca32cf7 100644 --- a/code/modules/power/singularity/field_generator.dm +++ b/code/modules/power/singularity/field_generator.dm @@ -245,6 +245,7 @@ field_generator power level display if(state != FG_WELDED || !anchored) turn_off() return + move_resist = INFINITY spawn(1) setup_field(1) spawn(2) @@ -335,6 +336,7 @@ field_generator power level display message_admins("A singulo exists and a containment field has failed at [ADMIN_VERBOSEJMP(T)].") investigate_log("has failed whilst a singulo exists at [AREACOORD(T)].", INVESTIGATE_SINGULO) O.last_warning = world.time + move_resist = initial(move_resist) /obj/machinery/field/generator/shock(mob/living/user) if(fields.len) diff --git a/code/modules/power/singularity/singularity.dm b/code/modules/power/singularity/singularity.dm index a14a6d76bc..76eeeae205 100644 --- a/code/modules/power/singularity/singularity.dm +++ b/code/modules/power/singularity/singularity.dm @@ -7,6 +7,7 @@ icon_state = "singularity_s1" anchored = TRUE density = TRUE + move_resist = INFINITY layer = MASSIVE_OBJ_LAYER light_range = 6 appearance_flags = 0 diff --git a/code/modules/power/tesla/coil.dm b/code/modules/power/tesla/coil.dm index 2265f806a5..e29ffa865e 100644 --- a/code/modules/power/tesla/coil.dm +++ b/code/modules/power/tesla/coil.dm @@ -36,6 +36,11 @@ zap_cooldown -= (C.rating * 20) input_power_multiplier = power_multiplier +/obj/machinery/power/tesla_coil/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Power generation at [input_power_multiplier*100]%.
Shock interval at [zap_cooldown*0.1] seconds.
" + /obj/machinery/power/tesla_coil/on_construction() if(anchored) connect_to_network() diff --git a/code/modules/power/turbine.dm b/code/modules/power/turbine.dm index 85ee7589b9..423aaae3f9 100644 --- a/code/modules/power/turbine.dm +++ b/code/modules/power/turbine.dm @@ -94,6 +94,11 @@ E += M.rating efficiency = E / 6 +/obj/machinery/power/compressor/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Efficiency at [efficiency*100]%." + /obj/machinery/power/compressor/attackby(obj/item/I, mob/user, params) if(default_deconstruction_screwdriver(user, initial(icon_state), initial(icon_state), I)) return @@ -176,6 +181,11 @@ P += C.rating productivity = P / 6 +/obj/machinery/power/turbine/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Productivity at [productivity*100]%." + /obj/machinery/power/turbine/locate_machinery() if(compressor) return diff --git a/code/modules/procedural_mapping/mapGenerators/lavaland.dm b/code/modules/procedural_mapping/mapGenerators/lavaland.dm index 6ad21eb959..20194a24ec 100644 --- a/code/modules/procedural_mapping/mapGenerators/lavaland.dm +++ b/code/modules/procedural_mapping/mapGenerators/lavaland.dm @@ -16,9 +16,9 @@ /datum/mapGeneratorModule/splatterLayer/lavalandTendrils spawnableTurfs = list() - spawnableAtoms = list(/mob/living/simple_animal/hostile/spawner/lavaland = 5, - /mob/living/simple_animal/hostile/spawner/lavaland/legion = 5, - /mob/living/simple_animal/hostile/spawner/lavaland/goliath = 5) + spawnableAtoms = list(/obj/structure/spawner/lavaland = 5, + /obj/structure/spawner/lavaland/legion = 5, + /obj/structure/spawner/lavaland/goliath = 5) /datum/mapGenerator/lavaland/ground_only modules = list(/datum/mapGeneratorModule/bottomLayer/lavaland_default) diff --git a/code/modules/projectiles/ammunition/_ammunition.dm b/code/modules/projectiles/ammunition/_ammunition.dm index ccd43e734b..a9e4fa1646 100644 --- a/code/modules/projectiles/ammunition/_ammunition.dm +++ b/code/modules/projectiles/ammunition/_ammunition.dm @@ -65,7 +65,7 @@ else return ..() -/obj/item/ammo_casing/throw_impact(atom/A) +/obj/item/ammo_casing/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(heavy_metal) bounce_away(FALSE, NONE) . = ..() diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 424f2bce30..ce839f33d7 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -113,7 +113,9 @@ if(panel_open) . += "[src]'s maintenance hatch is open!" if(in_range(user, src) || isobserver(user)) - . += "The status display reads:
Recharging [recharge_amount] power units per interval.
Power efficiency increased by [(powerefficiency*1000)-100]%." + . += "The status display reads:\n\ + Recharging [recharge_amount] power units per interval.\n\ + Power efficiency increased by [round((powerefficiency*1000)-100, 1)]%." switch(macrotier) if(1) . += "Macro granularity at 5u." diff --git a/code/modules/reagents/chemistry/machinery/chem_heater.dm b/code/modules/reagents/chemistry/machinery/chem_heater.dm index b4f14c69a7..f4014387c6 100644 --- a/code/modules/reagents/chemistry/machinery/chem_heater.dm +++ b/code/modules/reagents/chemistry/machinery/chem_heater.dm @@ -52,6 +52,11 @@ for(var/obj/item/stock_parts/micro_laser/M in component_parts) heater_coefficient *= M.rating +/obj/machinery/chem_heater/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Heating reagents at [heater_coefficient*1000]% speed." + /obj/machinery/chem_heater/process() ..() if(stat & NOPOWER) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 321b63da1e..f311537641 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -102,9 +102,9 @@ reagents.expose_temperature(exposed_temperature) ..() -/obj/item/reagent_containers/throw_impact(atom/target) +/obj/item/reagent_containers/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) . = ..() - SplashReagents(target, TRUE) + SplashReagents(hit_atom, TRUE) /obj/item/reagent_containers/proc/bartender_check(atom/target) . = FALSE diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index 7025a649e6..b5cdba21c1 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -374,7 +374,7 @@ return TRUE return FALSE -/obj/machinery/disposal/bin/hitby(atom/movable/AM) +/obj/machinery/disposal/bin/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(isitem(AM) && AM.CanEnterDisposals()) if(prob(75)) AM.forceMove(src) diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index bff8df8816..681195bcc3 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -82,6 +82,11 @@ for(var/obj/item/stock_parts/micro_laser/M in component_parts) badThingCoeff += M.rating +/obj/machinery/rnd/experimentor/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Malfunction probability reduced by [badThingCoeff]%.
Cooldown interval between experiments at [resetTime*0.1] seconds.
" + /obj/machinery/rnd/experimentor/proc/checkCircumstances(obj/item/O) //snowflake check to only take "made" bombs if(istype(O, /obj/item/transfer_valve)) diff --git a/code/modules/research/machinery/_production.dm b/code/modules/research/machinery/_production.dm index d93355b36c..659a83c703 100644 --- a/code/modules/research/machinery/_production.dm +++ b/code/modules/research/machinery/_production.dm @@ -73,6 +73,12 @@ total_rating = max(1, total_rating) efficiency_coeff = total_rating +/obj/machinery/rnd/production/examine(mob/user) + . = ..() + var/datum/component/remote_materials/materials = GetComponent(/datum/component/remote_materials) + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Storing up to [materials.local_size] material units locally.
Material usage efficiency at [efficiency_coeff*100]%.
" + //we eject the materials upon deconstruction. /obj/machinery/rnd/production/on_deconstruction() for(var/obj/item/reagent_containers/glass/G in component_parts) diff --git a/code/modules/research/nanites/nanite_chamber.dm b/code/modules/research/nanites/nanite_chamber.dm index 1fc2633989..515231c24c 100644 --- a/code/modules/research/nanites/nanite_chamber.dm +++ b/code/modules/research/nanites/nanite_chamber.dm @@ -29,6 +29,11 @@ for(var/obj/item/stock_parts/scanning_module/P in component_parts) scan_level += P.rating +/obj/machinery/nanite_chamber/examine(mob/user) + . = ..() + if(in_range(user, src) || isobserver(user)) + . += "The status display reads: Scanning module has been upgraded to level [scan_level]." + /obj/machinery/nanite_chamber/proc/set_busy(status, message, working_icon) busy = status busy_message = message diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 74f07e4ce3..2fa5901ec9 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -80,7 +80,7 @@ display_name = "Advanced Biotechnology" description = "Advanced Biotechnology" prereq_ids = list("biotech") - design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "detective_scanner", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter") + design_ids = list("piercesyringe", "crewpinpointer", "smoke_machine", "plasmarefiller", "limbgrower", "meta_beaker", "healthanalyzer_advanced", "harvester", "holobarrier_med", "defibrillator_compact", "smartdartgun", "medicinalsmartdart", "pHmeter") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) export_price = 5000 @@ -1117,7 +1117,7 @@ id = "advanced_illegal_ballistics" display_name = "Advanced Non-Standard Ballistics" description = "Ballistic ammunition for non-standard firearms. Usually the ones you don't have nor want to be involved with." - design_ids = list("10mm","10mmap","10mminc","10mmhp","sl357","pistolm9mm","m45","bolt_clip") + design_ids = list("10mm","10mmap","10mminc","10mmhp","sl357","sl357ap","pistolm9mm","m45","bolt_clip") prereq_ids = list("ballistic_weapons","syndicate_basic","explosive_weapons") research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 25000) //This gives sec lethal mags/clips for guns from traitors, space, or anything in between. export_price = 7000 diff --git a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm index 5425ddbdc4..2401fc63a0 100644 --- a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm +++ b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm @@ -1,26 +1,31 @@ #define ASH_WALKER_SPAWN_THRESHOLD 2 //The ash walker den consumes corpses or unconscious mobs to create ash walker eggs. For more info on those, check ghost_role_spawners.dm -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker +/obj/structure/lavaland/ash_walker name = "necropolis tendril nest" desc = "A vile tendril of corruption. It's surrounded by a nest of rapidly growing eggs..." + icon = 'icons/mob/nest.dmi' icon_state = "ash_walker_nest" - icon_living = "ash_walker_nest" - icon_dead = "ash_walker_nest" - faction = list("ashwalker") - health = 200 - maxHealth = 200 - loot = list(/obj/effect/collapse) + move_resist=INFINITY // just killing it tears a massive hole in the ground, let's not move it + anchored = TRUE + density = TRUE + resistance_flags = FIRE_PROOF | LAVA_PROOF + max_integrity = 200 + var/faction = list("ashwalker") var/meat_counter = 6 -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/death() +/obj/structure/lavaland/ash_walker/Initialize() + .=..() + START_PROCESSING(SSprocessing, src) + +/obj/structure/lavaland/ash_walker/deconstruct(disassembled) new /obj/item/assembly/signaler/anomaly (get_step(loc, pick(GLOB.alldirs))) - return ..() + new /obj/effect/collapse(loc) -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/Life() +/obj/structure/lavaland/ash_walker/process() consume() - return ..() + spawn_mob() -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/proc/consume() +/obj/structure/lavaland/ash_walker/proc/consume() for(var/mob/living/H in view(src, 1)) //Only for corpse right next to/on same tile if(H.stat) visible_message("Serrated tendrils eagerly pull [H] to [src], tearing the body apart as its blood seeps over the eggs.") @@ -33,9 +38,9 @@ else meat_counter++ H.gib() - adjustHealth(-maxHealth * 0.05)//restores 5% hp of tendril + obj_integrity = min(obj_integrity + max_integrity*0.05,max_integrity)//restores 5% hp of tendril -/mob/living/simple_animal/hostile/spawner/lavaland/ash_walker/spawn_mob() +/obj/structure/lavaland/ash_walker/proc/spawn_mob() if(meat_counter >= ASH_WALKER_SPAWN_THRESHOLD) new /obj/effect/mob_spawn/human/ash_walker(get_step(loc, pick(GLOB.alldirs))) visible_message("One of the eggs swells to an unnatural size and tumbles free. It's ready to hatch!") diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index f64b5e4d01..dc721506a5 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -172,6 +172,15 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) var/turf/T = locate(_x, _y, _z) A.forceMove(T) +/obj/item/hilbertshotel/ghostdojo + name = "Infinite Dormitories" + anchored = TRUE + interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND + +/obj/item/hilbertshotel/ghostdojo/interact(mob/user) + . = ..() + promptAndCheckIn(user) + //Template Stuff /datum/map_template/hilbertshotel name = "Hilbert's Hotel Room" diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 121ee2e07f..beaaa51adb 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -131,7 +131,7 @@ All ShuttleMove procs go here var/range = throw_force * 10 range = CEILING(rand(range-(range*0.1), range+(range*0.1)), 10)/10 var/speed = range/5 - throw_at(target, range, speed) + safe_throw_at(target, range, speed) ///////////////////////////////////////////////////////////////////////////////////// diff --git a/code/modules/spells/spell_types/conjure.dm b/code/modules/spells/spell_types/conjure.dm index a04a86b928..8336c06edb 100644 --- a/code/modules/spells/spell_types/conjure.dm +++ b/code/modules/spells/spell_types/conjure.dm @@ -63,7 +63,7 @@ clothes_req = FALSE charge_max = 600 cooldown_min = 200 - summon_type = list(/mob/living/simple_animal/hostile/spawner/nether) + summon_type = list(/obj/structure/spawner/nether) summon_amt = 1 range = 1 cast_sound = 'sound/weapons/marauder.ogg' diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index 262f656967..a2d7612681 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -363,7 +363,7 @@ icon_state = "snappop" w_class = WEIGHT_CLASS_TINY -/obj/item/spellpacket/lightningbolt/throw_impact(atom/hit_atom) +/obj/item/spellpacket/lightningbolt/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!..()) if(isliving(hit_atom)) var/mob/living/M = hit_atom diff --git a/code/modules/surgery/bodyparts/bodyparts.dm b/code/modules/surgery/bodyparts/bodyparts.dm index 63a392bf06..e2c77fa177 100644 --- a/code/modules/surgery/bodyparts/bodyparts.dm +++ b/code/modules/surgery/bodyparts/bodyparts.dm @@ -29,6 +29,7 @@ var/burn_dam = 0 var/stamina_dam = 0 var/max_stamina_damage = 0 + var/incoming_stam_mult = 1 //Multiplier for incoming staminaloss, decreases when taking staminaloss when the limb is disabled, resets back to 1 when limb is no longer disabled. var/max_damage = 0 var/stam_heal_tick = 0 //per Life(). Defaults to 0 due to citadel changes @@ -115,7 +116,7 @@ else return ..() -/obj/item/bodypart/throw_impact(atom/hit_atom) +/obj/item/bodypart/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) ..() if(status != BODYPART_ROBOTIC) playsound(get_turf(src), 'sound/misc/splort.ogg', 50, 1, -1) @@ -141,7 +142,7 @@ //Return TRUE to get whatever mob this is in to update health. /obj/item/bodypart/proc/on_life() if(stam_heal_tick && stamina_dam > DAMAGE_PRECISION) //DO NOT update health here, it'll be done in the carbon's life. - if(heal_damage(brute = 0, burn = 0, stamina = stam_heal_tick, only_robotic = FALSE, only_organic = FALSE, updating_health = FALSE)) + if(heal_damage(brute = 0, burn = 0, stamina = (stam_heal_tick * (disabled ? 2 : 1)), only_robotic = FALSE, only_organic = FALSE, updating_health = FALSE)) . |= BODYPART_LIFE_UPDATE_HEALTH //Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. @@ -153,7 +154,7 @@ var/dmg_mlt = CONFIG_GET(number/damage_multiplier) brute = round(max(brute * dmg_mlt, 0),DAMAGE_PRECISION) burn = round(max(burn * dmg_mlt, 0),DAMAGE_PRECISION) - stamina = round(max(stamina * dmg_mlt, 0),DAMAGE_PRECISION) + stamina = round(max((stamina * dmg_mlt) * incoming_stam_mult, 0),DAMAGE_PRECISION) brute = max(0, brute - brute_reduction) burn = max(0, burn - burn_reduction) //No stamina scaling.. for now.. @@ -183,6 +184,9 @@ var/available_damage = max_damage - current_damage stamina_dam += round(CLAMP(stamina, 0, min(max_stamina_damage - stamina_dam, available_damage)), DAMAGE_PRECISION) + if(disabled && stamina > 10) + incoming_stam_mult = max(0.01, incoming_stam_mult/(stamina*0.1)) + if(owner && updating_health) owner.updatehealth() if(stamina > DAMAGE_PRECISION) @@ -252,6 +256,8 @@ owner.update_health_hud() //update the healthdoll owner.update_body() owner.update_canmove() + if(!disabled) + incoming_stam_mult = 1 return TRUE //Updates an organ's brute/burn states for use by update_damage_overlays() @@ -645,7 +651,7 @@ held_index = 1 px_x = -6 px_y = 0 - stam_heal_tick = 2 + stam_heal_tick = 4 /obj/item/bodypart/l_arm/is_disabled() if(HAS_TRAIT(owner, TRAIT_PARALYSIS_L_ARM)) @@ -705,7 +711,7 @@ held_index = 2 px_x = 6 px_y = 0 - stam_heal_tick = 2 + stam_heal_tick = 4 max_stamina_damage = 50 /obj/item/bodypart/r_arm/is_disabled() @@ -765,7 +771,7 @@ body_damage_coeff = 0.75 px_x = -2 px_y = 12 - stam_heal_tick = 2 + stam_heal_tick = 4 max_stamina_damage = 50 var/blood_state = BLOOD_STATE_NOT_BLOODY var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) @@ -826,7 +832,7 @@ px_x = 2 px_y = 12 max_stamina_damage = 50 - stam_heal_tick = 2 + stam_heal_tick = 4 var/blood_state = BLOOD_STATE_NOT_BLOODY var/list/bloody_legs = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index c23662de5a..c739d426c2 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -2,6 +2,7 @@ //Keep this sorted alphabetically #ifdef UNIT_TESTS +#include "anchored_mobs.dm" #include "component_tests.dm" #include "reagent_id_typos.dm" #include "reagent_recipe_collisions.dm" diff --git a/code/modules/unit_tests/anchored_mobs.dm b/code/modules/unit_tests/anchored_mobs.dm new file mode 100644 index 0000000000..5324179bb7 --- /dev/null +++ b/code/modules/unit_tests/anchored_mobs.dm @@ -0,0 +1,9 @@ +/datum/unit_test/anchored_mobs/Run() + var/list/L = list() + for(var/i in typesof(/mob)) + var/mob/M = i + if(initial(M.anchored)) + L += "[i]" + if(!L.len) + return //passed! + Fail("The following mobs are defined as anchored. This is incompatible with the new move force/resist system and needs to be revised.: [L.Join(" ")]") \ No newline at end of file diff --git a/code/modules/uplink/uplink_items/uplink_clothing.dm b/code/modules/uplink/uplink_items/uplink_clothing.dm index 2881aa8dfd..3a3c53288a 100644 --- a/code/modules/uplink/uplink_items/uplink_clothing.dm +++ b/code/modules/uplink/uplink_items/uplink_clothing.dm @@ -23,21 +23,21 @@ /datum/uplink_item/suits/padding name = "Soft Padding" - desc = "Padding to add to a jumpsuit to help against melee and bullets." + desc = "An inconspicious soft padding meant to be worn underneath jumpsuits, will cushion the user from melee harm." item = /obj/item/clothing/accessory/padding cost = 2 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/suits/kevlar - name = "Kevlar sheets" - desc = "Kevlar sheets to add to jumpsuit to help against bullets and melee." + name = "Kevlar Padding" + desc = "An inconspicious kevlar padding meant to be worn underneath jumpsuits, will cushion the wearer from ballistic harm." item = /obj/item/clothing/accessory/kevlar cost = 2 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) /datum/uplink_item/suits/plastic - name = "Plastic sheet" - desc = "Plastic body sheet to add to a jumpsuit to help against laser and energy harm." + name = "Ablative Padding" + desc = "An inconspicious ablative padding meant to be worn underneath jumpsuits, will cushion the wearer from energy lasers harm." item = /obj/item/clothing/accessory/plastics cost = 2 exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops) diff --git a/config/game_options.txt b/config/game_options.txt index b8b89de17c..9fc50fcd0f 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -597,3 +597,6 @@ MODETIER_VOTING ## Number of modes dropped by the modetier vote during mode selection, after vote. DROPPED_MODES 3 + +## Whether the suicide verb is allowed. +# SUICIDE_ALLOWED diff --git a/html/changelogs/AutoChangeLog-pr-10097.yml b/html/changelogs/AutoChangeLog-pr-10097.yml new file mode 100644 index 0000000000..9b9a2c9a58 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10097.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - tweak: "Attached kevlar/soft/plastic padding accessories are now stealthier and will no longer be displayed on mob examine." diff --git a/html/changelogs/AutoChangeLog-pr-10307.yml b/html/changelogs/AutoChangeLog-pr-10307.yml new file mode 100644 index 0000000000..279dbe2840 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10307.yml @@ -0,0 +1,4 @@ +author: "Seris02" +delete-after: True +changes: + - rscadd: "stunglasses" diff --git a/html/changelogs/AutoChangeLog-pr-10346.yml b/html/changelogs/AutoChangeLog-pr-10346.yml new file mode 100644 index 0000000000..3a0cd6dae4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10346.yml @@ -0,0 +1,6 @@ +author: "Bhijn" +delete-after: True +changes: + - rscadd: "Limbs now regenerate their stamina faster while disabled" + - rscadd: "Limbs now have the same incoming stamina damage multiplier mechanics as spacemen, where the more staminaloss they take while disabled, the less staminaloss they'll take." + - balance: "Limbs have had their base stamina regen rate doubled to match the doubled stamina regen rate of standard spacemen." diff --git a/html/changelogs/AutoChangeLog-pr-10520.yml b/html/changelogs/AutoChangeLog-pr-10520.yml new file mode 100644 index 0000000000..ae23c082d8 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10520.yml @@ -0,0 +1,7 @@ +author: "Denton, ported by Hatterhat" +delete-after: True +changes: + - tweak: "Most upgradeable machines now show their upgrade status when examined while standing right next to them." + - tweak: "Added examine messages to teleporter stations that hint at their multitool/wirecutter interactions." + - tweak: "Renamed teleporter stations from station to teleporter station." + - code_imp: "Changed the teleporter hub accurate var to accuracy; the old name misled people into thinking that it was a boolean." diff --git a/html/changelogs/AutoChangeLog-pr-10547.yml b/html/changelogs/AutoChangeLog-pr-10547.yml new file mode 100644 index 0000000000..41d255e991 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10547.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - tweak: "Ghost dojo spawns will dust if their owner suicides or uses the \"ghost\" verb." diff --git a/html/changelogs/AutoChangeLog-pr-10597.yml b/html/changelogs/AutoChangeLog-pr-10597.yml new file mode 100644 index 0000000000..9f28c4f84c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10597.yml @@ -0,0 +1,5 @@ +author: "Putnam3145" +delete-after: True +changes: + - code_imp: "demodularized player panel code, mostly" + - admin: "added ghost role eligibility delay removal to player panel" diff --git a/html/changelogs/AutoChangeLog-pr-10614.yml b/html/changelogs/AutoChangeLog-pr-10614.yml new file mode 100644 index 0000000000..4c4d8bfdbd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10614.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - config: "Added suicide to the config." diff --git a/html/changelogs/AutoChangeLog-pr-10615.yml b/html/changelogs/AutoChangeLog-pr-10615.yml new file mode 100644 index 0000000000..f67392cd7f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10615.yml @@ -0,0 +1,4 @@ +author: "keronshb" +delete-after: True +changes: + - bugfix: "fixed my messup" diff --git a/html/changelogs/AutoChangeLog-pr-10617.yml b/html/changelogs/AutoChangeLog-pr-10617.yml new file mode 100644 index 0000000000..923913a043 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10617.yml @@ -0,0 +1,4 @@ +author: "kevinz000" +delete-after: True +changes: + - bugfix: "Grenades can now have their timers adjusted." diff --git a/html/changelogs/AutoChangeLog-pr-10621.yml b/html/changelogs/AutoChangeLog-pr-10621.yml new file mode 100644 index 0000000000..0bb08dee2c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10621.yml @@ -0,0 +1,4 @@ +author: "Hatterhat" +delete-after: True +changes: + - rscadd: "You can now print .357 AP speedloaders from Security techfabs after you pick up the Advanced Non-Standard Ballistics node." diff --git a/html/changelogs/AutoChangeLog-pr-10635.yml b/html/changelogs/AutoChangeLog-pr-10635.yml new file mode 100644 index 0000000000..66c90808d6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-10635.yml @@ -0,0 +1,4 @@ +author: "Hatterhat" +delete-after: True +changes: + - rscdel: "Forensic scanner removed from Advanced Biotechnology node." diff --git a/html/changelogs/AutoChangeLog-pr-9601.yml b/html/changelogs/AutoChangeLog-pr-9601.yml new file mode 100644 index 0000000000..c54279627f --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9601.yml @@ -0,0 +1,9 @@ +author: "Ghommie (original PRs by Kevinz000, ShivCalez, 4dplanner, Barhandar, 81Denton, zxaber, Fox-McCloud)" +delete-after: True +changes: + - rscadd: "All atom movables now have move force and move resist, and pull force An atom can only pull another atom if its pull force is stronger than that atom's move resist" + - rscadd: "Mobs with a higher move force than an atom's move resist will automatically try to force the atom out of its way. This might not always work, depending on how snowflakey code is. +experimental: As of right now, everything has a move force and resist of 100, and a pull force of 101. Things take (resist - force) damage when bumped into +experimental: Failing to move onto a tile will now still bump up your last move timer. However, successfully pushing something out of your way will result in you automatically moving into where it was." + - bugfix: "Bolted AIs can no longer be teleported by launchpads." + - balance: "Megafauna cannot teleport" diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index 71fceba8b4..c5a6914cf4 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ diff --git a/modular_citadel/code/modules/admin/admin.dm b/modular_citadel/code/modules/admin/admin.dm deleted file mode 100644 index 529d0c79ec..0000000000 --- a/modular_citadel/code/modules/admin/admin.dm +++ /dev/null @@ -1,39 +0,0 @@ -/client/proc/citaPPoptions(mob/M) // why is this client and not /datum/admins? noone knows, in PP src == client, instead of holder. wtf. - var/body = "
" - if(M.client) - body += "Make mentor | " - body += "Remove mentor" - return body - -/client/proc/cmd_admin_man_up(mob/M in GLOB.mob_list) - set category = "Special Verbs" - set name = "Man Up" - - if(!M) - return - if(!check_rights(R_ADMIN)) - return - - to_chat(M, "Man up, and deal with it.
Move on.") - M.playsound_local(M, 'sound/voice/manup.ogg', 50, FALSE, pressure_affected = FALSE) - - log_admin("Man up: [key_name(usr)] told [key_name(M)] to man up") - var/message = "[key_name_admin(usr)] told [key_name_admin(M)] to man up." - message_admins(message) - admin_ticket_log(M, message) - SSblackbox.record_feedback("tally", "admin_verb", 1, "Man Up") - -/client/proc/cmd_admin_man_up_global() - set category = "Special Verbs" - set name = "Man Up Global" - - if(!check_rights(R_ADMIN)) - return - - to_chat(world, "Man up, and deal with it.
Move on.") - for(var/mob/M in GLOB.player_list) - M.playsound_local(M, 'sound/voice/manup.ogg', 50, FALSE, pressure_affected = FALSE) - - log_admin("Man up global: [key_name(usr)] told everybody to man up") - message_admins("[key_name_admin(usr)] told everybody to man up.") - SSblackbox.record_feedback("tally", "admin_verb", 1, "Man Up Global") diff --git a/modular_citadel/code/modules/admin/topic.dm b/modular_citadel/code/modules/admin/topic.dm deleted file mode 100644 index 26bc902bef..0000000000 --- a/modular_citadel/code/modules/admin/topic.dm +++ /dev/null @@ -1,59 +0,0 @@ -/datum/admins/proc/citaTopic(href, href_list) - if(href_list["makementor"]) - makeMentor(href_list["makementor"]) - else if(href_list["removementor"]) - removeMentor(href_list["removementor"]) - -/datum/admins/proc/makeMentor(ckey) - if(!usr.client) - return - if (!check_rights(0)) - return - if(!ckey) - return - var/client/C = GLOB.directory[ckey] - if(C) - if(check_rights_for(C, R_ADMIN,0)) - to_chat(usr, "The client chosen is an admin! Cannot mentorize.") - return - if(SSdbcore.Connect()) - var/datum/DBQuery/query_get_mentor = SSdbcore.NewQuery("SELECT id FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") - if(query_get_mentor.NextRow()) - to_chat(usr, "[ckey] is already a mentor.") - return - var/datum/DBQuery/query_add_mentor = SSdbcore.NewQuery("INSERT INTO `[format_table_name("mentor")]` (`id`, `ckey`) VALUES (null, '[ckey]')") - if(!query_add_mentor.warn_execute()) - return - var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Added new mentor [ckey]');") - if(!query_add_admin_log.warn_execute()) - return - else - to_chat(usr, "Failed to establish database connection. The changes will last only for the current round.") - new /datum/mentors(ckey) - to_chat(usr, "New mentor added.") - -/datum/admins/proc/removeMentor(ckey) - if(!usr.client) - return - if (!check_rights(0)) - return - if(!ckey) - return - var/client/C = GLOB.directory[ckey] - if(C) - if(check_rights_for(C, R_ADMIN,0)) - to_chat(usr, "The client chosen is an admin, not a mentor! Cannot de-mentorize.") - return - C.remove_mentor_verbs() - C.mentor_datum = null - GLOB.mentors -= C - if(SSdbcore.Connect()) - var/datum/DBQuery/query_remove_mentor = SSdbcore.NewQuery("DELETE FROM [format_table_name("mentor")] WHERE ckey = '[ckey]'") - if(!query_remove_mentor.warn_execute()) - return - var/datum/DBQuery/query_add_admin_log = SSdbcore.NewQuery("INSERT INTO `[format_table_name("admin_log")]` (`id` ,`datetime` ,`adminckey` ,`adminip` ,`log` ) VALUES (NULL , NOW( ) , '[usr.ckey]', '[usr.client.address]', 'Removed mentor [ckey]');") - if(!query_add_admin_log.warn_execute()) - return - else - to_chat(usr, "Failed to establish database connection. The changes will last only for the current round.") - to_chat(usr, "Mentor removed.") \ No newline at end of file diff --git a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm index f2743d853b..c2b8ff0868 100644 --- a/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm +++ b/modular_citadel/code/modules/mob/living/silicon/robot/dogborg_equipment.dm @@ -416,14 +416,14 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! playsound(src, 'sound/effects/stealthoff.ogg', 25, TRUE, -1) weather_immunities -= "lava" -/mob/living/silicon/robot/throw_impact(atom/A) +/mob/living/silicon/robot/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) if(!leaping) return ..() - if(A) - if(isliving(A)) - var/mob/living/L = A + if(hit_atom) + if(isliving(hit_atom)) + var/mob/living/L = hit_atom if(!L.check_shields(0, "the [name]", src, attack_type = LEAP_ATTACK)) L.visible_message("[src] pounces on [L]!", "[src] pounces on you!") L.Knockdown(iscarbon(L) ? 60 : 45, override_stamdmg = CLAMP(pounce_stamloss, 0, pounce_stamloss_cap-L.getStaminaLoss())) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice. @@ -437,8 +437,8 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm ! pounce_cooldown = !pounce_cooldown spawn(pounce_cooldown_time) //3s by default pounce_cooldown = !pounce_cooldown - else if(A.density && !A.CanPass(src)) - visible_message("[src] smashes into [A]!", "You smash into [A]!") + else if(hit_atom.density && !hit_atom.CanPass(src)) + visible_message("[src] smashes into [hit_atom]!", "You smash into [hit_atom]!") playsound(src, 'sound/items/trayhit1.ogg', 50, 1) Knockdown(15, 1, 1) diff --git a/modular_citadel/code/modules/projectiles/boxes_magazines/external/pistol.dm b/modular_citadel/code/modules/projectiles/boxes_magazines/external/pistol.dm index 4ae3e5c488..dd45c0278a 100644 --- a/modular_citadel/code/modules/projectiles/boxes_magazines/external/pistol.dm +++ b/modular_citadel/code/modules/projectiles/boxes_magazines/external/pistol.dm @@ -78,3 +78,13 @@ build_path = /obj/item/ammo_box/a357 category = list("Ammo") departmental_flags = DEPARTMENTAL_FLAG_SECURITY + +/datum/design/sl357ap + name = "revolver speedloader (.357 AP)" + desc = "A revolver speedloader. Cuts through like a hot knife through butter." + id = "sl357ap" + build_type = PROTOLATHE + materials = list(MAT_METAL = 30000, MAT_TITANIUM = 45000) + build_path = /obj/item/ammo_box/a357/ap + category = list("Ammo") + departmental_flags = DEPARTMENTAL_FLAG_SECURITY diff --git a/tgstation.dme b/tgstation.dme index 1c7d5112e7..43301633c2 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -70,6 +70,7 @@ #include "code\__DEFINES\misc.dm" #include "code\__DEFINES\mobs.dm" #include "code\__DEFINES\monkeys.dm" +#include "code\__DEFINES\move_force.dm" #include "code\__DEFINES\movespeed_modification.dm" #include "code\__DEFINES\nanites.dm" #include "code\__DEFINES\networks.dm" @@ -391,6 +392,7 @@ #include "code\datums\components\shrink.dm" #include "code\datums\components\sizzle.dm" #include "code\datums\components\slippery.dm" +#include "code\datums\components\spawner.dm" #include "code\datums\components\spooky.dm" #include "code\datums\components\squeak.dm" #include "code\datums\components\stationloving.dm" @@ -471,6 +473,7 @@ #include "code\datums\diseases\advance\symptoms\youth.dm" #include "code\datums\elements\_element.dm" #include "code\datums\elements\cleaning.dm" +#include "code\datums\elements\dusts_on_catatonia.dm" #include "code\datums\elements\earhealing.dm" #include "code\datums\elements\ghost_role_eligibility.dm" #include "code\datums\elements\wuv.dm" @@ -1070,6 +1073,7 @@ #include "code\game\objects\structures\reflector.dm" #include "code\game\objects\structures\safe.dm" #include "code\game\objects\structures\showcase.dm" +#include "code\game\objects\structures\spawner.dm" #include "code\game\objects\structures\spirit_board.dm" #include "code\game\objects\structures\stairs.dm" #include "code\game\objects\structures\statues.dm" @@ -1113,6 +1117,7 @@ #include "code\game\objects\structures\crates_lockers\crates\large.dm" #include "code\game\objects\structures\crates_lockers\crates\secure.dm" #include "code\game\objects\structures\crates_lockers\crates\wooden.dm" +#include "code\game\objects\structures\lavaland\necropolis_tendril.dm" #include "code\game\objects\structures\signs\_signs.dm" #include "code\game\objects\structures\signs\signs_departments.dm" #include "code\game\objects\structures\signs\signs_maps.dm" @@ -2291,7 +2296,6 @@ #include "code\modules\mob\living\simple_animal\simple_animal.dm" #include "code\modules\mob\living\simple_animal\simple_animal_vr.dm" #include "code\modules\mob\living\simple_animal\simplemob_vore_values.dm" -#include "code\modules\mob\living\simple_animal\spawner.dm" #include "code\modules\mob\living\simple_animal\status_procs.dm" #include "code\modules\mob\living\simple_animal\bot\bot.dm" #include "code\modules\mob\living\simple_animal\bot\cleanbot.dm" @@ -2396,7 +2400,6 @@ #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\gutlunch.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\hivelord.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\mining_mobs.dm" -#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\necropolis_tendril.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\elite.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\goliath_broodmother.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\herald.dm" @@ -3098,11 +3101,9 @@ #include "modular_citadel\code\game\machinery\wishgranter.dm" #include "modular_citadel\code\game\objects\cit_screenshake.dm" #include "modular_citadel\code\game\objects\effects\temporary_visuals\souldeath.dm" -#include "modular_citadel\code\modules\admin\admin.dm" #include "modular_citadel\code\modules\admin\chat_commands.dm" #include "modular_citadel\code\modules\admin\holder2.dm" #include "modular_citadel\code\modules\admin\secrets.dm" -#include "modular_citadel\code\modules\admin\topic.dm" #include "modular_citadel\code\modules\arousal\arousal.dm" #include "modular_citadel\code\modules\arousal\genitals.dm" #include "modular_citadel\code\modules\arousal\genitals_sprite_accessories.dm"