diff --git a/code/__DEFINES/robots.dm b/code/__DEFINES/robots.dm index b3273da3175..1be12363ca2 100644 --- a/code/__DEFINES/robots.dm +++ b/code/__DEFINES/robots.dm @@ -88,6 +88,8 @@ #define BOT_MODE_REMOTE_ENABLED (1<<2) ///The Bot is allowed to have a ghost placed in control of it. #define BOT_MODE_CAN_BE_SAPIENT (1<<3) +///The Bot is allowed to be possessed if it is present on mapload. +#define BOT_MODE_ROUNDSTART_POSSESSION (1<<4) //Bot cover defines indicating the Bot's status ///The Bot's cover is open and can be modified/emagged by anyone. diff --git a/code/datums/status_effects/debuffs/debuffs.dm b/code/datums/status_effects/debuffs/debuffs.dm index 47b0e5c9678..161fa6312d7 100644 --- a/code/datums/status_effects/debuffs/debuffs.dm +++ b/code/datums/status_effects/debuffs/debuffs.dm @@ -933,5 +933,27 @@ /datum/status_effect/teleport_madness/tick() dump_in_space(owner) +/datum/status_effect/careful_driving + id = "careful_driving" + alert_type = /atom/movable/screen/alert/status_effect/careful_driving + duration = 5 SECONDS + status_type = STATUS_EFFECT_REPLACE + +/datum/status_effect/careful_driving/on_apply() + . = ..() + owner.add_movespeed_modifier(/datum/movespeed_modifier/careful_driving, update = TRUE) + +/datum/status_effect/careful_driving/on_remove() + . = ..() + owner.remove_movespeed_modifier(/datum/movespeed_modifier/careful_driving, update = TRUE) + +/atom/movable/screen/alert/status_effect/careful_driving + name = "Careful Driving" + desc = "That was close! You almost ran that one over!" + icon_state = "paralysis" + +/datum/movespeed_modifier/careful_driving + multiplicative_slowdown = 3 + #undef HEALING_SLEEP_DEFAULT #undef HEALING_SLEEP_ORGAN_MULTIPLIER diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index e107076d8bb..8dbc20ff92c 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -153,25 +153,25 @@ /datum/wires/proc/is_dud_color(color) return is_dud(get_wire(color)) -/datum/wires/proc/cut(wire) +/datum/wires/proc/cut(wire, source) if(is_cut(wire)) cut_wires -= wire SEND_SIGNAL(src, COMSIG_MEND_WIRE(wire), wire) - on_cut(wire, mend = TRUE) + on_cut(wire, mend = TRUE, source = source) else cut_wires += wire SEND_SIGNAL(src, COMSIG_CUT_WIRE(wire), wire) - on_cut(wire, mend = FALSE) + on_cut(wire, mend = FALSE, source = source) -/datum/wires/proc/cut_color(color) - cut(get_wire(color)) +/datum/wires/proc/cut_color(color, source) + cut(get_wire(color), source) -/datum/wires/proc/cut_random() - cut(wires[rand(1, wires.len)]) +/datum/wires/proc/cut_random(source) + cut(wires[rand(1, wires.len)], source) -/datum/wires/proc/cut_all() +/datum/wires/proc/cut_all(source) for(var/wire in wires) - cut(wire) + cut(wire, source) /datum/wires/proc/pulse(wire, user, force=FALSE) if(!force && is_cut(wire)) @@ -232,7 +232,7 @@ /datum/wires/proc/get_status() return list() -/datum/wires/proc/on_cut(wire, mend = FALSE) +/datum/wires/proc/on_cut(wire, mend = FALSE, source = null) return /datum/wires/proc/on_pulse(wire, user) @@ -329,7 +329,7 @@ if(I || isAdminGhostAI(usr)) if(I && holder) I.play_tool_sound(holder, 20) - cut_color(target_wire) + cut_color(target_wire, source = L) . = TRUE else to_chat(L, span_warning("You need wirecutters!")) diff --git a/code/datums/wires/airalarm.dm b/code/datums/wires/airalarm.dm index 5fe9768d591..2dc3244e9ca 100644 --- a/code/datums/wires/airalarm.dm +++ b/code/datums/wires/airalarm.dm @@ -52,7 +52,7 @@ A.danger_level = AIR_ALARM_ALERT_NONE A.update_appearance() -/datum/wires/airalarm/on_cut(wire, mend) +/datum/wires/airalarm/on_cut(wire, mend, source) var/obj/machinery/airalarm/A = holder switch(wire) if(WIRE_POWER) // Short out forever. diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm index e7914d4fe70..994ea6f85fc 100644 --- a/code/datums/wires/airlock.dm +++ b/code/datums/wires/airlock.dm @@ -157,7 +157,7 @@ else if(aiControlDisabled == AI_WIRE_HACKED) aiControlDisabled = AI_WIRE_DISABLED_HACKED -/datum/wires/airlock/on_cut(wire, mend) +/datum/wires/airlock/on_cut(wire, mend, source) var/obj/machinery/door/airlock/A = holder switch(wire) if(WIRE_POWER1, WIRE_POWER2) // Cut to lose power, repair all to gain power. @@ -189,6 +189,8 @@ else if(A.aiControlDisabled == AI_WIRE_DISABLED_HACKED) A.aiControlDisabled = AI_WIRE_HACKED if(WIRE_SHOCK) // Cut to shock the door, mend to unshock. + if (!isnull(source)) + log_combat(source, A, "[mend ? "disabled" : "enabled"] shocking for") if(mend) if(A.secondsElectrified) A.set_electrified(MACHINE_NOT_ELECTRIFIED, usr) @@ -198,6 +200,8 @@ A.shock(usr, 100) if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. A.safe = mend + if (!isnull(source)) + log_combat(source, A, "[mend ? "enabled" : "disabled"] door safeties for") if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable. A.autoclose = mend if(A.autoclose && !A.density) diff --git a/code/datums/wires/apc.dm b/code/datums/wires/apc.dm index eebab28613a..54d179802a3 100644 --- a/code/datums/wires/apc.dm +++ b/code/datums/wires/apc.dm @@ -40,7 +40,7 @@ A.aidisabled = TRUE addtimer(CALLBACK(A, TYPE_PROC_REF(/obj/machinery/power/apc, reset), wire), 1 SECONDS) -/datum/wires/apc/on_cut(wire, mend) +/datum/wires/apc/on_cut(wire, mend, source) var/obj/machinery/power/apc/A = holder switch(wire) if(WIRE_POWER1, WIRE_POWER2) // Short out. diff --git a/code/datums/wires/autolathe.dm b/code/datums/wires/autolathe.dm index bf30ba39c08..ca55dad954f 100644 --- a/code/datums/wires/autolathe.dm +++ b/code/datums/wires/autolathe.dm @@ -37,7 +37,7 @@ A.disabled = !A.disabled addtimer(CALLBACK(A, TYPE_PROC_REF(/obj/machinery/autolathe, reset), wire), 60) -/datum/wires/autolathe/on_cut(wire, mend) +/datum/wires/autolathe/on_cut(wire, mend, source) var/obj/machinery/autolathe/A = holder switch(wire) if(WIRE_HACK) diff --git a/code/datums/wires/ecto_sniffer.dm b/code/datums/wires/ecto_sniffer.dm index d4dcae6fb00..e8006bd4f3b 100644 --- a/code/datums/wires/ecto_sniffer.dm +++ b/code/datums/wires/ecto_sniffer.dm @@ -12,6 +12,6 @@ our_sniffer.activate() ..() -/datum/wires/ecto_sniffer/on_cut(wire, mend) +/datum/wires/ecto_sniffer/on_cut(wire, mend, source) var/obj/machinery/ecto_sniffer/our_sniffer = holder our_sniffer.sensor_enabled = mend diff --git a/code/datums/wires/explosive.dm b/code/datums/wires/explosive.dm index 762a5552df0..925c9481831 100644 --- a/code/datums/wires/explosive.dm +++ b/code/datums/wires/explosive.dm @@ -10,7 +10,9 @@ /datum/wires/explosive/on_pulse(index) explode() -/datum/wires/explosive/on_cut(index, mend) +/datum/wires/explosive/on_cut(index, mend, source) + if (!isnull(source)) + log_combat(source, holder, "cut the detonation wire for") explode() /datum/wires/explosive/proc/explode() @@ -34,7 +36,7 @@ return . = ..() -/datum/wires/explosive/chem_grenade/on_cut(index, mend) +/datum/wires/explosive/chem_grenade/on_cut(index, mend, source) var/obj/item/grenade/chem_grenade/grenade = holder if(grenade.stage != GRENADE_READY) return @@ -127,7 +129,7 @@ else // Boom explode() -/datum/wires/explosive/pizza/on_cut(wire, mend) +/datum/wires/explosive/pizza/on_cut(wire, mend, source) var/obj/item/pizzabox/P = holder switch(wire) if(WIRE_DISARM) // Disarm and untrap the box. @@ -135,6 +137,8 @@ P.bomb_defused = TRUE else if(!mend && !P.bomb_defused) + if (!isnull(source)) + log_combat(source, holder, "cut the detonation wire for") explode() /datum/wires/explosive/pizza/explode() diff --git a/code/datums/wires/fax.dm b/code/datums/wires/fax.dm index 3a0193e5a4c..8c189d68df8 100644 --- a/code/datums/wires/fax.dm +++ b/code/datums/wires/fax.dm @@ -38,7 +38,7 @@ if(WIRE_LOADCHECK) machine.allow_exotic_faxes = !machine.allow_exotic_faxes -/datum/wires/fax/on_cut(wire, mend) +/datum/wires/fax/on_cut(wire, mend, source) var/obj/machinery/fax/machine = holder switch(wire) if(WIRE_SHOCK) diff --git a/code/datums/wires/microwave.dm b/code/datums/wires/microwave.dm index b89aef6f8c9..abce90e8de5 100644 --- a/code/datums/wires/microwave.dm +++ b/code/datums/wires/microwave.dm @@ -22,7 +22,7 @@ if(WIRE_ACTIVATE) M.cook() -/datum/wires/microwave/on_cut(wire, mend) +/datum/wires/microwave/on_cut(wire, mend, source) var/obj/machinery/microwave/M = holder switch(wire) if(WIRE_ACTIVATE) diff --git a/code/datums/wires/mod.dm b/code/datums/wires/mod.dm index b5805557eaf..2ce7b48440f 100644 --- a/code/datums/wires/mod.dm +++ b/code/datums/wires/mod.dm @@ -34,7 +34,7 @@ if(WIRE_INTERFACE) mod.interface_break = !mod.interface_break -/datum/wires/mod/on_cut(wire, mend) +/datum/wires/mod/on_cut(wire, mend, source) var/obj/item/mod/control/mod = holder switch(wire) if(WIRE_HACK) diff --git a/code/datums/wires/mulebot.dm b/code/datums/wires/mulebot.dm index 8351da231b0..9ec8cbe4db1 100644 --- a/code/datums/wires/mulebot.dm +++ b/code/datums/wires/mulebot.dm @@ -23,7 +23,7 @@ if(mule.bot_cover_flags & BOT_COVER_OPEN) return TRUE -/datum/wires/mulebot/on_cut(wire, mend) +/datum/wires/mulebot/on_cut(wire, mend, source) var/mob/living/simple_animal/bot/mulebot/mule = holder switch(wire) if(WIRE_MOTOR1, WIRE_MOTOR2) @@ -38,6 +38,9 @@ mule.set_varspeed(AVERAGE_MOTOR_SPEED) else mule.set_varspeed(SLOW_MOTOR_SPEED) + if(WIRE_AVOIDANCE) + if (!isnull(source)) + log_combat(source, mule, "[is_cut(WIRE_AVOIDANCE) ? "cut" : "mended"] the MULE safety wire of") /datum/wires/mulebot/on_pulse(wire) var/mob/living/simple_animal/bot/mulebot/mule = holder diff --git a/code/datums/wires/r_n_d.dm b/code/datums/wires/r_n_d.dm index 9e483b397c9..b38c1bcd9b5 100644 --- a/code/datums/wires/r_n_d.dm +++ b/code/datums/wires/r_n_d.dm @@ -33,7 +33,7 @@ R.hacked = !R.hacked if(WIRE_DISABLE) R.disabled = !R.disabled -/datum/wires/rnd/on_cut(wire, mend) +/datum/wires/rnd/on_cut(wire, mend, source) var/obj/machinery/rnd/R = holder switch(wire) if(WIRE_HACK) diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm index 9d209df7b54..dee0112f375 100644 --- a/code/datums/wires/robot.dm +++ b/code/datums/wires/robot.dm @@ -68,7 +68,7 @@ if(R.has_model()) R.visible_message(span_notice("[R]'s model servos twitch."), span_notice("Your model display flickers.")) -/datum/wires/robot/on_cut(wire, mend) +/datum/wires/robot/on_cut(wire, mend, source) var/mob/living/silicon/robot/R = holder switch(wire) if(WIRE_AI) // Cut the AI wire to reset AI control. diff --git a/code/datums/wires/roulette.dm b/code/datums/wires/roulette.dm index ac57bbbe2ed..f93bc341699 100644 --- a/code/datums/wires/roulette.dm +++ b/code/datums/wires/roulette.dm @@ -51,7 +51,7 @@ R.audible_message(span_warning("Unauthorized prize vend detected! Locking down machine!")) R.prize_theft(0.20) -/datum/wires/roulette/on_cut(wire, mend) +/datum/wires/roulette/on_cut(wire, mend, source) var/obj/machinery/roulette/R = holder switch(wire) if(WIRE_SHOCK) diff --git a/code/datums/wires/suit_storage_unit.dm b/code/datums/wires/suit_storage_unit.dm index be313dca17c..26ab49763dd 100644 --- a/code/datums/wires/suit_storage_unit.dm +++ b/code/datums/wires/suit_storage_unit.dm @@ -35,7 +35,7 @@ if(usr) SSU.shock(usr) -/datum/wires/suit_storage_unit/on_cut(wire, mend) +/datum/wires/suit_storage_unit/on_cut(wire, mend, source) var/obj/machinery/suit_storage_unit/SSU = holder switch(wire) if(WIRE_HACK) diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm index adb829d7dc0..fa939d5b560 100644 --- a/code/datums/wires/syndicatebomb.dm +++ b/code/datums/wires/syndicatebomb.dm @@ -69,7 +69,7 @@ B.detonation_timer += 100 B.delayedlittle = TRUE -/datum/wires/syndicatebomb/on_cut(wire, mend) +/datum/wires/syndicatebomb/on_cut(wire, mend, source) var/obj/machinery/syndicatebomb/B = holder switch(wire) if(WIRE_BOOM,WIRE_BOOM2) @@ -78,9 +78,9 @@ B.explode_now = TRUE if(!istype(B.payload, /obj/machinery/syndicatebomb/training)) tell_admins(B) - // Cursed usr use but no easy way to get the cutter - if(isliving(usr)) - add_memory_in_range(B, 7, /datum/memory/bomb_defuse_failure, protagonist = usr, antagonist = B) + if(isliving(source)) + log_combat(source, holder, "cut the detonation wire for") + add_memory_in_range(B, 7, /datum/memory/bomb_defuse_failure, protagonist = source, antagonist = B) if(WIRE_UNBOLT) if(!mend && B.anchored) diff --git a/code/datums/wires/vending.dm b/code/datums/wires/vending.dm index 6c4caa70556..4e037f3e24b 100644 --- a/code/datums/wires/vending.dm +++ b/code/datums/wires/vending.dm @@ -66,7 +66,7 @@ if(WIRE_AGELIMIT) vending_machine.age_restrictions = !vending_machine.age_restrictions -/datum/wires/vending/on_cut(wire, mend) +/datum/wires/vending/on_cut(wire, mend, source) var/obj/machinery/vending/vending_machine = holder switch(wire) if(WIRE_THROW) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index a3e58b4b756..b7bad9a6603 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -47,8 +47,8 @@ ///All initial access this bot started with. var/list/prev_access = list() - ///Bot-related mode flags on the Bot indicating how they will act. BOT_MODE_ON | BOT_MODE_AUTOPATROL | BOT_MODE_REMOTE_ENABLED | BOT_MODE_CAN_BE_SAPIENT - var/bot_mode_flags = BOT_MODE_ON | BOT_MODE_REMOTE_ENABLED | BOT_MODE_CAN_BE_SAPIENT + ///Bot-related mode flags on the Bot indicating how they will act. BOT_MODE_ON | BOT_MODE_AUTOPATROL | BOT_MODE_REMOTE_ENABLED | BOT_MODE_CAN_BE_SAPIENT | BOT_MODE_ROUNDSTART_POSSESSION + var/bot_mode_flags = BOT_MODE_ON | BOT_MODE_REMOTE_ENABLED | BOT_MODE_CAN_BE_SAPIENT | BOT_MODE_ROUNDSTART_POSSESSION ///Bot-related cover flags on the Bot to deal with what has been done to their cover, including emagging. BOT_COVER_OPEN | BOT_COVER_LOCKED | BOT_COVER_EMAGGED | BOT_COVER_HACKED var/bot_cover_flags = BOT_COVER_LOCKED @@ -192,7 +192,7 @@ if(HAS_TRAIT(SSstation, STATION_TRAIT_BOTS_GLITCHED)) randomize_language_if_on_station() - if(mapload && is_station_level(z) && (bot_mode_flags & BOT_MODE_CAN_BE_SAPIENT)) + if(mapload && is_station_level(z) && bot_mode_flags & BOT_MODE_CAN_BE_SAPIENT && bot_mode_flags & BOT_MODE_ROUNDSTART_POSSESSION) enable_possession(mapload = mapload) /mob/living/simple_animal/bot/Destroy() @@ -252,13 +252,16 @@ /// Allows renaming the bot to something else /mob/living/simple_animal/bot/proc/rename(mob/user) - var/new_name = sanitize_name(reject_bad_text(tgui_input_text( - user = user, - message = "This machine is designated [real_name]. Would you like to update its registration?", - title = "Name change", - default = real_name, - max_length = MAX_NAME_LEN, - ))) + var/new_name = sanitize_name( + reject_bad_text(tgui_input_text( + user = user, + message = "This machine is designated [real_name]. Would you like to update its registration?", + title = "Name change", + default = real_name, + max_length = MAX_NAME_LEN, + )), + allow_numbers = TRUE + ) if (isnull(new_name) || QDELETED(src)) return if (key && user != src) diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index d0081f62ab8..f07074cc733 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -24,6 +24,7 @@ buckle_lying = 0 mob_size = MOB_SIZE_LARGE buckle_prevents_pull = TRUE // No pulling loaded shit + bot_mode_flags = ~BOT_MODE_ROUNDSTART_POSSESSION maints_access_required = list(ACCESS_ROBOTICS, ACCESS_CARGO) radio_key = /obj/item/encryptionkey/headset_cargo @@ -232,7 +233,7 @@ unload(0) if(prob(25)) visible_message(span_danger("Something shorts out inside [src]!")) - wires.cut_random() + wires.cut_random(source = Proj.firer) /mob/living/simple_animal/bot/mulebot/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) @@ -671,6 +672,12 @@ // when mulebot is in the same loc /mob/living/simple_animal/bot/mulebot/proc/run_over(mob/living/carbon/human/crushed) + if (!(bot_cover_flags & BOT_COVER_EMAGGED) && !wires.is_cut(WIRE_AVOIDANCE)) + if (!has_status_effect(/datum/status_effect/careful_driving)) + crushed.visible_message(span_notice("[src] slows down to avoid crushing [crushed].")) + apply_status_effect(/datum/status_effect/careful_driving) + return // Player mules must be emagged before they can trample + log_combat(src, crushed, "run over", addition = "(DAMTYPE: [uppertext(BRUTE)])") crushed.visible_message( span_danger("[src] drives over [crushed]!"), diff --git a/code/modules/wiremod/shell/airlock.dm b/code/modules/wiremod/shell/airlock.dm index ea7d9662cfc..6c5cd11df7d 100644 --- a/code/modules/wiremod/shell/airlock.dm +++ b/code/modules/wiremod/shell/airlock.dm @@ -2,7 +2,7 @@ holder_type = /obj/machinery/door/airlock/shell proper_name = "Circuit Airlock" -/datum/wires/airlock/shell/on_cut(wire, mend) +/datum/wires/airlock/shell/on_cut(wire, mend, source) // Don't allow them to re-enable autoclose. if(wire == WIRE_TIMING) return