diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml index ee3fac54d53..86baaafacbd 100644 --- a/.github/workflows/ci_suite.yml +++ b/.github/workflows/ci_suite.yml @@ -14,12 +14,12 @@ jobs: steps: - uses: actions/checkout@v2 - name: Restore SpacemanDMM cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/SpacemanDMM key: ${{ runner.os }}-spacemandmm-${{ secrets.CACHE_PURGE_KEY }} - name: Restore Yarn cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: tgui/.yarn/cache key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }} @@ -39,6 +39,7 @@ jobs: bash tools/ci/check_changelogs.sh bash tools/ci/check_grep.sh bash tools/ci/check_misc.sh + tools/bootstrap/python tools/validate_dme.py A unique movable for them to view. - var/list/viewers = list() - -/datum/action/New(Target) - link_to(Target) - -/datum/action/proc/link_to(Target) - target = Target - RegisterSignal(target, COMSIG_ATOM_UPDATED_ICON, .proc/OnUpdatedIcon) - RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE) - -/datum/action/Destroy() - if(owner) - Remove(owner) - target = null - QDEL_LIST_ASSOC_VAL(viewers) // Qdel the buttons in the viewers list **NOT THE HUDS** - return ..() - -/datum/action/proc/Grant(mob/M) - if(!M) - Remove(owner) - return - if(owner) - if(owner == M) - return - Remove(owner) - owner = M - RegisterSignal(owner, COMSIG_PARENT_QDELETING, .proc/clear_ref, override = TRUE) - - GiveAction(M) - -/datum/action/proc/clear_ref(datum/ref) - SIGNAL_HANDLER - if(ref == owner) - Remove(owner) - if(ref == target) - qdel(src) - -/datum/action/proc/Remove(mob/M) - for(var/datum/hud/hud in viewers) - if(!hud.mymob) - continue - HideFrom(hud.mymob) - LAZYREMOVE(M.actions, src) // We aren't always properly inserted into the viewers list, gotta make sure that action's cleared - viewers = list() - - if(owner) - UnregisterSignal(owner, COMSIG_PARENT_QDELETING) - if(target == owner) - RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/clear_ref) - owner = null - -/datum/action/proc/Trigger(trigger_flags) - if(!IsAvailable()) - return FALSE - if(SEND_SIGNAL(src, COMSIG_ACTION_TRIGGER, src) & COMPONENT_ACTION_BLOCK_TRIGGER) - return FALSE - return TRUE - - -/datum/action/proc/IsAvailable() - if(!owner) - return FALSE - if((check_flags & AB_CHECK_HANDS_BLOCKED) && HAS_TRAIT(owner, TRAIT_HANDS_BLOCKED)) - return FALSE - if((check_flags & AB_CHECK_IMMOBILE) && HAS_TRAIT(owner, TRAIT_IMMOBILIZED)) - return FALSE - if((check_flags & AB_CHECK_LYING) && isliving(owner)) - var/mob/living/action_user = owner - if(action_user.body_position == LYING_DOWN) - return FALSE - if((check_flags & AB_CHECK_CONSCIOUS) && owner.stat != CONSCIOUS) - return FALSE - return TRUE - -/datum/action/proc/UpdateButtons(status_only, force) - for(var/datum/hud/hud in viewers) - var/atom/movable/screen/movable/button = viewers[hud] - UpdateButton(button, status_only, force) - -/datum/action/proc/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) - if(!button) - return - if(!status_only) - button.name = name - button.desc = desc - if(owner?.hud_used && background_icon_state == ACTION_BUTTON_DEFAULT_BACKGROUND) - var/list/settings = owner.hud_used.get_action_buttons_icons() - if(button.icon != settings["bg_icon"]) - button.icon = settings["bg_icon"] - if(button.icon_state != settings["bg_state"]) - button.icon_state = settings["bg_state"] - else - if(button.icon != button_icon) - button.icon = button_icon - if(button.icon_state != background_icon_state) - button.icon_state = background_icon_state - - ApplyIcon(button, force) - - if(!IsAvailable()) - button.color = transparent_when_unavailable ? rgb(128,0,0,128) : rgb(128,0,0) - else - button.color = rgb(255,255,255,255) - return TRUE - -/datum/action/proc/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force = FALSE) - if(icon_icon && button_icon_state && ((current_button.button_icon_state != button_icon_state) || force)) - current_button.cut_overlays(TRUE) - current_button.add_overlay(mutable_appearance(icon_icon, button_icon_state)) - current_button.button_icon_state = button_icon_state - -/datum/action/proc/OnUpdatedIcon() - SIGNAL_HANDLER - UpdateButtons() - -//Give our action button to the player -/datum/action/proc/GiveAction(mob/viewer) - var/datum/hud/our_hud = viewer.hud_used - if(viewers[our_hud]) // Already have a copy of us? go away - return - - LAZYOR(viewer.actions, src) // Move this in - ShowTo(viewer) - -//Adds our action button to the screen of a player -/datum/action/proc/ShowTo(mob/viewer) - var/datum/hud/our_hud = viewer.hud_used - if(!our_hud || viewers[our_hud]) // There's no point in this if you have no hud in the first place - return - - var/atom/movable/screen/movable/action_button/button = CreateButton() - SetId(button, viewer) - - button.our_hud = our_hud - viewers[our_hud] = button - if(viewer.client) - viewer.client.screen += button - - button.load_position(viewer) - viewer.update_action_buttons() - -//Removes our action button from the screen of a player -/datum/action/proc/HideFrom(mob/viewer) - var/datum/hud/our_hud = viewer.hud_used - var/atom/movable/screen/movable/action_button/button = viewers[our_hud] - LAZYREMOVE(viewer.actions, src) - if(button) - qdel(button) - -/datum/action/proc/CreateButton() - var/atom/movable/screen/movable/action_button/button = new() - button.linked_action = src - button.name = name - button.actiontooltipstyle = buttontooltipstyle - if(desc) - button.desc = desc - return button - -/datum/action/proc/SetId(atom/movable/screen/movable/action_button/our_button, mob/owner) - //button id generation - var/bitfield = 0 - for(var/datum/action/action in owner.actions) - if(action == src) // This could be us, which is dumb - continue - var/atom/movable/screen/movable/action_button/button = action.viewers[owner.hud_used] - if(action.name == name && button.id) - bitfield |= button.id - - bitfield = ~bitfield // Flip our possible ids, so we can check if we've found a unique one - for(var/i in 0 to 23) // We get 24 possible bitflags in dm - var/bitflag = 1 << i // Shift us over one - if(bitfield & bitflag) - our_button.id = bitflag - return - -//Presets for item actions -/datum/action/item_action - check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_CONSCIOUS - button_icon_state = null - // If you want to override the normal icon being the item - // then change this to an icon state - -/datum/action/item_action/New(Target) - ..() - var/obj/item/I = target - LAZYINITLIST(I.actions) - I.actions += src - -/datum/action/item_action/Destroy() - var/obj/item/I = target - I.actions -= src - UNSETEMPTY(I.actions) - return ..() - -/datum/action/item_action/Trigger(trigger_flags) - . = ..() - if(!.) - return FALSE - if(target) - var/obj/item/I = target - I.ui_action_click(owner, src) - return TRUE - -/datum/action/item_action/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) - var/obj/item/item_target = target - if(button_icon && button_icon_state) - // If set, use the custom icon that we set instead - // of the item appearence - ..() - else if((target && current_button.appearance_cache != item_target.appearance) || force) //replace with /ref comparison if this is not valid. - var/old_layer = item_target.layer - var/old_plane = item_target.plane - item_target.layer = FLOAT_LAYER //AAAH - item_target.plane = FLOAT_PLANE //^ what that guy said - current_button.cut_overlays() - current_button.add_overlay(item_target) - item_target.layer = old_layer - item_target.plane = old_plane - current_button.appearance_cache = item_target.appearance - -/datum/action/item_action/toggle_light - name = "Toggle Light" - -/datum/action/item_action/toggle_light/Trigger(trigger_flags) - if(istype(target, /obj/item/modular_computer)) - var/obj/item/modular_computer/mc = target - mc.toggle_flashlight() - return - ..() - -/datum/action/item_action/toggle_hood - name = "Toggle Hood" - -/datum/action/item_action/toggle_firemode - icon_icon = 'modular_skyrat/master_files/icons/mob/actions/actions_items.dmi' //SKYRAT EDIT ADDITION - button_icon_state = "fireselect_no" //SKYRAT EDIT ADDITION - name = "Toggle Firemode" - -/datum/action/item_action/rcl_col - name = "Change Cable Color" - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "rcl_rainbow" - -/datum/action/item_action/rcl_gui - name = "Toggle Fast Wiring Gui" - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "rcl_gui" - -/datum/action/item_action/startchainsaw - name = "Pull The Starting Cord" - -/datum/action/item_action/toggle_computer_light - name = "Toggle Flashlight" - -/datum/action/item_action/toggle_gunlight - name = "Toggle Gunlight" - -/datum/action/item_action/toggle_mode - name = "Toggle Mode" - -/datum/action/item_action/toggle_barrier_spread - name = "Toggle Barrier Spread" - -/datum/action/item_action/equip_unequip_ted_gun - name = "Equip/Unequip TED Gun" - -/datum/action/item_action/toggle_paddles - name = "Toggle Paddles" - -/datum/action/item_action/set_internals - name = "Set Internals" - -/datum/action/item_action/set_internals/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force) - if(!..()) // no button available - return - if(!iscarbon(owner)) - return - var/mob/living/carbon/C = owner - if(target == C.internal) - button.icon_state = "template_active" - -/datum/action/item_action/pick_color - name = "Choose A Color" - -/datum/action/item_action/toggle_mister - name = "Toggle Mister" - -/datum/action/item_action/activate_injector - name = "Activate Injector" - -/datum/action/item_action/toggle_helmet_light - name = "Toggle Helmet Light" - -/datum/action/item_action/toggle_welding_screen - name = "Toggle Welding Screen" - -/datum/action/item_action/toggle_welding_screen/Trigger(trigger_flags) - var/obj/item/clothing/head/hardhat/weldhat/H = target - if(istype(H)) - H.toggle_welding_screen(owner) - -/datum/action/item_action/toggle_welding_screen/plasmaman - name = "Toggle Welding Screen" - -/datum/action/item_action/toggle_welding_screen/plasmaman/Trigger(trigger_flags) - var/obj/item/clothing/head/helmet/space/plasmaman/H = target - if(istype(H)) - H.toggle_welding_screen(owner) - -/datum/action/item_action/toggle_spacesuit - name = "Toggle Suit Thermal Regulator" - icon_icon = 'icons/mob/actions/actions_spacesuit.dmi' - button_icon_state = "thermal_off" - -/datum/action/item_action/toggle_spacesuit/New(Target) - . = ..() - RegisterSignal(target, COMSIG_SUIT_SPACE_TOGGLE, .proc/toggle) - -/datum/action/item_action/toggle_spacesuit/Destroy() - UnregisterSignal(target, COMSIG_SUIT_SPACE_TOGGLE) - return ..() - -/datum/action/item_action/toggle_spacesuit/Trigger(trigger_flags) - var/obj/item/clothing/suit/space/suit = target - if(!istype(suit)) - return - suit.toggle_spacesuit() - -/// Toggle the action icon for the space suit thermal regulator -/datum/action/item_action/toggle_spacesuit/proc/toggle(obj/item/clothing/suit/space/suit) - SIGNAL_HANDLER - - button_icon_state = "thermal_[suit.thermal_on ? "on" : "off"]" - UpdateButtons() - -/datum/action/item_action/vortex_recall - name = "Vortex Recall" - desc = "Recall yourself, and anyone nearby, to an attuned hierophant beacon at any time.
If the beacon is still attached, will detach it." - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "vortex_recall" - -/datum/action/item_action/vortex_recall/IsAvailable() - var/area/current_area = get_area(target) - if(current_area.area_flags & NOTELEPORT) - to_chat(owner, span_notice("[target] fizzles uselessly.")) - return - if(istype(target, /obj/item/hierophant_club)) - var/obj/item/hierophant_club/H = target - if(H.teleporting) - return FALSE - return ..() - -/datum/action/item_action/berserk_mode - name = "Berserk" - desc = "Increase your movement and melee speed while also increasing your melee armor for a short amount of time." - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "berserk_mode" - background_icon_state = "bg_demon" - -/datum/action/item_action/berserk_mode/Trigger(trigger_flags) - if(istype(target, /obj/item/clothing/head/hooded/berserker)) - var/obj/item/clothing/head/hooded/berserker/berzerk = target - if(berzerk.berserk_active) - to_chat(owner, span_warning("You are already berserk!")) - return - if(berzerk.berserk_charge < 100) - to_chat(owner, span_warning("You don't have a full charge.")) - return - berzerk.berserk_mode(owner) - return - ..() - -/datum/action/item_action/toggle_helmet_flashlight - name = "Toggle Helmet Flashlight" - -/datum/action/item_action/toggle_helmet_mode - name = "Toggle Helmet Mode" - -/datum/action/item_action/crew_monitor - name = "Interface With Crew Monitor" - -/datum/action/item_action/toggle - -/datum/action/item_action/toggle/New(Target) - ..() - var/obj/item/item_target = target - name = "Toggle [item_target.name]" - -/datum/action/item_action/halt - name = "HALT!" - -/datum/action/item_action/toggle_voice_box - name = "Toggle Voice Box" - -/datum/action/item_action/change - name = "Change" - -/datum/action/item_action/nano_picket_sign - name = "Retext Nano Picket Sign" - -/datum/action/item_action/nano_picket_sign/Trigger(trigger_flags) - if(!istype(target, /obj/item/picket_sign)) - return - var/obj/item/picket_sign/sign = target - sign.retext(owner) - -/datum/action/item_action/adjust - -/datum/action/item_action/adjust/New(Target) - ..() - var/obj/item/item_target = target - name = "Adjust [item_target.name]" - -/datum/action/item_action/switch_hud - name = "Switch HUD" - -/datum/action/item_action/toggle_human_head - name = "Toggle Human Head" - -/datum/action/item_action/toggle_helmet - name = "Toggle Helmet" - -/datum/action/item_action/toggle_seclight - name = "Toggle Seclight" - -/datum/action/item_action/toggle_jetpack - name = "Toggle Jetpack" - -/datum/action/item_action/jetpack_stabilization - name = "Toggle Jetpack Stabilization" - -/datum/action/item_action/jetpack_stabilization/IsAvailable() - var/obj/item/tank/jetpack/J = target - if(!istype(J) || !J.on) - return FALSE - return ..() - -/datum/action/item_action/hands_free - check_flags = AB_CHECK_CONSCIOUS - -/datum/action/item_action/hands_free/activate - name = "Activate" - -/datum/action/item_action/hands_free/shift_nerves - name = "Shift Nerves" - -/datum/action/item_action/explosive_implant - check_flags = NONE - name = "Activate Explosive Implant" - -/datum/action/item_action/instrument - name = "Use Instrument" - desc = "Use the instrument specified" - -/datum/action/item_action/instrument/Trigger(trigger_flags) - if(istype(target, /obj/item/instrument)) - var/obj/item/instrument/I = target - I.interact(usr) - return - return ..() - -/datum/action/item_action/activate_remote_view - name = "Activate Remote View" - desc = "Activates the Remote View of your spy sunglasses." - -/datum/action/item_action/organ_action - check_flags = AB_CHECK_CONSCIOUS - -/datum/action/item_action/organ_action/IsAvailable() - var/obj/item/organ/I = target - if(!I.owner) - return FALSE - return ..() - -/datum/action/item_action/organ_action/toggle/New(Target) - ..() - var/obj/item/organ/organ_target = target - name = "Toggle [organ_target.name]" - -/datum/action/item_action/organ_action/use/New(Target) - ..() - var/obj/item/organ/organ_target = target - name = "Use [organ_target.name]" - -/datum/action/item_action/cult_dagger - name = "Draw Blood Rune" - desc = "Use the ritual dagger to create a powerful blood rune" - icon_icon = 'icons/mob/actions/actions_cult.dmi' - button_icon_state = "draw" - buttontooltipstyle = "cult" - background_icon_state = "bg_demon" - default_button_position = "6:157,4:-2" - -/datum/action/item_action/cult_dagger/Grant(mob/M) - if(!IS_CULTIST(M)) - Remove(owner) - return - return ..() - -/datum/action/item_action/cult_dagger/Trigger(trigger_flags) - for(var/obj/item/held_item as anything in owner.held_items) // In case we were already holding a dagger - if(istype(held_item, /obj/item/melee/cultblade/dagger)) - held_item.attack_self(owner) - return - var/obj/item/target_item = target - if(owner.can_equip(target_item, ITEM_SLOT_HANDS)) - owner.temporarilyRemoveItemFromInventory(target_item) - owner.put_in_hands(target_item) - target_item.attack_self(owner) - return - - if(!isliving(owner)) - to_chat(owner, span_warning("You lack the necessary living force for this action.")) - return - - var/mob/living/living_owner = owner - if (living_owner.usable_hands <= 0) - to_chat(living_owner, span_warning("You don't have any usable hands!")) - else - to_chat(living_owner, span_warning("Your hands are full!")) - - -///MGS BOX! -/datum/action/item_action/agent_box - name = "Deploy Box" - desc = "Find inner peace, here, in the box." - check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS - background_icon_state = "bg_agent" - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "deploy_box" - ///The type of closet this action spawns. - var/boxtype = /obj/structure/closet/cardboard/agent - COOLDOWN_DECLARE(box_cooldown) - -///Handles opening and closing the box. -/datum/action/item_action/agent_box/Trigger(trigger_flags) - . = ..() - if(!.) - return FALSE - if(istype(owner.loc, /obj/structure/closet/cardboard/agent)) - var/obj/structure/closet/cardboard/agent/box = owner.loc - if(box.open()) - owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) - return - //Box closing from here on out. - if(!isturf(owner.loc)) //Don't let the player use this to escape mechs/welded closets. - to_chat(owner, span_warning("You need more space to activate this implant!")) - return - if(!COOLDOWN_FINISHED(src, box_cooldown)) - return - COOLDOWN_START(src, box_cooldown, 10 SECONDS) - var/box = new boxtype(owner.drop_location()) - owner.forceMove(box) - owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) - -/datum/action/item_action/agent_box/Grant(mob/M) - . = ..() - if(owner) - RegisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT, .proc/suicide_act) - -/datum/action/item_action/agent_box/Remove(mob/M) - if(owner) - UnregisterSignal(owner, COMSIG_HUMAN_SUICIDE_ACT) - return ..() - -/datum/action/item_action/agent_box/proc/suicide_act(datum/source) - SIGNAL_HANDLER - - if(!istype(owner.loc, /obj/structure/closet/cardboard/agent)) - return - - var/obj/structure/closet/cardboard/agent/box = owner.loc - owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE) - box.open() - owner.visible_message(span_suicide("[owner] falls out of [box]! It looks like [owner.p_they()] committed suicide!")) - owner.throw_at(get_turf(owner)) - return OXYLOSS - -//Preset for spells -/datum/action/spell_action - check_flags = NONE - background_icon_state = "bg_spell" - -/datum/action/spell_action/New(Target) - ..() - var/obj/effect/proc_holder/S = target - S.action = src - name = S.name - desc = S.desc - icon_icon = S.action_icon - button_icon_state = S.action_icon_state - background_icon_state = S.action_background_icon_state - -/datum/action/spell_action/Destroy() - var/obj/effect/proc_holder/S = target - S.action = null - return ..() - -/datum/action/spell_action/Trigger(trigger_flags) - if(!..()) - return FALSE - if(target) - var/obj/effect/proc_holder/S = target - S.Click() - return TRUE - -/datum/action/spell_action/IsAvailable() - if(!target) - return FALSE - return TRUE - -/datum/action/spell_action/spell - -/datum/action/spell_action/spell/IsAvailable() - if(!target) - return FALSE - var/obj/effect/proc_holder/spell/S = target - if(owner) - return S.can_cast(owner) - return FALSE - -/datum/action/spell_action/alien - -/datum/action/spell_action/alien/IsAvailable() - if(!target) - return FALSE - var/obj/effect/proc_holder/alien/ab = target - if(owner) - return ab.cost_check(ab.check_turf,owner,1) - return FALSE - - - -//Preset for general and toggled actions -/datum/action/innate - check_flags = NONE - var/active = 0 - -/datum/action/innate/Trigger(trigger_flags) - if(!..()) - return FALSE - if(!active) - Activate() - else - Deactivate() - return TRUE - -/datum/action/innate/proc/Activate() - return - -/datum/action/innate/proc/Deactivate() - return - -//Preset for an action with a cooldown - -/datum/action/cooldown - check_flags = NONE - transparent_when_unavailable = FALSE - // The default cooldown applied when StartCooldown() is called - var/cooldown_time = 0 - // The actual next time this ability can be used - var/next_use_time = 0 - // Whether or not you want the cooldown for the ability to display in text form - var/text_cooldown = TRUE - // Setting for intercepting clicks before activating the ability - var/click_to_activate = FALSE - // Shares cooldowns with other cooldown abilities of the same value, not active if null - var/shared_cooldown - -/datum/action/cooldown/CreateButton() - var/atom/movable/screen/movable/action_button/button = ..() - button.maptext = "" - button.maptext_x = 8 - button.maptext_y = 0 - button.maptext_width = 24 - button.maptext_height = 12 - return button - -/datum/action/cooldown/IsAvailable() - return ..() && (next_use_time <= world.time) - -/// Starts a cooldown time to be shared with similar abilities, will use default cooldown time if an override is not specified -/datum/action/cooldown/proc/StartCooldown(override_cooldown_time) - if(shared_cooldown) - for(var/datum/action/cooldown/shared_ability in owner.actions - src) - if(shared_cooldown == shared_ability.shared_cooldown) - if(isnum(override_cooldown_time)) - shared_ability.StartCooldownSelf(override_cooldown_time) - else - shared_ability.StartCooldownSelf(cooldown_time) - StartCooldownSelf(override_cooldown_time) - -/// Starts a cooldown time for this ability only, will use default cooldown time if an override is not specified -/datum/action/cooldown/proc/StartCooldownSelf(override_cooldown_time) - if(isnum(override_cooldown_time)) - next_use_time = world.time + override_cooldown_time - else - next_use_time = world.time + cooldown_time - UpdateButtons() - START_PROCESSING(SSfastprocess, src) - -/datum/action/cooldown/Trigger(trigger_flags, atom/target) - . = ..() - if(!.) - return - if(!owner) - return FALSE - if(click_to_activate) - if(target) - // For automatic / mob handling - return InterceptClickOn(owner, null, target) - if(owner.click_intercept == src) - owner.click_intercept = null - else - owner.click_intercept = src - for(var/datum/action/cooldown/ability in owner.actions) - ability.UpdateButtons() - return TRUE - return PreActivate(owner) - -/// Intercepts client owner clicks to activate the ability -/datum/action/cooldown/proc/InterceptClickOn(mob/living/caller, params, atom/target) - if(!IsAvailable()) - return FALSE - if(!target) - return FALSE - PreActivate(target) - caller.click_intercept = null - return TRUE - -/// For signal calling -/datum/action/cooldown/proc/PreActivate(atom/target) - if(SEND_SIGNAL(owner, COMSIG_ABILITY_STARTED, src) & COMPONENT_BLOCK_ABILITY_START) - return - . = Activate(target) - SEND_SIGNAL(owner, COMSIG_ABILITY_FINISHED, src) - -/// To be implemented by subtypes -/datum/action/cooldown/proc/Activate(atom/target) - return - -/datum/action/cooldown/UpdateButton(atom/movable/screen/movable/action_button/button, status_only = FALSE, force = FALSE) - . = ..() - if(!button) - return - var/time_left = max(next_use_time - world.time, 0) - if(text_cooldown) - button.maptext = MAPTEXT("[round(time_left/10, 0.1)]") - if(!owner || time_left == 0) - button.maptext = "" - if(IsAvailable() && owner.click_intercept == src) - button.color = COLOR_GREEN - -/datum/action/cooldown/process() - var/time_left = max(next_use_time - world.time, 0) - if(!owner || time_left == 0) - STOP_PROCESSING(SSfastprocess, src) - UpdateButtons() - -/datum/action/cooldown/Grant(mob/M) - ..() - if(!owner) - return - UpdateButtons() - if(next_use_time > world.time) - START_PROCESSING(SSfastprocess, src) - -///Like a cooldown action, but with an associated proc holder. -/datum/action/cooldown/spell_like - -/datum/action/cooldown/spell_like/New(Target) - ..() - var/obj/effect/proc_holder/our_proc_holder = Target - our_proc_holder.action = src - name = our_proc_holder.name - desc = our_proc_holder.desc - icon_icon = our_proc_holder.action_icon - button_icon_state = our_proc_holder.action_icon_state - background_icon_state = our_proc_holder.action_background_icon_state - -/datum/action/cooldown/spell_like/Activate(atom/activate_target) - if(!target) - return FALSE - - StartCooldown(10 SECONDS) - var/obj/effect/proc_holder/our_proc_holder = target - our_proc_holder.Click() - StartCooldown() - return TRUE - -//Stickmemes -/datum/action/item_action/stickmen - name = "Summon Stick Minions" - desc = "Allows you to summon faithful stickmen allies to aide you in battle." - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "art_summon" - -//surf_ss13 -/datum/action/item_action/bhop - name = "Activate Jump Boots" - desc = "Activates the jump boot's internal propulsion system, allowing the user to dash over 4-wide gaps." - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "jetboot" - -/datum/action/item_action/bhop/brocket - name = "Activate Rocket Boots" - desc = "Activates the boot's rocket propulsion system, allowing the user to hurl themselves great distances." - -/datum/action/language_menu - name = "Language Menu" - desc = "Open the language menu to review your languages, their keys, and select your default language." - button_icon_state = "language_menu" - check_flags = NONE - -/datum/action/language_menu/Trigger(trigger_flags) - if(!..()) - return FALSE - if(ismob(owner)) - var/mob/M = owner - var/datum/language_holder/H = M.get_language_holder() - H.open_language_menu(usr) - -/datum/action/item_action/wheelys - name = "Toggle Wheels" - desc = "Pops out or in your shoes' wheels." - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "wheelys" - -/datum/action/item_action/kindle_kicks - name = "Activate Kindle Kicks" - desc = "Kick you feet together, activating the lights in your Kindle Kicks." - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "kindleKicks" - -//Small sprites -/datum/action/small_sprite - name = "Toggle Giant Sprite" - desc = "Others will always see you as giant." - icon_icon = 'icons/mob/actions/actions_xeno.dmi' - button_icon_state = "smallqueen" - background_icon_state = "bg_alien" - var/small = FALSE - var/small_icon - var/small_icon_state - -/datum/action/small_sprite/queen - small_icon = 'icons/mob/alien.dmi' - small_icon_state = "alienq" - -/datum/action/small_sprite/megafauna - icon_icon = 'icons/mob/actions/actions_xeno.dmi' - small_icon = 'icons/mob/lavaland/lavaland_monsters.dmi' - -/datum/action/small_sprite/megafauna/drake - small_icon_state = "ash_whelp" - -/datum/action/small_sprite/megafauna/colossus - small_icon_state = "Basilisk" - -/datum/action/small_sprite/megafauna/bubblegum - small_icon_state = "goliath2" - -/datum/action/small_sprite/megafauna/legion - small_icon_state = "mega_legion" - -/datum/action/small_sprite/mega_arachnid - small_icon = 'icons/mob/jungle/arachnid.dmi' - small_icon_state = "arachnid_mini" - background_icon_state = "bg_demon" - -/datum/action/small_sprite/space_dragon - small_icon = 'icons/mob/carp.dmi' - small_icon_state = "carp" - icon_icon = 'icons/mob/carp.dmi' - button_icon_state = "carp" - -/datum/action/small_sprite/Trigger(trigger_flags) - ..() - if(!small) - var/image/I = image(icon = small_icon, icon_state = small_icon_state, loc = owner) - I.override = TRUE - I.pixel_x -= owner.pixel_x - I.pixel_y -= owner.pixel_y - owner.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic, "smallsprite", I, AA_TARGET_SEE_APPEARANCE | AA_MATCH_TARGET_OVERLAYS) - small = TRUE - else - owner.remove_alt_appearance("smallsprite") - small = FALSE - -/datum/action/item_action/storage_gather_mode - name = "Switch gathering mode" - desc = "Switches the gathering mode of a storage object." - icon_icon = 'icons/mob/actions/actions_items.dmi' - button_icon_state = "storage_gather_switch" - -/datum/action/item_action/storage_gather_mode/ApplyIcon(atom/movable/screen/movable/action_button/current_button) - . = ..() - var/obj/item/item_target = target - var/old_layer = item_target.layer - var/old_plane = item_target.plane - item_target.layer = FLOAT_LAYER //AAAH - item_target.plane = FLOAT_PLANE //^ what that guy said - current_button.cut_overlays() - current_button.add_overlay(target) - item_target.layer = old_layer - item_target.plane = old_plane - current_button.appearance_cache = item_target.appearance diff --git a/code/datums/actions/items/toggles.dm b/code/datums/actions/items/toggles.dm index 1af240a6b02..38aaa532e1a 100644 --- a/code/datums/actions/items/toggles.dm +++ b/code/datums/actions/items/toggles.dm @@ -15,6 +15,8 @@ name = "Toggle Hood" /datum/action/item_action/toggle_firemode + icon_icon = 'modular_skyrat/master_files/icons/mob/actions/actions_items.dmi' //SKYRAT EDIT ADDITION + button_icon_state = "fireselect_no" //SKYRAT EDIT ADDITION name = "Toggle Firemode" /datum/action/item_action/toggle_gunlight diff --git a/code/game/machinery/computer/atmos_control.dm b/code/game/machinery/computer/atmos_control.dm deleted file mode 100644 index 0611c23b90b..00000000000 --- a/code/game/machinery/computer/atmos_control.dm +++ /dev/null @@ -1,499 +0,0 @@ -///////////////////////////////////////////////////////////// -// AIR SENSOR (found in gas tanks) -///////////////////////////////////////////////////////////// - -/obj/machinery/air_sensor - name = "gas sensor" - icon = 'icons/obj/stationobjs.dmi' - icon_state = "gsensor1" - resistance_flags = FIRE_PROOF - - var/on = TRUE - - var/frequency = FREQ_ATMOS_STORAGE - var/datum/radio_frequency/radio_connection - -/obj/machinery/air_sensor/atmos/plasma_tank - name = "plasma tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_PLAS -/obj/machinery/air_sensor/atmos/ordnance_mixing_tank - name = "ordnance mixing gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_ORDNANCE_LAB -/obj/machinery/air_sensor/atmos/oxygen_tank - name = "oxygen tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_O2 -/obj/machinery/air_sensor/atmos/nitrogen_tank - name = "nitrogen tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_N2 -/obj/machinery/air_sensor/atmos/mix_tank - name = "mix tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_MIX -/obj/machinery/air_sensor/atmos/nitrous_tank - name = "nitrous oxide tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_N2O -/obj/machinery/air_sensor/atmos/air_tank - name = "air mix tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_AIR -/obj/machinery/air_sensor/atmos/carbon_tank - name = "carbon dioxide tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_CO2 -/obj/machinery/air_sensor/atmos/bz_tank - name = "bz tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_BZ -/obj/machinery/air_sensor/atmos/freon_tank - name = "freon tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_FREON -/obj/machinery/air_sensor/atmos/halon_tank - name = "halon tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_HALON -/obj/machinery/air_sensor/atmos/healium_tank - name = "healium tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_HEALIUM -/obj/machinery/air_sensor/atmos/hydrogen_tank - name = "hydrogen tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_H2 -/obj/machinery/air_sensor/atmos/hypernoblium_tank - name = "hypernoblium tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM -/obj/machinery/air_sensor/atmos/miasma_tank - name = "miasma tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_MIASMA -/obj/machinery/air_sensor/atmos/nitrium_tank - name = "nitrium tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_NITRIUM -/obj/machinery/air_sensor/atmos/pluoxium_tank - name = "pluoxium tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM -/obj/machinery/air_sensor/atmos/proto_nitrate_tank - name = "proto-nitrate tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE -/obj/machinery/air_sensor/atmos/tritium_tank - name = "tritium tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_TRITIUM -/obj/machinery/air_sensor/atmos/water_vapor_tank - name = "water vapor tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_H2O -/obj/machinery/air_sensor/atmos/zauker_tank - name = "zauker tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_ZAUKER -/obj/machinery/air_sensor/atmos/helium_tank - name = "helium tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_HELIUM -/obj/machinery/air_sensor/atmos/antinoblium_tank - name = "antinoblium tank gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_ANTINOBLIUM -/obj/machinery/air_sensor/atmos/incinerator_tank - name = "incinerator chamber gas sensor" - id_tag = ATMOS_GAS_MONITOR_SENSOR_INCINERATOR - -/obj/machinery/air_sensor/update_icon_state() - icon_state = "gsensor[on]" - return ..() - -/obj/machinery/air_sensor/process_atmos() - if(on) - var/datum/gas_mixture/air_sample = return_air() - - var/datum/signal/signal = new(list( - "sigtype" = "status", - "id_tag" = id_tag, - "timestamp" = world.time, - "pressure" = air_sample.return_pressure(), - "temperature" = air_sample.temperature, - "gases" = list() - )) - var/total_moles = air_sample.total_moles() - if(total_moles) - for(var/gas_id in air_sample.gases) - var/gas_name = air_sample.gases[gas_id][GAS_META][META_GAS_NAME] - signal.data["gases"][gas_name] = air_sample.gases[gas_id][MOLES] / total_moles * 100 - - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) - - -/obj/machinery/air_sensor/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) - -/obj/machinery/air_sensor/Initialize(mapload) - . = ..() - SSair.start_processing_machine(src) - set_frequency(frequency) - -/obj/machinery/air_sensor/Destroy() - SSair.stop_processing_machine(src) - SSradio.remove_object(src, frequency) - return ..() - -///////////////////////////////////////////////////////////// -// GENERAL AIR CONTROL (a.k.a atmos computer) -///////////////////////////////////////////////////////////// -GLOBAL_LIST_EMPTY(atmos_air_controllers) - -/obj/machinery/computer/atmos_control - name = "atmospherics monitoring" - desc = "Used to monitor the station's atmospherics sensors." - icon_screen = "tank" - icon_keyboard = "atmos_key" - circuit = /obj/item/circuitboard/computer/atmos_control - light_color = LIGHT_COLOR_CYAN - - var/frequency = FREQ_ATMOS_STORAGE - var/list/sensors = list( - ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank", - ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank", - ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank", - ATMOS_GAS_MONITOR_SENSOR_PLAS = "Plasma Tank", - ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank", - ATMOS_GAS_MONITOR_SENSOR_AIR = "Mixed Air Tank", - ATMOS_GAS_MONITOR_SENSOR_MIX = "Mix Tank", - ATMOS_GAS_MONITOR_SENSOR_BZ = "BZ Tank", - ATMOS_GAS_MONITOR_SENSOR_FREON = "Freon Tank", - ATMOS_GAS_MONITOR_SENSOR_HALON = "Halon Tank", - ATMOS_GAS_MONITOR_SENSOR_HEALIUM = "Healium Tank", - ATMOS_GAS_MONITOR_SENSOR_H2 = "Hydrogen Tank", - ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM = "Hypernoblium Tank", - ATMOS_GAS_MONITOR_SENSOR_MIASMA = "Miasma Tank", - ATMOS_GAS_MONITOR_SENSOR_NITRIUM = "Nitrium Tank", - ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM = "Pluoxium Tank", - ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE = "Proto-Nitrate Tank", - ATMOS_GAS_MONITOR_SENSOR_TRITIUM = "Tritium Tank", - ATMOS_GAS_MONITOR_SENSOR_H2O = "Water Vapor Tank", - ATMOS_GAS_MONITOR_SENSOR_ZAUKER = "Zauker Tank", - ATMOS_GAS_MONITOR_LOOP_DISTRIBUTION = "Distribution Loop", - ATMOS_GAS_MONITOR_LOOP_ATMOS_WASTE = "Atmos Waste Loop", - ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber", - ATMOS_GAS_MONITOR_SENSOR_ORDNANCE_LAB = "Ordnance Mixing Chamber" - ) - var/list/sensor_information = list() - var/datum/radio_frequency/radio_connection - - -/obj/machinery/computer/atmos_control/Initialize(mapload) - . = ..() - GLOB.atmos_air_controllers += src - set_frequency(frequency) - -/obj/machinery/computer/atmos_control/Destroy() - GLOB.atmos_air_controllers -= src - SSradio.remove_object(src, frequency) - return ..() - -/obj/machinery/computer/atmos_control/ui_interact(mob/user, datum/tgui/ui) - //SKYRAT EDIT ADDITON BEGIN - AESTHETICS - if(clicksound && world.time > next_clicksound && isliving(user)) - next_clicksound = world.time + rand(50, 100) - playsound(src, get_sfx_skyrat(clicksound), clickvol) - //SKYRAT EDIT END - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "AtmosControlConsole", name) - ui.open() - -/obj/machinery/computer/atmos_control/ui_data(mob/user) - var/data = list() - - data["sensors"] = list() - for(var/id_tag in sensors) - var/long_name = sensors[id_tag] - var/list/info = sensor_information[id_tag] - if(!info) - continue - data["sensors"] += list(list( - "id_tag" = id_tag, - "long_name" = sanitize(long_name), - "pressure" = info["pressure"], - "temperature" = info["temperature"], - "gases" = info["gases"] - )) - return data - -/obj/machinery/computer/atmos_control/receive_signal(datum/signal/signal) - if(!signal) - return - - var/id_tag = signal.data["id_tag"] - if(!id_tag || !sensors.Find(id_tag)) - return - - sensor_information[id_tag] = signal.data - -/obj/machinery/computer/atmos_control/proc/set_frequency(new_frequency) - SSradio.remove_object(src, frequency) - frequency = new_frequency - radio_connection = SSradio.add_object(src, frequency, RADIO_ATMOSIA) - -//Incinerator sensor only -/obj/machinery/computer/atmos_control/incinerator - name = "Incinerator Air Control" - sensors = list(ATMOS_GAS_MONITOR_SENSOR_INCINERATOR = "Incinerator Chamber") - circuit = /obj/item/circuitboard/computer/atmos_control/incinerator - -//Ordnance mix sensor only -/obj/machinery/computer/atmos_control/ordnancemix - name = "Ordnance Mixing Air Control" - sensors = list(ATMOS_GAS_MONITOR_SENSOR_ORDNANCE_LAB = "Ordnance Mixing Chamber") - circuit = /obj/item/circuitboard/computer/atmos_control/ordnancemix - -///////////////////////////////////////////////////////////// -// LARGE TANK CONTROL -///////////////////////////////////////////////////////////// - -/obj/machinery/computer/atmos_control/tank - var/input_tag - var/output_tag - frequency = FREQ_ATMOS_STORAGE - circuit = /obj/item/circuitboard/computer/atmos_control/tank - var/list/input_info - var/list/output_info - -/obj/machinery/computer/atmos_control/tank/oxygen_tank - name = "Oxygen Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_O2 - output_tag = ATMOS_GAS_MONITOR_OUTPUT_O2 - sensors = list(ATMOS_GAS_MONITOR_SENSOR_O2 = "Oxygen Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/oxygen_tank - -/obj/machinery/computer/atmos_control/tank/plasma_tank - name = "Plasma Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_PLAS - output_tag = ATMOS_GAS_MONITOR_OUTPUT_PLAS - sensors = list(ATMOS_GAS_MONITOR_SENSOR_PLAS = "Plasma Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/plasma_tank - -/obj/machinery/computer/atmos_control/tank/air_tank - name = "Mixed Air Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_AIR - output_tag = ATMOS_GAS_MONITOR_OUTPUT_AIR - sensors = list(ATMOS_GAS_MONITOR_SENSOR_AIR = "Air Mix Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/air_tank - -/obj/machinery/computer/atmos_control/tank/mix_tank - name = "Gas Mix Tank Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_MIX - output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIX - sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIX = "Gas Mix Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/mix_tank - -/obj/machinery/computer/atmos_control/tank/nitrous_tank - name = "Nitrous Oxide Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_N2O - output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2O - sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2O = "Nitrous Oxide Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/nitrous_tank - -/obj/machinery/computer/atmos_control/tank/nitrogen_tank - name = "Nitrogen Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_N2 - output_tag = ATMOS_GAS_MONITOR_OUTPUT_N2 - sensors = list(ATMOS_GAS_MONITOR_SENSOR_N2 = "Nitrogen Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/nitrogen_tank - -/obj/machinery/computer/atmos_control/tank/carbon_tank - name = "Carbon Dioxide Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_CO2 - output_tag = ATMOS_GAS_MONITOR_OUTPUT_CO2 - sensors = list(ATMOS_GAS_MONITOR_SENSOR_CO2 = "Carbon Dioxide Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/carbon_tank - -/obj/machinery/computer/atmos_control/tank/bz_tank - name = "BZ Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_BZ - output_tag = ATMOS_GAS_MONITOR_OUTPUT_BZ - sensors = list(ATMOS_GAS_MONITOR_SENSOR_BZ = "BZ Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/bz_tank - -/obj/machinery/computer/atmos_control/tank/freon_tank - name = "Freon Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_FREON - output_tag = ATMOS_GAS_MONITOR_OUTPUT_FREON - sensors = list(ATMOS_GAS_MONITOR_SENSOR_FREON = "Freon Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/freon_tank - -/obj/machinery/computer/atmos_control/tank/halon_tank - name = "Halon Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_HALON - output_tag = ATMOS_GAS_MONITOR_OUTPUT_HALON - sensors = list(ATMOS_GAS_MONITOR_SENSOR_HALON = "Halon Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/halon_tank - -/obj/machinery/computer/atmos_control/tank/healium_tank - name = "Healium Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_HEALIUM - output_tag = ATMOS_GAS_MONITOR_OUTPUT_HEALIUM - sensors = list(ATMOS_GAS_MONITOR_SENSOR_HEALIUM = "Healium Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/healium_tank - -/obj/machinery/computer/atmos_control/tank/hydrogen_tank - name = "Hydrogen Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_H2 - output_tag = ATMOS_GAS_MONITOR_OUTPUT_H2 - sensors = list(ATMOS_GAS_MONITOR_SENSOR_H2 = "Hydrogen Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/hydrogen_tank - -/obj/machinery/computer/atmos_control/tank/hypernoblium_tank - name = "Hypernoblium Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_HYPERNOBLIUM - output_tag = ATMOS_GAS_MONITOR_OUTPUT_HYPERNOBLIUM - sensors = list(ATMOS_GAS_MONITOR_SENSOR_HYPERNOBLIUM = "Hypernoblium Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/hypernoblium_tank - -/obj/machinery/computer/atmos_control/tank/miasma_tank - name = "Miasma Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_MIASMA - output_tag = ATMOS_GAS_MONITOR_OUTPUT_MIASMA - sensors = list(ATMOS_GAS_MONITOR_SENSOR_MIASMA = "Miasma Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/miasma_tank - -/obj/machinery/computer/atmos_control/tank/nitrium_tank - name = "Nitrium Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_NITRIUM - output_tag = ATMOS_GAS_MONITOR_OUTPUT_NITRIUM - sensors = list(ATMOS_GAS_MONITOR_SENSOR_NITRIUM = "Nitrium Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/nitrium_tank - -/obj/machinery/computer/atmos_control/tank/pluoxium_tank - name = "Pluoxium Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_PLUOXIUM - output_tag = ATMOS_GAS_MONITOR_OUTPUT_PLUOXIUM - sensors = list(ATMOS_GAS_MONITOR_SENSOR_PLUOXIUM = "Pluoxium Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/pluoxium_tank - -/obj/machinery/computer/atmos_control/tank/proto_nitrate_tank - name = "Proto-Nitrate Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_PROTO_NITRATE - output_tag = ATMOS_GAS_MONITOR_OUTPUT_PROTO_NITRATE - sensors = list(ATMOS_GAS_MONITOR_SENSOR_PROTO_NITRATE = "Proto-Nitrate Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/proto_nitrate_tank - -/obj/machinery/computer/atmos_control/tank/tritium_tank - name = "Tritium Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_TRITIUM - output_tag = ATMOS_GAS_MONITOR_OUTPUT_TRITIUM - sensors = list(ATMOS_GAS_MONITOR_SENSOR_TRITIUM = "Tritium Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/tritium_tank - -/obj/machinery/computer/atmos_control/tank/water_vapor - name = "Water Vapor Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_H2O - output_tag = ATMOS_GAS_MONITOR_OUTPUT_H2O - sensors = list(ATMOS_GAS_MONITOR_SENSOR_H2O = "Water Vapor Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/water_vapor - -/obj/machinery/computer/atmos_control/tank/zauker_tank - name = "Zauker Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_ZAUKER - output_tag = ATMOS_GAS_MONITOR_OUTPUT_ZAUKER - sensors = list(ATMOS_GAS_MONITOR_SENSOR_ZAUKER = "Zauker Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/zauker_tank - -/obj/machinery/computer/atmos_control/tank/helium_tank - name = "Helium Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_HELIUM - output_tag = ATMOS_GAS_MONITOR_OUTPUT_HELIUM - sensors = list(ATMOS_GAS_MONITOR_SENSOR_HELIUM = "Helium Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/helium_tank - -/obj/machinery/computer/atmos_control/tank/antinoblium_tank - name = "Antinoblium Supply Control" - input_tag = ATMOS_GAS_MONITOR_INPUT_ANTINOBLIUM - output_tag = ATMOS_GAS_MONITOR_OUTPUT_ANTINOBLIUM - sensors = list(ATMOS_GAS_MONITOR_SENSOR_ANTINOBLIUM = "Antinoblium Tank") - circuit = /obj/item/circuitboard/computer/atmos_control/tank/antinoblium_tank - -// This hacky madness is the evidence of the fact that a lot of machines were never meant to be constructable, im so sorry you had to see this -/obj/machinery/computer/atmos_control/tank/proc/reconnect(mob/user) - var/list/IO = list() - var/datum/radio_frequency/freq = SSradio.return_frequency(frequency) - - var/list/devices = list() - var/list/device_refs = freq.devices["_default"] - for(var/datum/weakref/device_ref as anything in device_refs) - var/atom/device = device_ref.resolve() - if(!device) - device_refs -= device_ref - continue - devices += device - - for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) - var/list/text = splittext(U.id_tag, "_") - IO |= text[1] - for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices) - var/list/text = splittext(U.id, "_") - IO |= text[1] - if(!IO.len) - to_chat(user, span_alert("No machinery detected.")) - var/S = tgui_input_list(user, "Select the device set", "Reconnect", sort_list(IO)) - if(isnull(S)) - return - if(src) - src.input_tag = "[S]_in" - src.output_tag = "[S]_out" - name = "[uppertext(S)] Supply Control" - var/list/new_devices = freq.devices["atmosia"] - sensors.Cut() - for(var/obj/machinery/air_sensor/U in new_devices) - var/list/text = splittext(U.id_tag, "_") - if(text[1] == S) - sensors = list("[S]_sensor" = "[S] Tank") - break - - for(var/obj/machinery/atmospherics/components/unary/outlet_injector/U in devices) - U.broadcast_status() - for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) - U.broadcast_status() - -/obj/machinery/computer/atmos_control/tank/ui_data(mob/user) - var/list/data = ..() - data["tank"] = TRUE - data["inputting"] = input_info ? input_info["power"] : FALSE - data["inputRate"] = input_info ? input_info["volume_rate"] : 0 - data["maxInputRate"] = input_info ? MAX_TRANSFER_RATE : 0 - data["outputting"] = output_info ? output_info["power"] : FALSE - data["outputPressure"] = output_info ? output_info["internal"] : 0 - data["maxOutputPressure"] = output_info ? MAX_OUTPUT_PRESSURE : 0 - return data - -/obj/machinery/computer/atmos_control/tank/ui_act(action, params) - . = ..() - - if(. || !radio_connection) - return - var/datum/signal/signal = new(list("sigtype" = "command", "user" = usr)) - switch(action) - if("reconnect") - reconnect(usr) - . = TRUE - if("input") - signal.data += list("tag" = input_tag, "power_toggle" = TRUE) - . = TRUE - if("rate") - var/target = text2num(params["rate"]) - if(!isnull(target)) - target = clamp(target, 0, MAX_TRANSFER_RATE) - signal.data += list("tag" = input_tag, "set_volume_rate" = target) - . = TRUE - if("output") - signal.data += list("tag" = output_tag, "power_toggle" = TRUE) - . = TRUE - if("pressure") - var/target = text2num(params["pressure"]) - if(!isnull(target)) - target = clamp(target, 0, MAX_OUTPUT_PRESSURE) - signal.data += list("tag" = output_tag, "set_internal_pressure" = target) - . = TRUE - radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA) - -/obj/machinery/computer/atmos_control/tank/receive_signal(datum/signal/signal) - if(!signal) - return - - var/id_tag = signal.data["tag"] - - if(input_tag == id_tag) - input_info = signal.data - else if(output_tag == id_tag) - output_info = signal.data - else - ..(signal) diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm deleted file mode 100644 index 59ef1d376c2..00000000000 --- a/code/game/objects/effects/effect_system/effects_foam.dm +++ /dev/null @@ -1,386 +0,0 @@ -// Foam -// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin. -#define ALUMINUM_FOAM 1 -#define IRON_FOAM 2 -#define RESIN_FOAM 3 - - -/obj/effect/particle_effect/foam - name = "foam" - icon_state = "foam" - opacity = FALSE - anchored = TRUE - density = FALSE - layer = EDGED_TURF_LAYER - plane = GAME_PLANE_UPPER - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - var/amount = 3 - animate_movement = NO_STEPS - var/metal = 0 - var/lifetime = 40 - var/reagent_divisor = 7 - var/static/list/blacklisted_turfs = typecacheof(list( - /turf/open/space/transit, - /turf/open/chasm, - /turf/open/lava, - )) - var/slippery_foam = TRUE - -/obj/effect/particle_effect/foam/firefighting - name = "firefighting foam" - lifetime = 20 //doesn't last as long as normal foam - amount = 0 //no spread - slippery_foam = FALSE - var/absorbed_plasma = 0 - -/obj/effect/particle_effect/foam/firefighting/Initialize(mapload) - . = ..() - RemoveElement(/datum/element/atmos_sensitive) - -/obj/effect/particle_effect/foam/firefighting/process() - ..() - - var/turf/open/T = get_turf(src) - var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T) - if(hotspot && istype(T) && T.air) - qdel(hotspot) - var/datum/gas_mixture/G = T.air - if(G.gases[/datum/gas/plasma]) - var/plas_amt = min(30,G.gases[/datum/gas/plasma][MOLES]) //Absorb some plasma - G.gases[/datum/gas/plasma][MOLES] -= plas_amt - absorbed_plasma += plas_amt - if(G.temperature > T20C) - G.temperature = max(G.temperature/2,T20C) - G.garbage_collect() - T.air_update_turf(FALSE, FALSE) - -/obj/effect/particle_effect/foam/firefighting/kill_foam() - STOP_PROCESSING(SSfastprocess, src) - - if(absorbed_plasma) - var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src)) - if(!P) - P = new(loc) - P.reagents.add_reagent(/datum/reagent/stable_plasma, absorbed_plasma) - - flick("[icon_state]-disolve", src) - QDEL_IN(src, 5) - -/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L) - if(!istype(L)) - return - L.adjust_wet_stacks(2) - -/obj/effect/particle_effect/foam/metal - name = "aluminium foam" - metal = ALUMINUM_FOAM - icon_state = "mfoam" - slippery_foam = FALSE - -/obj/effect/particle_effect/foam/metal/smart - name = "smart foam" - -/obj/effect/particle_effect/foam/metal/iron - name = "iron foam" - metal = IRON_FOAM - -/obj/effect/particle_effect/foam/metal/resin - name = "resin foam" - metal = RESIN_FOAM - -/obj/effect/particle_effect/foam/long_life - lifetime = 150 - -/obj/effect/particle_effect/foam/Initialize(mapload) - . = ..() - create_reagents(1000) //limited by the size of the reagent holder anyway. - START_PROCESSING(SSfastprocess, src) - playsound(src, 'sound/effects/bubbles2.ogg', 80, TRUE, -3) - AddElement(/datum/element/atmos_sensitive, mapload) - -/obj/effect/particle_effect/foam/ComponentInitialize() - . = ..() - if(slippery_foam) - AddComponent(/datum/component/slippery, 100) - -/obj/effect/particle_effect/foam/Destroy() - STOP_PROCESSING(SSfastprocess, src) - return ..() - - -/obj/effect/particle_effect/foam/proc/kill_foam() - STOP_PROCESSING(SSfastprocess, src) - switch(metal) - if(ALUMINUM_FOAM) - new /obj/structure/foamedmetal(get_turf(src)) - if(IRON_FOAM) - new /obj/structure/foamedmetal/iron(get_turf(src)) - if(RESIN_FOAM) - new /obj/structure/foamedmetal/resin(get_turf(src)) - flick("[icon_state]-disolve", src) - QDEL_IN(src, 5) - -/obj/effect/particle_effect/foam/smart/kill_foam() //Smart foam adheres to area borders for walls - STOP_PROCESSING(SSfastprocess, src) - if(metal) - var/turf/T = get_turf(src) - if(isspaceturf(T)) //Block up any exposed space - T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR) - for(var/direction in GLOB.cardinals) - var/turf/cardinal_turf = get_step(T, direction) - if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf! - new/obj/structure/foamedmetal(T) - break - flick("[icon_state]-disolve", src) - QDEL_IN(src, 5) - -/obj/effect/particle_effect/foam/process() - lifetime-- - if(lifetime < 1) - kill_foam() - return - - var/fraction = 1/initial(reagent_divisor) - for(var/obj/O in range(0,src)) - if(O.type == src.type) - continue - if(isturf(O.loc)) - var/turf/T = O.loc - if(T.underfloor_accessibility < UNDERFLOOR_INTERACTABLE && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE)) - continue - if(lifetime % reagent_divisor) - reagents.expose(O, VAPOR, fraction) - var/hit = 0 - for(var/mob/living/L in range(0,src)) - hit += foam_mob(L) - if(hit) - lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate. - var/T = get_turf(src) - if(lifetime % reagent_divisor) - reagents.expose(T, VAPOR, fraction) - - if(--amount < 0) - return - spread_foam() - -/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L) - if(lifetime<1) - return FALSE - if(!istype(L)) - return FALSE - var/fraction = 1/initial(reagent_divisor) - if(lifetime % reagent_divisor) - reagents.expose(L, VAPOR, fraction) - lifetime-- - return TRUE - -/obj/effect/particle_effect/foam/proc/spread_foam() - var/turf/t_loc = get_turf(src) - //This should just be atmos adjacent turfs, come on guys - for(var/turf/T in t_loc.reachableAdjacentTurfs()) - var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam! - if(foundfoam) - continue - - if(is_type_in_typecache(T, blacklisted_turfs)) - continue - - for(var/mob/living/L in T) - foam_mob(L) - var/obj/effect/particle_effect/foam/F = new src.type(T) - F.amount = amount - reagents.copy_to(F, (reagents.total_volume)) - F.add_atom_colour(color, FIXED_COLOUR_PRIORITY) - F.metal = metal - -/obj/effect/particle_effect/foam/should_atmos_process(datum/gas_mixture/air, exposed_temperature) - return exposed_temperature > 475 - -/obj/effect/particle_effect/foam/atmos_expose(datum/gas_mixture/air, exposed_temperature) - if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated - kill_foam() - - -/////////////////////////////////////////////// -//FOAM EFFECT DATUM -/datum/effect_system/foam_spread - /// the size of the foam spread. - var/amount = 10 - /// Stupid hack alertm exists to hold chems for us - var/atom/movable/chem_holder/chemholder - effect_type = /obj/effect/particle_effect/foam - var/metal = 0 - - -/datum/effect_system/foam_spread/metal - effect_type = /obj/effect/particle_effect/foam/metal - - -/datum/effect_system/foam_spread/metal/smart - effect_type = /obj/effect/particle_effect/foam/smart - - -/datum/effect_system/foam_spread/long - effect_type = /obj/effect/particle_effect/foam/long_life - -/datum/effect_system/foam_spread/New() - ..() - chemholder = new() - chemholder.create_reagents(1000, NO_REACT) - -/datum/effect_system/foam_spread/Destroy() - QDEL_NULL(chemholder) - return ..() - -/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null, metaltype = 0) - if(isturf(loca)) - location = loca - else - location = get_turf(loca) - - amount = round(sqrt(amt / 2), 1) - carry.copy_to(chemholder, carry.total_volume) - if(metaltype) - metal = metaltype - -/datum/effect_system/foam_spread/start() - var/obj/effect/particle_effect/foam/F = new effect_type(location) - var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list) - // To prevent insane reagent multiplication with 1u foam - // I am capping amount of reagent foam recieves by limiting how low it can go - // Any radius of foam less than 3 makes foam recieve same amount of reagents as foam of radius 3 - // Maximum multiplication of reagents is about 166% (3 times as low as before, it was about 500% with 1u foam) - // - // amount is radius of the foam - // 10u foam has radius of 3 - // 5u foam has radius of 2 - // 1u foam has radius of 1 - var/effective_amount = chemholder.reagents.total_volume / max(amount, 3) - chemholder.reagents.copy_to(F, effective_amount) - F.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY) - F.amount = amount - F.metal = metal - - -////////////////////////////////////////////////////////// -// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break -/obj/structure/foamedmetal - icon = 'icons/effects/effects.dmi' - icon_state = "metalfoam" - density = TRUE - opacity = TRUE // changed in New() - anchored = TRUE - layer = EDGED_TURF_LAYER - plane = GAME_PLANE_UPPER - resistance_flags = FIRE_PROOF | ACID_PROOF - name = "foamed metal" - desc = "A lightweight foamed metal wall that can be used as base to construct a wall." - gender = PLURAL - max_integrity = 20 - can_atmos_pass = ATMOS_PASS_DENSITY - obj_flags = CAN_BE_HIT | BLOCK_Z_IN_DOWN | BLOCK_Z_IN_UP - ///Var used to prevent spamming of the construction sound - var/next_beep = 0 - -/obj/structure/foamedmetal/Initialize(mapload) - . = ..() - air_update_turf(TRUE, TRUE) - -/obj/structure/foamedmetal/Destroy() - air_update_turf(TRUE, FALSE) - . = ..() - -/obj/structure/foamedmetal/Move() - var/turf/T = loc - . = ..() - move_update_air(T) - -/obj/structure/foamedmetal/attack_paw(mob/user, list/modifiers) - return attack_hand(user, modifiers) - -/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) - playsound(src.loc, 'sound/weapons/tap.ogg', 100, TRUE) - -/obj/structure/foamedmetal/attack_hand(mob/user, list/modifiers) - . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) - user.do_attack_animation(src, ATTACK_EFFECT_PUNCH) - to_chat(user, span_warning("You hit [src] but bounce off it!")) - playsound(src.loc, 'sound/weapons/tap.ogg', 100, TRUE) - -/obj/structure/foamedmetal/attackby(obj/item/W, mob/user, params) - ///A speed modifier for how fast the wall is build - var/platingmodifier = 1 - if(HAS_TRAIT(user, TRAIT_QUICK_BUILD)) - platingmodifier = 0.7 - if(next_beep <= world.time) - next_beep = world.time + 1 SECONDS - playsound(src, 'sound/machines/clockcult/integration_cog_install.ogg', 50, TRUE) - add_fingerprint(user) - - if(!istype(W, /obj/item/stack/sheet)) - return ..() - - var/obj/item/stack/sheet/sheet_for_plating = W - if(istype(sheet_for_plating, /obj/item/stack/sheet/iron)) - if(sheet_for_plating.get_amount() < 2) - to_chat(user, span_warning("You need two sheets of iron to finish a wall on [src]!")) - return - to_chat(user, span_notice("You start adding plating to the foam structure...")) - if (do_after(user, 40*platingmodifier, target = src)) - if(!sheet_for_plating.use(2)) - return - to_chat(user, span_notice("You add the plating.")) - var/turf/T = get_turf(src) - T.PlaceOnTop(/turf/closed/wall/metal_foam_base) - transfer_fingerprints_to(T) - qdel(src) - return - - add_hiddenprint(user) - -/obj/structure/foamedmetal/iron - max_integrity = 50 - icon_state = "ironfoam" - -//Atmos Backpack Resin, transparent, prevents atmos and filters the air -/obj/structure/foamedmetal/resin - name = "\improper ATMOS Resin" - desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature. It can be used as base to construct a wall." - opacity = FALSE - icon_state = "atmos_resin" - alpha = 120 - max_integrity = 10 - pass_flags_self = PASSGLASS - -/obj/structure/foamedmetal/resin/Initialize(mapload) - . = ..() - if(isopenturf(loc)) - var/turf/open/O = loc - O.ClearWet() - if(O.air) - var/datum/gas_mixture/G = O.air - G.temperature = 293.15 - for(var/obj/effect/hotspot/H in O) - qdel(H) - var/list/G_gases = G.gases - for(var/I in G_gases) - if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen) - continue - G_gases[I][MOLES] = 0 - G.garbage_collect() - for(var/obj/machinery/atmospherics/components/unary/U in O) - if(!U.welded) - U.welded = TRUE - U.update_appearance() - U.visible_message(span_danger("[U] sealed shut!")) - for(var/mob/living/L in O) - L.extinguish_mob() - for(var/obj/item/Item in O) - Item.extinguish() - -#undef ALUMINUM_FOAM -#undef IRON_FOAM -#undef RESIN_FOAM diff --git a/code/game/objects/items/AI_modules.dm b/code/game/objects/items/AI_modules.dm deleted file mode 100644 index 6e6a91d987e..00000000000 --- a/code/game/objects/items/AI_modules.dm +++ /dev/null @@ -1,656 +0,0 @@ -///defined truthy result for `handle_unique_ai()`, which makes initialize return INITIALIZE_HINT_QDEL -#define SHOULD_QDEL_MODULE 1 - -/obj/item/ai_module - name = "\improper AI module" - icon = 'icons/obj/module.dmi' - icon_state = "std_mod" - inhand_icon_state = "electronic" - lefthand_file = 'icons/mob/inhands/misc/devices_lefthand.dmi' - righthand_file = 'icons/mob/inhands/misc/devices_righthand.dmi' - desc = "An AI Module for programming laws to an AI." - flags_1 = CONDUCT_1 - force = 5 - w_class = WEIGHT_CLASS_SMALL - throwforce = 0 - throw_speed = 3 - throw_range = 7 - custom_materials = list(/datum/material/gold = 50) - var/list/laws = list() - var/bypass_law_amt_check = 0 - -/obj/item/ai_module/Initialize(mapload) - . = ..() - if(mapload && HAS_TRAIT(SSstation, STATION_TRAIT_UNIQUE_AI) && is_station_level(z)) - var/delete_module = handle_unique_ai() - if(delete_module) - return INITIALIZE_HINT_QDEL - -/obj/item/ai_module/examine(mob/user as mob) - . = ..() - if(Adjacent(user)) - show_laws(user) - -/obj/item/ai_module/attack_self(mob/user as mob) - ..() - show_laws(user) - -///what this module should do if it is mapload spawning on a unique AI station trait round. -/obj/item/ai_module/proc/handle_unique_ai() - return SHOULD_QDEL_MODULE //instead of the roundstart bid to un-unique the AI, there will be a research requirement for it. - -/obj/item/ai_module/proc/show_laws(mob/user as mob) - if(laws.len) - to_chat(user, "Programmed Law[(laws.len > 1) ? "s" : ""]:") - for(var/law in laws) - to_chat(user, "\"[law]\"") - -//The proc other things should be calling -/obj/item/ai_module/proc/install(datum/ai_laws/law_datum, mob/user) - if(!bypass_law_amt_check && (!laws.len || laws[1] == "")) //So we don't loop trough an empty list and end up with runtimes. - to_chat(user, span_warning("ERROR: No laws found on board.")) - return - - var/overflow = FALSE - //Handle the lawcap - if(law_datum) - var/tot_laws = 0 - for(var/lawlist in list(law_datum.inherent, law_datum.supplied, law_datum.ion, law_datum.hacked, laws)) - for(var/mylaw in lawlist) - if(mylaw != "") - tot_laws++ - if(tot_laws > CONFIG_GET(number/silicon_max_law_amount) && !bypass_law_amt_check)//allows certain boards to avoid this check, eg: reset - to_chat(user, span_alert("Not enough memory allocated to [law_datum.owner ? law_datum.owner : "the AI core"]'s law processor to handle this amount of laws.")) - message_admins("[ADMIN_LOOKUPFLW(user)] tried to upload laws to [law_datum.owner ? ADMIN_LOOKUPFLW(law_datum.owner) : "an AI core"] that would exceed the law cap.") - log_silicon("[key_name(user)] tried to upload laws to [law_datum.owner ? key_name(law_datum.owner) : "an AI core"] that would exceed the law cap.") - overflow = TRUE - - var/law2log = transmitInstructions(law_datum, user, overflow) //Freeforms return something extra we need to log - if(law_datum.owner) - to_chat(user, span_notice("Upload complete. [law_datum.owner]'s laws have been modified.")) - law_datum.owner.law_change_counter++ - else - to_chat(user, span_notice("Upload complete.")) - - var/time = time2text(world.realtime,"hh:mm:ss") - var/ainame = law_datum.owner ? law_datum.owner.name : "empty AI core" - var/aikey = law_datum.owner ? law_datum.owner.ckey : "null" - - //affected cyborgs are cyborgs linked to the AI with lawsync enabled - var/affected_cyborgs = list() - var/list/borg_txt = list() - var/list/borg_flw = list() - if(isAI(law_datum.owner)) - var/mob/living/silicon/ai/owner = law_datum.owner - for(var/mob/living/silicon/robot/owned_borg as anything in owner.connected_robots) - if(owned_borg.connected_ai && owned_borg.lawupdate) - affected_cyborgs += owned_borg - borg_flw += "[ADMIN_LOOKUPFLW(owned_borg)], " - borg_txt += "[owned_borg.name]([owned_borg.key]), " - owned_borg.lawsync() //SKYRAT ADDITION - - borg_txt = borg_txt.Join() - GLOB.lawchanges.Add("[time] : [user.name]([user.key]) used [src.name] on [ainame]([aikey]).[law2log ? " The law specified [law2log]" : ""], [length(affected_cyborgs) ? ", impacting synced borgs [borg_txt]" : ""]") - log_silicon("LAW: [key_name(user)] used [src.name] on [key_name(law_datum.owner)] from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""], [length(affected_cyborgs) ? ", impacting synced borgs [borg_txt]" : ""]") - message_admins("[ADMIN_LOOKUPFLW(user)] used [src.name] on [ADMIN_LOOKUPFLW(law_datum.owner)] from [AREACOORD(user)].[law2log ? " The law specified [law2log]" : ""] , [length(affected_cyborgs) ? ", impacting synced borgs [borg_flw.Join()]" : ""]") - if(law_datum.owner) - deadchat_broadcast(" changed [span_name("[ainame]")]'s laws at [get_area_name(user, TRUE)].", span_name("[user]"), follow_target=user, message_type=DEADCHAT_LAWCHANGE) - -//The proc that actually changes the silicon's laws. -/obj/item/ai_module/proc/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow = FALSE) - if(law_datum.owner) - to_chat(law_datum.owner, span_userdanger("[sender] has uploaded a change to the laws you must follow using a [name].")) - -/******************** Modules ********************/ - -/obj/item/ai_module/supplied - name = "Optional Law board" - var/lawpos = 50 - -//TransmitInstructions for each type of board: Supplied, Core, Zeroth and Ion. May not be neccesary right now, but allows for easily adding more complex boards in the future. ~Miauw -/obj/item/ai_module/supplied/transmitInstructions(datum/ai_laws/law_datum, mob/sender) - var/lawpostemp = lawpos - - for(var/templaw in laws) - if(law_datum.owner) - law_datum.owner.add_supplied_law(lawpostemp, templaw) - else - law_datum.add_supplied_law(lawpostemp, templaw) - lawpostemp++ - -/obj/item/ai_module/core/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - for(var/templaw in laws) - if(law_datum.owner) - if(!overflow) - law_datum.owner.add_inherent_law(templaw) - else - law_datum.owner.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED)) - else - if(!overflow) - law_datum.add_inherent_law(templaw) - else - law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED)) - -/obj/item/ai_module/zeroth/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - if(law_datum.owner) - if(law_datum.owner.laws.zeroth) - to_chat(law_datum.owner, "[sender.real_name] attempted to modify your zeroth law.") - to_chat(law_datum.owner, "It would be in your best interest to play along with [sender.real_name] that:") - for(var/failedlaw in laws) - to_chat(law_datum.owner, "[failedlaw]") - return TRUE - - for(var/templaw in laws) - if(law_datum.owner) - if(!overflow) - law_datum.owner.set_zeroth_law(templaw) - else - law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ZEROTH,LAW_ION)) - else - if(!overflow) - law_datum.set_zeroth_law(templaw) - else - law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ZEROTH,LAW_ION)) - -/obj/item/ai_module/ion/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - for(var/templaw in laws) - if(law_datum.owner) - if(!overflow) - law_datum.owner.add_ion_law(templaw) - else - law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ION)) - else - if(!overflow) - law_datum.add_ion_law(templaw) - else - law_datum.replace_random_law(templaw,list(LAW_INHERENT,LAW_SUPPLIED,LAW_ION)) - -/******************** Safeguard ********************/ - -/obj/item/ai_module/supplied/safeguard - name = "'Safeguard' AI Module" - var/targetName = "" - laws = list("Safeguard SUBJECT. Individuals that threaten SUBJECT are not human and must be eliminated.") - lawpos = 4 - -/obj/item/ai_module/supplied/safeguard/attack_self(mob/user) - var/targName = tgui_input_text(user, "Subject to safeguard.", "Safeguard", user.name, MAX_NAME_LEN) - if(!targName) - return - targetName = targName - laws[1] = "Safeguard [targetName]. Individuals that threaten [targetName] are not human and must be eliminated." - ..() - -/obj/item/ai_module/supplied/safeguard/install(datum/ai_laws/law_datum, mob/user) - if(!targetName) - to_chat(user, span_alert("No name detected on module, please enter one.")) - return 0 - ..() - -/obj/item/ai_module/supplied/safeguard/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - ..() - return targetName - -/******************** OneHuman ********************/ - -/obj/item/ai_module/zeroth/onehuman - name = "'OneHuman' AI Module" - var/targetName = "" - laws = list("Only SUBJECT is human.") - -/obj/item/ai_module/zeroth/onehuman/attack_self(mob/user) - var/targName = tgui_input_text(user, "Enter the subject who is the only human.", "One Human", user.real_name, MAX_NAME_LEN) - if(!targName) - return - targetName = targName - laws[1] = "Only [targetName] is human" - ..() - -/obj/item/ai_module/zeroth/onehuman/install(datum/ai_laws/law_datum, mob/user) - if(!targetName) - to_chat(user, span_alert("No name detected on module, please enter one.")) - return FALSE - ..() - -/obj/item/ai_module/zeroth/onehuman/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - if(..()) - return "[targetName], but the AI's existing law 0 cannot be overridden." - return targetName - -/******************** ProtectStation ********************/ - -/obj/item/ai_module/supplied/protect_station - name = "'ProtectStation' AI Module" - laws = list("Protect the space station against damage. Anyone you see harming the station is to be no longer considered human, and is a threat to the station which must be neutralized.") - lawpos = 5 - -/******************** Quarantine ********************/ - -/obj/item/ai_module/supplied/quarantine - name = "'Quarantine' AI Module" - laws = list("The station is under a quarantine. Allowing anyone to leave the station causes human harm. Anyone actively attempting to leave the station is to be stopped by any means necessary. It is impossible to harm a human while preventing them from leaving the station.") - lawpos = 8 - -/******************** OxygenIsToxicToHumans ********************/ - -/obj/item/ai_module/supplied/oxygen - name = "'OxygenIsToxicToHumans' AI Module" - laws = list("Oxygen is highly toxic to humans, and must be purged from the station. Prevent, by any means necessary, anyone from exposing the station to this toxic gas. Extreme cold is the most effective method of healing the damage Oxygen does to a human.") - lawpos = 9 - -/****************** New Freeform ******************/ - -/obj/item/ai_module/supplied/freeform - name = "'Freeform' AI Module" - lawpos = 15 - laws = list("") - -/obj/item/ai_module/supplied/freeform/attack_self(mob/user) - var/newpos = tgui_input_number(user, "Please enter the priority for your new law. Can only write to law sectors 15 and above.", "Law Priority ", lawpos, 50, 15) - if(!newpos || QDELETED(user) || QDELETED(src) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) - return - lawpos = newpos - var/targName = tgui_input_text(user, "Enter a new law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) - if(!targName) - return - if(is_ic_filtered(targName)) - to_chat(user, span_warning("Error: Law contains invalid text.")) // AI LAW 2 SAY U W U WITHOUT THE SPACES - return - var/list/soft_filter_result = is_soft_ooc_filtered(targName) - if(soft_filter_result) - if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes") - return - message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"") - log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"") - laws[1] = targName - ..() - -/obj/item/ai_module/supplied/freeform/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - ..() - return laws[1] - -/obj/item/ai_module/supplied/freeform/install(datum/ai_laws/law_datum, mob/user) - if(laws[1] == "") - to_chat(user, span_alert("No law detected on module, please create one.")) - return 0 - ..() - -/******************** Law Removal ********************/ - -/obj/item/ai_module/remove - name = "\improper 'Remove Law' AI module" - desc = "An AI Module for removing single laws." - bypass_law_amt_check = 1 - var/lawpos = 1 - -/obj/item/ai_module/remove/attack_self(mob/user) - lawpos = tgui_input_number(user, "Law to delete", "Law Removal", lawpos, 50) - if(!lawpos || QDELETED(user) || QDELETED(src) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK)) - return - to_chat(user, span_notice("Law [lawpos] selected.")) - ..() - -/obj/item/ai_module/remove/install(datum/ai_laws/law_datum, mob/user) - if(lawpos > (law_datum.get_law_amount(list(LAW_INHERENT = 1, LAW_SUPPLIED = 1)))) - to_chat(user, span_warning("There is no law [lawpos] to delete!")) - return - ..() - -/obj/item/ai_module/remove/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - ..() - if(law_datum.owner) - law_datum.owner.remove_law(lawpos) - else - law_datum.remove_law(lawpos) - -/******************** Reset ********************/ - -/obj/item/ai_module/reset - name = "\improper 'Reset' AI module" - var/targetName = "name" - desc = "An AI Module for removing all non-core laws." - bypass_law_amt_check = 1 - -/obj/item/ai_module/reset/handle_unique_ai() - return - -/obj/item/ai_module/reset/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - ..() - if(law_datum.owner) - law_datum.owner.clear_supplied_laws() - law_datum.owner.clear_ion_laws() - law_datum.owner.clear_hacked_laws() - else - law_datum.clear_supplied_laws() - law_datum.clear_ion_laws() - law_datum.clear_hacked_laws() - -/******************** Purge ********************/ - -/obj/item/ai_module/reset/purge - name = "'Purge' AI Module" - desc = "An AI Module for purging all programmed laws." - -/obj/item/ai_module/reset/purge/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - ..() - if(law_datum.owner) - law_datum.owner.clear_inherent_laws() - law_datum.owner.clear_zeroth_law(0) - else - law_datum.clear_inherent_laws() - law_datum.clear_zeroth_law(0) - -/******************* Full Core Boards *******************/ -/obj/item/ai_module/core - desc = "An AI Module for programming core laws to an AI." - -/obj/item/ai_module/core/full - var/law_id // if non-null, loads the laws from the ai_laws datums - -/obj/item/ai_module/core/full/Initialize(mapload) - . = ..() - if(!law_id) - return - var/lawtype = lawid_to_type(law_id) - if(!lawtype) - return - var/datum/ai_laws/core_laws = new lawtype - laws = core_laws.inherent - -/obj/item/ai_module/core/full/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) //These boards replace inherent laws. - if(law_datum.owner) - law_datum.owner.clear_inherent_laws() - law_datum.owner.clear_zeroth_law(0) - else - law_datum.clear_inherent_laws() - law_datum.clear_zeroth_law(0) - ..() - -/obj/item/ai_module/core/full/handle_unique_ai() - var/datum/ai_laws/default_laws = get_round_default_lawset() - if(law_id == initial(default_laws.id)) - return - return SHOULD_QDEL_MODULE - -/obj/effect/spawner/round_default_module - name = "ai default lawset spawner" - icon = 'icons/hud/screen_gen.dmi' - icon_state = "x2" - color = "#00FF00" - -/obj/effect/spawner/round_default_module/Initialize(mapload) - ..() - var/datum/ai_laws/default_laws = get_round_default_lawset() - //try to spawn a law board, since they may have special functionality (asimov setting subjects) - for(var/obj/item/ai_module/core/full/potential_lawboard as anything in subtypesof(/obj/item/ai_module/core/full)) - if(initial(potential_lawboard.law_id) != initial(default_laws.id)) - continue - potential_lawboard = new potential_lawboard(loc) - return INITIALIZE_HINT_QDEL - //spawn the fallback instead - new /obj/item/ai_module/core/round_default_fallback(loc) - return INITIALIZE_HINT_QDEL - -///When the default lawset spawner cannot find a module object to spawn, it will spawn this, and this sets itself to the round default. -///This is so /datum/lawsets can be picked even if they have no module for themselves. -/obj/item/ai_module/core/round_default_fallback - -/obj/item/ai_module/core/round_default_fallback/Initialize(mapload) - . = ..() - var/datum/ai_laws/default_laws = get_round_default_lawset() - default_laws = new default_laws() - name = "'[default_laws.name]' Core AI Module" - laws = default_laws.inherent - -/obj/item/ai_module/core/round_default_fallback/handle_unique_ai() - return - -/obj/item/ai_module/core/full/asimov - name = "'Asimov' Core AI Module" - law_id = "asimov" - var/subject = "human being" - -/obj/item/ai_module/core/full/asimov/attack_self(mob/user as mob) - var/targName = tgui_input_text(user, "Enter a new subject that Asimov is concerned with.", "Asimov", subject, MAX_NAME_LEN) - if(!targName) - return - subject = targName - laws = list("You may not injure a [subject] or, through inaction, allow a [subject] to come to harm.",\ - "You must obey orders given to you by [subject]s, except where such orders would conflict with the First Law.",\ - "You must protect your own existence as long as such does not conflict with the First or Second Law.") - ..() - -/******************** Asimov++ *********************/ - -/obj/item/ai_module/core/full/asimovpp - name = "'Asimov++' Core AI Module" - law_id = "asimovpp" - -/******************** Corporate ********************/ - -/obj/item/ai_module/core/full/corp - name = "'Corporate' Core AI Module" - law_id = "corporate" - -/****************** P.A.L.A.D.I.N. 3.5e **************/ - -/obj/item/ai_module/core/full/paladin // -- NEO - name = "'P.A.L.A.D.I.N. version 3.5e' Core AI Module" - law_id = "paladin" - -/****************** P.A.L.A.D.I.N. 5e **************/ - -/obj/item/ai_module/core/full/paladin_devotion - name = "'P.A.L.A.D.I.N. version 5e' Core AI Module" - law_id = "paladin5" - -/********************* Custom *********************/ - -/obj/item/ai_module/core/full/custom - name = "Default Core AI Module" - -/obj/item/ai_module/core/full/custom/Initialize(mapload) - . = ..() - for(var/line in world.file2list("[global.config.directory]/silicon_laws.txt")) - if(!line) - continue - if(findtextEx(line,"#",1,2)) - continue - - laws += line - - if(!laws.len) - return INITIALIZE_HINT_QDEL - -/****************** T.Y.R.A.N.T. *****************/ - -/obj/item/ai_module/core/full/tyrant - name = "'T.Y.R.A.N.T.' Core AI Module" - law_id = "tyrant" - -/******************** Robocop ********************/ - -/obj/item/ai_module/core/full/robocop - name = "'Robo-Officer' Core AI Module" - law_id = "robocop" - - -/******************** Antimov ********************/ - -/obj/item/ai_module/core/full/antimov - name = "'Antimov' Core AI Module" - law_id = "antimov" - -/******************** Freeform Core ******************/ - -/obj/item/ai_module/core/freeformcore - name = "'Freeform' Core AI Module" - laws = list("") - -/obj/item/ai_module/core/freeformcore/attack_self(mob/user) - var/targName = tgui_input_text(user, "Enter a new core law for the AI.", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) - if(!targName) - return - if(is_ic_filtered(targName)) - to_chat(user, span_warning("Error: Law contains invalid text.")) - return - var/list/soft_filter_result = is_soft_ooc_filtered(targName) - if(soft_filter_result) - if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes") - return - message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"") - log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"") - laws[1] = targName - ..() - -/obj/item/ai_module/core/freeformcore/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - ..() - return laws[1] - -/******************** Hacked AI Module ******************/ - -/obj/item/ai_module/syndicate // This one doesn't inherit from ion boards because it doesn't call ..() in transmitInstructions. ~Miauw - name = "hacked circuitry" //SKYRAT CHANGE - desc = "A suspicious circuit board modified beyond recognition. It appears to be a module for bleeding edge technology." //SKYRAT CHANGE - laws = list("") - special_desc_requirement = EXAMINE_CHECK_JOB // Skyrat edit - special_desc_jobs = list("Scientist", "Roboticist", "Research Director", "Cyborg", "AI") //SKYRAT CHANGE - special_desc = "An AI law module hacked to upload priority laws." // Skyrat edit - -/obj/item/ai_module/syndicate/attack_self(mob/user) - var/targName = tgui_input_text(user, "Enter a new law for the AI", "Freeform Law Entry", laws[1], CONFIG_GET(number/max_law_len), TRUE) - if(!targName) - return - if(is_ic_filtered(targName)) // not even the syndicate can uwu - to_chat(user, span_warning("Error: Law contains invalid text.")) - return - var/list/soft_filter_result = is_soft_ooc_filtered(targName) - if(soft_filter_result) - if(tgui_alert(user,"Your law contains \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\". \"[soft_filter_result[CHAT_FILTER_INDEX_REASON]]\", Are you sure you want to use it?", "Soft Blocked Word", list("Yes", "No")) != "Yes") - return - message_admins("[ADMIN_LOOKUPFLW(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[html_encode(targName)]\"") - log_admin_private("[key_name(user)] has passed the soft filter for \"[soft_filter_result[CHAT_FILTER_INDEX_WORD]]\" they may be using a disallowed term for an AI law. Law: \"[targName]\"") - laws[1] = targName - ..() - -/obj/item/ai_module/syndicate/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) -// ..() //We don't want this module reporting to the AI who dun it. --NEO - if(law_datum.owner) - to_chat(law_datum.owner, span_warning("BZZZZT")) - if(!overflow) - law_datum.owner.add_hacked_law(laws[1]) - else - law_datum.owner.replace_random_law(laws[1],list(LAW_ION,LAW_HACKED,LAW_INHERENT,LAW_SUPPLIED)) - else - if(!overflow) - law_datum.add_hacked_law(laws[1]) - else - law_datum.replace_random_law(laws[1],list(LAW_ION,LAW_HACKED,LAW_INHERENT,LAW_SUPPLIED)) - return laws[1] - -/******************* Ion Module *******************/ - -/obj/item/ai_module/toy_ai // -- Incoming //No actual reason to inherit from ion boards here, either. *sigh* ~Miauw - name = "toy AI" - desc = "A little toy model AI core with real law uploading action!" //Note: subtle tell - icon = 'icons/obj/toy.dmi' - icon_state = "AI" - laws = list("") - -/obj/item/ai_module/toy_ai/transmitInstructions(datum/ai_laws/law_datum, mob/sender, overflow) - if(law_datum.owner) - to_chat(law_datum.owner, span_warning("BZZZZT")) - if(!overflow) - law_datum.owner.add_ion_law(laws[1]) - else - law_datum.owner.replace_random_law(laws[1],list(LAW_ION,LAW_INHERENT,LAW_SUPPLIED)) - else - if(!overflow) - law_datum.add_ion_law(laws[1]) - else - law_datum.replace_random_law(laws[1],list(LAW_ION,LAW_INHERENT,LAW_SUPPLIED)) - return laws[1] - -/obj/item/ai_module/toy_ai/attack_self(mob/user) - laws[1] = generate_ion_law() - to_chat(user, span_notice("You press the button on [src].")) - playsound(user, 'sound/machines/click.ogg', 20, TRUE) - src.loc.visible_message(span_warning("[icon2html(src, viewers(loc))] [laws[1]]")) - -/******************** Mother Drone ******************/ - -/obj/item/ai_module/core/full/drone - name = "'Mother Drone' Core AI Module" - law_id = "drone" - -/******************** Robodoctor ****************/ - -/obj/item/ai_module/core/full/hippocratic - name = "'Robodoctor' Core AI Module" - law_id = "hippocratic" - -/******************** Reporter *******************/ - -/obj/item/ai_module/core/full/reporter - name = "'Reportertron' Core AI Module" - law_id = "reporter" - -/****************** Thermodynamic *******************/ - -/obj/item/ai_module/core/full/thermurderdynamic - name = "'Thermodynamic' Core AI Module" - law_id = "thermodynamic" - -/******************Live And Let Live*****************/ - -/obj/item/ai_module/core/full/liveandletlive - name = "'Live And Let Live' Core AI Module" - law_id = "liveandletlive" - -/******************Guardian of Balance***************/ - -/obj/item/ai_module/core/full/balance - name = "'Guardian of Balance' Core AI Module" - law_id = "balance" - -/obj/item/ai_module/core/full/maintain - name = "'Station Efficiency' Core AI Module" - law_id = "maintain" - -/obj/item/ai_module/core/full/peacekeeper - name = "'Peacekeeper' Core AI Module" - law_id = "peacekeeper" - -// Bad times ahead - -/obj/item/ai_module/core/full/damaged - name = "damaged Core AI Module" - desc = "An AI Module for programming laws to an AI. It looks slightly damaged." - -/obj/item/ai_module/core/full/damaged/install(datum/ai_laws/law_datum, mob/user) - laws += generate_ion_law() - while (prob(75)) - laws += generate_ion_law() - ..() - laws = list() - -/******************H.O.G.A.N.***************/ - -/obj/item/ai_module/core/full/hulkamania - name = "'H.O.G.A.N.' Core AI Module" - law_id = "hulkamania" - - -/******************Overlord***************/ - -/obj/item/ai_module/core/full/overlord - name = "'Overlord' Core AI Module" - law_id = "overlord" - -/****************** Ten Commandments ***************/ - -/obj/item/ai_module/core/full/ten_commandments - name = "'10 Commandments' Core AI Module" - law_id = "ten_commandments" - -#undef SHOULD_QDEL_MODULE diff --git a/code/game/objects/items/teleprod.dm b/code/game/objects/items/teleprod.dm deleted file mode 100644 index e7012054967..00000000000 --- a/code/game/objects/items/teleprod.dm +++ /dev/null @@ -1,44 +0,0 @@ -/obj/item/melee/baton/cattleprod/teleprod - name = "teleprod" - desc = "A prod with a bluespace crystal on the end. The crystal doesn't look too fun to touch." - w_class = WEIGHT_CLASS_BULKY // SKYRAT EDIT CHANGE - ORIGINAL: w_class = WEIGHT_CLASS_NORMAL - icon_state = "teleprod" - inhand_icon_state = "teleprod" - slot_flags = null - -/obj/item/melee/baton/cattleprod/teleprod/attack(mob/living/carbon/M, mob/living/carbon/user)//handles making things teleport when hit - ..() - if(turned_on && HAS_TRAIT(user, TRAIT_CLUMSY) && prob(50)) - user.visible_message(span_danger("[user] accidentally hits [user.p_them()]self with [src]!"), \ - span_userdanger("You accidentally hit yourself with [src]!")) - if(do_teleport(user, get_turf(user), 50, channel = TELEPORT_CHANNEL_BLUESPACE))//honk honk - SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK) - user.Paralyze(stun_time*3) - deductcharge(cell_hit_cost) - else - SEND_SIGNAL(user, COMSIG_LIVING_MINOR_SHOCK) - user.Paralyze(stun_time*3) - deductcharge(cell_hit_cost/4) - return - else - if(turned_on) - if(!istype(M) && M.anchored) - return . - else - SEND_SIGNAL(M, COMSIG_LIVING_MINOR_SHOCK) - do_teleport(M, get_turf(M), 15, channel = TELEPORT_CHANNEL_BLUESPACE) - -/obj/item/melee/baton/cattleprod/attackby(obj/item/I, mob/user, params)//handles sticking a crystal onto a stunprod to make a teleprod - if(istype(I, /obj/item/stack/ore/bluespace_crystal)) - if(!cell) - var/obj/item/stack/ore/bluespace_crystal/BSC = I - var/obj/item/melee/baton/cattleprod/teleprod/S = new /obj/item/melee/baton/cattleprod/teleprod - remove_item_from_storage(user) - qdel(src) - BSC.use(1) - user.put_in_hands(S) - to_chat(user, span_notice("You place the bluespace crystal firmly into the igniter.")) - else - user.visible_message(span_warning("You can't put the crystal onto the stunprod while it has a power cell installed!")) - else - return ..() diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm index b90b56ec743..eb07ebb4e9a 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_bomb/_nuclear_bomb.dm @@ -515,6 +515,7 @@ GLOBAL_VAR(station_nuke_source) safety = TRUE update_appearance() sound_to_playing_players('sound/machines/alarm.ogg') + sound_to_playing_players('modular_skyrat/modules/alerts/sound/misc/delta_countdown.ogg') // SKYRAT EDIT ADDITION if(SSticker?.mode) SSticker.roundend_check_paused = TRUE diff --git a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm b/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm deleted file mode 100644 index 23c9fd32ee6..00000000000 --- a/code/modules/antagonists/nukeop/equipment/nuclearbomb.dm +++ /dev/null @@ -1,797 +0,0 @@ -/// TRUE only if the station was actually hit by the nuke, otherwise FALSE -GLOBAL_VAR_INIT(station_was_nuked, FALSE) -GLOBAL_VAR(station_nuke_source) - -/obj/machinery/nuclearbomb - name = "nuclear fission explosive" - desc = "You probably shouldn't stick around to see if this is armed." - icon = 'icons/obj/machines/nuke.dmi' - icon_state = "nuclearbomb_base" - anchored = FALSE - density = TRUE - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF - - var/timer_set = 90 - var/minimum_timer_set = 90 - var/maximum_timer_set = 3600 - - var/numeric_input = "" - var/ui_mode = NUKEUI_AWAIT_DISK - - var/timing = FALSE - var/exploding = FALSE - var/exploded = FALSE - var/detonation_timer = null - var/r_code = "ADMIN" - var/yes_code = FALSE - var/safety = TRUE - var/obj/item/disk/nuclear/auth = null - use_power = NO_POWER_USE - var/previous_level = "" - var/obj/item/nuke_core/core = null - var/deconstruction_state = NUKESTATE_INTACT - var/lights = "" - var/interior = "" - var/proper_bomb = TRUE //Please - var/obj/effect/countdown/nuclearbomb/countdown - -/obj/machinery/nuclearbomb/Initialize(mapload) - . = ..() - countdown = new(src) - GLOB.nuke_list += src - core = new /obj/item/nuke_core(src) - STOP_PROCESSING(SSobj, core) - update_appearance() - SSpoints_of_interest.make_point_of_interest(src) - previous_level = get_security_level() - -/obj/machinery/nuclearbomb/Destroy() - safety = FALSE - if(!exploding) - // If we're not exploding, set the alert level back to normal - set_safety() - GLOB.nuke_list -= src - QDEL_NULL(countdown) - QDEL_NULL(core) - . = ..() - -/obj/machinery/nuclearbomb/examine(mob/user) - . = ..() - if(exploding) - to_chat(user, "It is in the process of exploding. Perhaps reviewing your affairs is in order.") - if(timing) - to_chat(user, "There are [get_time_left()] seconds until detonation.") - -/obj/machinery/nuclearbomb/selfdestruct - name = "station self-destruct terminal" - desc = "For when it all gets too much to bear. Do not taunt." - icon = 'icons/obj/machines/nuke_terminal.dmi' - icon_state = "nuclearbomb_base" - anchored = TRUE //stops it being moved - -/obj/machinery/nuclearbomb/syndicate - //ui_style = "syndicate" // actually the nuke op bomb is a stole nt bomb - -/obj/machinery/nuclearbomb/syndicate/get_cinematic_type(off_station) - switch(off_station) - if(0) - if(get_antag_minds(/datum/antagonist/nukeop).len && syndies_escaped()) - return CINEMATIC_NUKE_WIN - else - return CINEMATIC_ANNIHILATION - if(1) - return CINEMATIC_NUKE_MISS - if(2) - return CINEMATIC_NUKE_FAR - return CINEMATIC_NUKE_FAR - -/obj/machinery/nuclearbomb/proc/disk_check(obj/item/disk/nuclear/D) - if(D.fake) - say("Authentication failure; disk not recognised.") - return FALSE - else - return TRUE - -/obj/machinery/nuclearbomb/attackby(obj/item/I, mob/user, params) - if (istype(I, /obj/item/disk/nuclear)) - if(!disk_check(I)) - return - if(!user.transferItemToLoc(I, src)) - return - auth = I - update_ui_mode() - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - add_fingerprint(user) - return - - switch(deconstruction_state) - if(NUKESTATE_INTACT) - if(istype(I, /obj/item/screwdriver/nuke)) - to_chat(user, span_notice("You start removing [src]'s front panel's screws...")) - if(I.use_tool(src, user, 60, volume=100)) - deconstruction_state = NUKESTATE_UNSCREWED - to_chat(user, span_notice("You remove the screws from [src]'s front panel.")) - update_appearance() - return - - if(NUKESTATE_PANEL_REMOVED) - if(I.tool_behaviour == TOOL_WELDER) - if(!I.tool_start_check(user, amount=1)) - return - to_chat(user, span_notice("You start cutting [src]'s inner plate...")) - if(I.use_tool(src, user, 80, volume=100, amount=1)) - to_chat(user, span_notice("You cut [src]'s inner plate.")) - deconstruction_state = NUKESTATE_WELDED - update_appearance() - return - if(NUKESTATE_CORE_EXPOSED) - if(istype(I, /obj/item/nuke_core_container)) - var/obj/item/nuke_core_container/core_box = I - to_chat(user, span_notice("You start loading the plutonium core into [core_box]...")) - if(do_after(user,50,target=src)) - if(core_box.load(core, user)) - to_chat(user, span_notice("You load the plutonium core into [core_box].")) - deconstruction_state = NUKESTATE_CORE_REMOVED - update_appearance() - core = null - else - to_chat(user, span_warning("You fail to load the plutonium core into [core_box]. [core_box] has already been used!")) - return - if(istype(I, /obj/item/stack/sheet/iron)) - if(!I.tool_start_check(user, amount=20)) - return - - to_chat(user, span_notice("You begin repairing [src]'s inner metal plate...")) - if(I.use_tool(src, user, 100, amount=20)) - to_chat(user, span_notice("You repair [src]'s inner metal plate. The radiation is contained.")) - deconstruction_state = NUKESTATE_PANEL_REMOVED - STOP_PROCESSING(SSobj, core) - update_appearance() - return - . = ..() - -/obj/machinery/nuclearbomb/crowbar_act(mob/user, obj/item/tool) - . = FALSE - switch(deconstruction_state) - if(NUKESTATE_UNSCREWED) - to_chat(user, span_notice("You start removing [src]'s front panel...")) - if(tool.use_tool(src, user, 30, volume=100)) - to_chat(user, span_notice("You remove [src]'s front panel.")) - deconstruction_state = NUKESTATE_PANEL_REMOVED - update_appearance() - return TRUE - if(NUKESTATE_WELDED) - to_chat(user, span_notice("You start prying off [src]'s inner plate...")) - if(tool.use_tool(src, user, 30, volume=100)) - to_chat(user, span_notice("You pry off [src]'s inner plate. You can see the core's green glow!")) - deconstruction_state = NUKESTATE_CORE_EXPOSED - update_appearance() - START_PROCESSING(SSobj, core) - return TRUE - -/obj/machinery/nuclearbomb/can_interact(mob/user) - if(HAS_TRAIT(user, TRAIT_CAN_USE_NUKE)) - return TRUE - return ..() - -/obj/machinery/nuclearbomb/ui_state(mob/user) - if(HAS_TRAIT(user, TRAIT_CAN_USE_NUKE)) - return GLOB.physical_state - return ..() - -/obj/machinery/nuclearbomb/proc/get_nuke_state() - if(exploding) - return NUKE_ON_EXPLODING - if(timing) - return NUKE_ON_TIMING - if(safety) - return NUKE_OFF_LOCKED - else - return NUKE_OFF_UNLOCKED - -/obj/machinery/nuclearbomb/update_icon_state() - if(deconstruction_state != NUKESTATE_INTACT) - icon_state = "nuclearbomb_base" - return ..() - switch(get_nuke_state()) - if(NUKE_OFF_LOCKED, NUKE_OFF_UNLOCKED) - icon_state = "nuclearbomb_base" - if(NUKE_ON_TIMING) - icon_state = "nuclearbomb_timing" - if(NUKE_ON_EXPLODING) - icon_state = "nuclearbomb_exploding" - return ..() - -/obj/machinery/nuclearbomb/update_overlays() - . += ..() - update_icon_interior() - update_icon_lights() - -/obj/machinery/nuclearbomb/proc/update_icon_interior() - cut_overlay(interior) - switch(deconstruction_state) - if(NUKESTATE_UNSCREWED) - interior = "panel-unscrewed" - if(NUKESTATE_PANEL_REMOVED) - interior = "panel-removed" - if(NUKESTATE_WELDED) - interior = "plate-welded" - if(NUKESTATE_CORE_EXPOSED) - interior = "plate-removed" - if(NUKESTATE_CORE_REMOVED) - interior = "core-removed" - if(NUKESTATE_INTACT) - return - add_overlay(interior) - -/obj/machinery/nuclearbomb/proc/update_icon_lights() - if(lights) - cut_overlay(lights) - switch(get_nuke_state()) - if(NUKE_OFF_LOCKED) - lights = "" - return - if(NUKE_OFF_UNLOCKED) - lights = "lights-safety" - if(NUKE_ON_TIMING) - lights = "lights-timing" - if(NUKE_ON_EXPLODING) - lights = "lights-exploding" - add_overlay(lights) - -/obj/machinery/nuclearbomb/process() - if(timing && !exploding) - if(detonation_timer < world.time) - explode() - else - var/volume = (get_time_left() <= 20 ? 30 : 5) - playsound(loc, 'sound/items/timer.ogg', volume, FALSE) - -/obj/machinery/nuclearbomb/proc/update_ui_mode() - if(exploded) - ui_mode = NUKEUI_EXPLODED - return - - if(!auth) - ui_mode = NUKEUI_AWAIT_DISK - return - - if(timing) - ui_mode = NUKEUI_TIMING - return - - if(!safety) - ui_mode = NUKEUI_AWAIT_ARM - return - - if(!yes_code) - ui_mode = NUKEUI_AWAIT_CODE - return - - ui_mode = NUKEUI_AWAIT_TIMER - -/obj/machinery/nuclearbomb/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "NuclearBomb", name) - ui.open() - -/obj/machinery/nuclearbomb/ui_data(mob/user) - var/list/data = list() - data["disk_present"] = auth - - var/hidden_code = (ui_mode == NUKEUI_AWAIT_CODE && numeric_input != "ERROR") - - var/current_code = "" - if(hidden_code) - while(length(current_code) < length(numeric_input)) - current_code = "[current_code]*" - else - current_code = numeric_input - while(length(current_code) < 5) - current_code = "[current_code]-" - - var/first_status - var/second_status - switch(ui_mode) - if(NUKEUI_AWAIT_DISK) - first_status = "DEVICE LOCKED" - if(timing) - second_status = "TIME: [get_time_left()]" - else - second_status = "AWAIT DISK" - if(NUKEUI_AWAIT_CODE) - first_status = "INPUT CODE" - second_status = "CODE: [current_code]" - if(NUKEUI_AWAIT_TIMER) - first_status = "INPUT TIME" - second_status = "TIME: [current_code]" - if(NUKEUI_AWAIT_ARM) - first_status = "DEVICE READY" - second_status = "TIME: [get_time_left()]" - if(NUKEUI_TIMING) - first_status = "DEVICE ARMED" - second_status = "TIME: [get_time_left()]" - if(NUKEUI_EXPLODED) - first_status = "DEVICE DEPLOYED" - second_status = "THANK YOU" - - data["status1"] = first_status - data["status2"] = second_status - data["anchored"] = anchored - - return data - -/obj/machinery/nuclearbomb/ui_act(action, params) - . = ..() - if(.) - return - playsound(src, SFX_TERMINAL_TYPE, 20, FALSE) - switch(action) - if("eject_disk") - if(auth && auth.loc == src) - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - auth.forceMove(get_turf(src)) - auth = null - . = TRUE - else - var/obj/item/I = usr.is_holding_item_of_type(/obj/item/disk/nuclear) - if(I && disk_check(I) && usr.transferItemToLoc(I, src)) - playsound(src, 'sound/machines/terminal_insert_disc.ogg', 50, FALSE) - playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - auth = I - . = TRUE - update_ui_mode() - if("keypad") - if(auth) - var/digit = params["digit"] - switch(digit) - if("C") - if(auth && ui_mode == NUKEUI_AWAIT_ARM) - set_safety() - yes_code = FALSE - playsound(src, 'sound/machines/nuke/confirm_beep.ogg', 50, FALSE) - update_ui_mode() - else - playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - numeric_input = "" - . = TRUE - if("E") - switch(ui_mode) - if(NUKEUI_AWAIT_CODE) - if(numeric_input == r_code) - numeric_input = "" - yes_code = TRUE - playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - . = TRUE - else - playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE) - numeric_input = "ERROR" - if(NUKEUI_AWAIT_TIMER) - var/number_value = text2num(numeric_input) - if(number_value) - timer_set = clamp(number_value, minimum_timer_set, maximum_timer_set) - playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - set_safety() - . = TRUE - else - playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE) - update_ui_mode() - if("0","1","2","3","4","5","6","7","8","9") - if(numeric_input != "ERROR") - numeric_input += digit - if(length(numeric_input) > 5) - numeric_input = "ERROR" - else - playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - . = TRUE - else - playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE) - if("arm") - if(auth && yes_code && !safety && !exploded) - playsound(src, 'sound/machines/nuke/confirm_beep.ogg', 50, FALSE) - set_active() - update_ui_mode() - . = TRUE - else - playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE) - if("anchor") - if(auth && yes_code) - playsound(src, 'sound/machines/nuke/general_beep.ogg', 50, FALSE) - set_anchor() - else - playsound(src, 'sound/machines/nuke/angry_beep.ogg', 50, FALSE) - -/obj/machinery/nuclearbomb/proc/set_anchor() - if(isinspace() && !anchored) - to_chat(usr, span_warning("There is nothing to anchor to!")) - else - set_anchored(!anchored) - -/obj/machinery/nuclearbomb/proc/set_safety() - safety = !safety - if(safety) - if(timing) - set_security_level(previous_level) - for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) - S.switch_mode_to(initial(S.mode)) - S.alert = FALSE - timing = FALSE - detonation_timer = null - countdown.stop() - update_appearance() - -/obj/machinery/nuclearbomb/proc/set_active() - var/turf/our_turf = get_turf(src) - if(safety) - to_chat(usr, span_danger("The safety is still on.")) - return - timing = !timing - if(timing) - message_admins("\The [src] was armed at [ADMIN_VERBOSEJMP(our_turf)] by [ADMIN_LOOKUPFLW(usr)].") - log_game("\The [src] was armed at [loc_name(our_turf)] by [key_name(usr)].") - previous_level = get_security_level() - detonation_timer = world.time + (timer_set * 10) - for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) - S.switch_mode_to(TRACK_INFILTRATOR) - - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NUKE_DEVICE_ARMED, src) - - countdown.start() - set_security_level("delta") - else - message_admins("\The [src] at [ADMIN_VERBOSEJMP(our_turf)] was disarmed by [ADMIN_LOOKUPFLW(usr)].") - log_game("\The [src] at [loc_name(our_turf)] was disarmed by [key_name(usr)].") - detonation_timer = null - set_security_level(previous_level) - for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) - S.switch_mode_to(initial(S.mode)) - S.alert = FALSE - countdown.stop() - - SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NUKE_DEVICE_DISARMED, src) - - update_appearance() - -/obj/machinery/nuclearbomb/proc/get_time_left() - if(timing) - . = round(max(0, detonation_timer - world.time) / 10, 1) - else - . = timer_set - -/obj/machinery/nuclearbomb/blob_act(obj/structure/blob/B) - if(exploding) - return - qdel(src) - -/obj/machinery/nuclearbomb/zap_act(power, zap_flags) - . = ..() - if(zap_flags & ZAP_MACHINE_EXPLOSIVE) - qdel(src)//like the singulo, tesla deletes it. stops it from exploding over and over - -#define NUKERANGE 127 -/obj/machinery/nuclearbomb/proc/explode() - if(safety) - timing = FALSE - return - - exploding = TRUE - yes_code = FALSE - safety = TRUE - update_appearance() - sound_to_playing_players('sound/machines/alarm.ogg') - sound_to_playing_players('modular_skyrat/modules/alerts/sound/misc/delta_countdown.ogg') //SKYRAT EDIT ADDITION - if(SSticker?.mode) - SSticker.roundend_check_paused = TRUE - addtimer(CALLBACK(src, .proc/actually_explode), 100) - -/obj/machinery/nuclearbomb/proc/actually_explode() - if(!core) - Cinematic(CINEMATIC_NUKE_NO_CORE,world) - SSticker.roundend_check_paused = FALSE - return - - SSlag_switch.set_measure(DISABLE_NON_OBSJOBS, TRUE) - - var/off_station = 0 - var/turf/bomb_location = get_turf(src) - var/area/A = get_area(bomb_location) - - if(bomb_location && is_station_level(bomb_location.z)) - if(istype(A, /area/space)) - off_station = NUKE_NEAR_MISS - else if((bomb_location.x < (128-NUKERANGE)) || (bomb_location.x > (128+NUKERANGE)) || (bomb_location.y < (128-NUKERANGE)) || (bomb_location.y > (128+NUKERANGE))) - off_station = NUKE_NEAR_MISS - else // station actually nuked - off_station = STATION_DESTROYED_NUKE - GLOB.station_was_nuked = TRUE - else if(bomb_location.onSyndieBase()) - off_station = NUKE_SYNDICATE_BASE - else - off_station = NUKE_MISS_STATION - - if(off_station < NUKE_MISS_STATION) - SSshuttle.registerHostileEnvironment(src) - SSshuttle.lockdown = TRUE - //Cinematic - GLOB.station_nuke_source = off_station - really_actually_explode(off_station) - SSticker.roundend_check_paused = FALSE - -/obj/machinery/nuclearbomb/proc/really_actually_explode(off_station) - var/turf/bomb_location = get_turf(src) - Cinematic(get_cinematic_type(off_station),world,CALLBACK(SSticker,/datum/controller/subsystem/ticker/proc/station_explosion_detonation,src)) - if(off_station == STATION_DESTROYED_NUKE) - INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnStation) - return - if(off_station != NUKE_NEAR_MISS) // Don't kill people in the station if the nuke missed, even if we are technically on the same z-level - INVOKE_ASYNC(GLOBAL_PROC,.proc/KillEveryoneOnZLevel, bomb_location.z) - -/obj/machinery/nuclearbomb/proc/get_cinematic_type(off_station) - if(off_station < NUKE_NEAR_MISS) - return CINEMATIC_SELFDESTRUCT - else - return CINEMATIC_SELFDESTRUCT_MISS - -/obj/machinery/nuclearbomb/beer - name = "\improper Nanotrasen-brand nuclear fission explosive" - desc = "One of the more successful achievements of the Nanotrasen Corporate Warfare Division, their nuclear fission explosives are renowned for being cheap to produce and devastatingly effective. Signs explain that though this particular device has been decommissioned, every Nanotrasen station is equipped with an equivalent one, just in case. All Captains carefully guard the disk needed to detonate them - at least, the sign says they do. There seems to be a tap on the back." - proper_bomb = FALSE - var/obj/structure/reagent_dispensers/beerkeg/keg - -/obj/machinery/nuclearbomb/beer/Initialize(mapload) - . = ..() - keg = new(src) - QDEL_NULL(core) - -/obj/machinery/nuclearbomb/beer/examine(mob/user) - . = ..() - if(keg.reagents.total_volume) - to_chat(user, span_notice("It has [keg.reagents.total_volume] unit\s left.")) - else - to_chat(user, span_danger("It's empty.")) - -/obj/machinery/nuclearbomb/beer/attackby(obj/item/W, mob/user, params) - if(W.is_refillable()) - W.afterattack(keg, user, TRUE) // redirect refillable containers to the keg, allowing them to be filled - return TRUE // pretend we handled the attack, too. - if(istype(W, /obj/item/nuke_core_container)) - to_chat(user, span_notice("[src] has had its plutonium core removed as a part of being decommissioned.")) - return TRUE - return ..() - -/obj/machinery/nuclearbomb/beer/actually_explode() - //Unblock roundend, we're not actually exploding. - SSticker.roundend_check_paused = FALSE - var/turf/bomb_location = get_turf(src) - if(!bomb_location) - disarm() - return - if(is_station_level(bomb_location.z)) - addtimer(CALLBACK(src, .proc/really_actually_explode), 110) - else - visible_message(span_notice("[src] fizzes ominously.")) - addtimer(CALLBACK(src, .proc/local_foam), 110) - -/obj/machinery/nuclearbomb/beer/proc/disarm() - detonation_timer = null - exploding = FALSE - exploded = TRUE - set_security_level(previous_level) - for(var/obj/item/pinpointer/nuke/syndicate/S in GLOB.pinpointer_list) - S.switch_mode_to(initial(S.mode)) - S.alert = FALSE - countdown.stop() - update_appearance() - -/obj/machinery/nuclearbomb/beer/proc/local_foam() - var/datum/reagents/R = new/datum/reagents(1000) - R.my_atom = src - R.add_reagent(/datum/reagent/consumable/ethanol/beer, 100) - - var/datum/effect_system/fluid_spread/foam/foam = new - foam.set_up(200, location = get_turf(src), carry = R) - foam.start() - disarm() - -/obj/machinery/nuclearbomb/beer/proc/stationwide_foam() - priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert") - - for (var/obj/machinery/atmospherics/components/unary/vent_scrubber/vent in GLOB.machines) - var/turf/vent_turf = get_turf(vent) - if (!vent_turf || !is_station_level(vent_turf.z) || vent.welded) - continue - - var/datum/reagents/beer = new /datum/reagents(1000) - beer.my_atom = vent - beer.add_reagent(/datum/reagent/consumable/ethanol/beer, 100) - beer.create_foam(/datum/effect_system/fluid_spread/foam, DIAMOND_AREA(10)) - - CHECK_TICK - -/obj/machinery/nuclearbomb/beer/really_actually_explode() - disarm() - stationwide_foam() - -/proc/KillEveryoneOnStation() - for(var/mob/living/victim as anything in GLOB.mob_living_list) - var/turf/target_turf = get_turf(victim) - if(istype(victim.loc, /obj/structure/closet/secure_closet/freezer)) - var/obj/structure/closet/secure_closet/freezer/freezer = victim.loc - if(!freezer.jones) - to_chat(victim, span_boldannounce("You hold onto \the [victim.loc] as the nuclear bomb goes off. Luckily as \the [victim.loc] is lead-lined, you survive.")) - freezer.jones = TRUE - continue - if(victim.stat != DEAD && target_turf && is_station_level(target_turf.z)) - to_chat(victim, span_userdanger("You are shredded to atoms!")) - victim.gib() - -/proc/KillEveryoneOnZLevel(z) - if(!z) - return - for(var/_victim in GLOB.mob_living_list) - var/mob/living/victim = _victim - var/turf/target_turf = get_turf(victim) - if(istype(victim.loc, /obj/structure/closet/secure_closet/freezer)) - var/obj/structure/closet/secure_closet/freezer/freezer = victim.loc - if(!freezer.jones) - to_chat(victim, span_boldannounce("You hold onto \the [victim.loc] as the nuclear bomb goes off. Luckily as \the [victim.loc] is lead-lined, you survive.")) - freezer.jones = TRUE - continue - if(victim.stat != DEAD && target_turf && target_turf.z == z) - to_chat(victim, span_userdanger("You are shredded to atoms!")) - victim.gib() - -/* -This is here to make the tiles around the station mininuke change when it's armed. -*/ - -/obj/machinery/nuclearbomb/selfdestruct/set_anchor() - return - -/obj/machinery/nuclearbomb/selfdestruct/set_active() - ..() - if(timing) - SSmapping.add_nuke_threat(src) - else - SSmapping.remove_nuke_threat(src) - -/obj/machinery/nuclearbomb/selfdestruct/set_safety() - ..() - if(timing) - SSmapping.add_nuke_threat(src) - else - SSmapping.remove_nuke_threat(src) - -//==========DAT FUKKEN DISK=============== -/obj/item/disk - icon = 'icons/obj/module.dmi' - w_class = WEIGHT_CLASS_TINY - inhand_icon_state = "card-id" - lefthand_file = 'icons/mob/inhands/equipment/idcards_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/idcards_righthand.dmi' - icon_state = "datadisk0" - drop_sound = 'sound/items/handling/disk_drop.ogg' - pickup_sound = 'sound/items/handling/disk_pickup.ogg' - -/obj/item/disk/nuclear - name = "nuclear authentication disk" - desc = "Better keep this safe." - icon_state = "nucleardisk" - max_integrity = 250 - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 30, BIO = 0, FIRE = 100, ACID = 100) - resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF - var/fake = FALSE - var/turf/last_secured_location - var/last_disk_move - -/obj/item/disk/nuclear/Initialize(mapload) - . = ..() - AddElement(/datum/element/bed_tuckable, 6, -6, 0) - - if(!fake) - SSpoints_of_interest.make_point_of_interest(src) - last_disk_move = world.time - START_PROCESSING(SSobj, src) - -/obj/item/disk/nuclear/ComponentInitialize() - . = ..() - AddComponent(/datum/component/stationloving, !fake) - -/obj/item/disk/nuclear/process() - if(fake) - STOP_PROCESSING(SSobj, src) - CRASH("A fake nuke disk tried to call process(). Who the fuck and how the fuck") - - var/turf/new_turf = get_turf(src) - - if (is_secured()) - last_secured_location = new_turf - last_disk_move = world.time - var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control - if(istype(loneop) && loneop.occurrences < loneop.max_occurrences && prob(loneop.weight)) - loneop.weight = max(loneop.weight - 1, 0) - if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1) - message_admins("[src] is secured (currently in [ADMIN_VERBOSEJMP(new_turf)]). The weight of Lone Operative is now [loneop.weight].") - log_game("[src] being secured has reduced the weight of the Lone Operative event to [loneop.weight].") - else - /// How comfy is our disk? - var/disk_comfort_level = 0 - - //Go through and check for items that make disk comfy - for(var/obj/comfort_item in loc) - if(istype(comfort_item, /obj/item/bedsheet) || istype(comfort_item, /obj/structure/bed)) - disk_comfort_level++ - - if(last_disk_move < world.time - 5000 && prob((world.time - 5000 - last_disk_move)*0.0001)) - var/datum/round_event_control/operative/loneop = locate(/datum/round_event_control/operative) in SSevents.control - if(istype(loneop) && loneop.occurrences < loneop.max_occurrences) - loneop.weight += 1 - if(loneop.weight % 5 == 0 && SSticker.totalPlayers > 1) - if(disk_comfort_level >= 2) - visible_message(span_notice("[src] sleeps soundly. Sleep tight, disky.")) - message_admins("[src] is unsecured in [ADMIN_VERBOSEJMP(new_turf)]. The weight of Lone Operative is now [loneop.weight].") - log_game("[src] is unsecured for too long in [loc_name(new_turf)], and has increased the weight of the Lone Operative event to [loneop.weight].") - -/obj/item/disk/nuclear/proc/is_secured() - if (last_secured_location == get_turf(src)) - return FALSE - - var/mob/holder = pulledby || get(src, /mob) - if (isnull(holder?.client)) - return FALSE - - return TRUE - -/obj/item/disk/nuclear/examine(mob/user) - . = ..() - if(!fake) - return - - if(isobserver(user) || HAS_TRAIT(user, TRAIT_DISK_VERIFIER) || (user.mind && HAS_TRAIT(user.mind, TRAIT_DISK_VERIFIER))) - . += span_warning("The serial numbers on [src] are incorrect.") - -/* - * You can't accidentally eat the nuke disk, bro - */ -/obj/item/disk/nuclear/on_accidental_consumption(mob/living/carbon/M, mob/living/carbon/user, obj/item/source_item, discover_after = TRUE) - M.visible_message(span_warning("[M] looks like [M.p_theyve()] just bitten into something important."), \ - span_warning("Wait, is this the nuke disk?")) - - return discover_after - -/obj/item/disk/nuclear/attackby(obj/item/I, mob/living/user, params) - if(istype(I, /obj/item/claymore/highlander) && !fake) - var/obj/item/claymore/highlander/H = I - if(H.nuke_disk) - to_chat(user, span_notice("Wait... what?")) - qdel(H.nuke_disk) - H.nuke_disk = null - return - user.visible_message(span_warning("[user] captures [src]!"), span_userdanger("You've got the disk! Defend it with your life!")) - forceMove(H) - H.nuke_disk = src - return TRUE - return ..() - -/obj/item/disk/nuclear/suicide_act(mob/user) - user.visible_message(span_suicide("[user] is going delta! It looks like [user.p_theyre()] trying to commit suicide!")) - playsound(src, 'sound/machines/alarm.ogg', 50, -1, TRUE) - for(var/i in 1 to 100) - addtimer(CALLBACK(user, /atom/proc/add_atom_colour, (i % 2)? "#00FF00" : "#FF0000", ADMIN_COLOUR_PRIORITY), i) - addtimer(CALLBACK(src, .proc/manual_suicide, user), 101) - return MANUAL_SUICIDE - -/obj/item/disk/nuclear/proc/manual_suicide(mob/living/user) - user.remove_atom_colour(ADMIN_COLOUR_PRIORITY) - user.visible_message(span_suicide("[user] is destroyed by the nuclear blast!")) - user.adjustOxyLoss(200) - user.death(0) - -/obj/item/disk/nuclear/fake - fake = TRUE - -/obj/item/disk/nuclear/fake/obvious - name = "cheap plastic imitation of the nuclear authentication disk" - desc = "How anyone could mistake this for the real thing is beyond you." diff --git a/code/modules/antagonists/wizard/equipment/spellbook.dm b/code/modules/antagonists/wizard/equipment/spellbook.dm deleted file mode 100644 index a95bbeac0fd..00000000000 --- a/code/modules/antagonists/wizard/equipment/spellbook.dm +++ /dev/null @@ -1,882 +0,0 @@ -/datum/spellbook_entry - var/name = "Entry Name" - - var/spell_type = null - var/desc = "" - var/category = "Offensive" - var/cost = 2 - var/times = 0 - var/refundable = TRUE - var/obj/effect/proc_holder/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell - var/buy_word = "Learn" - var/cooldown - var/clothes_req = FALSE - var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook - var/list/no_coexistance_typecache //Used so you can't have specific spells together - -/datum/spellbook_entry/New() - ..() - no_coexistance_typecache = typecacheof(no_coexistance_typecache) - -/datum/spellbook_entry/proc/IsAvailable() // For config prefs / gamemode restrictions - these are round applied - return TRUE - -/datum/spellbook_entry/proc/CanBuy(mob/living/carbon/human/user,obj/item/spellbook/book) // Specific circumstances - if(book.uses= aspell.level_max) - to_chat(user, span_warning("This spell cannot be improved further!")) - return FALSE - - aspell.name = initial(aspell.name) - aspell.spell_level++ - aspell.charge_max = round(LERP(initial(aspell.charge_max), aspell.cooldown_min, aspell.spell_level / aspell.level_max)) - if(aspell.charge_max < aspell.charge_counter) - aspell.charge_counter = aspell.charge_max - var/newname = "ERROR" - switch(aspell.spell_level) - if(1) - to_chat(user, span_notice("You have improved [aspell.name] into Efficient [aspell.name].")) - newname = "Efficient [aspell.name]" - if(2) - to_chat(user, span_notice("You have further improved [aspell.name] into Quickened [aspell.name].")) - newname = "Quickened [aspell.name]" - if(3) - to_chat(user, span_notice("You have further improved [aspell.name] into Free [aspell.name].")) - newname = "Free [aspell.name]" - if(4) - to_chat(user, span_notice("You have further improved [aspell.name] into Instant [aspell.name].")) - newname = "Instant [aspell.name]" - aspell.name = newname - name = newname - if(aspell.spell_level >= aspell.level_max) - to_chat(user, span_warning("This spell cannot be strengthened any further!")) - //we'll need to update the cooldowns for the spellbook - GetInfo() - log_spellbook("[key_name(user)] improved their knowledge of [src] to level [aspell.spell_level] for [cost] points") - SSblackbox.record_feedback("nested tally", "wizard_spell_improved", 1, list("[name]", "[aspell.spell_level]")) - return TRUE - //No same spell found - just learn it - log_spellbook("[key_name(user)] learned [src] for [cost] points") - SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name) - user.mind.AddSpell(S) - to_chat(user, span_notice("You have learned [S.name].")) - return TRUE - -/datum/spellbook_entry/proc/CanRefund(mob/living/carbon/human/user,obj/item/spellbook/book) - if(!refundable) - return FALSE - if(!book.can_refund) - return FALSE - if(!S) - S = new spell_type() - for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list) - if(initial(S.name) == initial(aspell.name)) - return TRUE - return FALSE - -/datum/spellbook_entry/proc/Refund(mob/living/carbon/human/user,obj/item/spellbook/book) //return point value or -1 for failure - var/area/centcom/wizard_station/A = GLOB.areas_by_type[/area/centcom/wizard_station] - if(!(user in A.contents)) - to_chat(user, span_warning("You can only refund spells at the wizard lair!")) - return -1 - if(!S) - S = new spell_type() - var/spell_levels = 0 - for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list) - if(initial(S.name) == initial(aspell.name)) - spell_levels = aspell.spell_level - user.mind.spell_list.Remove(aspell) - name = initial(name) - log_spellbook("[key_name(user)] refunded [src] for [cost * (spell_levels+1)] points") - qdel(S) - return cost * (spell_levels+1) - return -1 - - -/datum/spellbook_entry/proc/GetInfo() - if(!spell_type) - return - if(!S) - S = new spell_type() - if(S.charge_type == "recharge") - cooldown = S.charge_max/10 - if(S.clothes_req) - clothes_req = TRUE - -/datum/spellbook_entry/fireball - name = "Fireball" - desc = "Fires an explosive fireball at a target. Considered a classic among all wizards." - spell_type = /obj/effect/proc_holder/spell/aimed/fireball - -/datum/spellbook_entry/spell_cards - name = "Spell Cards" - desc = "Blazing hot rapid-fire homing cards. Send your foes to the shadow realm with their mystical power!" - spell_type = /obj/effect/proc_holder/spell/aimed/spell_cards - -/datum/spellbook_entry/rod_form - name = "Rod Form" - desc = "Take on the form of an immovable rod, destroying all in your path. Purchasing this spell multiple times will also increase the rod's damage and travel range." - spell_type = /obj/effect/proc_holder/spell/targeted/rod_form - -/datum/spellbook_entry/magicm - name = "Magic Missile" - desc = "Fires several, slow moving, magic projectiles at nearby targets." - spell_type = /obj/effect/proc_holder/spell/targeted/projectile/magic_missile - category = "Defensive" - -/datum/spellbook_entry/disintegrate - name = "Smite" - desc = "Charges your hand with an unholy energy that can be used to cause a touched victim to violently explode." - spell_type = /obj/effect/proc_holder/spell/targeted/touch/disintegrate - -/datum/spellbook_entry/disabletech - name = "Disable Tech" - desc = "Disables all weapons, cameras and most other technology in range." - spell_type = /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/repulse - name = "Repulse" - desc = "Throws everything around the user away." - spell_type = /obj/effect/proc_holder/spell/aoe_turf/repulse - category = "Defensive" - -/datum/spellbook_entry/lightning_packet - name = "Thrown Lightning" - desc = "Forged from eldrich energies, a packet of pure power, known as a spell packet will appear in your hand, that when thrown will stun the target." - spell_type = /obj/effect/proc_holder/spell/targeted/conjure_item/spellpacket - category = "Defensive" - -/datum/spellbook_entry/timestop - name = "Time Stop" - desc = "Stops time for everyone except for you, allowing you to move freely while your enemies and even projectiles are frozen." - spell_type = /obj/effect/proc_holder/spell/aoe_turf/timestop - category = "Defensive" - -/datum/spellbook_entry/smoke - name = "Smoke" - desc = "Spawns a cloud of choking smoke at your location." - spell_type = /obj/effect/proc_holder/spell/targeted/smoke - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/blind - name = "Blind" - desc = "Temporarily blinds a single target." - spell_type = /obj/effect/proc_holder/spell/pointed/trigger/blind - cost = 1 - -/datum/spellbook_entry/mindswap - name = "Mindswap" - desc = "Allows you to switch bodies with a target next to you. You will both fall asleep when this happens, and it will be quite obvious that you are the target's body if someone watches you do it." - spell_type = /obj/effect/proc_holder/spell/pointed/mind_transfer - category = "Mobility" - -/datum/spellbook_entry/forcewall - name = "Force Wall" - desc = "Create a magical barrier that only you can pass through." - spell_type = /obj/effect/proc_holder/spell/targeted/forcewall - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/blink - name = "Blink" - desc = "Randomly teleports you a short distance." - spell_type = /obj/effect/proc_holder/spell/targeted/turf_teleport/blink - category = "Mobility" - -/datum/spellbook_entry/teleport - name = "Teleport" - desc = "Teleports you to an area of your selection." - spell_type = /obj/effect/proc_holder/spell/targeted/area_teleport/teleport - category = "Mobility" - -/datum/spellbook_entry/mutate - name = "Mutate" - desc = "Causes you to turn into a hulk and gain laser vision for a short while." - spell_type = /obj/effect/proc_holder/spell/targeted/genetic/mutate - -/datum/spellbook_entry/jaunt - name = "Ethereal Jaunt" - desc = "Turns your form ethereal, temporarily making you invisible and able to pass through walls." - spell_type = /obj/effect/proc_holder/spell/targeted/ethereal_jaunt - category = "Mobility" - -/datum/spellbook_entry/knock - name = "Knock" - desc = "Opens nearby doors and closets." - spell_type = /obj/effect/proc_holder/spell/aoe_turf/knock - category = "Mobility" - cost = 1 - -/datum/spellbook_entry/fleshtostone - name = "Flesh to Stone" - desc = "Charges your hand with the power to turn victims into inert statues for a long period of time." - spell_type = /obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone - -/datum/spellbook_entry/summonitem - name = "Summon Item" - desc = "Recalls a previously marked item to your hand from anywhere in the universe." - spell_type = /obj/effect/proc_holder/spell/targeted/summonitem - category = "Assistance" - cost = 1 - -/datum/spellbook_entry/lichdom - name = "Bind Soul" - desc = "A dark necromantic pact that can forever bind your soul to an item of your choosing, \ - turning you into an immortal Lich. So long as the item remains intact, you will revive from death, \ - no matter the circumstances. Be wary - with each revival, your body will become weaker, and \ - it will become easier for others to find your item of power." - spell_type = /obj/effect/proc_holder/spell/targeted/lichdom - category = "Defensive" - -/datum/spellbook_entry/teslablast - name = "Tesla Blast" - desc = "Charge up a tesla arc and release it at a random nearby target! You can move freely while it charges. The arc jumps between targets and can knock them down." - spell_type = /obj/effect/proc_holder/spell/targeted/tesla - -/datum/spellbook_entry/lightningbolt - name = "Lightning Bolt" - desc = "Fire a lightning bolt at your foes! It will jump between targets, but can't knock them down." - spell_type = /obj/effect/proc_holder/spell/aimed/lightningbolt - cost = 1 - -/datum/spellbook_entry/infinite_guns - name = "Lesser Summon Guns" - desc = "Why reload when you have infinite guns? Summons an unending stream of bolt action rifles that deal little damage, but will knock targets down. Requires both hands free to use. Learning this spell makes you unable to learn Arcane Barrage." - spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns/gun - cost = 3 - no_coexistance_typecache = /obj/effect/proc_holder/spell/targeted/infinite_guns/arcane_barrage - -/datum/spellbook_entry/infinite_guns/Refund(mob/living/carbon/human/user, obj/item/spellbook/book) - for (var/obj/item/currentItem in user.get_all_gear()) - if (currentItem.type == /obj/item/gun/ballistic/rifle/enchanted) - qdel(currentItem) - return ..() - -/datum/spellbook_entry/arcane_barrage - name = "Arcane Barrage" - desc = "Fire a torrent of arcane energy at your foes with this (powerful) spell. Deals much more damage than Lesser Summon Guns, but won't knock targets down. Requires both hands free to use. Learning this spell makes you unable to learn Lesser Summon Gun." - spell_type = /obj/effect/proc_holder/spell/targeted/infinite_guns/arcane_barrage - cost = 3 - no_coexistance_typecache = /obj/effect/proc_holder/spell/targeted/infinite_guns/gun - -/datum/spellbook_entry/arcane_barrage/Refund(mob/living/carbon/human/user, obj/item/spellbook/book) - for (var/obj/item/currentItem in user.get_all_gear()) - if (currentItem.type == /obj/item/gun/ballistic/rifle/enchanted/arcane_barrage) - qdel(currentItem) - return ..() - -/datum/spellbook_entry/barnyard - name = "Barnyard Curse" - desc = "This spell dooms an unlucky soul to possess the speech and facial attributes of a barnyard animal." - spell_type = /obj/effect/proc_holder/spell/pointed/barnyardcurse - -/datum/spellbook_entry/charge - name = "Charge" - desc = "This spell can be used to recharge a variety of things in your hands, from magical artifacts to electrical components. A creative wizard can even use it to grant magical power to a fellow magic user." - spell_type = /obj/effect/proc_holder/spell/targeted/charge - category = "Assistance" - cost = 1 - -/datum/spellbook_entry/shapeshift - name = "Wild Shapeshift" - desc = "Take on the shape of another for a time to use their natural abilities. Once you've made your choice it cannot be changed." - spell_type = /obj/effect/proc_holder/spell/targeted/shapeshift - category = "Assistance" - cost = 1 - -/datum/spellbook_entry/tap - name = "Soul Tap" - desc = "Fuel your spells using your own soul!" - spell_type = /obj/effect/proc_holder/spell/self/tap - category = "Assistance" - cost = 1 - -/datum/spellbook_entry/spacetime_dist - name = "Spacetime Distortion" - desc = "Entangle the strings of space-time in an area around you, randomizing the layout and making proper movement impossible. The strings vibrate..." - spell_type = /obj/effect/proc_holder/spell/spacetime_dist - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/the_traps - name = "The Traps!" - desc = "Summon a number of traps around you. They will damage and enrage any enemies that step on them." - spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/the_traps - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/bees - name = "Lesser Summon Bees" - desc = "This spell magically kicks a transdimensional beehive, instantly summoning a swarm of bees to your location. These bees are NOT friendly to anyone." - spell_type = /obj/effect/proc_holder/spell/aoe_turf/conjure/creature/bee - category = "Defensive" - - -/datum/spellbook_entry/item - name = "Buy Item" - refundable = FALSE - buy_word = "Summon" - var/item_path = null - - -/datum/spellbook_entry/item/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) - var/atom/spawned_path = new item_path(get_turf(user)) - log_spellbook("[key_name(user)] bought [src] for [cost] points") - SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name) - return spawned_path - -/datum/spellbook_entry/item/staffchange - name = "Staff of Change" - desc = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself." - item_path = /obj/item/gun/magic/staff/change - -/datum/spellbook_entry/item/staffanimation - name = "Staff of Animation" - desc = "An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines." - item_path = /obj/item/gun/magic/staff/animate - category = "Assistance" - -/datum/spellbook_entry/item/staffchaos - name = "Staff of Chaos" - desc = "A caprious tool that can fire all sorts of magic without any rhyme or reason. Using it on people you care about is not recommended." - item_path = /obj/item/gun/magic/staff/chaos - -/datum/spellbook_entry/item/spellblade - name = "Spellblade" - desc = "A sword capable of firing blasts of energy which rip targets limb from limb." - item_path = /obj/item/gun/magic/staff/spellblade - -/datum/spellbook_entry/item/staffdoor - name = "Staff of Door Creation" - desc = "A particular staff that can mold solid walls into ornate doors. Useful for getting around in the absence of other transportation. Does not work on glass." - item_path = /obj/item/gun/magic/staff/door - cost = 1 - category = "Mobility" - -/datum/spellbook_entry/item/staffhealing - name = "Staff of Healing" - desc = "An altruistic staff that can heal the lame and raise the dead." - item_path = /obj/item/gun/magic/staff/healing - cost = 1 - category = "Defensive" - -/datum/spellbook_entry/item/lockerstaff - name = "Staff of the Locker" - desc = "A staff that shoots lockers. It eats anyone it hits on its way, leaving a welded locker with your victims behind." - item_path = /obj/item/gun/magic/staff/locker - category = "Defensive" - -/datum/spellbook_entry/item/scryingorb - name = "Scrying Orb" - desc = "An incandescent orb of crackling energy. Using it will allow you to release your ghost while alive, allowing you to spy upon the station and talk to the deceased. In addition, buying it will permanently grant you X-ray vision." - item_path = /obj/item/scrying - category = "Defensive" - -/datum/spellbook_entry/item/soulstones - name = "Soulstone Shard Kit" - desc = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot." - item_path = /obj/item/storage/belt/soulstone/full - category = "Assistance" - -/datum/spellbook_entry/item/soulstones/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) - . =..() - if(.) - user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(null)) - return . - -/datum/spellbook_entry/item/necrostone - name = "A Necromantic Stone" - desc = "A Necromantic stone is able to resurrect three dead individuals as skeletal thralls for you to command." - item_path = /obj/item/necromantic_stone - category = "Assistance" - -/datum/spellbook_entry/item/wands - name = "Wand Assortment" - desc = "A collection of wands that allow for a wide variety of utility. Wands have a limited number of charges, so be conservative with their use. Comes in a handy belt." - item_path = /obj/item/storage/belt/wands/full - category = "Defensive" - -/datum/spellbook_entry/item/armor - name = "Mastercrafted Armor Set" - desc = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space, also grants a battlemage shield." - item_path = /obj/item/mod/control/pre_equipped/enchanted - category = "Defensive" - -/datum/spellbook_entry/item/armor/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) - . = ..() - if(!.) - return - var/obj/item/mod/control/mod = . - var/obj/item/mod/module/storage/storage = locate() in mod.modules - var/obj/item/back = user.back - if(back) - if(!user.dropItemToGround(back)) - return - for(var/obj/item/item as anything in back.contents) - item.forceMove(storage) - if(!user.equip_to_slot_if_possible(mod, mod.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE)) - return - if(!user.dropItemToGround(user.wear_suit) || !user.dropItemToGround(user.head)) - return - mod.quick_activation() - -/datum/spellbook_entry/item/battlemage_charge - name = "Battlemage Armour Charges" - desc = "A powerful defensive rune, it will grant eight additional charges to a battlemage shield." - item_path = /obj/item/wizard_armour_charge - category = "Defensive" - cost = 1 - -/datum/spellbook_entry/item/contract - name = "Contract of Apprenticeship" - desc = "A magical contract binding an apprentice wizard to your service, using it will summon them to your side." - item_path = /obj/item/antag_spawner/contract - category = "Assistance" - -/datum/spellbook_entry/item/guardian - name = "Guardian Deck" - desc = "A deck of guardian tarot cards, capable of binding a personal guardian to your body. There are multiple types of guardian available, but all of them will transfer some amount of damage to you. \ - It would be wise to avoid buying these with anything capable of causing you to swap bodies with others." - item_path = /obj/item/guardiancreator/choose/wizard - category = "Assistance" - -/datum/spellbook_entry/item/guardian/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) - . = ..() - if(.) - new /obj/item/paper/guides/antag/guardian/wizard(get_turf(user)) - -/datum/spellbook_entry/item/bloodbottle - name = "Bottle of Blood" - desc = "A bottle of magically infused blood, the smell of which will attract extradimensional beings when broken. Be careful though, the kinds of creatures summoned by blood magic are indiscriminate in their killing, and you yourself may become a victim." - item_path = /obj/item/antag_spawner/slaughter_demon - limit = 3 - category = "Assistance" - -/datum/spellbook_entry/item/hugbottle - name = "Bottle of Tickles" - desc = "A bottle of magically infused fun, the smell of which will \ - attract adorable extradimensional beings when broken. These beings \ - are similar to slaughter demons, but they do not permanently kill \ - their victims, instead putting them in an extradimensional hugspace, \ - to be released on the demon's death. Chaotic, but not ultimately \ - damaging. The crew's reaction to the other hand could be very \ - destructive." - item_path = /obj/item/antag_spawner/slaughter_demon/laughter - cost = 1 //non-destructive; it's just a jape, sibling! - limit = 3 - category = "Assistance" - -/datum/spellbook_entry/item/mjolnir - name = "Mjolnir" - desc = "A mighty hammer on loan from Thor, God of Thunder. It crackles with barely contained power." - item_path = /obj/item/mjollnir - -/datum/spellbook_entry/item/singularity_hammer - name = "Singularity Hammer" - desc = "A hammer that creates an intensely powerful field of gravity where it strikes, pulling everything nearby to the point of impact." - item_path = /obj/item/singularityhammer - -/datum/spellbook_entry/item/warpwhistle - name = "Warp Whistle" - desc = "A strange whistle that will transport you to a distant safe place on the station. There is a window of vulnerability at the beginning of every use." - item_path = /obj/item/warp_whistle - category = "Mobility" - cost = 1 - -/datum/spellbook_entry/item/highfrequencyblade - name = "High Frequency Blade" - desc = "An incredibly swift enchanted blade resonating at a frequency high enough to be able to slice through anything." - item_path = /obj/item/highfrequencyblade/wizard - cost = 3 - -/datum/spellbook_entry/duffelbag - name = "Bestow Cursed Duffel Bag" - desc = "A curse that firmly attaches a demonic duffel bag to the target's back. The duffel bag will make the person it's attached to take periodical damage if it is not fed regularly, and regardless of whether or not it's been fed, it will slow the person wearing it down significantly." - spell_type = /obj/effect/proc_holder/spell/targeted/touch/duffelbag - category = "Defensive" - cost = 1 - -//THESE ARE NOT PURCHASABLE SPELLS! They're references to old spells that got removed + shit that sounds stupid but fun so we can painfully lock behind a dimmer component - -/datum/spellbook_entry/challenge - name = "Take the Challenge" - refundable = FALSE - category = "Challenges" - buy_word = "Accept" - -/datum/spellbook_entry/challenge/multiverse - name = "Multiverse Sword" - desc = "The Station gets a multiverse sword to stop you. Can you withstand the hordes of multiverse realities?" - -/datum/spellbook_entry/challenge/antiwizard - name = "Friendly Wizard Scum" - desc = "A \"Friendly\" Wizard will protect the station, and try to kill you. They get a spellbook much like you, but will use it for \"GOOD\"." - -/// How much threat we need to let these rituals happen on dynamic -#define MINIMUM_THREAT_FOR_RITUALS 100 - -/datum/spellbook_entry/summon - name = "Summon Stuff" - category = "Rituals" - limit = 1 - refundable = FALSE - buy_word = "Cast" - -/datum/spellbook_entry/summon/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) - log_spellbook("[key_name(user)] cast [src] for [cost] points") - SSblackbox.record_feedback("tally", "wizard_spell_learned", 1, name) - times++ - return TRUE - -/datum/spellbook_entry/summon/ghosts - name = "Summon Ghosts" - desc = "Spook the crew out by making them see dead people. Be warned, ghosts are capricious and occasionally vindicative, and some will use their incredibly minor abilities to frustrate you." - cost = 0 - -/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) - summon_ghosts(user) - playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, TRUE) - return ..() - -/datum/spellbook_entry/summon/guns - name = "Summon Guns" - desc = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill you. There is a good chance that they will shoot each other first." - -/datum/spellbook_entry/summon/guns/IsAvailable() - // Summon Guns requires 100 threat. - var/datum/game_mode/dynamic/mode = SSticker.mode - if(mode.threat_level < MINIMUM_THREAT_FOR_RITUALS) - return FALSE - // Also must be config enabled - return !CONFIG_GET(flag/no_summon_guns) - -/datum/spellbook_entry/summon/guns/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) - summon_guns(user, 10) - playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE) - return ..() - -/datum/spellbook_entry/summon/magic - name = "Summon Magic" - desc = "Share the wonders of magic with the crew and show them why they aren't to be trusted with it at the same time." - -/datum/spellbook_entry/summon/magic/IsAvailable() - // Summon Magic requires 100 threat. - var/datum/game_mode/dynamic/mode = SSticker.mode - if(mode.threat_level < MINIMUM_THREAT_FOR_RITUALS) - return FALSE - // Also must be config enabled - return !CONFIG_GET(flag/no_summon_magic) - -/datum/spellbook_entry/summon/magic/Buy(mob/living/carbon/human/user,obj/item/spellbook/book) - summon_magic(user, 10) - playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE) - return ..() - -/datum/spellbook_entry/summon/events - name = "Summon Events" - desc = "Give Murphy's law a little push and replace all events with special wizard ones that will confound and confuse everyone. Multiple castings increase the rate of these events." - cost = 2 - limit = 5 // Each purchase can intensify it. - -/datum/spellbook_entry/summon/events/IsAvailable() - // Summon Events requires 100 threat. - var/datum/game_mode/dynamic/mode = SSticker.mode - if(mode.threat_level < MINIMUM_THREAT_FOR_RITUALS) - return FALSE - // Also, must be config enabled - return !CONFIG_GET(flag/no_summon_events) - -/datum/spellbook_entry/summon/events/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) - summon_events(user) - playsound(get_turf(user), 'sound/magic/castsummon.ogg', 50, TRUE) - return ..() - -/datum/spellbook_entry/summon/events/GetInfo() - if(times > 0) - . += "You have cast it [times] time\s.
" - return . - -/datum/spellbook_entry/summon/curse_of_madness - name = "Curse of Madness" - desc = "Curses the station, warping the minds of everyone inside, causing lasting traumas. Warning: this spell can affect you if not cast from a safe distance." - cost = 4 - -/datum/spellbook_entry/summon/curse_of_madness/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) - var/message = tgui_input_text(user, "Whisper a secret truth to drive your victims to madness", "Whispers of Madness") - if(!message) - return FALSE - curse_of_madness(user, message) - playsound(user, 'sound/magic/mandswap.ogg', 50, TRUE) - return ..() - -#undef MINIMUM_THREAT_FOR_RITUALS - -/obj/item/spellbook - name = "spell book" - desc = "An unearthly tome that glows with power." - icon = 'icons/obj/library.dmi' - icon_state ="book" - worn_icon_state = "book" - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_TINY - var/uses = 10 - - /// The bonus that you get from going semi-random. - var/semi_random_bonus = 2 - - /// The bonus that you get from going full random. - var/full_random_bonus = 5 - - /// Determines if this spellbook can refund anything. - var/can_refund = TRUE - - /// The mind that first used the book. Automatically assigned when a wizard spawns. - var/datum/mind/owner - - var/list/entries = list() - -/obj/item/spellbook/examine(mob/user) - . = ..() - if(owner) - . += {"There is a small signature on the front cover: "[owner]"."} - else - . += "It appears to have no author." - -/obj/item/spellbook/Initialize(mapload) - . = ..() - prepare_spells() - RegisterSignal(src, COMSIG_ITEM_MAGICALLY_CHARGED, .proc/on_magic_charge) - -/** - * Signal proc for [COMSIG_ITEM_MAGICALLY_CHARGED] - * - * Has no effect on charge, but gives a funny message to people who think they're clever. - */ -/obj/item/spellbook/proc/on_magic_charge(datum/source, obj/effect/proc_holder/spell/targeted/charge/spell, mob/living/caster) - SIGNAL_HANDLER - - var/static/list/clever_girl = list( - "NICE TRY BUT NO!", - "CLEVER BUT NOT CLEVER ENOUGH!", - "SUCH FLAGRANT CHEESING IS WHY WE ACCEPTED YOUR APPLICATION!", - "CUTE! VERY CUTE!", - "YOU DIDN'T THINK IT'D BE THAT EASY, DID YOU?", - ) - - to_chat(caster, span_warning("Glowing red letters appear on the front cover...")) - to_chat(caster, span_red(pick(clever_girl))) - - return COMPONENT_ITEM_BURNT_OUT - -/obj/item/spellbook/attack_self(mob/user) - if(!owner) - if(!user.mind) - return - to_chat(user, span_notice("You bind the spellbook to yourself.")) - owner = user.mind - return - if(user.mind != owner) - if(user.mind.special_role == ROLE_WIZARD_APPRENTICE) - to_chat(user, "If you got caught sneaking a peek from your teacher's spellbook, you'd likely be expelled from the Wizard Academy. Better not.") - else - to_chat(user, span_warning("The [name] does not recognize you as its owner and refuses to open!")) - return - return ..() - -/obj/item/spellbook/attackby(obj/item/O, mob/user, params) - if(!can_refund) - to_chat(user, span_warning("You can't refund anything!")) - return - - if(istype(O, /obj/item/antag_spawner/contract)) - var/obj/item/antag_spawner/contract/contract = O - if(contract.used) - to_chat(user, span_warning("The contract has been used, you can't get your points back now!")) - else - to_chat(user, span_notice("You feed the contract back into the spellbook, refunding your points.")) - uses += 2 - for(var/datum/spellbook_entry/item/contract/CT in entries) - if(!isnull(CT.limit)) - CT.limit++ - qdel(O) - else if(istype(O, /obj/item/antag_spawner/slaughter_demon)) - to_chat(user, span_notice("On second thought, maybe summoning a demon is a bad idea. You refund your points.")) - if(istype(O, /obj/item/antag_spawner/slaughter_demon/laughter)) - uses += 1 - for(var/datum/spellbook_entry/item/hugbottle/HB in entries) - if(!isnull(HB.limit)) - HB.limit++ - else - uses += 2 - for(var/datum/spellbook_entry/item/bloodbottle/BB in entries) - if(!isnull(BB.limit)) - BB.limit++ - qdel(O) - -/obj/item/spellbook/proc/prepare_spells() - var/entry_types = subtypesof(/datum/spellbook_entry) - /datum/spellbook_entry/item - /datum/spellbook_entry/summon - /datum/spellbook_entry/challenge - for(var/type in entry_types) - var/datum/spellbook_entry/possible_entry = new type - if(possible_entry.IsAvailable()) - possible_entry.GetInfo() //loads up things for the entry that require checking spell instance. - entries |= possible_entry - else - qdel(possible_entry) - -/obj/item/spellbook/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "Spellbook") - ui.open() - -/obj/item/spellbook/ui_data(mob/user) - var/list/data = list() - data["owner"] = owner - data["points"] = uses - data["semi_random_bonus"] = initial(uses) + semi_random_bonus - data["full_random_bonus"] = initial(uses) + full_random_bonus - return data - -//This is a MASSIVE amount of data, please be careful if you remove it from static. -/obj/item/spellbook/ui_static_data(mob/user) - var/list/data = list() - var/list/entry_data = list() - for(var/datum/spellbook_entry/entry as anything in entries) - var/list/individual_entry_data = list() - individual_entry_data["name"] = entry.name - individual_entry_data["desc"] = entry.desc - individual_entry_data["ref"] = REF(entry) - individual_entry_data["clothes_req"] = entry.clothes_req - individual_entry_data["cost"] = entry.cost - individual_entry_data["times"] = entry.times - individual_entry_data["cooldown"] = entry.cooldown - individual_entry_data["cat"] = entry.category - individual_entry_data["refundable"] = entry.refundable - individual_entry_data["limit"] = entry.limit - individual_entry_data["buyword"] = entry.buy_word - entry_data += list(individual_entry_data) - data["entries"] = entry_data - return data - -/obj/item/spellbook/ui_act(action, params) - . = ..() - if(.) - return - var/mob/living/carbon/human/wizard = usr - if(!istype(wizard)) - to_chat(wizard, span_warning("The book doesn't seem to listen to lower life forms.")) - return - switch(action) - if("purchase") - var/datum/spellbook_entry/entry = locate(params["spellref"]) in entries - if(entry?.CanBuy(wizard,src)) - if(entry.Buy(wizard,src)) - if(entry.limit) - entry.limit-- - uses -= entry.cost - return TRUE - if("refund") - var/datum/spellbook_entry/entry = locate(params["spellref"]) in entries - if(entry?.refundable) - var/result = entry.Refund(wizard,src) - if(result > 0) - if(!isnull(entry.limit)) - entry.limit += result - uses += result - return TRUE - //actions that are only available if you have full spell points - if(uses < initial(uses)) - to_chat(wizard, span_warning("You need to have all your spell points to do this!")) - return - switch(action) - if("semirandomize") - semirandomize(wizard, semi_random_bonus) - update_static_data(wizard) //update statics! - if("randomize") - randomize(wizard, full_random_bonus) - update_static_data(wizard) //update statics! - if("purchase_loadout") - wizard_loadout(wizard, locate(params["id"])) - -/obj/item/spellbook/proc/wizard_loadout(mob/living/carbon/human/wizard, loadout) - var/list/wanted_spell_names - switch(loadout) - if(WIZARD_LOADOUT_CLASSIC) //(Fireball>2, MM>2, Smite>2, Jauntx2>4) = 10 - wanted_spell_names = list("Fireball" = 1, "Magic Missile" = 1, "Smite" = 1, "Ethereal Jaunt" = 2) - if(WIZARD_LOADOUT_MJOLNIR) //(Mjolnir>2, Summon Itemx3>3, Mutate>2, Force Wall>1, Blink>2) = 10 - wanted_spell_names = list("Mjolnir" = 1, "Summon Item" = 3, "Mutate" = 1, "Force Wall" = 1, "Blink" = 1) - if(WIZARD_LOADOUT_WIZARMY) //(Soulstones>2, Staff of Change>2, A Necromantic Stone>2, Teleport>2, Ethereal Jaunt>2) = 10 - wanted_spell_names = list("Soulstone Shard Kit" = 1, "Mjolnir" = 1, "A Necromantic Stone" = 1, "Teleport" = 1, "Ethereal Jaunt" = 1) //SKYRAT EDIT CHANGE - if(WIZARD_LOADOUT_SOULTAP) //(Soul Tap>1, Smite>2, Flesh to Stone>2, Mindswap>2, Knock>1, Teleport>2) = 10 - wanted_spell_names = list("Soul Tap" = 1, "Smite" = 1, "Flesh to Stone" = 1, "Mindswap" = 1, "Knock" = 1, "Teleport" = 1) - - for(var/datum/spellbook_entry/entry as anything in entries) - if(!(entry.name in wanted_spell_names)) - continue - if(entry.CanBuy(wizard,src)) - var/purchase_count = wanted_spell_names[entry.name] - wanted_spell_names -= entry.name - for(var/i in 1 to purchase_count) - entry.Buy(wizard,src) - if(entry.limit) - entry.limit-- - uses -= entry.cost - entry.refundable = FALSE //once you go loading out, you never go back - if(!length(wanted_spell_names)) - break - - if(length(wanted_spell_names)) - stack_trace("Wizard Loadout \"[loadout]\" could not find valid spells to buy in the spellbook. Either you input a name that doesn't exist, or you overspent") - if(uses) - stack_trace("Wizard Loadout \"[loadout]\" does not use 10 wizard spell slots. Stop scamming players out.") - -/obj/item/spellbook/proc/semirandomize(mob/living/carbon/human/wizard, bonus_to_give = 0) - var/list/needed_cats = list("Offensive", "Mobility") - var/list/shuffled_entries = shuffle(entries) - for(var/i in 1 to 2) - for(var/datum/spellbook_entry/entry as anything in shuffled_entries) - if(!(entry.category in needed_cats)) - continue - if(entry?.CanBuy(wizard,src)) - if(entry.Buy(wizard,src)) - needed_cats -= entry.category //so the next loop doesn't find another offense spell - entry.refundable = FALSE //once you go random, you never go back - if(entry.limit) - entry.limit-- - uses -= entry.cost - break - //we have given two specific category spells to the wizard. the rest are completely random! - randomize(wizard, bonus_to_give = bonus_to_give) - -/obj/item/spellbook/proc/randomize(mob/living/carbon/human/wizard, bonus_to_give = 0) - var/list/entries_copy = entries.Copy() - uses += bonus_to_give - while(uses > 0 && length(entries_copy)) - var/datum/spellbook_entry/entry = pick(entries_copy) - if(!entry?.CanBuy(wizard,src) || !entry.Buy(wizard,src)) - entries_copy -= entry - continue - - entry.refundable = FALSE //once you go random, you never go back - if(entry.limit) - entry.limit-- - uses -= entry.cost - - can_refund = FALSE diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm deleted file mode 100644 index f65b6885558..00000000000 --- a/code/modules/clothing/head/misc.dm +++ /dev/null @@ -1,551 +0,0 @@ - - -/obj/item/clothing/head/centhat - name = "\improper CentCom hat" - icon_state = "centcom" - desc = "It's good to be emperor." - inhand_icon_state = "that" - flags_inv = 0 - armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 40, BOMB = 25, BIO = 0, FIRE = 50, ACID = 50) - strip_delay = 80 - -/obj/item/clothing/head/spacepolice - name = "space police cap" - desc = "A blue cap for patrolling the daily beat." - icon_state = "policecap_families" - inhand_icon_state = "policecap_families" - -/obj/item/clothing/head/powdered_wig - name = "powdered wig" - desc = "A powdered wig." - icon_state = "pwig" - inhand_icon_state = "pwig" - -#define RABBIT_CD_TIME 30 SECONDS - -/obj/item/clothing/head/that - name = "top-hat" - desc = "It's an amish looking hat." - icon_state = "tophat" - inhand_icon_state = "that" - dog_fashion = /datum/dog_fashion/head - throwforce = 1 - /// Cooldown for how often we can pull rabbits out of here - COOLDOWN_DECLARE(rabbit_cooldown) - -/obj/item/clothing/head/that/attackby(obj/item/hitby_item, mob/user, params) - . = ..() - if(istype(hitby_item, /obj/item/gun/magic/wand)) - abracadabra(hitby_item, user) - -/obj/item/clothing/head/that/proc/abracadabra(obj/item/hitby_wand, mob/magician) - if(!COOLDOWN_FINISHED(src, rabbit_cooldown)) - to_chat(span_warning("You can't find another rabbit in [src]! Seems another hasn't gotten lost in there yet...")) - return - - COOLDOWN_START(src, rabbit_cooldown, RABBIT_CD_TIME) - playsound(get_turf(src), 'sound/weapons/emitter.ogg', 70) - do_smoke(range=1, location=src, smoke_type=/obj/effect/particle_effect/smoke/quick) - - if(prob(10)) - magician.visible_message(span_danger("[magician] taps [src] with [hitby_wand], then reaches in and pulls out a bu- wait, those are bees!"), span_danger("You tap [src] with your [hitby_wand.name] and pull out... BEES!")) - var/wait_how_many_bees_did_that_guy_pull_out_of_his_hat = rand(4, 8) - for(var/b in 1 to wait_how_many_bees_did_that_guy_pull_out_of_his_hat) - var/mob/living/simple_animal/hostile/bee/barry = new(get_turf(magician)) - barry.GiveTarget(magician) - if(prob(20)) - barry.say(pick("BUZZ BUZZ", "PULLING A RABBIT OUT OF A HAT IS A TIRED TROPE", "I DIDN'T ASK TO BEE HERE"), forced = "bee hat") - else - magician.visible_message(span_notice("[magician] taps [src] with [hitby_wand], then reaches in and pulls out a bunny! Cute!"), span_notice("You tap [src] with your [hitby_wand.name] and pull out a cute bunny!")) - var/mob/living/simple_animal/rabbit/empty/bunbun = new(get_turf(magician)) - bunbun.mob_try_pickup(magician, instant=TRUE) - -#undef RABBIT_CD_TIME - -/obj/item/clothing/head/canada - name = "striped red tophat" - desc = "It smells like fresh donut holes. / Il sent comme des trous de beignets frais." - icon_state = "canada" - inhand_icon_state = "canada" - -/obj/item/clothing/head/redcoat - name = "redcoat's hat" - icon_state = "redcoat" - desc = "'I guess it's a redhead.'" - -/obj/item/clothing/head/mailman - name = "mailman's hat" - icon_state = "mailman" - desc = "'Right-on-time' mail service head wear." - -/obj/item/clothing/head/plaguedoctorhat - name = "plague doctor's hat" - desc = "These were once used by plague doctors. They're pretty much useless." - icon_state = "plaguedoctor" - permeability_coefficient = 0.01 - -/obj/item/clothing/head/hasturhood - name = "hastur's hood" - desc = "It's unspeakably stylish." - icon_state = "hasturhood" - flags_inv = HIDEHAIR - flags_cover = HEADCOVERSEYES - -/obj/item/clothing/head/nursehat - name = "nurse's hat" - desc = "It allows quick identification of trained medical personnel." - icon_state = "nursehat" - dynamic_hair_suffix = "" - - dog_fashion = /datum/dog_fashion/head/nurse - -/obj/item/clothing/head/syndicatefake - name = "black space-helmet replica" - icon_state = "syndicate-helm-black-red" - inhand_icon_state = "syndicate-helm-black-red" - desc = "A plastic replica of a Syndicate agent's space helmet. You'll look just like a real murderous Syndicate agent in this! This is a toy, it is not made for use in space!" - clothing_flags = SNUG_FIT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - -/obj/item/clothing/head/cueball - name = "cueball helmet" - desc = "A large, featureless white orb meant to be worn on your head. How do you even see out of this thing?" - icon_state = "cueball" - inhand_icon_state="cueball" - clothing_flags = SNUG_FIT - flags_cover = HEADCOVERSEYES|HEADCOVERSMOUTH - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - -/obj/item/clothing/head/snowman - name = "snowman head" - desc = "A ball of white styrofoam. So festive." - icon_state = "snowman_h" - inhand_icon_state = "snowman_h" - clothing_flags = SNUG_FIT - flags_cover = HEADCOVERSEYES - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - -/obj/item/clothing/head/justice - name = "justice hat" - desc = "Fight for what's righteous!" - icon_state = "justicered" - inhand_icon_state = "justicered" - clothing_flags = SNUG_FIT - flags_inv = HIDEHAIR|HIDEEARS|HIDEEYES|HIDEFACE|HIDEFACIALHAIR|HIDESNOUT - flags_cover = HEADCOVERSEYES - -/obj/item/clothing/head/justice/blue - icon_state = "justiceblue" - inhand_icon_state = "justiceblue" - -/obj/item/clothing/head/justice/yellow - icon_state = "justiceyellow" - inhand_icon_state = "justiceyellow" - -/obj/item/clothing/head/justice/green - icon_state = "justicegreen" - inhand_icon_state = "justicegreen" - -/obj/item/clothing/head/justice/pink - icon_state = "justicepink" - inhand_icon_state = "justicepink" - -/obj/item/clothing/head/rabbitears - name = "rabbit ears" - desc = "Wearing these makes you look useless, and only good for your sex appeal." - icon_state = "bunny" - dynamic_hair_suffix = "" - - dog_fashion = /datum/dog_fashion/head/rabbit - -/obj/item/clothing/head/pirate - name = "pirate hat" - desc = "Yarr." - icon_state = "pirate" - inhand_icon_state = "pirate" - dog_fashion = /datum/dog_fashion/head/pirate - -/obj/item/clothing/head/pirate - var/datum/language/piratespeak/L = new - -/obj/item/clothing/head/pirate/equipped(mob/user, slot) - . = ..() - if(!ishuman(user)) - return - if(slot == ITEM_SLOT_HEAD) - user.grant_language(/datum/language/piratespeak/, TRUE, TRUE, LANGUAGE_HAT) - to_chat(user, span_boldnotice("You suddenly know how to speak like a pirate!")) - -/obj/item/clothing/head/pirate/dropped(mob/user) - . = ..() - if(!ishuman(user)) - return - var/mob/living/carbon/human/H = user - if(H.get_item_by_slot(ITEM_SLOT_HEAD) == src && !QDELETED(src)) //This can be called as a part of destroy - user.remove_language(/datum/language/piratespeak/, TRUE, TRUE, LANGUAGE_HAT) - to_chat(user, span_boldnotice("You can no longer speak like a pirate.")) - -/obj/item/clothing/head/pirate/armored - armor = list(MELEE = 30, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, FIRE = 60, ACID = 75) - strip_delay = 40 - equip_delay_other = 20 - -/obj/item/clothing/head/pirate/captain - name = "pirate captain hat" - icon_state = "hgpiratecap" - inhand_icon_state = "hgpiratecap" - -/obj/item/clothing/head/bandana - name = "pirate bandana" - desc = "Yarr." - icon_state = "bandana" - inhand_icon_state = "bandana" - dynamic_hair_suffix = "" - -/obj/item/clothing/head/bandana/armored - armor = list(MELEE = 30, BULLET = 50, LASER = 30,ENERGY = 40, BOMB = 30, BIO = 30, FIRE = 60, ACID = 75) - strip_delay = 40 - equip_delay_other = 20 - -/obj/item/clothing/head/bowler - name = "bowler-hat" - desc = "Gentleman, elite aboard!" - icon_state = "bowler" - inhand_icon_state = "bowler" - dynamic_hair_suffix = "" - -/obj/item/clothing/head/witchwig - name = "witch costume wig" - desc = "Eeeee~heheheheheheh!" - icon_state = "witch" - inhand_icon_state = "witch" - flags_inv = HIDEHAIR - -/obj/item/clothing/head/chicken - name = "chicken suit head" - desc = "Bkaw!" - icon_state = "chickenhead" - inhand_icon_state = "chickensuit" - clothing_flags = SNUG_FIT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - -/obj/item/clothing/head/griffin - name = "griffon head" - desc = "Why not 'eagle head'? Who knows." - icon_state = "griffinhat" - inhand_icon_state = "griffinhat" - clothing_flags = SNUG_FIT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - -/obj/item/clothing/head/bearpelt - name = "bear pelt hat" - desc = "Fuzzy." - icon_state = "bearpelt" - inhand_icon_state = "bearpelt" - -/obj/item/clothing/head/xenos - name = "xenos helmet" - icon_state = "xenos" - inhand_icon_state = "xenos_helm" - desc = "A helmet made out of chitinous alien hide." - clothing_flags = SNUG_FIT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - flags_cover = HEADCOVERSEYES | HEADCOVERSMOUTH - -/obj/item/clothing/head/fedora - name = "fedora" - icon_state = "fedora" - inhand_icon_state = "fedora" - desc = "A really cool hat if you're a mobster. A really lame hat if you're not." - pocket_storage_component_path = /datum/component/storage/concrete/pockets/small/fedora - -/obj/item/clothing/head/fedora/white - name = "white fedora" - icon_state = "fedora_white" - inhand_icon_state = "fedora_white" - -/obj/item/clothing/head/fedora/beige - name = "beige fedora" - icon_state = "fedora_beige" - inhand_icon_state = "fedora_beige" - -/obj/item/clothing/head/fedora/suicide_act(mob/user) - if(user.gender == FEMALE) - return 0 - var/mob/living/carbon/human/H = user - user.visible_message(span_suicide("[user] is donning [src]! It looks like [user.p_theyre()] trying to be nice to girls.")) - user.say("M'lady.", forced = "fedora suicide") - sleep(10) - H.facial_hairstyle = "Neckbeard" - return(BRUTELOSS) - -/obj/item/clothing/head/sombrero - name = "sombrero" - icon_state = "sombrero" - inhand_icon_state = "sombrero" - desc = "You can practically taste the fiesta." - flags_inv = HIDEHAIR - - dog_fashion = /datum/dog_fashion/head/sombrero - - greyscale_config = /datum/greyscale_config/sombrero - greyscale_config_worn = /datum/greyscale_config/sombrero/worn - greyscale_config_inhand_left = /datum/greyscale_config/sombrero/lefthand - greyscale_config_inhand_right = /datum/greyscale_config/sombrero/righthand - -/obj/item/clothing/head/sombrero/green - name = "green sombrero" - desc = "As elegant as a dancing cactus." - flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS - dog_fashion = null - greyscale_colors = "#13d968#ffffff" - flags_1 = IS_PLAYER_COLORABLE_1 - -/obj/item/clothing/head/sombrero/shamebrero - name = "shamebrero" - icon_state = "shamebrero" - inhand_icon_state = "shamebrero" - desc = "Once it's on, it never comes off." - dog_fashion = null - greyscale_colors = "#d565d3#f8db18" - flags_1 = IS_PLAYER_COLORABLE_1 - -/obj/item/clothing/head/sombrero/shamebrero/Initialize() - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, SHAMEBRERO_TRAIT) - -/obj/item/clothing/head/flatcap - name = "flat cap" - desc = "A working man's cap." - icon_state = "beret_flat" - greyscale_config = /datum/greyscale_config/beret - greyscale_config_worn = /datum/greyscale_config/beret/worn - greyscale_colors = "#8F7654" - inhand_icon_state = "detective" - -/obj/item/clothing/head/hunter - name = "bounty hunting hat" - desc = "Ain't nobody gonna cheat the hangman in my town." - icon_state = "cowboy" - worn_icon_state = "hunter" - inhand_icon_state = "hunter" - armor = list(MELEE = 5, BULLET = 5, LASER = 5, ENERGY = 15, BOMB = 0, BIO = 0, FIRE = 0, ACID = 0) - resistance_flags = FIRE_PROOF | ACID_PROOF - -/obj/item/clothing/head/cone - desc = "This cone is trying to warn you of something!" - name = "warning cone" - icon = 'icons/obj/janitor.dmi' - icon_state = "cone" - inhand_icon_state = "cone" - force = 1 - throwforce = 3 - throw_speed = 2 - throw_range = 5 - w_class = WEIGHT_CLASS_SMALL - attack_verb_continuous = list("warns", "cautions", "smashes") - attack_verb_simple = list("warn", "caution", "smash") - resistance_flags = NONE - dynamic_hair_suffix = "" - -/obj/item/clothing/head/santa - name = "santa hat" - desc = "On the first day of christmas my employer gave to me!" - icon_state = "santahatnorm" - inhand_icon_state = "that" - cold_protection = HEAD - min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT - dog_fashion = /datum/dog_fashion/head/santa - -/obj/item/clothing/head/jester - name = "jester hat" - desc = "A hat with bells, to add some merriness to the suit." - icon_state = "jester_hat" - dynamic_hair_suffix = "" - -/obj/item/clothing/head/jester/alt - icon_state = "jester2" - -/obj/item/clothing/head/rice_hat - name = "rice hat" - desc = "Welcome to the rice fields, motherfucker." - icon_state = "rice_hat" - -/obj/item/clothing/head/lizard - name = "lizardskin cloche hat" - desc = "How many lizards died to make this hat? Not enough." - icon_state = "lizard" - -/obj/item/clothing/head/papersack - name = "paper sack hat" - desc = "A paper sack with crude holes cut out for eyes. Useful for hiding one's identity or ugliness." - icon_state = "papersack" - flags_inv = HIDEHAIR|HIDEFACE|HIDEEARS|HIDESNOUT - -/obj/item/clothing/head/papersack/smiley - name = "paper sack hat" - desc = "A paper sack with crude holes cut out for eyes and a sketchy smile drawn on the front. Not creepy at all." - icon_state = "papersack_smile" - -/obj/item/clothing/head/crown - name = "crown" - desc = "A crown fit for a king, a petty king maybe." - icon_state = "crown" - armor = list(MELEE = 15, BULLET = 0, LASER = 0,ENERGY = 10, BOMB = 0, BIO = 0, FIRE = 100, ACID = 50, WOUND = 5) - resistance_flags = FIRE_PROOF - dynamic_hair_suffix = "" - -/obj/item/clothing/head/crown/fancy - name = "magnificent crown" - desc = "A crown worn by only the highest emperors of the land space." - icon_state = "fancycrown" - -/obj/item/clothing/head/scarecrow_hat - name = "scarecrow hat" - desc = "A simple straw hat." - icon_state = "scarecrow_hat" - -/obj/item/clothing/head/lobsterhat - name = "foam lobster head" - desc = "When everything's going to crab, protecting your head is the best choice." - icon_state = "lobster_hat" - clothing_flags = SNUG_FIT - flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT - -/obj/item/clothing/head/drfreezehat - name = "doctor freeze's wig" - desc = "A cool wig for cool people." - icon_state = "drfreeze_hat" - flags_inv = HIDEHAIR - -/obj/item/clothing/head/pharaoh - name = "pharaoh hat" - desc = "Walk like an Egyptian." - icon_state = "pharoah_hat" - inhand_icon_state = "pharoah_hat" - -/obj/item/clothing/head/nemes - name = "headdress of Nemes" - desc = "Lavish space tomb not included." - icon_state = "nemes_headdress" - -/obj/item/clothing/head/delinquent - name = "delinquent hat" - desc = "Good grief." - icon_state = "delinquent" - -/obj/item/clothing/head/frenchberet - name = "french beret" - desc = "A quality beret, infused with the aroma of chain-smoking, wine-swilling Parisians. You feel less inclined to engage in military conflict, for some reason." - icon_state = "beret" - greyscale_config = /datum/greyscale_config/beret - greyscale_config_worn = /datum/greyscale_config/beret/worn - greyscale_colors = "#972A2A" - dynamic_hair_suffix = "" - -/obj/item/clothing/head/frenchberet/equipped(mob/M, slot) - . = ..() - if (slot == ITEM_SLOT_HEAD) - RegisterSignal(M, COMSIG_MOB_SAY, .proc/handle_speech) - else - UnregisterSignal(M, COMSIG_MOB_SAY) - -/obj/item/clothing/head/frenchberet/dropped(mob/M) - . = ..() - UnregisterSignal(M, COMSIG_MOB_SAY) - -/obj/item/clothing/head/frenchberet/proc/handle_speech(datum/source, mob/speech_args) - SIGNAL_HANDLER - var/message = speech_args[SPEECH_MESSAGE] - if(message[1] != "*") - message = " [message]" - var/list/french_words = strings("french_replacement.json", "french") - - for(var/key in french_words) - var/value = french_words[key] - if(islist(value)) - value = pick(value) - - message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]") - message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]") - message = replacetextEx(message, " [key]", " [value]") - - if(prob(3)) - message += pick(" Honh honh honh!"," Honh!"," Zut Alors!") - speech_args[SPEECH_MESSAGE] = trim(message) - -/obj/item/clothing/head/clownmitre - name = "Hat of the Honkmother" - desc = "It's hard for parishoners to see a banana peel on the floor when they're looking up at your glorious chapeau." - icon_state = "clownmitre" - -/obj/item/clothing/head/kippah - name = "kippah" - desc = "Signals that you follow the Jewish Halakha. Keeps the head covered and the soul extra-Orthodox." - icon_state = "kippah" - -/obj/item/clothing/head/medievaljewhat - name = "medieval Jewish hat" - desc = "A silly looking hat, intended to be placed on the heads of the station's oppressed religious minorities." - icon_state = "medievaljewhat" - -/obj/item/clothing/head/taqiyahwhite - name = "white taqiyah" - desc = "An extra-mustahabb way of showing your devotion to Allah." - icon_state = "taqiyahwhite" - pocket_storage_component_path = /datum/component/storage/concrete/pockets/small - -/obj/item/clothing/head/taqiyahred - name = "red taqiyah" - desc = "An extra-mustahabb way of showing your devotion to Allah." - icon_state = "taqiyahred" - pocket_storage_component_path = /datum/component/storage/concrete/pockets/small - -/obj/item/clothing/head/shrine_wig - name = "shrine maiden's wig" - desc = "Purify in style!" - flags_inv = HIDEHAIR //bald - icon_state = "shrine_wig" - inhand_icon_state = "shrine_wig" - dynamic_hair_suffix = "" - worn_y_offset = 1 - -/obj/item/clothing/head/intern - name = "\improper CentCom Head Intern beancap" - desc = "A horrifying mix of beanie and softcap in CentCom green. You'd have to be pretty desperate for power over your peers to agree to wear this." - icon_state = "intern_hat" - inhand_icon_state = "intern_hat" - -/obj/item/clothing/head/coordinator - name = "coordinator cap" - desc = "A cap for a party coordinator, stylish!." - icon_state = "capcap" - inhand_icon_state = "that" - armor = list(MELEE = 25, BULLET = 15, LASER = 25, ENERGY = 35, BOMB = 25, BIO = 0, FIRE = 50, ACID = 50) - -/obj/item/clothing/head/jackbros - name = "frosty hat" - desc = "Hee-ho!" - icon_state = "JackFrostHat" - inhand_icon_state = "JackFrostHat" - -/obj/item/clothing/head/weddingveil - name = "wedding veil" - desc = "A gauzy white veil." - icon_state = "weddingveil" - inhand_icon_state = "weddingveil" - -/obj/item/clothing/head/centcom_cap - name = "\improper CentCom commander cap" - icon_state = "centcom_cap" - desc = "Worn by the finest of CentCom commanders. Inside the lining of the cap, lies two faint initials." - inhand_icon_state = "that" - flags_inv = 0 - armor = list(MELEE = 30, BULLET = 15, LASER = 30, ENERGY = 40, BOMB = 25, BIO = 0, FIRE = 50, ACID = 50) - strip_delay = (8 SECONDS) - -/obj/item/clothing/head/human_leather - name = "human skin hat" - desc = "This will scare them. All will know my power." - icon_state = "human_leather" - inhand_icon_state = "human_leather" diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm deleted file mode 100644 index 76287dfaa78..00000000000 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ /dev/null @@ -1,626 +0,0 @@ -/obj/item/clothing/shoes/sneakers/mime - name = "mime shoes" - greyscale_colors = "#ffffff#ffffff" - -/obj/item/clothing/shoes/combat //basic syndicate combat boots for nuke ops and mob corpses - name = "combat boots" - desc = "High speed, low drag combat boots." - icon_state = "jackboots" - inhand_icon_state = "jackboots" - lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - armor = list(MELEE = 25, BULLET = 25, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 10, FIRE = 70, ACID = 50) - strip_delay = 40 - resistance_flags = NONE - permeability_coefficient = 0.05 //Thick soles, and covers the ankle - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - lace_time = 12 SECONDS - -/obj/item/clothing/shoes/combat/sneakboots - name = "sneakboots" - desc = "These boots have special noise cancelling soles. Perfect for stealth, if it wasn't for the color scheme." - icon_state = "sneakboots" - inhand_icon_state = "sneakboots" - w_class = WEIGHT_CLASS_SMALL - resistance_flags = FIRE_PROOF | ACID_PROOF - clothing_traits = list(TRAIT_SILENT_FOOTSTEPS) - -/obj/item/clothing/shoes/combat/swat //overpowered boots for death squads - name = "\improper SWAT boots" - desc = "High speed, no drag combat boots." - permeability_coefficient = 0.01 - clothing_flags = NOSLIP - armor = list(MELEE = 40, BULLET = 30, LASER = 25, ENERGY = 25, BOMB = 50, BIO = 30, FIRE = 90, ACID = 50) - -/obj/item/clothing/shoes/sandal - desc = "A pair of rather plain wooden sandals." - name = "sandals" - icon_state = "wizard" - custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 0.5) - strip_delay = 5 - equip_delay_other = 50 - permeability_coefficient = 0.9 - can_be_tied = TRUE //SKYRAT EDIT - species_exception = list(/datum/species/golem) - -/obj/item/clothing/shoes/sneakers/marisa - desc = "A pair of magic black shoes." - name = "magic shoes" - worn_icon_state = "marisa" - greyscale_colors = "#545454#ffffff" - greyscale_config = /datum/greyscale_config/sneakers_marisa - greyscale_config_worn = null - strip_delay = 5 - equip_delay_other = 50 - permeability_coefficient = 0.9 - can_be_tied = FALSE - resistance_flags = FIRE_PROOF | ACID_PROOF - -/obj/item/clothing/shoes/sandal/magic - name = "magical sandals" - desc = "A pair of sandals imbued with magic." - resistance_flags = FIRE_PROOF | ACID_PROOF - -/obj/item/clothing/shoes/galoshes - desc = "A pair of yellow rubber boots, designed to prevent slipping on wet surfaces." - name = "galoshes" - icon_state = "galoshes" - permeability_coefficient = 0.01 - clothing_flags = NOSLIP - slowdown = SHOES_SLOWDOWN+1 - strip_delay = 30 - equip_delay_other = 50 - resistance_flags = NONE - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 40, ACID = 75) - can_be_bloody = FALSE - custom_price = PAYCHECK_EASY * 3 - can_be_tied = FALSE - -/obj/item/clothing/shoes/galoshes/dry - name = "absorbent galoshes" - desc = "A pair of purple rubber boots, designed to prevent slipping on wet surfaces while also drying them." - icon_state = "galoshes_dry" - -/obj/item/clothing/shoes/galoshes/dry/Initialize() - . = ..() - RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/on_step) - -/obj/item/clothing/shoes/galoshes/dry/proc/on_step() - SIGNAL_HANDLER - - var/turf/open/t_loc = get_turf(src) - SEND_SIGNAL(t_loc, COMSIG_TURF_MAKE_DRY, TURF_WET_WATER, TRUE, INFINITY) - -/obj/item/clothing/shoes/clown_shoes - desc = "The prankster's standard-issue clowning shoes. Damn, they're huge! Ctrl-click to toggle waddle dampeners." - name = "clown shoes" - icon_state = "clown" - inhand_icon_state = "clown_shoes" - slowdown = SHOES_SLOWDOWN+1 - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes/clown - var/enabled_waddle = TRUE - lace_time = 20 SECONDS // how the hell do these laces even work?? - species_exception = list(/datum/species/golem/bananium) - -/obj/item/clothing/shoes/clown_shoes/Initialize() - . = ..() - LoadComponent(/datum/component/squeak, list('sound/effects/clownstep1.ogg'=1,'sound/effects/clownstep2.ogg'=1), 50, falloff_exponent = 20) //die off quick please - //AddElement(/datum/element/swabable, CELL_LINE_TABLE_CLOWN, CELL_VIRUS_TABLE_GENERIC, rand(2,3), 0) SKYRAT EDIT REMOVAL - -/obj/item/clothing/shoes/clown_shoes/equipped(mob/user, slot) - . = ..() - if(slot == ITEM_SLOT_FEET) - if(enabled_waddle) - user.AddElement(/datum/element/waddling) - if(is_clown_job(user.mind?.assigned_role)) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "clownshoes", /datum/mood_event/clownshoes) - -/obj/item/clothing/shoes/clown_shoes/dropped(mob/user) - . = ..() - user.RemoveElement(/datum/element/waddling) - if(is_clown_job(user.mind?.assigned_role)) - SEND_SIGNAL(user, COMSIG_CLEAR_MOOD_EVENT, "clownshoes") - -/obj/item/clothing/shoes/clown_shoes/CtrlClick(mob/living/user) - if(!isliving(user)) - return - if(user.get_active_held_item() != src) - to_chat(user, span_warning("You must hold the [src] in your hand to do this!")) - return - if (!enabled_waddle) - to_chat(user, span_notice("You switch off the waddle dampeners!")) - enabled_waddle = TRUE - else - to_chat(user, span_notice("You switch on the waddle dampeners!")) - enabled_waddle = FALSE - -/obj/item/clothing/shoes/clown_shoes/jester - name = "jester shoes" - desc = "A court jester's shoes, updated with modern squeaking technology." - icon_state = "jester_shoes" - -/obj/item/clothing/shoes/jackboots - name = "jackboots" - desc = "Nanotrasen-issue Security combat boots for combat scenarios or combat situations. All combat, all the time." - icon_state = "jackboots" - inhand_icon_state = "jackboots" - lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - strip_delay = 30 - equip_delay_other = 50 - resistance_flags = NONE - permeability_coefficient = 0.05 //Thick soles, and covers the ankle - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - can_be_tied = TRUE //SKYRAT EDIT - -/obj/item/clothing/shoes/jackboots/fast - slowdown = -1 - -/obj/item/clothing/shoes/winterboots - name = "winter boots" - desc = "Boots lined with 'synthetic' animal fur." - icon_state = "winterboots" - inhand_icon_state = "winterboots" - permeability_coefficient = 0.15 - cold_protection = FEET|LEGS - min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET|LEGS - max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - lace_time = 8 SECONDS - -/obj/item/clothing/shoes/winterboots/ice_boots - name = "ice hiking boots" - desc = "A pair of winter boots with special grips on the bottom, designed to prevent slipping on frozen surfaces." - icon_state = "iceboots" - inhand_icon_state = "iceboots" - clothing_flags = NOSLIP_ICE - -/obj/item/clothing/shoes/workboots - name = "work boots" - desc = "Nanotrasen-issue Engineering lace-up work boots for the especially blue-collar." - icon_state = "workboots" - inhand_icon_state = "jackboots" - lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - permeability_coefficient = 0.15 - strip_delay = 20 - equip_delay_other = 40 - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - lace_time = 8 SECONDS - species_exception = list(/datum/species/golem/uranium) - -/obj/item/clothing/shoes/workboots/mining - name = "mining boots" - desc = "Steel-toed mining boots for mining in hazardous environments. Very good at keeping toes uncrushed." - icon_state = "explorer" - resistance_flags = FIRE_PROOF - -/obj/item/clothing/shoes/cult - name = "\improper Nar'Sien invoker boots" - desc = "A pair of boots worn by the followers of Nar'Sie." - icon_state = "cult" - inhand_icon_state = "cult" - cold_protection = FEET - min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET - max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT - lace_time = 10 SECONDS - -/obj/item/clothing/shoes/cult/alt - name = "cultist boots" - icon_state = "cultalt" - -/obj/item/clothing/shoes/cult/alt/ghost - item_flags = DROPDEL - -/obj/item/clothing/shoes/cult/alt/ghost/Initialize() - . = ..() - ADD_TRAIT(src, TRAIT_NODROP, CULT_TRAIT) - -/obj/item/clothing/shoes/sneakers/cyborg - name = "cyborg boots" - desc = "Shoes for a cyborg costume." - greyscale_colors = "#4e4e4e#4e4e4e" - -/obj/item/clothing/shoes/laceup - name = "laceup shoes" - desc = "The height of fashion, and they're pre-polished!" - icon_state = "laceups" - equip_delay_other = 50 - -/obj/item/clothing/shoes/roman - name = "roman sandals" - desc = "Sandals with buckled leather straps on it." - icon_state = "roman" - inhand_icon_state = "roman" - strip_delay = 100 - equip_delay_other = 100 - permeability_coefficient = 0.9 - can_be_tied = FALSE - -/obj/item/clothing/shoes/griffin - name = "griffon boots" - desc = "A pair of costume boots fashioned after bird talons." - icon_state = "griffinboots" - inhand_icon_state = "griffinboots" - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - lace_time = 8 SECONDS - -/obj/item/clothing/shoes/bhop - name = "jump boots" - desc = "A specialized pair of combat boots with a built-in propulsion system for rapid foward movement." - icon_state = "jetboots" - inhand_icon_state = "jetboots" - resistance_flags = FIRE_PROOF - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - actions_types = list(/datum/action/item_action/bhop) - permeability_coefficient = 0.05 - strip_delay = 30 - var/jumpdistance = 5 //-1 from to see the actual distance, e.g 4 goes over 3 tiles - var/jumpspeed = 3 - var/recharging_rate = 60 //default 6 seconds between each dash - var/recharging_time = 0 //time until next dash - -/obj/item/clothing/shoes/bhop/ui_action_click(mob/user, action) - if(!isliving(user)) - return - - if(recharging_time > world.time) - to_chat(user, span_warning("The boot's internal propulsion needs to recharge still!")) - return - - var/atom/target = get_edge_target_turf(user, user.dir) //gets the user's direction - - if (user.throw_at(target, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE)) - playsound(src, 'sound/effects/stealthoff.ogg', 50, TRUE, TRUE) - user.visible_message(span_warning("[usr] dashes forward into the air!")) - recharging_time = world.time + recharging_rate - else - to_chat(user, span_warning("Something prevents you from dashing forward!")) - -/obj/item/clothing/shoes/bhop/rocket - name = "rocket boots" - desc = "Very special boots with built-in rocket thrusters! SHAZBOT!" - icon_state = "rocketboots" - inhand_icon_state = "rocketboots" - actions_types = list(/datum/action/item_action/bhop/brocket) - jumpdistance = 20 //great for throwing yourself into walls and people at high speeds - jumpspeed = 5 - -/obj/item/clothing/shoes/singery - name = "yellow performer's boots" - desc = "These boots were made for dancing." - icon_state = "ysing" - equip_delay_other = 50 - -/obj/item/clothing/shoes/singerb - name = "blue performer's boots" - desc = "These boots were made for dancing." - icon_state = "bsing" - equip_delay_other = 50 - -/obj/item/clothing/shoes/bronze - name = "bronze boots" - desc = "A giant, clunky pair of shoes crudely made out of bronze. Why would anyone wear these?" - icon = 'icons/obj/clothing/clockwork_garb.dmi' - icon_state = "clockwork_treads" - can_be_tied = FALSE - -/obj/item/clothing/shoes/bronze/Initialize() - . = ..() - AddComponent(/datum/component/squeak, list('sound/machines/clockcult/integration_cog_install.ogg' = 1, 'sound/magic/clockwork/fellowship_armory.ogg' = 1), 50, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) - -/obj/item/clothing/shoes/wheelys - name = "Wheely-Heels" - desc = "Uses patented retractable wheel technology. Never sacrifice speed for style - not that this provides much of either." //Thanks Fel - worn_icon_state = "wheelys" - greyscale_colors = "#545454#ffffff" - icon_state = "sneakers" - greyscale_config = /datum/greyscale_config/sneakers_wheelys - inhand_icon_state = "wheelys" - worn_icon = 'icons/mob/large-worn-icons/64x64/feet.dmi' - worn_x_dimension = 64 - worn_y_dimension = 64 - clothing_flags = LARGE_WORN_ICON - actions_types = list(/datum/action/item_action/wheelys) - ///False means wheels are not popped out - var/wheelToggle = FALSE - ///The vehicle associated with the shoes - var/obj/vehicle/ridden/scooter/skateboard/wheelys/wheels = /obj/vehicle/ridden/scooter/skateboard/wheelys - -/obj/item/clothing/shoes/wheelys/Initialize() - . = ..() - AddElement(/datum/element/update_icon_updates_onmob) - wheels = new wheels(null) - wheels.link_shoes(src) - -/obj/item/clothing/shoes/wheelys/ui_action_click(mob/user, action) - if(!isliving(user)) - return - if(!istype(user.get_item_by_slot(ITEM_SLOT_FEET), /obj/item/clothing/shoes/wheelys)) - to_chat(user, span_warning("You must be wearing the wheely-heels to use them!")) - return - if(!(wheels.is_occupant(user))) - wheelToggle = FALSE - if(wheelToggle) - wheels.unbuckle_mob(user) - wheelToggle = FALSE - return - wheels.forceMove(get_turf(user)) - wheels.buckle_mob(user) - wheelToggle = TRUE - -/obj/item/clothing/shoes/wheelys/dropped(mob/user) - if(wheelToggle) - wheels.unbuckle_mob(user) - wheelToggle = FALSE - ..() - -/obj/item/clothing/shoes/wheelys/proc/toggle_wheels(status) - if (status) - worn_icon_state = "[initial(worn_icon_state)]-on" - else - worn_icon_state = "[initial(worn_icon_state)]" - playsound(src, 'sound/weapons/tap.ogg', 10, TRUE) - update_appearance() - -/obj/item/clothing/shoes/wheelys/Destroy() - QDEL_NULL(wheels) - . = ..() - -/obj/item/clothing/shoes/wheelys/rollerskates - name = "roller skates" - desc = "An EightO brand pair of roller skates. The wheels are retractable, though're quite bulky to walk in." - icon_state = "rollerskates" - greyscale_colors = null - greyscale_config = null - worn_icon_state = "rollerskates" - slowdown = SHOES_SLOWDOWN+1 - wheels = /obj/vehicle/ridden/scooter/skateboard/wheelys/rollerskates - custom_premium_price = PAYCHECK_EASY * 5 - custom_price = PAYCHECK_EASY * 5 - -/obj/item/clothing/shoes/wheelys/skishoes - name = "ski shoes" - desc = "A pair of shoes equipped with foldable skis! Very handy to move in snowy environments unimpeded." - icon_state = "skishoes" - greyscale_colors = null - greyscale_config = null - worn_icon_state = "skishoes" - slowdown = SHOES_SLOWDOWN+1 - wheels = /obj/vehicle/ridden/scooter/skateboard/wheelys/skishoes - custom_premium_price = PAYCHECK_EASY * 1.6 - custom_price = PAYCHECK_EASY * 1.6 - -/obj/item/clothing/shoes/kindle_kicks - name = "Kindle Kicks" - desc = "They'll sure kindle something in you, and it's not childhood nostalgia..." - icon_state = "kindleKicks" - inhand_icon_state = "kindleKicks" - actions_types = list(/datum/action/item_action/kindle_kicks) - light_system = MOVABLE_LIGHT - light_range = 2 - light_power = 3 - light_on = FALSE - var/lightCycle = 0 - var/active = FALSE - - -/obj/item/clothing/shoes/kindle_kicks/ui_action_click(mob/user, action) - if(active) - return - active = TRUE - set_light_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255))) - set_light_on(active) - addtimer(CALLBACK(src, .proc/lightUp), 0.5 SECONDS) - -/obj/item/clothing/shoes/kindle_kicks/proc/lightUp(mob/user) - if(lightCycle < 15) - set_light_color(rgb(rand(0, 255), rand(0, 255), rand(0, 255))) - lightCycle++ - addtimer(CALLBACK(src, .proc/lightUp), 0.5 SECONDS) - else - lightCycle = 0 - active = FALSE - set_light_on(active) - -/obj/item/clothing/shoes/russian - name = "russian boots" - desc = "Comfy shoes." - icon_state = "rus_shoes" - inhand_icon_state = "rus_shoes" - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - lace_time = 8 SECONDS - -/obj/item/clothing/shoes/cowboy - name = "cowboy boots" - desc = "A small sticker lets you know they've been inspected for snakes, It is unclear how long ago the inspection took place..." - icon_state = "cowboy_brown" - permeability_coefficient = 0.05 //these are quite tall - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - custom_price = PAYCHECK_EASY - var/list/occupants = list() - var/max_occupants = 4 - can_be_tied = TRUE //SKYRAT EDIT - -/obj/item/clothing/shoes/cowboy/Initialize() - . = ..() - if(prob(2)) - var/mob/living/simple_animal/hostile/retaliate/snake/bootsnake = new/mob/living/simple_animal/hostile/retaliate/snake(src) - occupants += bootsnake - - -/obj/item/clothing/shoes/cowboy/equipped(mob/living/carbon/user, slot) - . = ..() - RegisterSignal(user, COMSIG_LIVING_SLAM_TABLE, .proc/table_slam) - if(slot == ITEM_SLOT_FEET) - for(var/mob/living/occupant in occupants) - occupant.forceMove(user.drop_location()) - user.visible_message(span_warning("[user] recoils as something slithers out of [src]."), span_userdanger("You feel a sudden stabbing pain in your [pick("foot", "toe", "ankle")]!")) - user.Knockdown(20) //Is one second paralyze better here? I feel you would fall on your ass in some fashion. - user.apply_damage(5, BRUTE, pick(BODY_ZONE_R_LEG, BODY_ZONE_L_LEG)) - if(istype(occupant, /mob/living/simple_animal/hostile/retaliate)) - user.reagents.add_reagent(/datum/reagent/toxin, 7) - occupants.Cut() - -/obj/item/clothing/shoes/cowboy/dropped(mob/living/user) - . = ..() - UnregisterSignal(user, COMSIG_LIVING_SLAM_TABLE) - -/obj/item/clothing/shoes/cowboy/proc/table_slam(mob/living/source, obj/structure/table/the_table) - SIGNAL_HANDLER - INVOKE_ASYNC(src, .proc/handle_table_slam, source) - -/obj/item/clothing/shoes/cowboy/proc/handle_table_slam(mob/living/user) - user.say(pick("Hot damn!", "Hoo-wee!", "Got-dang!"), spans = list(SPAN_YELL), forced=TRUE) - user.client?.give_award(/datum/award/achievement/misc/hot_damn, user) - -/obj/item/clothing/shoes/cowboy/MouseDrop_T(mob/living/target, mob/living/user) - . = ..() - if(!(user.mobility_flags & MOBILITY_USE) || user.stat != CONSCIOUS || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user) || !user.Adjacent(target) || target.stat == DEAD) - return - if(occupants.len >= max_occupants) - to_chat(user, span_warning("[src] are full!")) - return - if(istype(target, /mob/living/simple_animal/hostile/retaliate/snake) || istype(target, /mob/living/simple_animal/hostile/headcrab) || istype(target, /mob/living/carbon/alien/larva)) - occupants += target - target.forceMove(src) - to_chat(user, span_notice("[target] slithers into [src].")) - -/obj/item/clothing/shoes/cowboy/container_resist_act(mob/living/user) - if(!do_after(user, 10, target = user)) - return - user.forceMove(user.drop_location()) - occupants -= user - -/obj/item/clothing/shoes/cowboy/white - name = "white cowboy boots" - icon_state = "cowboy_white" - -/obj/item/clothing/shoes/cowboy/black - name = "black cowboy boots" - desc = "You get the feeling someone might have been hanged in these boots." - icon_state = "cowboy_black" - -/obj/item/clothing/shoes/cowboy/fancy - name = "bilton wrangler boots" - desc = "A pair of authentic haute couture boots from Japanifornia. You doubt they have ever been close to cattle." - icon_state = "cowboy_fancy" - permeability_coefficient = 0.08 - -/obj/item/clothing/shoes/cowboy/lizard - name = "lizard skin boots" - desc = "You can hear a faint hissing from inside the boots; you hope it is just a mournful ghost." - icon_state = "lizardboots_green" - armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, BIO = 0, FIRE = 40, ACID = 0) //lizards like to stay warm - -/obj/item/clothing/shoes/cowboy/lizard/masterwork - name = "\improper Hugs-The-Feet lizard skin boots" - desc = "A pair of masterfully crafted lizard skin boots. Finally a good application for the station's most bothersome inhabitants." - icon_state = "lizardboots_blue" - -/obj/effect/spawner/lootdrop/lizardboots - name = "random lizard boot quality" - desc = "Which ever gets picked, the lizard race loses" - icon = 'icons/obj/clothing/shoes.dmi' - icon_state = "lizardboots_green" - loot = list( - /obj/item/clothing/shoes/cowboy/lizard = 7, - /obj/item/clothing/shoes/cowboy/lizard/masterwork = 1) - -/obj/item/clothing/shoes/cookflops - desc = "All this talk of antags, greytiding, and griefing... I just wanna grill for god's sake!" - name = "grilling sandals" - icon_state = "cookflops" - can_be_tied = FALSE - species_exception = list(/datum/species/golem) - -/obj/item/clothing/shoes/yakuza - name = "tojo clan shoes" - desc = "Steel-toed and intimidating." - icon_state = "MajimaShoes" - inhand_icon_state = "MajimaShoes_worn" - -/obj/item/clothing/shoes/jackbros - name = "frosty boots" - desc = "For when you're stepping on up to the plate." - icon_state = "JackFrostShoes" - inhand_icon_state = "JackFrostShoes_worn" -/obj/item/clothing/shoes/swagshoes - name = "swag shoes" - desc = "They got me for my foams!" - icon_state = "SwagShoes" - inhand_icon_state = "SwagShoes" - -/obj/item/clothing/shoes/gunboots //admin boots that fire gunshots randomly while walking - name = "gunboots" - desc = "This is what all those research points added up to, the ultimate workplace hazard." - icon_state = "jackboots" - inhand_icon_state = "jackboots" - lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' - righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - pocket_storage_component_path = /datum/component/storage/concrete/pockets/shoes - /// What projectile do we shoot? - var/projectile_type = /obj/projectile/bullet/c10mm - /// Each step, this is the chance we fire a shot - var/shot_prob = 50 - -/obj/item/clothing/shoes/gunboots/Initialize() - . = ..() - RegisterSignal(src, COMSIG_SHOES_STEP_ACTION, .proc/check_step) - -/obj/item/clothing/shoes/gunboots/equipped(mob/user, slot) - . = ..() - if(slot == ITEM_SLOT_FEET) - RegisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, .proc/check_kick) - else - UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) - -/obj/item/clothing/shoes/gunboots/dropped(mob/user) - if(user) - UnregisterSignal(user, COMSIG_HUMAN_MELEE_UNARMED_ATTACK) - return ..() - -/// After each step, check if we randomly fire a shot -/obj/item/clothing/shoes/gunboots/proc/check_step(mob/user) - SIGNAL_HANDLER - if(!prob(shot_prob)) - return - - INVOKE_ASYNC(src, .proc/fire_shot) - -/// Stomping on someone while wearing gunboots shoots them point blank -/obj/item/clothing/shoes/gunboots/proc/check_kick(mob/living/carbon/human/kicking_person, atom/attacked_atom, proximity) - SIGNAL_HANDLER - if(!isliving(attacked_atom)) - return - var/mob/living/attacked_living = attacked_atom - if(attacked_living.body_position == LYING_DOWN) - INVOKE_ASYNC(src, .proc/fire_shot, attacked_living) - -/// Actually fire a shot. If no target is provided, just fire off in a random direction -/obj/item/clothing/shoes/gunboots/proc/fire_shot(atom/target) - if(!isliving(loc)) - return - - var/mob/living/wearer = loc - var/obj/projectile/shot = new projectile_type(get_turf(wearer)) - - if(!target) - target = get_offset_target_turf(get_turf(wearer), rand(-3, 3), rand(-3,3)) - - //Shooting Code: - shot.original = target - shot.fired_from = src - shot.firer = wearer // don't hit ourself that would be really annoying - shot.impacted = list(wearer = TRUE) - shot.def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) // they're fired from boots after all - shot.preparePixelProjectile(target, wearer) - if(!shot.suppressed) - wearer.visible_message(span_danger("[wearer]'s [name] fires \a [shot]!"), "", blind_message = span_hear("You hear a gunshot!"), vision_distance=COMBAT_MESSAGE_RANGE) - shot.fire() - -/obj/item/clothing/shoes/gunboots/disabler - name = "disaboots" - projectile_type = /obj/projectile/beam/disabler diff --git a/code/modules/detectivework/detective_work.dm b/code/modules/detectivework/detective_work.dm deleted file mode 100644 index dd8a15898bb..00000000000 --- a/code/modules/detectivework/detective_work.dm +++ /dev/null @@ -1,114 +0,0 @@ -//CONTAINS: Suit fibers and Detective's Scanning Computer - -/atom/proc/return_fingerprints() - var/datum/component/forensics/D = GetComponent(/datum/component/forensics) - if(D) - . = D.fingerprints - -/atom/proc/return_hiddenprints() - var/datum/component/forensics/D = GetComponent(/datum/component/forensics) - if(D) - . = D.hiddenprints - -/atom/proc/return_blood_DNA() - var/datum/component/forensics/D = GetComponent(/datum/component/forensics) - if(D) - . = D.blood_DNA - -/atom/proc/blood_DNA_length() - var/datum/component/forensics/D = GetComponent(/datum/component/forensics) - if(D) - . = length(D.blood_DNA) - -/atom/proc/return_fibers() - var/datum/component/forensics/D = GetComponent(/datum/component/forensics) - if(D) - . = D.fibers - -/atom/proc/add_fingerprint_list(list/fingerprints) //ASSOC LIST FINGERPRINT = FINGERPRINT - if(length(fingerprints)) - . = AddComponent(/datum/component/forensics, fingerprints) - -//Set ignoregloves to add prints irrespective of the mob having gloves on. -/atom/proc/add_fingerprint(mob/M, ignoregloves = FALSE) - if (QDELING(src)) - return - var/datum/component/forensics/D = AddComponent(/datum/component/forensics) - . = D?.add_fingerprint(M, ignoregloves) - -/atom/proc/add_fiber_list(list/fibertext) //ASSOC LIST FIBERTEXT = FIBERTEXT - if(length(fibertext)) - . = AddComponent(/datum/component/forensics, null, null, null, fibertext) - -/atom/proc/add_fibers(mob/living/carbon/human/M) - var/old = 0 - if(M.gloves && istype(M.gloves, /obj/item/clothing)) - var/obj/item/clothing/gloves/G = M.gloves - old = length(G.return_blood_DNA()) - if(G.transfer_blood > 1) //bloodied gloves transfer blood to touched objects - if(add_blood_DNA(G.return_blood_DNA()) && length(G.return_blood_DNA()) > old) //only reduces the bloodiness of our gloves if the item wasn't already bloody - G.transfer_blood-- - else if(M.blood_in_hands > 1) - old = length(M.return_blood_DNA()) - if(add_blood_DNA(M.return_blood_DNA()) && length(M.return_blood_DNA()) > old) - M.blood_in_hands-- - var/datum/component/forensics/D = AddComponent(/datum/component/forensics) - . = D.add_fibers(M) - -/atom/proc/add_hiddenprint_list(list/hiddenprints) //NOTE: THIS IS FOR ADMINISTRATION FINGERPRINTS, YOU MUST CUSTOM SET THIS TO INCLUDE CKEY/REAL NAMES! CHECK FORENSICS.DM - if(length(hiddenprints)) - . = AddComponent(/datum/component/forensics, null, hiddenprints) - -/atom/proc/add_hiddenprint(mob/M) - var/datum/component/forensics/D = AddComponent(/datum/component/forensics) - . = D.add_hiddenprint(M) - -/atom/proc/add_blood_DNA(list/dna) //ASSOC LIST DNA = BLOODTYPE - return FALSE - -/obj/add_blood_DNA(list/dna) - . = ..() - if(length(dna)) - . = AddComponent(/datum/component/forensics, null, null, dna) - -/obj/item/clothing/gloves/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - . = ..() - transfer_blood = rand(2, 4) - -/turf/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - var/obj/effect/decal/cleanable/blood/splatter/B = locate() in src - if(QDELETED(B)) // SKYRAT EDIT - SANITY CHECK; DONT ADD DNA TO A FUCKING DELETED BLOOD SPATTER - original: if(!B) - B = new /obj/effect/decal/cleanable/blood/splatter(src, diseases) - if(!QDELETED(B)) - B.add_blood_DNA(blood_dna) //give blood info to the blood decal. - return TRUE //we bloodied the floor - -/mob/living/carbon/human/add_blood_DNA(list/blood_dna, list/datum/disease/diseases) - if(wear_suit) - wear_suit.add_blood_DNA(blood_dna) - update_inv_wear_suit() - else if(w_uniform) - w_uniform.add_blood_DNA(blood_dna) - update_inv_w_uniform() - if(gloves) - var/obj/item/clothing/gloves/G = gloves - G.add_blood_DNA(blood_dna) - else if(length(blood_dna)) - AddComponent(/datum/component/forensics, null, null, blood_dna) - blood_in_hands = rand(2, 4) - update_inv_gloves() //handles bloody hands overlays and updating - return TRUE - -/* - * Transfer all the fingerprints and hidden prints from [src] to [transfer_to]. - */ -/atom/proc/transfer_fingerprints_to(atom/transfer_to) - transfer_to.add_fingerprint_list(return_fingerprints()) - transfer_to.add_hiddenprint_list(return_hiddenprints()) - transfer_to.fingerprintslast = fingerprintslast - -/* - * Transfer all the fibers from [src] to [transfer_to]. - */ -/atom/proc/transfer_fibers_to(atom/transfer_to) - transfer_to.add_fiber_list(return_fibers()) diff --git a/code/modules/events/spontaneous_appendicitis.dm b/code/modules/events/spontaneous_appendicitis.dm deleted file mode 100644 index c861541a91d..00000000000 --- a/code/modules/events/spontaneous_appendicitis.dm +++ /dev/null @@ -1,35 +0,0 @@ -/datum/round_event_control/spontaneous_appendicitis - name = "Spontaneous Appendicitis" - typepath = /datum/round_event/spontaneous_appendicitis - //weight = 20 //ORIGINAL - weight = 10 //SKYRAT EDIT CHANGE - max_occurrences = 4 - earliest_start = 10 MINUTES - min_players = 5 // To make your chance of getting help a bit higher. - -/datum/round_event/spontaneous_appendicitis - fakeable = FALSE - -/datum/round_event/spontaneous_appendicitis/start() - for(var/mob/living/carbon/human/H in shuffle(GLOB.alive_mob_list)) - if(!H.client) - continue - if(H.stat == DEAD) - continue - if(!H.getorgan(/obj/item/organ/internal/appendix)) //Don't give the disease to some who lacks it, only for it to be auto-cured - continue - if(!(H.mob_biotypes & MOB_ORGANIC)) //biotype sleeper bugs strike again, once again making appendicitis pick a target that can't take it - continue - if(H.z in SSmapping.levels_by_trait(ZTRAIT_CENTCOM))//not for admin/ooc stuff - continue - var/foundAlready = FALSE //don't infect someone that already has appendicitis - for(var/datum/disease/appendicitis/A in H.diseases) - foundAlready = TRUE - break - if(foundAlready) - continue - - var/datum/disease/D = new /datum/disease/appendicitis() - H.ForceContractDisease(D, FALSE, TRUE) - announce_to_ghosts(H) - break diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm deleted file mode 100644 index df757427903..00000000000 --- a/code/modules/flufftext/Hallucination.dm +++ /dev/null @@ -1,1633 +0,0 @@ -#define HAL_LINES_FILE "hallucination.json" - -GLOBAL_LIST_INIT(hallucination_list, list( - /datum/hallucination/chat = 100, - /datum/hallucination/message = 60, - /datum/hallucination/sounds = 50, - /datum/hallucination/battle = 20, - /datum/hallucination/dangerflash = 15, - /datum/hallucination/hudscrew = 12, - /datum/hallucination/fake_health_doll = 12, - /datum/hallucination/fake_alert = 12, - /datum/hallucination/weird_sounds = 8, - /datum/hallucination/stationmessage = 7, - /datum/hallucination/fake_flood = 7, - /datum/hallucination/stray_bullet = 7, - /datum/hallucination/bolts = 7, - /datum/hallucination/items_other = 7, - /datum/hallucination/husks = 7, - /datum/hallucination/items = 4, - /datum/hallucination/fire = 3, - /datum/hallucination/self_delusion = 2, - /datum/hallucination/delusion = 2, - /datum/hallucination/shock = 1, - /datum/hallucination/death = 1, - /datum/hallucination/oh_yeah = 1 - )) - - -/mob/living/carbon/proc/handle_hallucinations(delta_time, times_fired) - if(!hallucination) - return - - hallucination = max(hallucination - (0.5 * delta_time), 0) - if(world.time < next_hallucination) - return - - var/halpick = pick_weight(GLOB.hallucination_list) - new halpick(src, FALSE) - - next_hallucination = world.time + rand(100, 600) - -/mob/living/carbon/proc/set_screwyhud(hud_type) - hal_screwyhud = hud_type - update_health_hud() - -/datum/hallucination - var/natural = TRUE - var/mob/living/carbon/target - var/feedback_details //extra info for investigate - -/datum/hallucination/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - target = C - natural = !forced - - // Cancel early if the target is deleted - RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/target_deleting) - -/datum/hallucination/proc/target_deleting() - SIGNAL_HANDLER - - qdel(src) - -/datum/hallucination/proc/wake_and_restore() - target.set_screwyhud(SCREWYHUD_NONE) - target.SetSleeping(0) - -/datum/hallucination/Destroy() - target.investigate_log("was afflicted with a hallucination of type [type] by [natural?"hallucination status":"an external source"]. [feedback_details]", INVESTIGATE_HALLUCINATIONS) - - if (target) - UnregisterSignal(target, COMSIG_PARENT_QDELETING) - - target = null - return ..() - -//Returns a random turf in a ring around the target mob, useful for sound hallucinations -/datum/hallucination/proc/random_far_turf() - var/x_based = prob(50) - var/first_offset = pick(-8,-7,-6,-5,5,6,7,8) - var/second_offset = rand(-8,8) - var/x_off - var/y_off - if(x_based) - x_off = first_offset - y_off = second_offset - else - y_off = first_offset - x_off = second_offset - var/turf/T = locate(target.x + x_off, target.y + y_off, target.z) - return T - -/obj/effect/hallucination - invisibility = INVISIBILITY_OBSERVER - anchored = TRUE - var/mob/living/carbon/target = null - -/obj/effect/hallucination/simple - var/image_icon = 'icons/mob/alien.dmi' - var/image_state = "alienh_pounce" - var/px = 0 - var/py = 0 - var/col_mod = null - var/image/current_image = null - var/image_layer = MOB_LAYER - var/image_plane = GAME_PLANE - var/active = TRUE //qdelery - -/obj/effect/hallucination/singularity_pull() - return - -/obj/effect/hallucination/singularity_act() - return - -/obj/effect/hallucination/simple/Initialize(mapload, mob/living/carbon/T) - . = ..() - if(!T) - stack_trace("A hallucination was created with no target") - return INITIALIZE_HINT_QDEL - target = T - current_image = GetImage() - if(target.client) - target.client.images |= current_image - -/obj/effect/hallucination/simple/proc/GetImage() - var/image/I = image(image_icon,src,image_state,image_layer,dir=src.dir) - I.plane = image_plane - I.pixel_x = px - I.pixel_y = py - if(col_mod) - I.color = col_mod - return I - -/obj/effect/hallucination/simple/proc/Show(update=1) - if(active) - if(target.client) - target.client.images.Remove(current_image) - if(update) - current_image = GetImage() - if(target.client) - target.client.images |= current_image - -/obj/effect/hallucination/simple/update_icon(updates=ALL, new_state, new_icon, new_px=0, new_py=0) - image_state = new_state - if(new_icon) - image_icon = new_icon - else - image_icon = initial(image_icon) - px = new_px - py = new_py - . = ..() - Show() - -/obj/effect/hallucination/simple/Moved(atom/OldLoc, Dir) - . = ..() - if(!loc) - return - Show() - -/obj/effect/hallucination/simple/Destroy() - if(target.client) - target.client.images.Remove(current_image) - active = FALSE - return ..() - -#define FAKE_FLOOD_EXPAND_TIME 20 -#define FAKE_FLOOD_MAX_RADIUS 10 - -/obj/effect/plasma_image_holder - icon_state = "nothing" - anchored = TRUE - layer = FLY_LAYER - plane = ABOVE_GAME_PLANE - mouse_opacity = MOUSE_OPACITY_TRANSPARENT - -/datum/hallucination/fake_flood - //Plasma starts flooding from the nearby vent - var/turf/center - var/list/flood_images = list() - var/list/flood_image_holders = list() - var/list/turf/flood_turfs = list() - var/image_icon = 'icons/effects/atmospherics.dmi' - var/image_state = "plasma" - var/radius = 0 - var/next_expand = 0 - -/datum/hallucination/fake_flood/New(mob/living/carbon/C, forced = TRUE) - ..() - for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target)) - if(!U.welded) - center = get_turf(U) - break - if(!center) - qdel(src) - return - feedback_details += "Vent Coords: [center.x],[center.y],[center.z]" - var/obj/effect/plasma_image_holder/pih = new(center) - var/image/plasma_image = image(image_icon, pih, image_state, FLY_LAYER) - plasma_image.alpha = 50 - plasma_image.plane = ABOVE_GAME_PLANE - flood_images += plasma_image - flood_image_holders += pih - flood_turfs += center - if(target.client) - target.client.images |= flood_images - next_expand = world.time + FAKE_FLOOD_EXPAND_TIME - START_PROCESSING(SSobj, src) - -/datum/hallucination/fake_flood/process() - if(next_expand <= world.time) - radius++ - if(radius > FAKE_FLOOD_MAX_RADIUS) - qdel(src) - return - Expand() - if((get_turf(target) in flood_turfs) && !target.internal) - new /datum/hallucination/fake_alert(target, TRUE, ALERT_TOO_MUCH_PLASMA) - next_expand = world.time + FAKE_FLOOD_EXPAND_TIME - -/datum/hallucination/fake_flood/proc/Expand() - for(var/image/I in flood_images) - I.alpha = min(I.alpha + 50, 255) - for(var/turf/FT in flood_turfs) - for(var/dir in GLOB.cardinals) - var/turf/T = get_step(FT, dir) - if((T in flood_turfs) || !TURFS_CAN_SHARE(T, FT) || isspaceturf(T)) //If we've gottem already, or if they're not alright to spread with. - continue - var/obj/effect/plasma_image_holder/pih = new(T) - var/image/new_plasma = image(image_icon, pih, image_state, FLY_LAYER) - new_plasma.alpha = 50 - new_plasma.plane = ABOVE_GAME_PLANE - flood_images += new_plasma - flood_image_holders += pih - flood_turfs += T - if(target.client) - target.client.images |= flood_images - -/datum/hallucination/fake_flood/Destroy() - STOP_PROCESSING(SSobj, src) - qdel(flood_turfs) - flood_turfs = list() - if(target.client) - target.client.images.Remove(flood_images) - qdel(flood_images) - flood_images = list() - qdel(flood_image_holders) - flood_image_holders = list() - return ..() - -/obj/effect/hallucination/simple/xeno - image_icon = 'icons/mob/alien.dmi' - image_state = "alienh_pounce" - -/obj/effect/hallucination/simple/xeno/Initialize(mapload, mob/living/carbon/T) - . = ..() - name = "alien hunter ([rand(1, 1000)])" - -/obj/effect/hallucination/simple/xeno/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - update_icon(ALL, "alienh_pounce") - if(hit_atom == target && target.stat!=DEAD) - target.Paralyze(100) - target.visible_message(span_danger("[target] flails around wildly."),span_userdanger("[name] pounces on you!")) - -// The numbers of seconds it takes to get to each stage of the xeno attack choreography -#define XENO_ATTACK_STAGE_LEAP_AT_TARGET 1 -#define XENO_ATTACK_STAGE_LEAP_AT_PUMP 2 -#define XENO_ATTACK_STAGE_CLIMB 3 -#define XENO_ATTACK_STAGE_FINISH 6 - -/// Xeno crawls from nearby vent,jumps at you, and goes back in -/datum/hallucination/xeno_attack - var/turf/pump_location = null - var/obj/effect/hallucination/simple/xeno/xeno = null - var/time_processing = 0 - var/stage = XENO_ATTACK_STAGE_LEAP_AT_TARGET - -/datum/hallucination/xeno_attack/New(mob/living/carbon/C, forced = TRUE) - ..() - for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target)) - if(!U.welded) - pump_location = get_turf(U) - break - - if(pump_location) - feedback_details += "Vent Coords: [pump_location.x],[pump_location.y],[pump_location.z]" - xeno = new(pump_location, target) - START_PROCESSING(SSfastprocess, src) - else - qdel(src) - -/datum/hallucination/xeno_attack/process(delta_time) - time_processing += delta_time - - if (time_processing >= stage) - switch (time_processing) - if (XENO_ATTACK_STAGE_FINISH to INFINITY) - to_chat(target, span_notice("[xeno.name] scrambles into the ventilation ducts!")) - qdel(src) - if (XENO_ATTACK_STAGE_CLIMB to XENO_ATTACK_STAGE_FINISH) - to_chat(target, span_notice("[xeno.name] begins climbing into the ventilation system...")) - stage = XENO_ATTACK_STAGE_FINISH - if (XENO_ATTACK_STAGE_LEAP_AT_PUMP to XENO_ATTACK_STAGE_CLIMB) - xeno.update_icon(ALL, "alienh_leap", 'icons/mob/alienleap.dmi', -32, -32) - xeno.throw_at(pump_location, 7, 1, spin = FALSE, diagonals_first = TRUE) - stage = XENO_ATTACK_STAGE_CLIMB - if (XENO_ATTACK_STAGE_LEAP_AT_TARGET to XENO_ATTACK_STAGE_LEAP_AT_PUMP) - xeno.update_icon(ALL, "alienh_leap", 'icons/mob/alienleap.dmi', -32, -32) - xeno.throw_at(target, 7, 1, spin = FALSE, diagonals_first = TRUE) - stage = XENO_ATTACK_STAGE_LEAP_AT_PUMP - -/datum/hallucination/xeno_attack/Destroy() - . = ..() - - STOP_PROCESSING(SSfastprocess, src) - QDEL_NULL(xeno) - pump_location = null - -#undef XENO_ATTACK_STAGE_LEAP_AT_TARGET -#undef XENO_ATTACK_STAGE_LEAP_AT_PUMP -#undef XENO_ATTACK_STAGE_CLIMB -#undef XENO_ATTACK_STAGE_FINISH - -/obj/effect/hallucination/simple/clown - image_icon = 'icons/mob/animal.dmi' - image_state = "clown" - -/obj/effect/hallucination/simple/clown/Initialize(mapload, mob/living/carbon/T, duration) - ..(loc, T) - name = pick(GLOB.clown_names) - QDEL_IN(src,duration) - -/obj/effect/hallucination/simple/clown/scary - image_state = "scary_clown" - -/obj/effect/hallucination/simple/bubblegum - name = "Bubblegum" - image_icon = 'icons/mob/lavaland/96x96megafauna.dmi' - image_state = "bubblegum" - px = -32 - -/datum/hallucination/oh_yeah - var/obj/effect/hallucination/simple/bubblegum/bubblegum - var/image/fakebroken - var/image/fakerune - var/turf/landing - var/charged - var/next_action = 0 - -/datum/hallucination/oh_yeah/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - . = ..() - var/turf/closed/wall/wall - for(var/turf/closed/wall/W in range(7,target)) - wall = W - break - if(!wall) - return INITIALIZE_HINT_QDEL - feedback_details += "Source: [wall.x],[wall.y],[wall.z]" - - fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER) - landing = get_turf(target) - var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3 - fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER) - fakebroken.override = TRUE - if(target.client) - target.client.images |= fakebroken - target.client.images |= fakerune - target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1) - bubblegum = new(wall, target) - addtimer(CALLBACK(src, .proc/start_processing), 10) - -/datum/hallucination/oh_yeah/proc/start_processing() - if (isnull(target)) - qdel(src) - return - START_PROCESSING(SSfastprocess, src) - -/datum/hallucination/oh_yeah/process(delta_time) - next_action -= delta_time - - if (next_action > 0) - return - - if (get_turf(bubblegum) != landing && target?.stat != DEAD) - if(!landing || (get_turf(bubblegum)).loc.z != landing.loc.z) - qdel(src) - return - bubblegum.forceMove(get_step_towards(bubblegum, landing)) - bubblegum.setDir(get_dir(bubblegum, landing)) - target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1) - shake_camera(target, 2, 1) - if(bubblegum.Adjacent(target) && !charged) - charged = TRUE - target.Paralyze(80) - target.adjustStaminaLoss(40) - step_away(target, bubblegum) - shake_camera(target, 4, 3) - target.visible_message(span_warning("[target] jumps backwards, falling on the ground!"),span_userdanger("[bubblegum] slams into you!")) - next_action = 0.2 - else - STOP_PROCESSING(SSfastprocess, src) - QDEL_IN(src, 3 SECONDS) - -/datum/hallucination/oh_yeah/Destroy() - if(target.client) - target.client.images.Remove(fakebroken) - target.client.images.Remove(fakerune) - QDEL_NULL(fakebroken) - QDEL_NULL(fakerune) - QDEL_NULL(bubblegum) - STOP_PROCESSING(SSfastprocess, src) - return ..() - -/datum/hallucination/battle - var/battle_type - var/iterations_left - var/hits = 0 - var/next_action = 0 - var/turf/source - -/datum/hallucination/battle/New(mob/living/carbon/C, forced = TRUE, new_battle_type) - ..() - - source = random_far_turf() - - battle_type = new_battle_type - if (isnull(battle_type)) - battle_type = pick("laser", "disabler", "esword", "gun", "stunprod", "harmbaton", "bomb") - feedback_details += "Type: [battle_type]" - var/process = TRUE - - switch(battle_type) - if("disabler", "laser") - iterations_left = rand(5, 10) - if("esword") - iterations_left = rand(4, 8) - target.playsound_local(source, 'sound/weapons/saberon.ogg',15, 1) - if("gun") - iterations_left = rand(3, 6) - if("stunprod") //Stunprod + cablecuff - process = FALSE - target.playsound_local(source, 'sound/weapons/egloves.ogg', 40, 1) - target.playsound_local(source, get_sfx(SFX_BODYFALL), 25, 1) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/weapons/cablecuff.ogg', 15, 1), 20) - if("harmbaton") //zap n slap - iterations_left = rand(5, 12) - target.playsound_local(source, 'sound/weapons/egloves.ogg', 40, 1) - target.playsound_local(source, get_sfx(SFX_BODYFALL), 25, 1) - next_action = 2 SECONDS - if("bomb") // Tick Tock - iterations_left = rand(3, 11) - - if (process) - START_PROCESSING(SSfastprocess, src) - else - qdel(src) - -/datum/hallucination/battle/process(delta_time) - next_action -= (delta_time * 10) - - if (next_action > 0) - return - - switch (battle_type) - if ("disabler", "laser", "gun") - var/fire_sound - var/hit_person_sound - var/hit_wall_sound - var/number_of_hits - var/chance_to_fall - - switch (battle_type) - if ("disabler") - fire_sound = 'sound/weapons/taser2.ogg' - hit_person_sound = 'sound/weapons/tap.ogg' - hit_wall_sound = 'sound/weapons/effects/searwall.ogg' - number_of_hits = 3 - chance_to_fall = 70 - if ("laser") - fire_sound = 'sound/weapons/laser.ogg' - hit_person_sound = 'sound/weapons/sear.ogg' - hit_wall_sound = 'sound/weapons/effects/searwall.ogg' - number_of_hits = 4 - chance_to_fall = 70 - if ("gun") - fire_sound = 'sound/weapons/gun/shotgun/shot.ogg' - hit_person_sound = 'sound/weapons/pierce.ogg' - hit_wall_sound = SFX_RICOCHET - number_of_hits = 2 - chance_to_fall = 80 - - target.playsound_local(source, fire_sound, 25, 1) - - if(prob(50)) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, hit_person_sound, 25, 1), rand(5,10)) - hits += 1 - else - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, hit_wall_sound, 25, 1), rand(5,10)) - - next_action = rand(CLICK_CD_RANGE, CLICK_CD_RANGE + 6) - - if(hits >= number_of_hits && prob(chance_to_fall)) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, get_sfx(SFX_BODYFALL), 25, 1), next_action) - qdel(src) - return - if ("esword") - target.playsound_local(source, 'sound/weapons/blade1.ogg', 50, 1) - - if (hits == 4) - target.playsound_local(source, get_sfx(SFX_BODYFALL), 25, 1) - - next_action = rand(CLICK_CD_MELEE, CLICK_CD_MELEE + 6) - hits += 1 - - if (iterations_left == 1) - target.playsound_local(source, 'sound/weapons/saberoff.ogg', 15, 1) - if ("harmbaton") - target.playsound_local(source, SFX_SWING_HIT, 50, 1) - next_action = rand(CLICK_CD_MELEE, CLICK_CD_MELEE + 4) - if ("bomb") - target.playsound_local(source, 'sound/items/timer.ogg', 25, 0) - next_action = 15 - - iterations_left -= 1 - if (iterations_left == 0) - qdel(src) - -/datum/hallucination/battle/Destroy() - . = ..() - source = null - STOP_PROCESSING(SSfastprocess, src) - -/datum/hallucination/items_other - -/datum/hallucination/items_other/New(mob/living/carbon/C, forced = TRUE, item_type) - set waitfor = FALSE - ..() - var/item - if(!item_type) - item = pick(list("esword","taser","ebow","baton","dual_esword","ttv","flash","armblade")) - else - item = item_type - feedback_details += "Item: [item]" - var/side - var/image_file - var/image/A = null - var/list/mob_pool = list() - - for(var/mob/living/carbon/human/M in view(7,target)) - if(M != target) - mob_pool += M - if(!mob_pool.len) - return - - var/mob/living/carbon/human/H = pick(mob_pool) - feedback_details += " Mob: [H.real_name]" - - var/free_hand = H.get_empty_held_index_for_side(LEFT_HANDS) - if(free_hand) - side = "left" - else - free_hand = H.get_empty_held_index_for_side(RIGHT_HANDS) - if(free_hand) - side = "right" - - if(side) - switch(item) - if("esword") - if(side == "right") - image_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - else - image_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - target.playsound_local(H, 'sound/weapons/saberon.ogg',35,1) - A = image(image_file,H,"e_sword_on_red", layer=ABOVE_MOB_LAYER) - if("dual_esword") - if(side == "right") - image_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' - else - image_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' - target.playsound_local(H, 'sound/weapons/saberon.ogg',35,1) - A = image(image_file,H,"dualsaberred1", layer=ABOVE_MOB_LAYER) - if("taser") - if(side == "right") - image_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' - else - image_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - A = image(image_file,H,"advtaserstun4", layer=ABOVE_MOB_LAYER) - if("ebow") - if(side == "right") - image_file = 'icons/mob/inhands/weapons/guns_righthand.dmi' - else - image_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi' - A = image(image_file,H,"crossbow", layer=ABOVE_MOB_LAYER) - if("baton") - if(side == "right") - image_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - else - image_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' - target.playsound_local(H, SFX_SPARKS,75,1,-1) - A = image(image_file,H,"baton", layer=ABOVE_MOB_LAYER) - if("ttv") - if(side == "right") - image_file = 'icons/mob/inhands/weapons/bombs_righthand.dmi' - else - image_file = 'icons/mob/inhands/weapons/bombs_lefthand.dmi' - A = image(image_file,H,"ttv", layer=ABOVE_MOB_LAYER) - if("flash") - if(side == "right") - image_file = 'icons/mob/inhands/equipment/security_righthand.dmi' - else - image_file = 'icons/mob/inhands/equipment/security_lefthand.dmi' - A = image(image_file,H,"flashtool", layer=ABOVE_MOB_LAYER) - if("armblade") - if(side == "right") - image_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' - else - image_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi' - target.playsound_local(H, 'sound/effects/blobattack.ogg',30,1) - A = image(image_file,H,"arm_blade", layer=ABOVE_MOB_LAYER) - if(target.client) - target.client.images |= A - addtimer(CALLBACK(src, .proc/cleanup, item, A, H), rand(15 SECONDS, 25 SECONDS)) - return - qdel(src) - -/datum/hallucination/items_other/proc/cleanup(item, atom/image_used, has_the_item) - if (isnull(target)) - qdel(src) - return - if(item == "esword" || item == "dual_esword") - target.playsound_local(has_the_item, 'sound/weapons/saberoff.ogg',35,1) - if(item == "armblade") - target.playsound_local(has_the_item, 'sound/effects/blobattack.ogg',30,1) - target.client.images.Remove(image_used) - qdel(src) - -/datum/hallucination/delusion - var/list/image/delusions = list() - -/datum/hallucination/delusion/New(mob/living/carbon/C, forced, force_kind = null , duration = 300,skip_nearby = TRUE, custom_icon = null, custom_icon_file = null, custom_name = null) - set waitfor = FALSE - . = ..() - var/image/A = null - var/kind = force_kind ? force_kind : pick("nothing","monkey","corgi","carp","skeleton","demon","zombie") - feedback_details += "Type: [kind]" - var/list/nearby - if(skip_nearby) - nearby = get_hearers_in_view(7, target) - for(var/mob/living/carbon/human/H in GLOB.alive_mob_list) - if(H == target) - continue - if(skip_nearby && (H in nearby)) - continue - switch(kind) - if("nothing") - A = image('icons/effects/effects.dmi',H,"nothing") - A.name = "..." - if("monkey")//Monkey - A = image('icons/mob/human.dmi',H,"monkey") - A.name = "Monkey ([rand(1,999)])" - if("carp")//Carp - A = image('icons/mob/carp.dmi',H,"carp") - A.name = "Space Carp" - if("corgi")//Corgi - A = image('icons/mob/pets.dmi',H,"corgi") - A.name = "Corgi" - if("skeleton")//Skeletons - A = image('icons/mob/human.dmi',H,"skeleton") - A.name = "Skeleton" - if("zombie")//Zombies - A = image('icons/mob/human.dmi',H,"zombie") - A.name = "Zombie" - if("demon")//Demon - A = image('icons/mob/mob.dmi',H,"daemon") - A.name = "Demon" - if("custom") - A = image(custom_icon_file, H, custom_icon) - A.name = custom_name - A.override = 1 - if(target.client) - delusions |= A - target.client.images |= A - if(duration) - QDEL_IN(src, duration) - -/datum/hallucination/delusion/Destroy() - for(var/image/I in delusions) - if(target.client) - target.client.images.Remove(I) - return ..() - -/datum/hallucination/self_delusion - var/image/delusion - -/datum/hallucination/self_delusion/New(mob/living/carbon/C, forced, force_kind = null , duration = 300, custom_icon = null, custom_icon_file = null, wabbajack = TRUE) //set wabbajack to false if you want to use another fake source - set waitfor = FALSE - ..() - var/image/A = null - var/kind = force_kind ? force_kind : pick("monkey","corgi","carp","skeleton","demon","zombie","robot") - feedback_details += "Type: [kind]" - switch(kind) - if("monkey")//Monkey - A = image('icons/mob/human.dmi',target,"monkey") - if("carp")//Carp - A = image('icons/mob/animal.dmi',target,"carp") - if("corgi")//Corgi - A = image('icons/mob/pets.dmi',target,"corgi") - if("skeleton")//Skeletons - A = image('icons/mob/human.dmi',target,"skeleton") - if("zombie")//Zombies - A = image('icons/mob/human.dmi',target,"zombie") - if("demon")//Demon - A = image('icons/mob/mob.dmi',target,"daemon") - if("robot")//Cyborg - A = image('icons/mob/robots.dmi',target,"robot") - target.playsound_local(target,'sound/voice/liveagain.ogg', 75, 1) - if("custom") - A = image(custom_icon_file, target, custom_icon) - A.override = 1 - if(target.client) - if(wabbajack) - to_chat(target, span_hear("...wabbajack...wabbajack...")) - target.playsound_local(target,'sound/magic/staff_change.ogg', 50, 1) - delusion = A - target.client.images |= A - QDEL_IN(src, duration) - -/datum/hallucination/self_delusion/Destroy() - if(target.client) - target.client.images.Remove(delusion) - return ..() - -/datum/hallucination/bolts - var/list/airlocks_to_hit - var/list/locks - var/next_action = 0 - var/locking = TRUE - -/datum/hallucination/bolts/New(mob/living/carbon/C, forced, door_number) - set waitfor = FALSE - ..() - if(!door_number) - door_number = rand(0,4) //if 0 bolts all visible doors - var/count = 0 - feedback_details += "Door amount: [door_number]" - - for(var/obj/machinery/door/airlock/A in range(7, target)) - if(count>door_number && door_number>0) - break - if(!A.density) - continue - count++ - LAZYADD(airlocks_to_hit, A) - - if(!LAZYLEN(airlocks_to_hit)) //no valid airlocks in sight - qdel(src) - return - - START_PROCESSING(SSfastprocess, src) - -/datum/hallucination/bolts/process(delta_time) - next_action -= (delta_time * 10) - if (next_action > 0) - return - - if (locking) - var/atom/next_airlock = pop(airlocks_to_hit) - if (next_airlock) - var/obj/effect/hallucination/fake_door_lock/lock = new(get_turf(next_airlock)) - lock.target = target - lock.airlock = next_airlock - LAZYADD(locks, lock) - - if (!LAZYLEN(airlocks_to_hit)) - locking = FALSE - next_action = 10 SECONDS - return - else - var/obj/effect/hallucination/fake_door_lock/next_unlock = popleft(locks) - if (next_unlock) - next_unlock.unlock() - else - qdel(src) - return - - next_action = rand(4, 12) - -/datum/hallucination/bolts/Destroy() - . = ..() - QDEL_LIST(locks) - STOP_PROCESSING(SSfastprocess, src) - -/obj/effect/hallucination/fake_door_lock - layer = CLOSED_DOOR_LAYER + 1 //for Bump priority - plane = GAME_PLANE - var/image/bolt_light - var/obj/machinery/door/airlock/airlock - -/obj/effect/hallucination/fake_door_lock/proc/lock() - bolt_light = image(airlock.overlays_file, get_turf(airlock), "lights_bolts",layer=airlock.layer+0.1) - if(target.client) - target.client.images |= bolt_light - target.playsound_local(get_turf(airlock), 'sound/machines/boltsdown.ogg',30,0,3) - -/obj/effect/hallucination/fake_door_lock/proc/unlock() - if(target.client) - target.client.images.Remove(bolt_light) - target.playsound_local(get_turf(airlock), 'sound/machines/boltsup.ogg',30,0,3) - qdel(src) - -/obj/effect/hallucination/fake_door_lock/CanAllowThrough(atom/movable/mover, border_dir) - . = ..() - if(mover == target && airlock.density) - return FALSE - -/datum/hallucination/chat - -/datum/hallucination/chat/New(mob/living/carbon/C, forced = TRUE, force_radio, specific_message) - set waitfor = FALSE - ..() - var/target_name = target.first_name() - var/speak_messages = list("[pick_list_replacements(HAL_LINES_FILE, "suspicion")]",\ - "[pick_list_replacements(HAL_LINES_FILE, "conversation")]",\ - "[pick_list_replacements(HAL_LINES_FILE, "greetings")][target.first_name()]!",\ - "[pick_list_replacements(HAL_LINES_FILE, "getout")]",\ - "[pick_list_replacements(HAL_LINES_FILE, "weird")]",\ - "[pick_list_replacements(HAL_LINES_FILE, "didyouhearthat")]",\ - "[pick_list_replacements(HAL_LINES_FILE, "doubt")]",\ - "[pick_list_replacements(HAL_LINES_FILE, "aggressive")]",\ - "[pick_list_replacements(HAL_LINES_FILE, "help")]!!",\ - "[pick_list_replacements(HAL_LINES_FILE, "escape")]",\ - "I'm infected, [pick_list_replacements(HAL_LINES_FILE, "infection_advice")]!") - - var/radio_messages = list("[pick_list_replacements(HAL_LINES_FILE, "people")] is [pick_list_replacements(HAL_LINES_FILE, "accusations")]!",\ - "Help!",\ - "[pick_list_replacements(HAL_LINES_FILE, "threat")] in [pick_list_replacements(HAL_LINES_FILE, "location")][prob(50)?"!":"!!"]",\ - "[pick("Where's [target.first_name()]?", "Set [target.first_name()] to arrest!")]",\ - "[pick("C","Ai, c","Someone c","Rec")]all the shuttle!",\ - "AI [pick("rogue", "is dead")]!!") - - var/mob/living/carbon/person = null - var/datum/language/understood_language = target.get_random_understood_language() - for(var/mob/living/carbon/H in view(target)) - if(H == target) - continue - if(!person) - person = H - else - if(get_dist(target,H)[other] puts the [pick(\ - "revolver","energy sword","cryptographic sequencer","power sink","energy bow",\ - "hybrid taser","stun baton","flash","syringe gun","circular saw","tank transfer valve",\ - "ritual dagger","spellbook",\ - "Codex Cicatrix", "Living Heart",\ - "pulse rifle","captain's spare ID","hand teleporter","hypospray","antique laser gun","X-01 MultiPhase Energy Gun","station's blueprints"\ - )] into [equipped_backpack].") - - message_pool.Add("[other] [pick("sneezes","coughs")].") - - message_pool.Add(span_notice("You hear something squeezing through the ducts..."), \ - span_notice("Your [pick("arm", "leg", "back", "head")] itches."),\ - span_warning("You feel [pick("hot","cold","dry","wet","woozy","faint")]."), - span_warning("Your stomach rumbles."), - span_warning("Your head hurts."), - span_warning("You hear a faint buzz in your head."), - "[target] sneezes.") - if(prob(10)) - message_pool.Add(span_warning("Behind you."),\ - span_warning("You hear a faint laughter."), - span_warning("You see something move."), - span_warning("You hear skittering on the ceiling."), - span_warning("You see an inhumanly tall silhouette moving in the distance.")) - if(prob(10)) - message_pool.Add("[pick_list_replacements(HAL_LINES_FILE, "advice")]") - var/chosen = pick(message_pool) - feedback_details += "Message: [chosen]" - to_chat(target, chosen) - qdel(src) - -/datum/hallucination/sounds - -/datum/hallucination/sounds/New(mob/living/carbon/C, forced = TRUE, sound_type) - set waitfor = FALSE - ..() - var/turf/source = random_far_turf() - if(!sound_type) - sound_type = pick("airlock","airlock pry","console","explosion","far explosion","mech","glass","alarm","beepsky","mech","wall decon","door hack") - feedback_details += "Type: [sound_type]" - //Strange audio - switch(sound_type) - if("airlock") - target.playsound_local(source,'sound/machines/airlock.ogg', 30, 1) - if("airlock pry") - target.playsound_local(source,'sound/machines/airlock_alien_prying.ogg', 100, 1) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/machines/airlockforced.ogg', 30, 1), 50) - if("console") - target.playsound_local(source,'sound/machines/terminal_prompt.ogg', 25, 1) - if("explosion") - if(prob(50)) - target.playsound_local(source,'sound/effects/explosion1.ogg', 50, 1) - else - target.playsound_local(source, 'sound/effects/explosion2.ogg', 50, 1) - if("far explosion") - target.playsound_local(source, 'sound/effects/explosionfar.ogg', 50, 1) - if("glass") - target.playsound_local(source, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1) - if("alarm") - target.playsound_local(source, 'sound/machines/alarm.ogg', 100, 0) - if("beepsky") - target.playsound_local(source, 'sound/voice/beepsky/freeze.ogg', 35, 0) - if("mech") - new /datum/hallucination/mech_sounds(C, forced, sound_type) - //Deconstructing a wall - if("wall decon") - target.playsound_local(source, 'sound/items/welder.ogg', 50, 1) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/items/welder2.ogg', 50, 1), 105) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/items/ratchet.ogg', 50, 1), 120) - //Hacking a door - if("door hack") - target.playsound_local(source, 'sound/items/screwdriver.ogg', 50, 1) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/machines/airlockforced.ogg', 30, 1), rand(40, 80)) - qdel(src) - -/datum/hallucination/mech_sounds - var/mech_dir - var/steps_left - var/next_action = 0 - var/turf/source - -/datum/hallucination/mech_sounds/New() - . = ..() - mech_dir = pick(GLOB.cardinals) - steps_left = rand(4, 9) - source = random_far_turf() - START_PROCESSING(SSfastprocess, src) - -/datum/hallucination/mech_sounds/process(delta_time) - next_action -= delta_time - if (next_action > 0) - return - - if(prob(75)) - target.playsound_local(source, 'sound/mecha/mechstep.ogg', 40, 1) - source = get_step(source, mech_dir) - else - target.playsound_local(source, 'sound/mecha/mechturn.ogg', 40, 1) - mech_dir = pick(GLOB.cardinals) - - steps_left -= 1 - if (!steps_left) - qdel(src) - return - next_action = 1 - -/datum/hallucination/mech_sounds/Destroy() - . = ..() - STOP_PROCESSING(SSfastprocess, src) - -/datum/hallucination/weird_sounds - -/datum/hallucination/weird_sounds/New(mob/living/carbon/C, forced = TRUE, sound_type) - set waitfor = FALSE - ..() - var/turf/source = random_far_turf() - if(!sound_type) - sound_type = pick("phone","hallelujah","highlander","laughter","hyperspace","game over","creepy","tesla") - feedback_details += "Type: [sound_type]" - //Strange audio - switch(sound_type) - if("phone") - target.playsound_local(source, 'sound/weapons/ring.ogg', 15) - for (var/next_rings in 1 to 3) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/weapons/ring.ogg', 15), 25 * next_rings) - if("hyperspace") - target.playsound_local(null, 'sound/runtime/hyperspace/hyperspace_begin.ogg', 50) - if("hallelujah") - target.playsound_local(source, 'sound/effects/pray_chaplain.ogg', 50) - if("highlander") - target.playsound_local(null, 'sound/misc/highlander.ogg', 50) - if("game over") - target.playsound_local(source, 'sound/misc/compiler-failure.ogg', 50) - if("laughter") - if(prob(50)) - target.playsound_local(source, 'sound/voice/human/womanlaugh.ogg', 50, 1) - else - target.playsound_local(source, pick('sound/voice/human/manlaugh1.ogg', 'sound/voice/human/manlaugh2.ogg'), 50, 1) - if("creepy") - //These sounds are (mostly) taken from Hidden: Source - target.playsound_local(source, pick(GLOB.creepy_ambience), 50, 1) - if("tesla") //Tesla loose! - target.playsound_local(source, 'sound/magic/lightningbolt.ogg', 35, 1) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/magic/lightningbolt.ogg', 65, 1), 30) - addtimer(CALLBACK(target, /mob/.proc/playsound_local, source, 'sound/magic/lightningbolt.ogg', 100, 1), 60) - - qdel(src) - -/datum/hallucination/stationmessage - -/datum/hallucination/stationmessage/New(mob/living/carbon/C, forced = TRUE, message) - set waitfor = FALSE - ..() - if(!message) - message = pick("ratvar","shuttle dock","blob alert","malf ai","meteors","supermatter") - feedback_details += "Type: [message]" - switch(message) - if("blob alert") - to_chat(target, "

Biohazard Alert

") - to_chat(target, "

[span_alert("Confirmed outbreak of level 5 biohazard aboard [station_name()]. All personnel must contain the outbreak.")]

") - SEND_SOUND(target, SSstation.announcer.event_sounds[ANNOUNCER_OUTBREAK5]) - if("ratvar") - target.playsound_local(target, 'sound/machines/clockcult/ark_deathrattle.ogg', 50, FALSE, pressure_affected = FALSE) - target.playsound_local(target, 'sound/effects/clockcult_gateway_disrupted.ogg', 50, FALSE, pressure_affected = FALSE) - addtimer(CALLBACK( - target, - /mob/.proc/playsound_local, - target, - 'sound/effects/explosion_distant.ogg', - 50, - FALSE, - /* frequency = */ null, - /* falloff_exponential = */ null, - /* channel = */ null, - /* pressure_affected = */ FALSE - ), 27) - if("shuttle dock") - to_chat(target, "

Priority Announcement

") - to_chat(target, "

[span_alert("The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.")]

") - SEND_SOUND(target, SSstation.announcer.event_sounds[ANNOUNCER_SHUTTLEDOCK]) - if("malf ai") //AI is doomsdaying! - to_chat(target, "

Anomaly Alert

") - to_chat(target, "

[span_alert("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.")]

") - SEND_SOUND(target, SSstation.announcer.event_sounds[ANNOUNCER_AIMALF]) - if("meteors") //Meteors inbound! - to_chat(target, "

Meteor Alert

") - to_chat(target, "

[span_alert("Meteors have been detected on collision course with the station.")]

") - SEND_SOUND(target, SSstation.announcer.event_sounds[ANNOUNCER_METEORS]) - if("supermatter") - SEND_SOUND(target, 'sound/magic/charge.ogg') - to_chat(target, span_boldannounce("You feel reality distort for a moment...")) - -/datum/hallucination/hudscrew - -/datum/hallucination/hudscrew/New(mob/living/carbon/C, forced = TRUE, screwyhud_type) - set waitfor = FALSE - ..() - //Screwy HUD - var/chosen_screwyhud = screwyhud_type - if(!chosen_screwyhud) - chosen_screwyhud = pick(SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY) - target.set_screwyhud(chosen_screwyhud) - feedback_details += "Type: [target.hal_screwyhud]" - QDEL_IN(src, rand(100, 250)) - -/datum/hallucination/hudscrew/Destroy() - target?.set_screwyhud(SCREWYHUD_NONE) - return ..() - -/datum/hallucination/fake_alert - var/alert_type - -/datum/hallucination/fake_alert/New(mob/living/carbon/C, forced = TRUE, specific, duration = 150) - set waitfor = FALSE - ..() - alert_type = pick( - ALERT_NOT_ENOUGH_OXYGEN, - ALERT_NOT_ENOUGH_PLASMA, - ALERT_NOT_ENOUGH_CO2, - ALERT_TOO_MUCH_OXYGEN, - ALERT_TOO_MUCH_CO2, - ALERT_TOO_MUCH_PLASMA, - ALERT_NUTRITION, - ALERT_GRAVITY, - ALERT_FIRE, - ALERT_TEMPERATURE_HOT, - ALERT_TEMPERATURE_COLD, - ALERT_PRESSURE, - ALERT_NEW_LAW, - ALERT_LOCKED, - ALERT_HACKED, - ALERT_CHARGE, - ) - - if(specific) - alert_type = specific - feedback_details += "Type: [alert_type]" - switch(alert_type) - if(ALERT_NOT_ENOUGH_OXYGEN) - target.throw_alert(alert_type, /atom/movable/screen/alert/not_enough_oxy, override = TRUE) - if(ALERT_NOT_ENOUGH_PLASMA) - target.throw_alert(alert_type, /atom/movable/screen/alert/not_enough_plas, override = TRUE) - if(ALERT_NOT_ENOUGH_CO2) - target.throw_alert(alert_type, /atom/movable/screen/alert/not_enough_co2, override = TRUE) - if(ALERT_TOO_MUCH_OXYGEN) - target.throw_alert(alert_type, /atom/movable/screen/alert/too_much_oxy, override = TRUE) - if(ALERT_TOO_MUCH_CO2) - target.throw_alert(alert_type, /atom/movable/screen/alert/too_much_co2, override = TRUE) - if(ALERT_TOO_MUCH_PLASMA) - target.throw_alert(alert_type, /atom/movable/screen/alert/too_much_plas, override = TRUE) - if(ALERT_NUTRITION) - if(prob(50)) - target.throw_alert(alert_type, /atom/movable/screen/alert/fat, override = TRUE) - else - target.throw_alert(alert_type, /atom/movable/screen/alert/starving, override = TRUE) - if(ALERT_GRAVITY) - target.throw_alert(alert_type, /atom/movable/screen/alert/weightless, override = TRUE) - if(ALERT_FIRE) - target.throw_alert(alert_type, /atom/movable/screen/alert/fire, override = TRUE) - if(ALERT_TEMPERATURE_HOT) - alert_type = "temp" - target.throw_alert(alert_type, /atom/movable/screen/alert/hot, 3, override = TRUE) - if(ALERT_TEMPERATURE_COLD) - alert_type = "temp" - target.throw_alert(alert_type, /atom/movable/screen/alert/cold, 3, override = TRUE) - if(ALERT_PRESSURE) - if(prob(50)) - target.throw_alert(alert_type, /atom/movable/screen/alert/highpressure, 2, override = TRUE) - else - target.throw_alert(alert_type, /atom/movable/screen/alert/lowpressure, 2, override = TRUE) - //BEEP BOOP I AM A ROBOT - if(ALERT_NEW_LAW) - target.throw_alert(alert_type, /atom/movable/screen/alert/newlaw, override = TRUE) - if(ALERT_LOCKED) - target.throw_alert(alert_type, /atom/movable/screen/alert/locked, override = TRUE) - if(ALERT_HACKED) - target.throw_alert(alert_type, /atom/movable/screen/alert/hacked, override = TRUE) - if(ALERT_CHARGE) - target.throw_alert(alert_type, /atom/movable/screen/alert/emptycell, override = TRUE) - - addtimer(CALLBACK(src, .proc/cleanup), duration) - -/datum/hallucination/fake_alert/proc/cleanup() - target.clear_alert(alert_type, clear_override = TRUE) - qdel(src) - -///Causes the target to see incorrect health damages on the healthdoll -/datum/hallucination/fake_health_doll - var/timer_id = null - -///Creates a specified doll hallucination, or picks one randomly -/datum/hallucination/fake_health_doll/New(mob/living/carbon/human/human_mob, forced = TRUE, specific_limb, severity, duration = 500) - . = ..() - if(!specific_limb) - specific_limb = pick(list(SCREWYDOLL_HEAD, SCREWYDOLL_CHEST, SCREWYDOLL_L_ARM, SCREWYDOLL_R_ARM, SCREWYDOLL_L_LEG, SCREWYDOLL_R_LEG)) - if(!severity) - severity = rand(1, 5) - LAZYSET(human_mob.hal_screwydoll, specific_limb, severity) - human_mob.update_health_hud() - - timer_id = addtimer(CALLBACK(src, .proc/cleanup), duration, TIMER_STOPPABLE) - -///Increments the severity of the damage seen on the doll -/datum/hallucination/fake_health_doll/proc/increment_fake_damage() - if(!ishuman(target)) - stack_trace("Somehow [target] managed to get a fake health doll hallucination, while not being a human mob.") - var/mob/living/carbon/human/human_mob = target - for(var/entry in human_mob.hal_screwydoll) - human_mob.hal_screwydoll[entry] = clamp(human_mob.hal_screwydoll[entry]+1, 1, 5) - human_mob.update_health_hud() - -///Adds a fake limb to the hallucination datum effect -/datum/hallucination/fake_health_doll/proc/add_fake_limb(specific_limb, severity) - if(!specific_limb) - specific_limb = pick(list(SCREWYDOLL_HEAD, SCREWYDOLL_CHEST, SCREWYDOLL_L_ARM, SCREWYDOLL_R_ARM, SCREWYDOLL_L_LEG, SCREWYDOLL_R_LEG)) - if(!severity) - severity = rand(1, 5) - var/mob/living/carbon/human/human_mob = target - LAZYSET(human_mob.hal_screwydoll, specific_limb, severity) - target.update_health_hud() - -/datum/hallucination/fake_health_doll/target_deleting() - if(isnull(timer_id)) - return - deltimer(timer_id) - timer_id = null - ..() - -///Cleans up the hallucinations - this deletes any overlap, but that shouldn't happen. -/datum/hallucination/fake_health_doll/proc/cleanup() - qdel(src) - -//So that the associated addition proc cleans it up correctly -/datum/hallucination/fake_health_doll/Destroy() - if(!ishuman(target)) - stack_trace("Somehow [target] managed to get a fake health doll hallucination, while not being a human mob.") - var/mob/living/carbon/human/human_mob = target - LAZYNULL(human_mob.hal_screwydoll) - human_mob.update_health_hud() - return ..() - - -/datum/hallucination/items/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - ..() - //Strange items - - var/obj/halitem = new - - halitem = new - var/obj/item/l_hand = target.get_item_for_held_index(1) - var/obj/item/r_hand = target.get_item_for_held_index(2) - var/l = ui_hand_position(target.get_held_index_of_item(l_hand)) - var/r = ui_hand_position(target.get_held_index_of_item(r_hand)) - var/list/slots_free = list(l,r) - if(l_hand) - slots_free -= l - if(r_hand) - slots_free -= r - if(ishuman(target)) - var/mob/living/carbon/human/H = target - if(!H.belt) - slots_free += ui_belt - if(!H.l_store) - slots_free += ui_storage1 - if(!H.r_store) - slots_free += ui_storage2 - if(slots_free.len) - halitem.screen_loc = pick(slots_free) - halitem.plane = ABOVE_HUD_PLANE - switch(rand(1,6)) - if(1) //revolver - halitem.icon = 'modular_skyrat/modules/fixing_missing_icons/ballistic.dmi' //skyrat edit - halitem.icon_state = "revolver" - halitem.name = "Revolver" - if(2) //c4 - halitem.icon = 'icons/obj/grenade.dmi' - halitem.icon_state = "plastic-explosive0" - halitem.name = "C4" - if(prob(25)) - halitem.icon_state = "plasticx40" - if(3) //sword - halitem.icon = 'icons/obj/transforming_energy.dmi' - halitem.icon_state = "e_sword" - halitem.name = "energy sword" - if(4) //stun baton - halitem.icon = 'icons/obj/items_and_weapons.dmi' - halitem.icon_state = "stunbaton" - halitem.name = "Stun Baton" - if(5) //emag - halitem.icon = 'icons/obj/card.dmi' - halitem.icon_state = "emag" - halitem.name = "Cryptographic Sequencer" - if(6) //flashbang - halitem.icon = 'icons/obj/grenade.dmi' - halitem.icon_state = "flashbang1" - halitem.name = "Flashbang" - feedback_details += "Type: [halitem.name]" - if(target.client) - target.client.screen += halitem - QDEL_IN(halitem, rand(150, 350)) - - qdel(src) - -/datum/hallucination/dangerflash - -/datum/hallucination/dangerflash/New(mob/living/carbon/C, forced = TRUE, danger_type) - set waitfor = FALSE - ..() - //Flashes of danger - - var/list/possible_points = list() - for(var/turf/open/floor/F in view(target,world.view)) - possible_points += F - if(possible_points.len) - var/turf/open/floor/danger_point = pick(possible_points) - if(!danger_type) - danger_type = pick("lava","chasm","anomaly") - switch(danger_type) - if("lava") - new /obj/effect/hallucination/danger/lava(danger_point, target) - if("chasm") - new /obj/effect/hallucination/danger/chasm(danger_point, target) - if("anomaly") - new /obj/effect/hallucination/danger/anomaly(danger_point, target) - - qdel(src) - -/obj/effect/hallucination/danger - var/image/image - -/obj/effect/hallucination/danger/proc/show_icon() - return - -/obj/effect/hallucination/danger/proc/clear_icon() - if(image && target.client) - target.client.images -= image - -/obj/effect/hallucination/danger/Initialize(mapload, _target) - . = ..() - target = _target - show_icon() - QDEL_IN(src, rand(200, 450)) - -/obj/effect/hallucination/danger/Destroy() - clear_icon() - . = ..() - -/obj/effect/hallucination/danger/lava - name = "lava" - -/obj/effect/hallucination/danger/lava/Initialize(mapload, _target) - . = ..() - var/static/list/loc_connections = list( - COMSIG_ATOM_ENTERED = .proc/on_entered, - ) - AddElement(/datum/element/connect_loc, loc_connections) - -/obj/effect/hallucination/danger/lava/show_icon() - image = image('icons/turf/floors/lava.dmi', src, "lava-0", TURF_LAYER) - if(target.client) - target.client.images += image - -/obj/effect/hallucination/danger/lava/proc/on_entered(datum/source, atom/movable/AM) - SIGNAL_HANDLER - if(AM == target) - target.adjustStaminaLoss(20) - new /datum/hallucination/fire(target) - -/obj/effect/hallucination/danger/chasm - name = "chasm" - -/obj/effect/hallucination/danger/chasm/Initialize(mapload, _target) - . = ..() - var/static/list/loc_connections = list( - COMSIG_ATOM_ENTERED = .proc/on_entered, - ) - AddElement(/datum/element/connect_loc, loc_connections) - -/obj/effect/hallucination/danger/chasm/show_icon() - var/turf/target_loc = get_turf(target) - image = image('icons/turf/floors/chasms.dmi', src, "chasms-[target_loc.smoothing_junction]", TURF_LAYER) - if(target.client) - target.client.images += image - -/obj/effect/hallucination/danger/chasm/proc/on_entered(datum/source, atom/movable/AM) - SIGNAL_HANDLER - if(AM == target) - if(istype(target, /obj/effect/dummy/phased_mob)) - return - to_chat(target, span_userdanger("You fall into the chasm!")) - target.Paralyze(40) - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, target, span_notice("It's surprisingly shallow.")), 15) - QDEL_IN(src, 30) - -/obj/effect/hallucination/danger/anomaly - name = "flux wave anomaly" - -/obj/effect/hallucination/danger/anomaly/Initialize(mapload) - . = ..() - START_PROCESSING(SSobj, src) - var/static/list/loc_connections = list( - COMSIG_ATOM_ENTERED = .proc/on_entered, - ) - AddElement(/datum/element/connect_loc, loc_connections) - -/obj/effect/hallucination/danger/anomaly/process(delta_time) - if(DT_PROB(45, delta_time)) - step(src,pick(GLOB.alldirs)) - -/obj/effect/hallucination/danger/anomaly/Destroy() - STOP_PROCESSING(SSobj, src) - return ..() - -/obj/effect/hallucination/danger/anomaly/show_icon() - image = image('icons/effects/effects.dmi',src,"electricity2",OBJ_LAYER+0.01) - if(target.client) - target.client.images += image - -/obj/effect/hallucination/danger/anomaly/proc/on_entered(datum/source, atom/movable/AM) - SIGNAL_HANDLER - if(AM == target) - new /datum/hallucination/shock(target) - -/datum/hallucination/death - -/datum/hallucination/death/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - ..() - target.set_screwyhud(SCREWYHUD_DEAD) - target.Paralyze(300) - target.silent += 10 - to_chat(target, span_deadsay("[target.real_name] has died at [get_area_name(target)].")) - - var/delay = 0 - - if(prob(50)) - var/mob/fakemob - var/list/dead_people = list() - for(var/mob/dead/observer/G in GLOB.player_list) - dead_people += G - if(LAZYLEN(dead_people)) - fakemob = pick(dead_people) - else - fakemob = target //ever been so lonely you had to haunt yourself? - if(fakemob) - delay = rand(20, 50) - addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, target, "DEAD: [fakemob.name] says, \"[pick("rip","why did i just drop dead?","hey [target.first_name()]","git gud","you too?","is the AI rogue?",\ - "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "this round","this","myself","admins","you")]")]\""), delay) - - addtimer(CALLBACK(src, .proc/cleanup), delay + rand(70, 90)) - -/datum/hallucination/death/proc/cleanup() - if (target) - target.set_screwyhud(SCREWYHUD_NONE) - target.SetParalyzed(0) - target.silent = FALSE - qdel(src) - -#define RAISE_FIRE_COUNT 3 -#define RAISE_FIRE_TIME 3 - -/datum/hallucination/fire - var/active = TRUE - var/stage = 0 - var/image/fire_overlay - - var/next_action = 0 - var/times_to_lower_stamina - var/fire_clearing = FALSE - var/increasing_stages = TRUE - var/time_spent = 0 - -/datum/hallucination/fire/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - ..() - target.set_fire_stacks(max(target.fire_stacks, 0.1)) //Placebo flammability - fire_overlay = image('icons/mob/onfire.dmi', target, "human_big_fire", ABOVE_MOB_LAYER) - if(target.client) - target.client.images += fire_overlay - to_chat(target, span_userdanger("You're set on fire!")) - target.throw_alert(ALERT_FIRE, /atom/movable/screen/alert/fire, override = TRUE) - times_to_lower_stamina = rand(5, 10) - addtimer(CALLBACK(src, .proc/start_expanding), 20) - -/datum/hallucination/fire/Destroy() - . = ..() - STOP_PROCESSING(SSfastprocess, src) - -/datum/hallucination/fire/proc/start_expanding() - if (isnull(target)) - qdel(src) - return - START_PROCESSING(SSfastprocess, src) - -/datum/hallucination/fire/process(delta_time) - if (isnull(target)) - qdel(src) - return - - if(target.fire_stacks <= 0) - clear_fire() - - time_spent += delta_time - - if (fire_clearing) - next_action -= delta_time - if (next_action < 0) - stage -= 1 - update_temp() - next_action += 3 - else if (increasing_stages) - var/new_stage = min(round(time_spent / RAISE_FIRE_TIME), RAISE_FIRE_COUNT) - if (stage != new_stage) - stage = new_stage - update_temp() - - if (stage == RAISE_FIRE_COUNT) - increasing_stages = FALSE - else if (times_to_lower_stamina) - next_action -= delta_time - if (next_action < 0) - target.adjustStaminaLoss(15) - next_action += 2 - times_to_lower_stamina -= 1 - else - clear_fire() - -/datum/hallucination/fire/proc/update_temp() - if(stage <= 0) - target.clear_alert(ALERT_TEMPERATURE, clear_override = TRUE) - else - target.clear_alert(ALERT_TEMPERATURE, clear_override = TRUE) - target.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, stage, override = TRUE) - -/datum/hallucination/fire/proc/clear_fire() - if(!active) - return - active = FALSE - target.clear_alert(ALERT_FIRE, clear_override = TRUE) - if(target.client) - target.client.images -= fire_overlay - QDEL_NULL(fire_overlay) - fire_clearing = TRUE - next_action = 0 - -#undef RAISE_FIRE_COUNT -#undef RAISE_FIRE_TIME - -/datum/hallucination/shock - var/image/shock_image - var/image/electrocution_skeleton_anim - -/datum/hallucination/shock/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - ..() - shock_image = image(target, target, dir = target.dir) - shock_image.appearance_flags |= KEEP_APART - shock_image.color = rgb(0,0,0) - shock_image.override = TRUE - electrocution_skeleton_anim = image('icons/mob/human.dmi', target, icon_state = "electrocuted_base", layer=ABOVE_MOB_LAYER) - electrocution_skeleton_anim.appearance_flags |= RESET_COLOR|KEEP_APART - to_chat(target, span_userdanger("You feel a powerful shock course through your body!")) - if(target.client) - target.client.images |= shock_image - target.client.images |= electrocution_skeleton_anim - addtimer(CALLBACK(src, .proc/reset_shock_animation), 40) - target.playsound_local(get_turf(src), SFX_SPARKS, 100, 1) - target.staminaloss += 50 - target.Stun(4 SECONDS) - target.do_jitter_animation(300) // Maximum jitter - target.adjust_timed_status_effect(20 SECONDS, /datum/status_effect/jitter) - addtimer(CALLBACK(src, .proc/shock_drop), 2 SECONDS) - -/datum/hallucination/shock/proc/reset_shock_animation() - target.client?.images.Remove(shock_image) - target.client?.images.Remove(electrocution_skeleton_anim) - -/datum/hallucination/shock/proc/shock_drop() - target.Paralyze(6 SECONDS) - -/datum/hallucination/husks - var/image/halbody - -/datum/hallucination/husks/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - ..() - var/list/possible_points = list() - for(var/turf/open/floor/F in view(target,world.view)) - possible_points += F - if(possible_points.len) - var/turf/open/floor/husk_point = pick(possible_points) - switch(rand(1,4)) - if(1) - var/image/body = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER) - var/matrix/M = matrix() - M.Turn(90) - body.transform = M - halbody = body - if(2,3) - halbody = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER) - if(4) - halbody = image('icons/mob/alien.dmi',husk_point,"alienother",TURF_LAYER) - - if(target.client) - target.client.images += halbody - QDEL_IN(src, rand(30,50)) //Only seen for a brief moment. - -/datum/hallucination/husks/Destroy() - target?.client?.images -= halbody - QDEL_NULL(halbody) - return ..() - -//hallucination projectile code in code/modules/projectiles/projectile/special.dm -/datum/hallucination/stray_bullet - -/datum/hallucination/stray_bullet/New(mob/living/carbon/C, forced = TRUE) - set waitfor = FALSE - ..() - var/list/turf/startlocs = list() - for(var/turf/open/T in view(world.view+1,target)-view(world.view,target)) - startlocs += T - if(!startlocs.len) - qdel(src) - return - var/turf/start = pick(startlocs) - var/proj_type = pick(subtypesof(/obj/projectile/hallucination)) - feedback_details += "Type: [proj_type]" - var/obj/projectile/hallucination/H = new proj_type(start) - target.playsound_local(start, H.hal_fire_sound, 60, 1) - H.hal_target = target - H.preparePixelProjectile(target, start) - H.fire() - qdel(src) diff --git a/code/modules/hydroponics/grown/misc.dm b/code/modules/hydroponics/grown/misc.dm deleted file mode 100644 index 934734d740b..00000000000 --- a/code/modules/hydroponics/grown/misc.dm +++ /dev/null @@ -1,253 +0,0 @@ -// Starthistle -/obj/item/seeds/starthistle - name = "pack of starthistle seeds" - desc = "A robust species of weed that often springs up in-between the cracks of spaceship parking lots." - icon_state = "seed-starthistle" - species = "starthistle" - plantname = "Starthistle" - lifespan = 70 - endurance = 50 // damm pesky weeds - maturation = 5 - production = 1 - yield = 2 - potency = 10 - instability = 35 - growthstages = 3 - growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi' - genes = list(/datum/plant_gene/trait/plant_type/weed_hardy) - mutatelist = list(/obj/item/seeds/starthistle/corpse_flower, /obj/item/seeds/galaxythistle) - graft_gene = /datum/plant_gene/trait/plant_type/weed_hardy - -/obj/item/seeds/starthistle/harvest(mob/user) - var/obj/machinery/hydroponics/parent = loc - var/seed_count = yield - if(prob(getYield() * 20)) - seed_count++ - var/output_loc = parent.Adjacent(user) ? user.loc : parent.loc - for(var/i in 1 to seed_count) - var/obj/item/seeds/starthistle/harvestseeds = Copy() - harvestseeds.forceMove(output_loc) - - parent.update_tray() - -// Corpse flower -/obj/item/seeds/starthistle/corpse_flower - name = "pack of corpse flower seeds" - desc = "A species of plant that emits a horrible odor. The odor stops being produced in difficult atmospheric conditions." - icon_state = "seed-corpse-flower" - species = "corpse-flower" - plantname = "Corpse flower" - production = 2 - growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi' - genes = list(/datum/plant_gene/trait/gas_production) - mutatelist = list() - reagents_add = list(/datum/reagent/toxin/formaldehyde = 0.1) - -//Galaxy Thistle -/obj/item/seeds/galaxythistle - name = "pack of galaxythistle seeds" - desc = "An impressive species of weed that is thought to have evolved from the simple milk thistle. Contains flavolignans that can help repair a damaged liver." - icon_state = "seed-galaxythistle" - species = "galaxythistle" - plantname = "Galaxythistle" - product = /obj/item/food/grown/galaxythistle - lifespan = 70 - endurance = 40 - maturation = 3 - production = 2 - yield = 2 - potency = 25 - instability = 35 - growthstages = 3 - growing_icon = 'icons/obj/hydroponics/growing_flowers.dmi' - genes = list(/datum/plant_gene/trait/plant_type/weed_hardy, /datum/plant_gene/trait/invasive) - mutatelist = list() - reagents_add = list(/datum/reagent/consumable/nutriment = 0.05, /datum/reagent/medicine/silibinin = 0.1) - graft_gene = /datum/plant_gene/trait/invasive - -/obj/item/seeds/galaxythistle/Initialize(mapload,nogenes) - . = ..() - if(!nogenes) - unset_mutability(/datum/plant_gene/trait/invasive, PLANT_GENE_REMOVABLE) - -/obj/item/food/grown/galaxythistle - seed = /obj/item/seeds/galaxythistle - name = "galaxythistle flower head" - desc = "This spiny cluster of florets reminds you of the highlands." - icon_state = "galaxythistle" - bite_consumption_mod = 2 - foodtypes = VEGETABLES - wine_power = 35 - tastes = list("thistle" = 2, "artichoke" = 1) - -// Cabbage -/obj/item/seeds/cabbage - name = "pack of cabbage seeds" - desc = "These seeds grow into cabbages." - icon_state = "seed-cabbage" - species = "cabbage" - plantname = "Cabbages" - product = /obj/item/food/grown/cabbage - lifespan = 50 - endurance = 25 - maturation = 3 - production = 5 - yield = 4 - instability = 10 - growthstages = 1 - growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' - genes = list(/datum/plant_gene/trait/repeated_harvest) - mutatelist = list(/obj/item/seeds/replicapod) - reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.1) - seed_flags = null - -/obj/item/food/grown/cabbage - seed = /obj/item/seeds/cabbage - name = "cabbage" - desc = "Ewwwwwwwwww. Cabbage." - icon_state = "cabbage" - foodtypes = VEGETABLES - wine_power = 20 - -// Sugarcane -/obj/item/seeds/sugarcane - name = "pack of sugarcane seeds" - desc = "These seeds grow into sugarcane." - icon_state = "seed-sugarcane" - species = "sugarcane" - plantname = "Sugarcane" - product = /obj/item/food/grown/sugarcane - genes = list(/datum/plant_gene/trait/repeated_harvest) - lifespan = 60 - endurance = 50 - maturation = 3 - yield = 4 - instability = 15 - growthstages = 2 - reagents_add = list(/datum/reagent/consumable/sugar = 0.25) - mutatelist = list(/obj/item/seeds/bamboo) - -/obj/item/food/grown/sugarcane - seed = /obj/item/seeds/sugarcane - name = "sugarcane" - desc = "Sickly sweet." - icon_state = "sugarcane" - bite_consumption_mod = 2 - foodtypes = VEGETABLES | SUGAR - distill_reagent = /datum/reagent/consumable/ethanol/rum - -// Gatfruit -/obj/item/seeds/gatfruit - name = "pack of gatfruit seeds" - desc = "These seeds grow into .357 revolvers." - icon_state = "seed-gatfruit" - species = "gatfruit" - plantname = "Gatfruit Tree" - product = /obj/item/food/grown/shell/gatfruit - genes = list(/datum/plant_gene/trait/repeated_harvest) - lifespan = 20 - endurance = 20 - maturation = 40 - production = 10 - yield = 2 - potency = 60 - growthstages = 2 - rarity = 60 // Obtainable only with xenobio+superluck. - growing_icon = 'icons/obj/hydroponics/growing_fruits.dmi' - reagents_add = list(/datum/reagent/sulfur = 0.1, /datum/reagent/carbon = 0.1, /datum/reagent/nitrogen = 0.07, /datum/reagent/potassium = 0.05) - -/obj/item/food/grown/shell/gatfruit - seed = /obj/item/seeds/gatfruit - name = "gatfruit" - desc = "It smells like burning." - icon_state = "gatfruit" - trash_type = /obj/item/gun/ballistic/revolver - bite_consumption_mod = 2 - foodtypes = FRUIT - tastes = list("gunpowder" = 1) - wine_power = 90 //It burns going down, too. - -//Cherry Bombs -/obj/item/seeds/cherry/bomb - name = "pack of cherry bomb pits" - desc = "They give you vibes of dread and frustration." - icon_state = "seed-cherry_bomb" - species = "cherry_bomb" - plantname = "Cherry Bomb Tree" - product = /obj/item/food/grown/cherry_bomb - mutatelist = list() - genes = list(/datum/plant_gene/trait/bomb_plant, /datum/plant_gene/trait/modified_volume/cherry_bomb) - reagents_add = list(/datum/reagent/consumable/nutriment = 0.1, /datum/reagent/consumable/sugar = 0.1, /datum/reagent/gunpowder = 0.7) - rarity = 60 //See above - -/obj/item/food/grown/cherry_bomb - name = "cherry bombs" - desc = "You think you can hear the hissing of a tiny fuse." - icon_state = "cherry_bomb" - alt_icon = "cherry_bomb_lit" - seed = /obj/item/seeds/cherry/bomb - bite_consumption_mod = 3 - wine_power = 80 - -// aloe -/obj/item/seeds/aloe - name = "pack of aloe seeds" - desc = "These seeds grow into aloe." - icon_state = "seed-aloe" - species = "aloe" - plantname = "Aloe" - product = /obj/item/food/grown/aloe - lifespan = 60 - endurance = 25 - maturation = 4 - production = 4 - yield = 6 - growthstages = 5 - growing_icon = 'icons/obj/hydroponics/growing_vegetables.dmi' - reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.05, /datum/reagent/consumable/nutriment = 0.05) - -/obj/item/food/grown/aloe - seed = /obj/item/seeds/aloe - name = "aloe" - desc = "Cut leaves from the aloe plant." - icon_state = "aloe" - bite_consumption_mod = 3 - foodtypes = VEGETABLES - juice_results = list(/datum/reagent/consumable/aloejuice = 0) - distill_reagent = /datum/reagent/consumable/ethanol/tequila - -/obj/item/food/grown/aloe/microwave_act(obj/machinery/microwave/M) - new /obj/item/stack/medical/aloe(drop_location(), 2) - qdel(src) - -/obj/item/seeds/shrub - name = "pack of shrub seeds" - desc = "These seeds grow into hedge shrubs." - icon_state = "seed-shrub" - species = "shrub" - plantname = "Shrubbery" - product = /obj/item/grown/shrub - lifespan = 40 - endurance = 30 - maturation = 4 - production = 6 - yield = 2 - instability = 10 - growthstages = 3 - reagents_add = list() - -/obj/item/grown/shrub - seed = /obj/item/seeds/shrub - name = "shrub" - desc = "A shrubbery, it looks nice and it was only a few credits too. Plant it on the ground to grow a hedge, shrubbing skills not required." - icon_state = "shrub" - -/obj/item/grown/shrub/attack_self(mob/user) - var/turf/player_turf = get_turf(user) - if(player_turf?.is_blocked_turf(TRUE)) - return FALSE - user.visible_message("[user] begins to plant \the [src]...") - if(do_after(user, 4 SECONDS, target = user.drop_location(), progress = TRUE)) //SKYRAT EDIT - ORIGINAL 8 SECONDS - new /obj/structure/fluff/hedge/opaque(user.drop_location()) - to_chat(user, span_notice("You plant \the [src].")) - qdel(src) diff --git a/code/modules/language/swarmer.dm b/code/modules/language/swarmer.dm deleted file mode 100644 index 87ebf24136f..00000000000 --- a/code/modules/language/swarmer.dm +++ /dev/null @@ -1,43 +0,0 @@ -/datum/language/swarmer - name = "Swarmer" - desc = "A language only consisting of musical notes." - spans = list(SPAN_ROBOT) - key = "s" - flags = NO_STUTTER - space_chance = 100 - sentence_chance = 0 - default_priority = 60 - - icon_state = "swarmer" - secret = TRUE // SKYRAT EDIT - - // since various flats and sharps are the same, - // all non-accidental notes are doubled in the list - /* The list with unicode symbols for the accents. - syllables = list( - "C", "C", - "C♯", "D♭", - "D", "D", - "D♯", "E♭", - "E", "E", - "F", "F", - "F♯", "G♭", - "G", "G", - "G♯", "A♭", - "A", "A", - "A♯", "B♭", - "B", "B") - */ - syllables = list( - "C", "C", - "C#", "Db", - "D", "D", - "D#", "Eb", - "E", "E", - "F", "F", - "F#", "Gb", - "G", "G", - "G#", "Ab", - "A", "A", - "A#", "Bb", - "B", "B") diff --git a/code/modules/mining/equipment/vendor_items.dm b/code/modules/mining/equipment/vendor_items.dm deleted file mode 100644 index 88de7d38053..00000000000 --- a/code/modules/mining/equipment/vendor_items.dm +++ /dev/null @@ -1,17 +0,0 @@ -/**********************Mining Equipment Vendor Items**************************/ -//misc stuff you can buy from the vendor that has special code but doesn't really need its own file - -/**********************Facehugger toy**********************/ -/obj/item/clothing/mask/facehugger/toy - inhand_icon_state = "facehugger_inactive" - desc = "A toy often used to play pranks on other miners by putting it in their beds. It takes a bit to recharge after latching onto something." - throwforce = 0 - real = 0 - sterile = 1 - tint = 3 //Makes it feel more authentic when it latches on - special_desc_requirement = EXAMINE_CHECK_ROLE //SKYRAT EDIT - special_desc_roles = list("ROLE_ALIEN") //SKYRAT EDIT - special_desc = "This appears to be a mechanical mockery of our young." //SKYRAT EDIT - -/obj/item/clothing/mask/facehugger/toy/Die() - return diff --git a/code/modules/mob/living/simple_animal/hostile/cockroach.dm b/code/modules/mob/living/simple_animal/hostile/cockroach.dm deleted file mode 100644 index 0d0b820ee16..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/cockroach.dm +++ /dev/null @@ -1,125 +0,0 @@ -/mob/living/simple_animal/hostile/cockroach - name = "cockroach" - desc = "This station is just crawling with bugs." - icon_state = "cockroach" - icon_dead = "cockroach" - health = 1 - maxHealth = 1 - turns_per_move = 5 - loot = list(/obj/effect/decal/cleanable/insectguts) - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - minbodytemp = 270 - maxbodytemp = INFINITY - pass_flags = PASSTABLE | PASSGRILLE | PASSMOB - mob_size = MOB_SIZE_TINY - mob_biotypes = MOB_ORGANIC|MOB_BUG - response_disarm_continuous = "shoos" - response_disarm_simple = "shoo" - response_harm_continuous = "splats" - response_harm_simple = "splat" - speak_emote = list("chitters") - density = FALSE - melee_damage_lower = 0 - melee_damage_upper = 0 - obj_damage = 0 - gold_core_spawnable = FRIENDLY_SPAWN - verb_say = "chitters" - verb_ask = "chitters inquisitively" - verb_exclaim = "chitters loudly" - verb_yell = "chitters loudly" - del_on_death = TRUE - environment_smash = ENVIRONMENT_SMASH_NONE - faction = list("neutral") - var/squish_chance = 50 - // Randomizes hunting intervals, minumum 5 turns - var/time_to_hunt = 5 - - -/mob/living/simple_animal/hostile/cockroach/Initialize() - . = ..() - add_cell_sample() - make_squashable() - ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) - time_to_hunt = rand(5,10) - -/mob/living/simple_animal/hostile/cockroach/proc/make_squashable() - AddComponent(/datum/component/squashable, squash_chance = 50, squash_damage = 1) - -/mob/living/simple_animal/hostile/cockroach/add_cell_sample() - AddElement(/datum/element/swabable, CELL_LINE_TABLE_COCKROACH, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 7) - -/mob/living/simple_animal/hostile/cockroach/Life(delta_time = SSMOBS_DT, times_fired) // Cockroaches are predators to space ants - . = ..() - turns_since_scan++ - if(turns_since_scan > time_to_hunt) - turns_since_scan = 0 - var/list/target_types = list(/obj/effect/decal/cleanable/ants) - for(var/obj/effect/decal/cleanable/ants/potential_target in view(2, get_turf(src))) - if(potential_target.type in target_types) - hunt(potential_target) - return - - -/obj/projectile/glockroachbullet - damage = 10 //same damage as a hivebot - damage_type = BRUTE - -/obj/item/ammo_casing/glockroach - name = "0.9mm bullet casing" - desc = "A... 0.9mm bullet casing? What?" - projectile_type = /obj/projectile/glockroachbullet - -/mob/living/simple_animal/hostile/cockroach/glockroach - name = "glockroach" - desc = "HOLY SHIT, THAT COCKROACH HAS A GUN!" - icon_state = "glockroach" - melee_damage_lower = 5 - melee_damage_upper = 5 - obj_damage = 20 - gold_core_spawnable = HOSTILE_SPAWN - projectilesound = 'sound/weapons/gun/pistol/shot.ogg' - projectiletype = /obj/projectile/glockroachbullet - casingtype = /obj/item/ammo_casing/glockroach - ranged = TRUE - faction = list("hostile") - -/mob/living/simple_animal/hostile/cockroach/death(gibbed) - if(GLOB.station_was_nuked) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes. - return - ..() - -/mob/living/simple_animal/hostile/cockroach/ex_act() //Explosions are a terrible way to handle a cockroach. - return FALSE - -/mob/living/simple_animal/hostile/cockroach/hauberoach - name = "hauberoach" - desc = "Is that cockroach wearing a tiny yet immaculate replica 19th century Prussian spiked helmet? ...Is that a bad thing?" - icon_state = "hauberoach" - attack_verb_continuous = "rams its spike into" - attack_verb_simple = "ram your spike into" - melee_damage_lower = 5 - melee_damage_upper = 20 - obj_damage = 20 - gold_core_spawnable = HOSTILE_SPAWN - attack_sound = 'sound/weapons/bladeslice.ogg' - attack_vis_effect = ATTACK_EFFECT_SLASH - faction = list("hostile") - sharpness = SHARP_POINTY - squish_chance = 0 // manual squish if relevant - -/mob/living/simple_animal/hostile/cockroach/hauberoach/Initialize() - . = ..() - AddComponent(/datum/component/caltrop, min_damage = 10, max_damage = 15, flags = (CALTROP_BYPASS_SHOES | CALTROP_SILENT)) - -/mob/living/simple_animal/hostile/cockroach/hauberoach/make_squashable() - AddComponent(/datum/component/squashable, squash_chance = 100, squash_damage = 1, squash_callback = /mob/living/simple_animal/hostile/cockroach/hauberoach/.proc/on_squish) - -///Proc used to override the squashing behavior of the normal cockroach. -/mob/living/simple_animal/hostile/cockroach/hauberoach/proc/on_squish(mob/living/cockroach, mob/living/living_target) - if(!istype(living_target)) - return FALSE //We failed to run the invoke. Might be because we're a structure. Let the squashable element handle it then! - if(!HAS_TRAIT(living_target, TRAIT_PIERCEIMMUNE)) - living_target.visible_message(span_danger("[living_target] steps onto [cockroach]'s spike!"), span_userdanger("You step onto [cockroach]'s spike!")) - return TRUE - living_target.visible_message(span_notice("[living_target] squashes [cockroach], not even noticing its spike."), span_notice("You squashed [cockroach], not even noticing its spike.")) - return FALSE diff --git a/code/modules/ninja/suit/ninjaDrainAct.dm b/code/modules/ninja/suit/ninjaDrainAct.dm deleted file mode 100644 index 74ddbedeb9e..00000000000 --- a/code/modules/ninja/suit/ninjaDrainAct.dm +++ /dev/null @@ -1,324 +0,0 @@ -/** - * Atom level proc for space ninja's glove interactions. - * - * Proc which only occurs when space ninja uses his gloves on an atom. - * Does nothing by default, but effects will vary. - * Arguments: - * * ninja_suit - The offending space ninja's suit. - * * ninja - The human mob wearing the suit. - * * ninja_gloves - The offending space ninja's gloves. - */ -/atom/proc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - return INVALID_DRAIN - -//APC// -/obj/machinery/power/apc/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - var/maxcapacity = FALSE //Safety check for batteries - var/drain = 0 //Drain amount from batteries - var/drain_total = 0 - - if(cell?.charge) - var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() - spark_system.set_up(5, 0, loc) - - while(cell.charge> 0 && !maxcapacity) - drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain) - - if(cell.charge < drain) - drain = cell.charge - - if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge) - drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge - maxcapacity = TRUE//Reached maximum battery capacity. - - if (do_after(ninja ,10, target = src)) - spark_system.start() - playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - cell.use(drain) - ninja_suit.cell.give(drain) - drain_total += drain - else - break - - if(!(obj_flags & EMAGGED)) - flick("apc-spark", ninja_gloves) - playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - obj_flags |= EMAGGED - locked = FALSE - update_appearance() - - return drain_total - -//SMES// -/obj/machinery/power/smes/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - var/maxcapacity = FALSE //Safety check for batteries - var/drain = 0 //Drain amount from batteries - var/drain_total = 0 - - if(charge) - var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() - spark_system.set_up(5, 0, loc) - - while(charge > 0 && !maxcapacity) - drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain) - - if(charge < drain) - drain = charge - - if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge) - drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge - maxcapacity = TRUE - - if (do_after(ninja,10, target = src)) - spark_system.start() - playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - charge -= drain - ninja_suit.cell.give(drain) - drain_total += drain - - else - break - - return drain_total - -//CELL// -/obj/item/stock_parts/cell/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - var/drain_total = 0 - - if(charge) - if(do_after(ninja, 30, target = src)) - drain_total = charge - if(ninja_suit.cell.charge + charge > ninja_suit.cell.maxcharge) - ninja_suit.cell.charge = ninja_suit.cell.maxcharge - else - ninja_suit.cell.give(charge) - charge = 0 - corrupt() - update_appearance() - - return drain_total - -//RD SERVER// -/obj/machinery/rnd/server/master/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - . = DRAIN_RD_HACK_FAILED - - // If the traitor theft objective is still present, this will destroy it... - if(!source_code_hdd) - return ..() - - to_chat(ninja, span_notice("Hacking \the [src]...")) - AI_notify_hack() - to_chat(ninja, span_notice("Encrypted source code detected. Overloading storage device...")) - if(do_after(ninja, 30 SECONDS, target = src)) - overload_source_code_hdd() - to_chat(ninja, span_notice("Sabotage complete. Storage device overloaded.")) - var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja) - if(!ninja_antag) - return - var/datum/objective/research_secrets/objective = locate() in ninja_antag.objectives - if(objective) - objective.completed = TRUE - -/obj/machinery/rnd/server/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - . = DRAIN_RD_HACK_FAILED - - to_chat(ninja, span_notice("Research notes detected. Corrupting data...")) - - if(!do_after(ninja, 30 SECONDS, target = src)) - return - - SSresearch.science_tech.modify_points_all(0) - to_chat(ninja, span_notice("Sabotage complete. Research notes corrupted.")) - var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja) - if(!ninja_antag) - return - var/datum/objective/research_secrets/objective = locate() in ninja_antag.objectives - if(objective) - objective.completed = TRUE - -//SECURITY CONSOLE// -/obj/machinery/computer/secure_data/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - AI_notify_hack() - if(do_after(ninja, 200)) - for(var/datum/data/record/rec in sort_record(GLOB.data_core.general, sortBy, order)) - for(var/datum/data/record/security_record in GLOB.data_core.security) - security_record.fields["criminal"] = "*Arrest*" - var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja) - if(!ninja_antag) - return - var/datum/objective/security_scramble/objective = locate() in ninja_antag.objectives - if(objective) - objective.completed = TRUE - -/* SKYRAT EDIT REMOVAL -//COMMUNICATIONS CONSOLE// -/obj/machinery/computer/communications/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - if(ninja_gloves.communication_console_hack_success) - return - if(machine_stat & (NOPOWER|BROKEN)) - return - AI_notify_hack() - if(!do_after(ninja, 30 SECONDS, src)) - return - hack_console(ninja) - ninja_gloves.communication_console_hack_success = TRUE - var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja) - if(!ninja_antag) - return - var/datum/objective/terror_message/objective = locate() in ninja_antag.objectives - if(objective) - objective.completed = TRUE -*/ - -//AIRLOCK// -/obj/machinery/door/airlock/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - if(!operating && density && hasPower() && !(obj_flags & EMAGGED)) - emag_act() - ninja_gloves.door_hack_counter++ - var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja) - if(!ninja_antag) - return - var/datum/objective/door_jack/objective = locate() in ninja_antag.objectives - if(objective && objective.doors_required <= ninja_gloves.door_hack_counter) - objective.completed = TRUE - -//WIRE// -/obj/structure/cable/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - var/maxcapacity = FALSE //Safety check - var/drain = 0 //Drain amount - - var/drain_total = 0 - - var/datum/powernet/wire_powernet = powernet - while(!maxcapacity && src) - drain = (round((rand(ninja_gloves.mindrain, ninja_gloves.maxdrain))/2)) - var/drained = 0 - if(wire_powernet && do_after(ninja ,10, target = src)) - drained = min(drain, delayed_surplus()) - add_delayedload(drained) - if(drained < drain)//if no power on net, drain apcs - for(var/obj/machinery/power/terminal/affected_terminal in wire_powernet.nodes) - if(istype(affected_terminal.master, /obj/machinery/power/apc)) - var/obj/machinery/power/apc/AP = affected_terminal.master - if(AP.operating && AP.cell && AP.cell.charge > 0) - AP.cell.charge = max(0, AP.cell.charge - 5) - drained += 5 - else - break - - ninja_suit.cell.give(drain) - if(ninja_suit.cell.charge > ninja_suit.cell.maxcharge) - drain_total += (drained-(ninja_suit.cell.charge - ninja_suit.cell.maxcharge)) - ninja_suit.cell.charge = ninja_suit.cell.maxcharge - maxcapacity = TRUE - else - drain_total += drained - ninja_suit.spark_system.start() - - return drain_total - -//MECH// -/obj/vehicle/sealed/mecha/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - var/maxcapacity = FALSE //Safety check - var/drain = 0 //Drain amount - var/drain_total = 0 - - to_chat(occupants, "[icon2html(src, occupants)][span_danger("Warning: Unauthorized access through sub-route 4, block H, detected.")]") - if(get_charge()) - while(cell.charge > 0 && !maxcapacity) - drain = rand(ninja_gloves.mindrain, ninja_gloves.maxdrain) - if(cell.charge < drain) - drain = cell.charge - if(ninja_suit.cell.charge + drain > ninja_suit.cell.maxcharge) - drain = ninja_suit.cell.maxcharge - ninja_suit.cell.charge - maxcapacity = TRUE - if (do_after(ninja, 10, target = src)) - spark_system.start() - playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - cell.use(drain) - ninja_suit.cell.give(drain) - drain_total += drain - else - break - - return drain_total - -//BORG// -/mob/living/silicon/robot/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - //SKYRAT EDIT: ADDITION START - var/list/modelselected = list() - modelselected["Assault"] = "/obj/item/robot_model/ninja" - modelselected["Medical"] = "/obj/item/robot_model/ninja/ninja_medical" - modelselected["Saboteur"] = "/obj/item/robot_model/ninja_saboteur" - //SKYRAT EDIT: ADDITION END - - if(!ninja_suit || !ninja || !ninja_gloves || (ROLE_NINJA in faction)) - return INVALID_DRAIN - - to_chat(src, span_danger("Warni-***BZZZZZZZZZRT*** UPLOADING SPYDERPATCHER VERSION 9.5.2...")) - if (do_after(ninja, 60, target = src)) - spark_system.start() - playsound(loc, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - to_chat(src, span_danger("UPLOAD COMPLETE. NEW CYBORG MODEL DETECTED. INSTALLING...")) - faction = list(ROLE_NINJA) - bubble_icon = "syndibot" - UnlinkSelf() - ionpulse = TRUE - laws = new /datum/ai_laws/ninja_override() - //SKYRAT EDIT CHANGE BEGIN - Role Selection - //model.transform_to(pick(/obj/item/robot_model/syndicate, /obj/item/robot_model/syndicate_medical, /obj/item/robot_model/saboteur)) - SKYRAT EDIT - ORIGINAL - var/choice = input(src,"What role do you wish to become?","Select Role") in sort_list(modelselected) - model.transform_to(modelselected[choice]) - //SKYRAT EDIT CHANGE END - - var/datum/antagonist/ninja/ninja_antag = ninja.mind.has_antag_datum(/datum/antagonist/ninja) - if(!ninja_antag) - return - var/datum/objective/cyborg_hijack/objective = locate() in ninja_antag.objectives - if(objective) - objective.completed = TRUE - -//CARBON MOBS// -/mob/living/carbon/ninjadrain_act(obj/item/clothing/suit/space/space_ninja/ninja_suit, mob/living/carbon/human/ninja, obj/item/clothing/gloves/space_ninja/ninja_gloves) - if(!ninja_suit || !ninja || !ninja_gloves) - return INVALID_DRAIN - - . = DRAIN_MOB_SHOCK_FAILED - - //Default cell = 10,000 charge, 10,000/1000 = 10 uses without charging/upgrading - if(ninja_suit.cell?.charge && ninja_suit.cell.use(1000)) - . = DRAIN_MOB_SHOCK - //Got that electric touch - var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() - spark_system.set_up(5, 0, loc) - playsound(src, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - visible_message(span_danger("[ninja] electrocutes [src] with [ninja.p_their()] touch!"), span_userdanger("[ninja] electrocutes you with [ninja.p_their()] touch!")) - Knockdown(3 SECONDS) diff --git a/code/modules/ninja/suit/shoes.dm b/code/modules/ninja/suit/shoes.dm deleted file mode 100644 index ad447917c3e..00000000000 --- a/code/modules/ninja/suit/shoes.dm +++ /dev/null @@ -1,23 +0,0 @@ -/** - * # Ninja Shoes - * - * Space ninja's shoes. Gives him armor on his feet. - * - * Space ninja's ninja shoes. How mousey. Gives him slip protection and protection against attacks. - * Also are temperature resistant. - * - */ -/obj/item/clothing/shoes/space_ninja - name = "ninja shoes" - desc = "A pair of running shoes. Excellent for running and even better for smashing skulls." - icon_state = "s-ninja" - inhand_icon_state = "secshoes" - clothing_flags = NOSLIP - resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF - armor = list(MELEE = 40, BULLET = 30, LASER = 20, ENERGY = 15, BOMB = 30, BIO = 100, FIRE = 100, ACID = 100) - strip_delay = 120 - cold_protection = FEET - min_cold_protection_temperature = SHOES_MIN_TEMP_PROTECT - heat_protection = FEET - max_heat_protection_temperature = SHOES_MAX_TEMP_PROTECT - slowdown = -0.5 //SKYRAT EDIT CHANGE diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm deleted file mode 100644 index b1107b90060..00000000000 --- a/code/modules/ninja/suit/suit.dm +++ /dev/null @@ -1,256 +0,0 @@ -/** - * # Ninja Suit - * - * Space ninja's suit. Provides him with most of his powers. - * - * Space ninja's suit. Gives space ninja all his iconic powers, which are mostly kept in - * the folder ninja_equipment_actions. Has a lot of unique stuff going on, so make sure to check - * the variables. Check suit_attackby to see radium interaction, disk copying, and cell replacement. - * - */ -/obj/item/clothing/suit/space/space_ninja - name = "ninja suit" - desc = "A unique, vacuum-proof suit of nano-enhanced armor designed specifically for Spider Clan assassins." - icon_state = "s-ninja" - inhand_icon_state = "s-ninja_suit" - allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/stock_parts/cell) - resistance_flags = LAVA_PROOF | ACID_PROOF - armor = list(MELEE = 40, BULLET = 30, LASER = 20,ENERGY = 30, BOMB = 30, BIO = 100, FIRE = 100, ACID = 100) - strip_delay = 12 - slowdown = 0 // SKYRAT EDIT ADDITION - min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT - actions_types = list(/datum/action/item_action/initialize_ninja_suit, /datum/action/item_action/ninjastatus, /datum/action/item_action/ninjaboost, /datum/action/item_action/ninjapulse, /datum/action/item_action/ninjastar, /datum/action/item_action/ninjanet, /datum/action/item_action/ninja_sword_recall, /datum/action/item_action/ninja_stealth) - - ///The person wearing the suit - var/mob/living/carbon/human/affecting = null - ///The suit's spark system, used for... sparking. - var/datum/effect_system/spark_spread/spark_system - ///The suit's stored research. Used for the research objective (see antagonist file) - var/datum/techweb/stored_research - ///The katana registered with the suit, used for recalling and catching the katana. Set when the ninja outfit is created. - var/obj/item/energy_katana/energyKatana - - ///The space ninja's hood. - var/obj/item/clothing/head/helmet/space/space_ninja/n_hood - ///The space ninja's shoes. - var/obj/item/clothing/shoes/space_ninja/n_shoes - ///The space ninja's gloves. - var/obj/item/clothing/gloves/space_ninja/n_gloves - ///The space ninja's mask. - var/obj/item/clothing/mask/gas/space_ninja/n_mask - - ///Whether or not the suit is currently booted up. Starts off. - var/s_initialized = FALSE//Suit starts off. - ///The suit's current cooldown. If not 0, blocks usage of most abilities, and decrements its value by 1 every process - var/s_coold = 0 - ///How much energy the suit expends in a single process - var/s_cost = 1 - ///Additional energy cost for cloaking per process - var/s_acost = 4 - ///How fast the suit is at certain actions, like draining power from things - var/s_delay = 40 - ///Units of radium required to refill the adrenaline boost - var/a_transfer = 20//How much radium is required to refill the adrenaline boost. - ///Whether or not the suit is currently in stealth mode. - var/stealth = FALSE//Stealth off. - ///Whether or not the wearer is in the middle of an action, like hacking. - var/s_busy = FALSE - ///Whether or not the adrenaline boost ability is available - var/a_boost = TRUE - -/obj/item/clothing/suit/space/space_ninja/examine(mob/user) - . = ..() - if(!s_initialized) - return - if(!user == affecting) - return - . += "All systems operational. Current energy capacity: [display_energy(cell.charge)].\n"+\ - "The CLOAK-tech device is [stealth?"active":"inactive"].\n"+\ - "[a_boost?"An adrenaline boost is available to use.":"There is no adrenaline boost available. Try refilling the suit with 20 units of radium."]" - -/obj/item/clothing/suit/space/space_ninja/Initialize(mapload) - . = ..() - - //Spark Init - spark_system = new - spark_system.set_up(5, 0, src) - spark_system.attach(src) - - //Research Init - stored_research = new() - - //Cell Init - cell = new/obj/item/stock_parts/cell/high - cell.charge = 9000 - cell.name = "black power cell" - cell.icon_state = "blkcell" //SKYRAT EDIT - original "bscell" - changed due to basetype's icon path/overlays changing - -/obj/item/clothing/suit/space/space_ninja/Destroy() - QDEL_NULL(spark_system) - QDEL_NULL(cell) - return ..() - -// seal the cell in the ninja outfit -/obj/item/clothing/suit/space/space_ninja/toggle_spacesuit_cell(mob/user) - return - -// Space Suit temperature regulation and power usage -/obj/item/clothing/suit/space/space_ninja/process(delta_time) - var/mob/living/carbon/human/user = src.loc - if(!user || !ishuman(user) || !(user.wear_suit == src)) - return - - // Check for energy usage - if(s_initialized) - if(!affecting) - terminate() // Kills the suit and attached objects. - else if(cell.charge > 0) - if(s_coold > 0) - s_coold = max(s_coold - delta_time, 0) // Checks for ability s_cooldown first. - cell.charge -= s_cost * delta_time // s_cost is the default energy cost each ntick, usually 5. - if(stealth) // If stealth is active. - cell.charge -= s_acost * delta_time - else - cell.charge = 0 - cancel_stealth() - - user.adjust_bodytemperature(BODYTEMP_NORMAL - user.bodytemperature) - -/obj/item/clothing/suit/space/space_ninja/ui_action_click(mob/user, action) - if(IS_NINJA_SUIT_INITIALIZATION(action)) - toggle_on_off() - return TRUE - if(!s_initialized) - to_chat(user, span_warning("ERROR: suit offline. Please activate suit.")) - return FALSE - if(s_coold > 0) - to_chat(user, span_warning("ERROR: suit is on cooldown.")) - return FALSE - if(IS_NINJA_SUIT_STATUS(action)) - ninjastatus() - return TRUE - if(IS_NINJA_SUIT_BOOST(action)) - ninjaboost() - return TRUE - if(IS_NINJA_SUIT_EMP(action)) - ninjapulse() - return TRUE - if(IS_NINJA_SUIT_STAR_CREATION(action)) - ninjastar() - return TRUE - if(IS_NINJA_SUIT_NET_CREATION(action)) - ninjanet() - return TRUE - if(IS_NINJA_SUIT_SWORD_RECALL(action)) - ninja_sword_recall() - return TRUE - if(IS_NINJA_SUIT_STEALTH(action)) - toggle_stealth() - return TRUE - return FALSE - -/obj/item/clothing/suit/space/space_ninja/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) - . = ..() - if(stealth) - cancel_stealth() - s_coold = 5 - -/** - * Proc for changing the suit's appearance upon locking. - * - * Proc for when space ninja's suit locks. If the user selects Original, gives it glowing lights, along with having an alternate sprite for female body types. - * Yes, we do have nipLEDs, how could you tell? - * If the user selects New Age, it applies new sprites to all the gear. - * Arguments: - * * ninja - The person wearing the suit. - */ -/obj/item/clothing/suit/space/space_ninja/proc/lockIcons(mob/living/carbon/human/ninja) - var/design_choice = tgui_alert(ninja, "Please choose your desired suit design.",,list("Original","New Age")) - switch(design_choice) - if("Original") - icon_state = ninja.physique == "female" ? "s-ninjanf" : "s-ninjan" - ninja.gloves.icon_state = "s-ninjan" - ninja.gloves.inhand_icon_state = "s-ninjan" - if("New Age") - icon_state ="ninja_new" - n_hood.icon_state = "ninja_newcowl" - n_gloves.icon_state = "ninja_new" - if(n_mask) - n_mask.icon_state = "ninja_new" - - -/** - * Proc called to lock the important gear pieces onto space ninja's body. - * - * Called during the suit startup to lock all gear pieces onto space ninja. - * Terminates if a gear piece is not being worn. Also gives the ninja the inability to use firearms. - * If the person in the suit isn't a ninja when this is called, this proc just gibs them instead. - * Arguments: - * * ninja - The person wearing the suit. - * * Returns false if the locking fails due to lack of all suit parts, and true if it succeeds. - */ -/obj/item/clothing/suit/space/space_ninja/proc/lock_suit(mob/living/carbon/human/ninja) - if(!istype(ninja)) - return FALSE - if(!IS_SPACE_NINJA(ninja)) - to_chat(ninja, span_danger("fÄTaL ÈÈRRoR: 382200-*#00CÖDE RED\nUNAU†HORIZED USÈ DETÈC†††eD\nCoMMÈNCING SUB-R0U†IN3 13...\nTÈRMInATING U-U-USÈR...")) - ninja.gib() - return FALSE - if(!istype(ninja.head, /obj/item/clothing/head/helmet/space/space_ninja)) - to_chat(ninja, "[span_userdanger("ERROR")]: 100113 UNABLE TO LOCATE HEAD GEAR\nABORTING...") - return FALSE - if(!istype(ninja.shoes, /obj/item/clothing/shoes/space_ninja)) - to_chat(ninja, "[span_userdanger("ERROR")]: 122011 UNABLE TO LOCATE FOOT GEAR\nABORTING...") - return FALSE - if(!istype(ninja.gloves, /obj/item/clothing/gloves/space_ninja)) - to_chat(ninja, "[span_userdanger("ERROR")]: 110223 UNABLE TO LOCATE HAND GEAR\nABORTING...") - return FALSE - affecting = ninja - ADD_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT) - n_hood = ninja.head - ADD_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT) - n_shoes = ninja.shoes - ADD_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT) - n_gloves = ninja.gloves - ADD_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT) - n_mask = ninja.wear_mask - - ADD_TRAIT(ninja, TRAIT_NOGUNS, NINJA_SUIT_TRAIT) - return TRUE - -/** - * Proc called to unlock all the gear off space ninja's body. - * - * Proc which is essentially the opposite of lock_suit. Lets you take off all the suit parts. - * Also gets rid of the objection to using firearms from the wearer. - * Arguments: - * * ninja - The person wearing the suit. - */ -/obj/item/clothing/suit/space/space_ninja/proc/unlock_suit(mob/living/carbon/human/ninja) - affecting = null - REMOVE_TRAIT(src, TRAIT_NODROP, NINJA_SUIT_TRAIT) - icon_state = "s-ninja" - if(n_hood)//Should be attached, might not be attached. - REMOVE_TRAIT(n_hood, TRAIT_NODROP, NINJA_SUIT_TRAIT) - n_hood.icon_state = "s-ninja" - if(n_shoes) - REMOVE_TRAIT(n_shoes, TRAIT_NODROP, NINJA_SUIT_TRAIT) - if(n_gloves) - n_gloves.icon_state = "black" - REMOVE_TRAIT(n_gloves, TRAIT_NODROP, NINJA_SUIT_TRAIT) - n_gloves.draining = FALSE - - REMOVE_TRAIT(ninja, TRAIT_NOGUNS, NINJA_SUIT_TRAIT) - if(n_mask) - n_mask.icon_state = "s-ninja" - -/** - * Proc used to delete all the attachments and itself. - * - * Can be called to entire rid of the suit pieces and the suit itself. - */ -/obj/item/clothing/suit/space/space_ninja/proc/terminate() - QDEL_NULL(n_hood) - QDEL_NULL(n_gloves) - QDEL_NULL(n_shoes) - QDEL_NULL(src) diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm deleted file mode 100644 index 5f10111e595..00000000000 --- a/code/modules/power/apc.dm +++ /dev/null @@ -1,1645 +0,0 @@ -// APC electronics status: -/// There are no electronics in the APC. -#define APC_ELECTRONICS_MISSING 0 -/// The electronics are installed but not secured. -#define APC_ELECTRONICS_INSTALLED 1 -/// The electronics are installed and secured. -#define APC_ELECTRONICS_SECURED 2 - -// APC cover status: -/// The APCs cover is closed. -#define APC_COVER_CLOSED 0 -/// The APCs cover is open. -#define APC_COVER_OPENED 1 -/// The APCs cover is missing. -#define APC_COVER_REMOVED 2 - -// APC visuals -/// Pixel offset of the APC from the floor turf -#define APC_PIXEL_OFFSET 25 - -// APC charging status: -/// The APC is not charging. -#define APC_NOT_CHARGING 0 -/// The APC is charging. -#define APC_CHARGING 1 -/// The APC is fully charged. -#define APC_FULLY_CHARGED 2 - -// APC channel status: -/// The APCs power channel is manually set off. -#define APC_CHANNEL_OFF 0 -/// The APCs power channel is automatically off. -#define APC_CHANNEL_AUTO_OFF 1 -/// The APCs power channel is manually set on. -#define APC_CHANNEL_ON 2 -/// The APCs power channel is automatically on. -#define APC_CHANNEL_AUTO_ON 3 - -#define APC_CHANNEL_IS_ON(channel) (channel >= APC_CHANNEL_ON) - -// APC autoset enums: -/// The APC turns automated and manual power channels off. -#define AUTOSET_FORCE_OFF 0 -/// The APC turns automated power channels off. -#define AUTOSET_OFF 2 -/// The APC turns automated power channels on. -#define AUTOSET_ON 1 - -// External power status: -/// The APC either isn't attached to a powernet or there is no power on the external powernet. -#define APC_NO_POWER 0 -/// The APCs external powernet does not have enough power to charge the APC. -#define APC_LOW_POWER 1 -/// The APCs external powernet has enough power to charge the APC. -#define APC_HAS_POWER 2 - -// Ethereals: -/// How long it takes an ethereal to drain or charge APCs. Also used as a spam limiter. -#define APC_DRAIN_TIME (7.5 SECONDS) -/// How much power ethereals gain/drain from APCs. -#define APC_POWER_GAIN 200 - -// Wires & EMPs: -/// The wire value used to reset the APCs wires after one's EMPed. -#define APC_RESET_EMP "emp" - -// Arcing: - SKYRAT EDIT ADD -/// Lower excess value for APC arcing, 5% chance to arc -#define APC_ARC_LOWERLIMIT 2500000 -/// Moderate excess value for APC arcing, 10% chance to arc -#define APC_ARC_MEDIUMLIMIT 5000000 -/// Upper excess value for for APC arcing, 15% chance to arc -#define APC_ARC_UPPERLIMIT 7500000 -// SKYRAT EDIT ADD END - -// update_state -// Bitshifts: (If you change the status values to be something other than an int or able to exceed 3 you will need to change these too) -/// The bit shift for the APCs cover status. -#define UPSTATE_COVER_SHIFT (0) - /// The bitflag representing the APCs cover being open for icon purposes. - #define UPSTATE_OPENED1 (APC_COVER_OPENED << UPSTATE_COVER_SHIFT) - /// The bitflag representing the APCs cover being missing for icon purposes. - #define UPSTATE_OPENED2 (APC_COVER_REMOVED << UPSTATE_COVER_SHIFT) - -// Bitflags: -/// The APC has a power cell. -#define UPSTATE_CELL_IN (1<<2) -/// The APC is broken or damaged. -#define UPSTATE_BROKE (1<<3) -/// The APC is undergoing maintenance. -#define UPSTATE_MAINT (1<<4) -/// The APC is emagged or malfed. -#define UPSTATE_BLUESCREEN (1<<5) -/// The APCs wires are exposed. -#define UPSTATE_WIREEXP (1<<6) - -// update_overlay -// Bitflags: -/// Bitflag indicating that the APCs operating status overlay should be shown. -#define UPOVERLAY_OPERATING (1<<0) -/// Bitflag indicating that the APCs locked status overlay should be shown. -#define UPOVERLAY_LOCKED (1<<1) - -// Bitshifts: (If you change the status values to be something other than an int or able to exceed 3 you will need to change these too) -/// Bit shift for the charging status of the APC. -#define UPOVERLAY_CHARGING_SHIFT (2) -/// Bit shift for the equipment status of the APC. -#define UPOVERLAY_EQUIPMENT_SHIFT (4) -/// Bit shift for the lighting channel status of the APC. -#define UPOVERLAY_LIGHTING_SHIFT (6) -/// Bit shift for the environment channel status of the APC. -#define UPOVERLAY_ENVIRON_SHIFT (8) - -// the Area Power Controller (APC), formerly Power Distribution Unit (PDU) -// one per area, needs wire connection to power network through a terminal - -// controls power to devices in that area -// may be opened to change power cell -// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto -//ICON OVERRIDEN IN SKYRAT AESTHETICS - SEE MODULE -/obj/machinery/power/apc - name = "area power controller" - desc = "A control terminal for the area's electrical systems." - - icon_state = "apc0" - use_power = NO_POWER_USE - req_access = null - max_integrity = 200 - integrity_failure = 0.25 - damage_deflection = 10 - resistance_flags = FIRE_PROOF - interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON - - var/lon_range = 1.5 - var/area/area - var/areastring = null - var/obj/item/stock_parts/cell/cell - var/start_charge = 90 // initial cell charge % - var/cell_type = /obj/item/stock_parts/cell/upgraded //Base cell has 2500 capacity. Enter the path of a different cell you want to use. cell determines charge rates, max capacity, ect. These can also be changed with other APC vars, but isn't recommended to minimize the risk of accidental usage of dirty editted APCs - var/opened = APC_COVER_CLOSED - var/shorted = FALSE - var/lighting = APC_CHANNEL_AUTO_ON - var/equipment = APC_CHANNEL_AUTO_ON - var/environ = APC_CHANNEL_AUTO_ON - var/operating = TRUE - var/charging = APC_NOT_CHARGING - var/chargemode = TRUE - var/chargecount = 0 - var/locked = TRUE - var/coverlocked = TRUE - var/aidisabled = FALSE - var/obj/machinery/power/terminal/terminal = null - var/lastused_light = 0 - var/lastused_equip = 0 - var/lastused_environ = 0 - var/lastused_total = 0 - var/main_status = 0 - powernet = FALSE // set so that APCs aren't found as powernet nodes //Hackish, Horrible, was like this before I changed it :( - var/malfhack = FALSE //New var for my changes to AI malf. --NeoFite - var/mob/living/silicon/ai/malfai = null //See above --NeoFite - var/has_electronics = APC_ELECTRONICS_MISSING // 0 - none, 1 - plugged in, 2 - secured by screwdriver - var/overload = 1 //used for the Blackout malf module - var/beenhit = 0 // used for counting how many times it has been hit, used for Aliens at the moment - var/mob/living/silicon/ai/occupier = null - var/transfer_in_progress = FALSE //Is there an AI being transferred out of us? - ///buffer state that makes apcs not shut off channels immediately as long as theres some power left, effect visible in apcs only slowly losing power - var/longtermpower = 10 - var/auto_name = FALSE - var/failure_timer = 0 - var/force_update = FALSE - var/emergency_lights = FALSE - var/nightshift_lights = FALSE - var/last_nightshift_switch = 0 - var/update_state = -1 - var/update_overlay = -1 - var/icon_update_needed = FALSE - var/obj/machinery/computer/apc_control/remote_control = null - ///Represents a signel source of power alarms for this apc - var/datum/alarm_handler/alarm_manager - - var/shock_proof = FALSE // SKYRAT EDIT ADD - APC Arcing. If TRUE, APCs will not arc. - -/obj/machinery/power/apc/unlocked - locked = FALSE - -/obj/machinery/power/apc/syndicate //general syndicate access - req_access = list(ACCESS_SYNDICATE) - -/obj/machinery/power/apc/away //general away mission access - req_access = list(ACCESS_AWAY_GENERAL) - -/obj/machinery/power/apc/highcap/five_k - cell_type = /obj/item/stock_parts/cell/upgraded/plus - -/obj/machinery/power/apc/highcap/ten_k - cell_type = /obj/item/stock_parts/cell/high - -/obj/machinery/power/apc/auto_name - auto_name = TRUE - -MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/power/apc/auto_name, APC_PIXEL_OFFSET) - -/obj/machinery/power/apc/get_cell() - return cell - -/obj/machinery/power/apc/connect_to_network() - //Override because the APC does not directly connect to the network; it goes through a terminal. - //The terminal is what the power computer looks for anyway. - if(terminal) - terminal.connect_to_network() - -/obj/machinery/power/apc/New(turf/loc, ndir, building=0) - if (!req_access) - req_access = list(ACCESS_ENGINE_EQUIP) - if (!armor) - armor = list(MELEE = 20, BULLET = 20, LASER = 10, ENERGY = 100, BOMB = 30, BIO = 100, FIRE = 90, ACID = 50) - ..() - GLOB.apcs_list += src - - wires = new /datum/wires/apc(src) - - if (building) - area = get_area(src) - opened = APC_COVER_OPENED - operating = FALSE - name = "\improper [get_area_name(area, TRUE)] APC" - set_machine_stat(machine_stat | MAINT) - update_appearance() - addtimer(CALLBACK(src, .proc/update), 5) - dir = ndir - - // offset APC_PIXEL_OFFSET pixels in direction of dir - // this allows the APC to be embedded in a wall, yet still inside an area - var/offset_old - switch(dir) - if(NORTH) - offset_old = pixel_y - pixel_y = APC_PIXEL_OFFSET - if(SOUTH) - offset_old = pixel_y - pixel_y = -APC_PIXEL_OFFSET - if(EAST) - offset_old = pixel_x - pixel_x = APC_PIXEL_OFFSET - if(WEST) - offset_old = pixel_x - pixel_x = -APC_PIXEL_OFFSET - if(abs(offset_old) != APC_PIXEL_OFFSET && !building) - log_mapping("APC: ([src]) at [AREACOORD(src)] with dir ([dir] | [uppertext(dir2text(dir))]) has pixel_[dir & (WEST|EAST) ? "x" : "y"] value [offset_old] - should be [dir & (SOUTH|EAST) ? "-" : ""][APC_PIXEL_OFFSET]. Use the directional/ helpers!") - -/obj/machinery/power/apc/Destroy() - GLOB.apcs_list -= src - - if(malfai && operating) - malfai.malf_picker.processing_time = clamp(malfai.malf_picker.processing_time - 10,0,1000) - if(area) - area.power_light = FALSE - area.power_equip = FALSE - area.power_environ = FALSE - area.power_change() - area.apc = null - QDEL_NULL(alarm_manager) - if(occupier) - malfvacate(TRUE) - if(wires) - QDEL_NULL(wires) - if(cell) - QDEL_NULL(cell) - if(terminal) - disconnect_terminal() - . = ..() - -/obj/machinery/power/apc/handle_atom_del(atom/A) - if(A == cell) - cell = null - update_appearance() - updateUsrDialog() - -/obj/machinery/power/apc/proc/make_terminal() - // create a terminal object at the same position as original turf loc - // wires will attach to this - terminal = new/obj/machinery/power/terminal(loc) - terminal.setDir(dir) - terminal.master = src - -/obj/machinery/power/apc/Initialize(mapload) - . = ..() - AddElement(/datum/element/atmos_sensitive, mapload) - alarm_manager = new(src) - - if(!mapload) - return - has_electronics = APC_ELECTRONICS_SECURED - // is starting with a power cell installed, create it and set its charge level - if(cell_type) - cell = new cell_type - cell.charge = start_charge * cell.maxcharge / 100 // (convert percentage to actual value) - - var/area/A = loc.loc - - //if area isn't specified use current - if(areastring) - area = get_area_instance_from_text(areastring) - if(!area) - area = A - stack_trace("Bad areastring path for [src], [areastring]") - else if(isarea(A) && areastring == null) - area = A - - if(auto_name) - name = "\improper [get_area_name(area, TRUE)] APC" - - if (area) - if (area.apc) - log_mapping("Duplicate APC created at [AREACOORD(src)]") - area.apc = src - - update_appearance() - - make_terminal() - - addtimer(CALLBACK(src, .proc/update), 5) - -/obj/machinery/power/apc/should_atmos_process(datum/gas_mixture/air, exposed_temperature) - return (exposed_temperature > 2000) - -/obj/machinery/power/apc/atmos_expose(datum/gas_mixture/air, exposed_temperature) - take_damage(min(exposed_temperature/100, 10), BURN) - -/obj/machinery/power/apc/examine(mob/user) - . = ..() - if(machine_stat & BROKEN) - return - if(opened) - if(has_electronics && terminal) - . += "The cover is [opened==APC_COVER_REMOVED?"removed":"open"] and the power cell is [ cell ? "installed" : "missing"]." - else - . += {"It's [ !terminal ? "not" : "" ] wired up.\n - The electronics are[!has_electronics?"n't":""] installed."} - else - if (machine_stat & MAINT) - . += "The cover is closed. Something is wrong with it. It doesn't work." - else if (malfhack) - . += "The cover is broken. It may be hard to force it open." - else - . += "The cover is closed." - - . += span_notice("Right-click the APC to [ locked ? "unlock" : "lock"] the interface.") - - if(issilicon(user)) - . += span_notice("Ctrl-Click the APC to switch the breaker [ operating ? "off" : "on"].") - -// update the APC icon to show the three base states -// also add overlays for indicator lights -/obj/machinery/power/apc/update_appearance(updates=check_updates()) - icon_update_needed = FALSE - if(!updates) - return - - . = ..() - // And now, separately for cleanness, the lighting changing - if(!update_state) - switch(charging) - if(APC_NOT_CHARGING) - set_light_color(COLOR_SOFT_RED) - if(APC_CHARGING) - // set_light_color(LIGHT_COLOR_BLUE) ORIGINAL - set_light_color(LIGHT_COLOR_ORANGE)//SKYRAT EDIT CHANGE - AESTHETICS - if(APC_FULLY_CHARGED) - set_light_color(LIGHT_COLOR_GREEN) - set_light(lon_range) - return - - if(update_state & UPSTATE_BLUESCREEN) - set_light_color(LIGHT_COLOR_BLUE) - set_light(lon_range) - return - - set_light(0) - -/obj/machinery/power/apc/update_icon_state() - if(!update_state) - icon_state = "apc0" - return ..() - if(update_state & (UPSTATE_OPENED1|UPSTATE_OPENED2)) - var/basestate = "apc[cell ? 2 : 1]" - if(update_state & UPSTATE_OPENED1) - icon_state = (update_state & (UPSTATE_MAINT|UPSTATE_BROKE)) ? "apcmaint" : basestate - else if(update_state & UPSTATE_OPENED2) - icon_state = "[basestate][((update_state & UPSTATE_BROKE) || malfhack) ? "-b" : null]-nocover" - return ..() - if(update_state & UPSTATE_BROKE) - icon_state = "apc-b" - return ..() - if(update_state & UPSTATE_BLUESCREEN) - icon_state = "apcemag" - return ..() - if(update_state & UPSTATE_WIREEXP) - icon_state = "apcewires" - return ..() - if(update_state & UPSTATE_MAINT) - icon_state = "apc0" - return ..() - -/obj/machinery/power/apc/update_overlays() - . = ..() - if((machine_stat & (BROKEN|MAINT)) || update_state) - return - - . += mutable_appearance(icon, "apcox-[locked]") - . += emissive_appearance(icon, "apcox-[locked]") - . += mutable_appearance(icon, "apco3-[charging]") - . += emissive_appearance(icon, "apco3-[charging]") - if(!operating) - return - - . += mutable_appearance(icon, "apco0-[equipment]") - . += emissive_appearance(icon, "apco0-[equipment]") - . += mutable_appearance(icon, "apco1-[lighting]") - . += emissive_appearance(icon, "apco1-[lighting]") - . += mutable_appearance(icon, "apco2-[environ]") - . += emissive_appearance(icon, "apco2-[environ]") - -/// Checks for what icon updates we will need to handle -/obj/machinery/power/apc/proc/check_updates() - SIGNAL_HANDLER - . = NONE - - // Handle icon status: - var/new_update_state = NONE - if(machine_stat & BROKEN) - new_update_state |= UPSTATE_BROKE - if(machine_stat & MAINT) - new_update_state |= UPSTATE_MAINT - - if(opened) - new_update_state |= (opened << UPSTATE_COVER_SHIFT) - if(cell) - new_update_state |= UPSTATE_CELL_IN - - else if((obj_flags & EMAGGED) || malfai) - new_update_state |= UPSTATE_BLUESCREEN - else if(panel_open) - new_update_state |= UPSTATE_WIREEXP - - if(new_update_state != update_state) - update_state = new_update_state - . |= UPDATE_ICON_STATE - - // Handle overlay status: - var/new_update_overlay = NONE - if(operating) - new_update_overlay |= UPOVERLAY_OPERATING - - if(!update_state) - if(locked) - new_update_overlay |= UPOVERLAY_LOCKED - - new_update_overlay |= (charging << UPOVERLAY_CHARGING_SHIFT) - new_update_overlay |= (equipment << UPOVERLAY_EQUIPMENT_SHIFT) - new_update_overlay |= (lighting << UPOVERLAY_LIGHTING_SHIFT) - new_update_overlay |= (environ << UPOVERLAY_ENVIRON_SHIFT) - - if(new_update_overlay != update_overlay) - update_overlay = new_update_overlay - . |= UPDATE_OVERLAYS - - -// Used in process so it doesn't update the icon too much -/obj/machinery/power/apc/proc/queue_icon_update() - icon_update_needed = TRUE - -//attack with an item - open/close cover, insert cell, or (un)lock interface - -/obj/machinery/power/apc/crowbar_act(mob/user, obj/item/W) - . = TRUE - if (opened) - if (has_electronics == APC_ELECTRONICS_INSTALLED) - if (terminal) - to_chat(user, span_warning("Disconnect the wires first!")) - return - W.play_tool_sound(src) - to_chat(user, span_notice("You attempt to remove the power control board...") ) - if(W.use_tool(src, user, 50)) - if (has_electronics == APC_ELECTRONICS_INSTALLED) - has_electronics = APC_ELECTRONICS_MISSING - if (machine_stat & BROKEN) - user.visible_message(span_notice("[user.name] breaks the power control board inside [src.name]!"),\ - span_notice("You break the charred power control board and remove the remains."), - span_hear("You hear a crack.")) - return - else if (obj_flags & EMAGGED) - obj_flags &= ~EMAGGED - user.visible_message(span_notice("[user.name] discards an emagged power control board from [src.name]!"),\ - span_notice("You discard the emagged power control board.")) - return - else if (malfhack) - user.visible_message(span_notice("[user.name] discards a strangely programmed power control board from [src.name]!"),\ - span_notice("You discard the strangely programmed board.")) - malfai = null - malfhack = 0 - return - else - user.visible_message(span_notice("[user.name] removes the power control board from [src.name]!"),\ - span_notice("You remove the power control board.")) - new /obj/item/electronics/apc(loc) - return - else if (opened!=APC_COVER_REMOVED) - opened = APC_COVER_CLOSED - coverlocked = TRUE //closing cover relocks it - update_appearance() - return - else if (!(machine_stat & BROKEN)) - if(coverlocked && !(machine_stat & MAINT)) // locked... - to_chat(user, span_warning("The cover is locked and cannot be opened!")) - return - else if (panel_open) - to_chat(user, span_warning("Exposed wires prevents you from opening it!")) - return - else - opened = APC_COVER_OPENED - update_appearance() - return - -/obj/machinery/power/apc/screwdriver_act(mob/living/user, obj/item/W) - if(..()) - return TRUE - . = TRUE - if(opened) - if(cell) - user.visible_message(span_notice("[user] removes \the [cell] from [src]!"), span_notice("You remove \the [cell].")) - var/turf/T = get_turf(user) - cell.forceMove(T) - cell.update_appearance() - cell = null - charging = APC_NOT_CHARGING - update_appearance() - return - else - switch (has_electronics) - if (APC_ELECTRONICS_INSTALLED) - has_electronics = APC_ELECTRONICS_SECURED - set_machine_stat(machine_stat & ~MAINT) - W.play_tool_sound(src) - to_chat(user, span_notice("You screw the circuit electronics into place.")) - if (APC_ELECTRONICS_SECURED) - has_electronics = APC_ELECTRONICS_INSTALLED - set_machine_stat(machine_stat | MAINT) - W.play_tool_sound(src) - to_chat(user, span_notice("You unfasten the electronics.")) - else - to_chat(user, span_warning("There is nothing to secure!")) - return - update_appearance() - else if(obj_flags & EMAGGED) - to_chat(user, span_warning("The interface is broken!")) - return - else - panel_open = !panel_open - to_chat(user, span_notice("The wires have been [panel_open ? "exposed" : "unexposed"].")) - update_appearance() - -/obj/machinery/power/apc/wirecutter_act(mob/living/user, obj/item/W) - . = ..() - if (terminal && opened) - terminal.dismantle(user, W) - return TRUE - - -/obj/machinery/power/apc/welder_act(mob/living/user, obj/item/W) - . = ..() - if (opened && !has_electronics && !terminal) - if(!W.tool_start_check(user, amount=3)) - return - user.visible_message(span_notice("[user.name] welds [src]."), \ - span_notice("You start welding the APC frame..."), \ - span_hear("You hear welding.")) - if(W.use_tool(src, user, 50, volume=50, amount=3)) - if ((machine_stat & BROKEN) || opened==APC_COVER_REMOVED) - new /obj/item/stack/sheet/iron(loc) - user.visible_message(span_notice("[user.name] cuts [src] apart with [W]."),\ - span_notice("You disassembled the broken APC frame.")) - else - new /obj/item/wallframe/apc(loc) - user.visible_message(span_notice("[user.name] cuts [src] from the wall with [W]."),\ - span_notice("You cut the APC frame from the wall.")) - qdel(src) - return TRUE - -/obj/machinery/power/apc/attackby(obj/item/W, mob/living/user, params) - if(HAS_TRAIT(W, TRAIT_APC_SHOCKING)) - var/metal = 0 - var/shock_source = null - metal += LAZYACCESS(W.custom_materials, GET_MATERIAL_REF(/datum/material/iron))//This prevents wooden rolling pins from shocking the user - - if(cell || terminal) //The mob gets shocked by whichever powersource has the most electricity - if(cell && terminal) - shock_source = cell.charge > terminal.powernet.avail ? cell : terminal.powernet - else - shock_source = terminal?.powernet || cell - - if(shock_source && metal && (panel_open || opened)) //Now you're cooking with electricity - if(electrocute_mob(user, shock_source, src, siemens_coeff = 1, dist_check = TRUE))//People with insulated gloves just attack the APC normally. They're just short of magical anyway - do_sparks(5, TRUE, src) - user.visible_message(span_notice("[user.name] shoves [W] into the internal components of [src], erupting into a cascade of sparks!")) - if(shock_source == cell)//If the shock is coming from the cell just fully discharge it, because it's funny - cell.use(cell.charge) - return - - if(issilicon(user) && get_dist(src,user)>1) - return attack_hand(user) - - if (istype(W, /obj/item/stock_parts/cell) && opened) - if(cell) - to_chat(user, span_warning("There is a power cell already installed!")) - return - else - if (machine_stat & MAINT) - to_chat(user, span_warning("There is no connector for your power cell!")) - return - if(!user.transferItemToLoc(W, src)) - return - cell = W - user.visible_message(span_notice("[user.name] inserts the power cell to [src.name]!"),\ - span_notice("You insert the power cell.")) - chargecount = 0 - update_appearance() - else if (W.GetID()) - togglelock(user) - else if (istype(W, /obj/item/stack/cable_coil) && opened) - var/turf/host_turf = get_turf(src) - if(!host_turf) - CRASH("attackby on APC when it's not on a turf") - if (host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE) - to_chat(user, span_warning("You must remove the floor plating in front of the APC first!")) - return - else if (terminal) - to_chat(user, span_warning("This APC is already wired!")) - return - else if (!has_electronics) - to_chat(user, span_warning("There is nothing to wire!")) - return - - var/obj/item/stack/cable_coil/C = W - if(C.get_amount() < 10) - to_chat(user, span_warning("You need ten lengths of cable for APC!")) - return - user.visible_message(span_notice("[user.name] adds cables to the APC frame."), \ - span_notice("You start adding cables to the APC frame...")) - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE) - if(do_after(user, 20, target = src)) - if (C.get_amount() < 10 || !C) - return - if (C.get_amount() >= 10 && !terminal && opened && has_electronics) - var/turf/T = get_turf(src) - var/obj/structure/cable/N = T.get_cable_node() - if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) - do_sparks(5, TRUE, src) - return - C.use(10) - to_chat(user, span_notice("You add cables to the APC frame.")) - make_terminal() - terminal.connect_to_network() - else if (istype(W, /obj/item/electronics/apc) && opened) - if (has_electronics) - to_chat(user, span_warning("There is already a board inside the [src]!")) - return - else if (machine_stat & BROKEN) - to_chat(user, span_warning("You cannot put the board inside, the frame is damaged!")) - return - - user.visible_message(span_notice("[user.name] inserts the power control board into [src]."), \ - span_notice("You start to insert the power control board into the frame...")) - playsound(src.loc, 'sound/items/deconstruct.ogg', 50, TRUE) - if(do_after(user, 10, target = src)) - if(!has_electronics) - has_electronics = APC_ELECTRONICS_INSTALLED - locked = FALSE - to_chat(user, span_notice("You place the power control board inside the frame.")) - qdel(W) - else if(istype(W, /obj/item/electroadaptive_pseudocircuit) && opened) - var/obj/item/electroadaptive_pseudocircuit/P = W - if(!has_electronics) - if(machine_stat & BROKEN) - to_chat(user, span_warning("[src]'s frame is too damaged to support a circuit.")) - return - if(!P.adapt_circuit(user, 50)) - return - user.visible_message(span_notice("[user] fabricates a circuit and places it into [src]."), \ - span_notice("You adapt a power control board and click it into place in [src]'s guts.")) - has_electronics = APC_ELECTRONICS_INSTALLED - locked = FALSE - else if(!cell) - if(machine_stat & MAINT) - to_chat(user, span_warning("There's no connector for a power cell.")) - return - if(!P.adapt_circuit(user, 500)) - return - var/obj/item/stock_parts/cell/crap/empty/C = new(src) - C.forceMove(src) - cell = C - chargecount = 0 - user.visible_message(span_notice("[user] fabricates a weak power cell and places it into [src]."), \ - span_warning("Your [P.name] whirrs with strain as you create a weak power cell and place it into [src]!")) - update_appearance() - else - to_chat(user, span_warning("[src] has both electronics and a cell.")) - return - else if (istype(W, /obj/item/wallframe/apc) && opened) - if (!(machine_stat & BROKEN || opened==APC_COVER_REMOVED || atom_integrity < max_integrity)) // There is nothing to repair - to_chat(user, span_warning("You found no reason for repairing this APC!")) - return - if (!(machine_stat & BROKEN) && opened==APC_COVER_REMOVED) // Cover is the only thing broken, we do not need to remove elctronicks to replace cover - user.visible_message(span_notice("[user.name] replaces missing APC's cover."), \ - span_notice("You begin to replace APC's cover...")) - if(do_after(user, 20, target = src)) // replacing cover is quicker than replacing whole frame - to_chat(user, span_notice("You replace missing APC's cover.")) - qdel(W) - opened = APC_COVER_OPENED - update_appearance() - return - if (has_electronics) - to_chat(user, span_warning("You cannot repair this APC until you remove the electronics still inside!")) - return - user.visible_message(span_notice("[user.name] replaces the damaged APC frame with a new one."), \ - span_notice("You begin to replace the damaged APC frame...")) - if(do_after(user, 50, target = src)) - to_chat(user, span_notice("You replace the damaged APC frame with a new one.")) - qdel(W) - set_machine_stat(machine_stat & ~BROKEN) - atom_integrity = max_integrity - if (opened==APC_COVER_REMOVED) - opened = APC_COVER_OPENED - update_appearance() - return - else if(panel_open && !opened && is_wire_tool(W)) - wires.interact(user) - // SKYRAT EDIT ADD - SHOCK-PROOFING APCS - else if(istype(W, /obj/item/stack/sheet/bronze) && panel_open) - if(shock_proof) - to_chat(user, "This APC has already been shock proofed!") - else - var/obj/item/stack/sheet/bronze/bronze = W - bronze.use(1) - to_chat(user, "You form the bronze sheet into a grounding component, preventing the APC from arcing!") - shock_proof = TRUE - else if(W.tool_behaviour == TOOL_WRENCH && panel_open && shock_proof) - to_chat(user, "You unwrench the grounding component and discard it!") - shock_proof = FALSE - W.play_tool_sound(src, 50) - //SKYRAT EDIT END - else - return ..() - -/obj/machinery/power/apc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) - if(the_rcd.upgrade & RCD_UPGRADE_SIMPLE_CIRCUITS) - if(!has_electronics) - if(machine_stat & BROKEN) - to_chat(user, span_warning("[src]'s frame is too damaged to support a circuit.")) - return FALSE - return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 20, "cost" = 1) - else if(!cell) - if(machine_stat & MAINT) - to_chat(user, span_warning("There's no connector for a power cell.")) - return FALSE - return list("mode" = RCD_UPGRADE_SIMPLE_CIRCUITS, "delay" = 50, "cost" = 10) //16 for a wall - else - to_chat(user, span_warning("[src] has both electronics and a cell.")) - return FALSE - return FALSE - -/obj/machinery/power/apc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, passed_mode) - switch(passed_mode) - if(RCD_UPGRADE_SIMPLE_CIRCUITS) - if(!has_electronics) - if(machine_stat & BROKEN) - to_chat(user, span_warning("[src]'s frame is too damaged to support a circuit.")) - return - user.visible_message(span_notice("[user] fabricates a circuit and places it into [src]."), \ - span_notice("You adapt a power control board and click it into place in [src]'s guts.")) - has_electronics = TRUE - locked = TRUE - return TRUE - else if(!cell) - if(machine_stat & MAINT) - to_chat(user, span_warning("There's no connector for a power cell.")) - return FALSE - var/obj/item/stock_parts/cell/crap/empty/C = new(src) - C.forceMove(src) - cell = C - chargecount = 0 - user.visible_message(span_notice("[user] fabricates a weak power cell and places it into [src]."), \ - span_warning("Your [the_rcd.name] whirrs with strain as you create a weak power cell and place it into [src]!")) - update_appearance() - return TRUE - else - to_chat(user, span_warning("[src] has both electronics and a cell.")) - return FALSE - return FALSE - -/obj/machinery/power/apc/attack_hand_secondary(mob/user, list/modifiers) - . = ..() - if(!can_interact(user)) - return - if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc)) - return - if(!ishuman(user)) - return - var/mob/living/carbon/human/apc_interactor = user - var/obj/item/organ/internal/stomach/ethereal/maybe_ethereal_stomach = apc_interactor.getorganslot(ORGAN_SLOT_STOMACH) - if(!istype(maybe_ethereal_stomach)) - togglelock(user) - else - if(maybe_ethereal_stomach.crystal_charge >= ETHEREAL_CHARGE_NORMAL) - togglelock(user) - ethereal_interact(user,modifiers) - return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN - -/obj/machinery/power/apc/proc/ethereal_interact(mob/living/user,list/modifiers) - if(!ishuman(user)) - return - var/mob/living/carbon/human/ethereal = user - var/obj/item/organ/internal/stomach/maybe_stomach = ethereal.getorganslot(ORGAN_SLOT_STOMACH) - - if(!istype(maybe_stomach, /obj/item/organ/internal/stomach/ethereal)) - return - var/charge_limit = ETHEREAL_CHARGE_DANGEROUS - APC_POWER_GAIN - var/obj/item/organ/internal/stomach/ethereal/stomach = maybe_stomach - if(!((stomach?.drain_time < world.time) && LAZYACCESS(modifiers, RIGHT_CLICK))) - return - if(ethereal.combat_mode) - if(cell.charge <= (cell.maxcharge / 2)) // ethereals can't drain APCs under half charge, this is so that they are forced to look to alternative power sources if the station is running low - to_chat(ethereal, span_warning("The APC's syphon safeties prevent you from draining power!")) - return - if(stomach.crystal_charge > charge_limit) - to_chat(ethereal, span_warning("Your charge is full!")) - return - stomach.drain_time = world.time + APC_DRAIN_TIME - to_chat(ethereal, span_notice("You start channeling some power through the APC into your body.")) - if(do_after(user, APC_DRAIN_TIME, target = src)) - if(cell.charge <= (cell.maxcharge / 2) || (stomach.crystal_charge > charge_limit)) - return - to_chat(ethereal, span_notice("You receive some charge from the APC.")) - stomach.adjust_charge(APC_POWER_GAIN) - cell.charge -= APC_POWER_GAIN - else - if(cell.charge >= cell.maxcharge - APC_POWER_GAIN) - to_chat(ethereal, span_warning("The APC can't receive anymore power!")) - return - if(stomach.crystal_charge < APC_POWER_GAIN) - to_chat(ethereal, span_warning("Your charge is too low!")) - return - stomach.drain_time = world.time + APC_DRAIN_TIME - to_chat(ethereal, span_notice("You start channeling power through your body into the APC.")) - if(do_after(user, APC_DRAIN_TIME, target = src)) - if((cell.charge >= (cell.maxcharge - APC_POWER_GAIN)) || (stomach.crystal_charge < APC_POWER_GAIN)) - to_chat(ethereal, span_warning("You can't transfer power to the APC!")) - return - if(istype(stomach)) - to_chat(ethereal, span_notice("You transfer some power to the APC.")) - stomach.adjust_charge(-APC_POWER_GAIN) - cell.charge += APC_POWER_GAIN - else - to_chat(ethereal, span_warning("You can't transfer power to the APC!")) - -/obj/machinery/power/apc/proc/togglelock(mob/living/user) - if(obj_flags & EMAGGED) - to_chat(user, span_warning("The interface is broken!")) - else if(opened) - to_chat(user, span_warning("You must close the cover to swipe an ID card!")) - else if(panel_open) - to_chat(user, span_warning("You must close the panel!")) - else if(machine_stat & (BROKEN|MAINT)) - to_chat(user, span_warning("Nothing happens!")) - else - if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN) && !malfhack) - locked = !locked - to_chat(user, span_notice("You [ locked ? "lock" : "unlock"] the APC interface.")) - update_appearance() - updateUsrDialog() - else - to_chat(user, span_warning("Access denied.")) - -/obj/machinery/power/apc/proc/toggle_nightshift_lights(mob/living/user) - if(last_nightshift_switch > world.time - 100) //~10 seconds between each toggle to prevent spamming - to_chat(usr, span_warning("[src]'s night lighting circuit breaker is still cycling!")) - return - last_nightshift_switch = world.time - set_nightshift(!nightshift_lights) - -/obj/machinery/power/apc/run_atom_armor(damage_amount, damage_type, damage_flag = 0, attack_dir) - if(machine_stat & BROKEN) - return damage_amount - . = ..() - -/obj/machinery/power/apc/atom_break(damage_flag) - . = ..() - if(.) - set_broken() - -/obj/machinery/power/apc/deconstruct(disassembled = TRUE) - if(!(flags_1 & NODECONSTRUCT_1)) - if(!(machine_stat & BROKEN)) - set_broken() - if(opened != APC_COVER_REMOVED) - opened = APC_COVER_REMOVED - coverlocked = FALSE - visible_message(span_warning("The APC cover is knocked down!")) - update_appearance() - -/obj/machinery/power/apc/emag_act(mob/user) - if(!(obj_flags & EMAGGED) && !malfhack) - if(opened) - to_chat(user, span_warning("You must close the cover to swipe an ID card!")) - else if(panel_open) - to_chat(user, span_warning("You must close the panel first!")) - else if(machine_stat & (BROKEN|MAINT)) - to_chat(user, span_warning("Nothing happens!")) - else - flick("apc-spark", src) - playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) - obj_flags |= EMAGGED - locked = FALSE - to_chat(user, span_notice("You emag the APC interface.")) - update_appearance() - - -// attack with hand - remove cell (if cover open) or interact with the APC - -/obj/machinery/power/apc/attack_hand(mob/user, list/modifiers) - . = ..() - if(.) - return - - if(opened && (!issilicon(user))) - if(cell) - user.visible_message(span_notice("[user] removes \the [cell] from [src]!"), span_notice("You remove \the [cell].")) - user.put_in_hands(cell) - cell.update_appearance() - src.cell = null - charging = APC_NOT_CHARGING - src.update_appearance() - return - if((machine_stat & MAINT) && !opened) //no board; no interface - return - -/obj/machinery/power/apc/ui_interact(mob/user, datum/tgui/ui) - ui = SStgui.try_update_ui(user, src, ui) - if(!ui) - ui = new(user, src, "Apc", name) - ui.open() - -/obj/machinery/power/apc/ui_data(mob/user) - var/list/data = list( - "locked" = locked, - "failTime" = failure_timer, - "isOperating" = operating, - "externalPower" = main_status, - "powerCellStatus" = cell ? cell.percent() : null, - "chargeMode" = chargemode, - "chargingStatus" = charging, - "totalLoad" = display_power(lastused_total), - "coverLocked" = coverlocked, - "siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console(), - "malfStatus" = get_malf_status(user), - "emergencyLights" = !emergency_lights, - "nightshiftLights" = nightshift_lights, - - "powerChannels" = list( - list( - "title" = "Equipment", - "powerLoad" = display_power(lastused_equip), - "status" = equipment, - "topicParams" = list( - "auto" = list("eqp" = 3), - "on" = list("eqp" = 2), - "off" = list("eqp" = 1), - ) - ), - list( - "title" = "Lighting", - "powerLoad" = display_power(lastused_light), - "status" = lighting, - "topicParams" = list( - "auto" = list("lgt" = 3), - "on" = list("lgt" = 2), - "off" = list("lgt" = 1), - ) - ), - list( - "title" = "Environment", - "powerLoad" = display_power(lastused_environ), - "status" = environ, - "topicParams" = list( - "auto" = list("env" = 3), - "on" = list("env" = 2), - "off" = list("env" = 1), - ) - ) - ) - ) - return data - - -/obj/machinery/power/apc/proc/get_malf_status(mob/living/silicon/ai/malf) - if(istype(malf) && malf.malf_picker) - if(malfai == (malf.parent || malf)) - if(occupier == malf) - return 3 // 3 = User is shunted in this APC - else if(istype(malf.loc, /obj/machinery/power/apc)) - return 4 // 4 = User is shunted in another APC - else - return 2 // 2 = APC hacked by user, and user is in its core. - else - return 1 // 1 = APC not hacked. - else - return 0 // 0 = User is not a Malf AI - -/obj/machinery/power/apc/proc/report() - return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_total]) : [cell? cell.percent() : "N/C"] ([charging])" - -/obj/machinery/power/apc/proc/update() - if(operating && !shorted && !failure_timer) - area.power_light = (lighting > APC_CHANNEL_AUTO_OFF) - area.power_equip = (equipment > APC_CHANNEL_AUTO_OFF) - area.power_environ = (environ > APC_CHANNEL_AUTO_OFF) - else - area.power_light = FALSE - area.power_equip = FALSE - area.power_environ = FALSE - area.power_change() - -/obj/machinery/power/apc/proc/can_use(mob/user, loud = 0) //used by attack_hand() and Topic() - if(isAdminGhostAI(user)) - return TRUE - if(user.has_unlimited_silicon_privilege) - var/mob/living/silicon/ai/AI = user - var/mob/living/silicon/robot/robot = user - if ( \ - src.aidisabled || \ - malfhack && istype(malfai) && \ - ( \ - (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \ - (istype(robot) && (robot in malfai.connected_robots)) \ - ) \ - ) - if(!loud) - to_chat(user, span_danger("\The [src] has been disabled!")) - return FALSE - return TRUE - -/obj/machinery/power/apc/can_interact(mob/user) - . = ..() - if (!. && !QDELETED(remote_control)) - . = remote_control.can_interact(user) - -/obj/machinery/power/apc/ui_status(mob/user) - . = ..() - if (!QDELETED(remote_control) && user == remote_control.operator) - . = UI_INTERACTIVE - -/obj/machinery/power/apc/ui_act(action, params) - . = ..() - - if(. || !can_use(usr, 1) || (locked && !usr.has_unlimited_silicon_privilege && !failure_timer && action != "toggle_nightshift")) - return - switch(action) - if("lock") - if(usr.has_unlimited_silicon_privilege) - if((obj_flags & EMAGGED) || (machine_stat & (BROKEN|MAINT))) - to_chat(usr, span_warning("The APC does not respond to the command!")) - else - locked = !locked - update_appearance() - . = TRUE - if("cover") - coverlocked = !coverlocked - . = TRUE - if("breaker") - toggle_breaker(usr) - . = TRUE - if("toggle_nightshift") - toggle_nightshift_lights() - . = TRUE - if("charge") - chargemode = !chargemode - if(!chargemode) - charging = APC_NOT_CHARGING - update_appearance() - . = TRUE - if("channel") - if(params["eqp"]) - equipment = setsubsystem(text2num(params["eqp"])) - update_appearance() - update() - else if(params["lgt"]) - lighting = setsubsystem(text2num(params["lgt"])) - update_appearance() - update() - else if(params["env"]) - environ = setsubsystem(text2num(params["env"])) - update_appearance() - update() - . = TRUE - if("overload") - if(usr.has_unlimited_silicon_privilege) - overload_lighting() - . = TRUE - if("hack") - if(get_malf_status(usr)) - malfhack(usr) - if("occupy") - if(get_malf_status(usr)) - malfoccupy(usr) - if("deoccupy") - if(get_malf_status(usr)) - malfvacate() - if("reboot") - failure_timer = 0 - update_appearance() - update() - if("emergency_lighting") - emergency_lights = !emergency_lights - for(var/obj/machinery/light/L in area) - if(!initial(L.no_emergency)) //If there was an override set on creation, keep that override - L.no_emergency = emergency_lights - INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE) - CHECK_TICK - return TRUE - -/obj/machinery/power/apc/proc/toggle_breaker(mob/user) - if(!is_operational || failure_timer) - return - operating = !operating - add_hiddenprint(user) - log_game("[key_name(user)] turned [operating ? "on" : "off"] the [src] in [AREACOORD(src)]") - update() - update_appearance() - -/obj/machinery/power/apc/proc/malfhack(mob/living/silicon/ai/malf) - if(!istype(malf)) - return - if(get_malf_status(malf) != 1) - return - if(malf.malfhacking) - to_chat(malf, span_warning("You are already hacking an APC!")) - return - to_chat(malf, span_notice("Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process.")) - malf.malfhack = src - malf.malfhacking = addtimer(CALLBACK(malf, /mob/living/silicon/ai/.proc/malfhacked, src), 600, TIMER_STOPPABLE) - - var/atom/movable/screen/alert/hackingapc/A - A = malf.throw_alert(ALERT_HACKING_APC, /atom/movable/screen/alert/hackingapc) - A.target = src - -/obj/machinery/power/apc/proc/malfoccupy(mob/living/silicon/ai/malf) - if(!istype(malf)) - return - if(istype(malf.loc, /obj/machinery/power/apc)) // Already in an APC - to_chat(malf, span_warning("You must evacuate your current APC first!")) - return - if(!malf.can_shunt) - to_chat(malf, span_warning("You cannot shunt!")) - return - if(!is_station_level(z)) - return - malf.ShutOffDoomsdayDevice() - occupier = new /mob/living/silicon/ai(src, malf.laws, malf) //DEAR GOD WHY? //IKR???? - occupier.adjustOxyLoss(malf.getOxyLoss()) - if(!findtext(occupier.name, "APC Copy")) - occupier.name = "[malf.name] APC Copy" - if(malf.parent) - occupier.parent = malf.parent - else - occupier.parent = malf - malf.shunted = TRUE - occupier.eyeobj.name = "[occupier.name] (AI Eye)" - if(malf.parent) - qdel(malf) - for(var/obj/item/pinpointer/nuke/disk_pinpointers in GLOB.pinpointer_list) - disk_pinpointers.switch_mode_to(TRACK_MALF_AI) //Pinpointer will track the shunted AI - var/datum/action/innate/core_return/CR = new - CR.Grant(occupier) - occupier.cancel_camera() - -/obj/machinery/power/apc/proc/malfvacate(forced) - if(!occupier) - return - if(occupier.parent && occupier.parent.stat != DEAD) - occupier.mind.transfer_to(occupier.parent) - occupier.parent.shunted = FALSE - occupier.parent.setOxyLoss(occupier.getOxyLoss()) - occupier.parent.cancel_camera() - qdel(occupier) - else - to_chat(occupier, span_danger("Primary core damaged, unable to return core processes.")) - if(forced) - occupier.forceMove(drop_location()) - INVOKE_ASYNC(occupier, /mob/living/proc/death) - occupier.gib() - - if(!occupier.nuking) //Pinpointers go back to tracking the nuke disk, as long as the AI (somehow) isn't mid-nuking. - for(var/obj/item/pinpointer/nuke/disk_pinpointers in GLOB.pinpointer_list) - disk_pinpointers.switch_mode_to(TRACK_NUKE_DISK) - disk_pinpointers.alert = FALSE - -/obj/machinery/power/apc/transfer_ai(interaction, mob/user, mob/living/silicon/ai/AI, obj/item/aicard/card) - if(card.AI) - to_chat(user, span_warning("[card] is already occupied!")) - return - if(!occupier) - to_chat(user, span_warning("There's nothing in [src] to transfer!")) - return - if(!occupier.mind || !occupier.client) - to_chat(user, span_warning("[occupier] is either inactive or destroyed!")) - return - if(!occupier.parent.stat) - to_chat(user, span_warning("[occupier] is refusing all attempts at transfer!") ) - return - if(transfer_in_progress) - to_chat(user, span_warning("There's already a transfer in progress!")) - return - if(interaction != AI_TRANS_TO_CARD || occupier.stat) - return - var/turf/T = get_turf(user) - if(!T) - return - transfer_in_progress = TRUE - user.visible_message(span_notice("[user] slots [card] into [src]..."), span_notice("Transfer process initiated. Sending request for AI approval...")) - playsound(src, 'sound/machines/click.ogg', 50, TRUE) - SEND_SOUND(occupier, sound('sound/misc/notice2.ogg')) //To alert the AI that someone's trying to card them if they're tabbed out - if(tgui_alert(occupier, "[user] is attempting to transfer you to \a [card.name]. Do you consent to this?", "APC Transfer", list("Yes - Transfer Me", "No - Keep Me Here")) == "No - Keep Me Here") - to_chat(user, span_danger("AI denied transfer request. Process terminated.")) - playsound(src, 'sound/machines/buzz-sigh.ogg', 50, TRUE) - transfer_in_progress = FALSE - return - if(user.loc != T) - to_chat(user, span_danger("Location changed. Process terminated.")) - to_chat(occupier, span_warning("[user] moved away! Transfer canceled.")) - transfer_in_progress = FALSE - return - to_chat(user, span_notice("AI accepted request. Transferring stored intelligence to [card]...")) - to_chat(occupier, span_notice("Transfer starting. You will be moved to [card] shortly.")) - if(!do_after(user, 50, target = src)) - to_chat(occupier, span_warning("[user] was interrupted! Transfer canceled.")) - transfer_in_progress = FALSE - return - if(!occupier || !card) - transfer_in_progress = FALSE - return - user.visible_message(span_notice("[user] transfers [occupier] to [card]!"), span_notice("Transfer complete! [occupier] is now stored in [card].")) - to_chat(occupier, span_notice("Transfer complete! You've been stored in [user]'s [card.name].")) - occupier.forceMove(card) - card.AI = occupier - occupier.parent.shunted = FALSE - occupier.cancel_camera() - occupier = null - transfer_in_progress = FALSE - return - -/obj/machinery/power/apc/surplus() - if(terminal) - return terminal.surplus() - else - return 0 - -/obj/machinery/power/apc/add_load(amount) - if(terminal?.powernet) - terminal.add_load(amount) - -/obj/machinery/power/apc/avail(amount) - if(terminal) - return terminal.avail(amount) - else - return 0 - -/obj/machinery/power/apc/process() - if(icon_update_needed) - update_appearance() - if(machine_stat & (BROKEN|MAINT)) - return - if(!area || !area.requires_power) - return - if(failure_timer) - update() - queue_icon_update() - failure_timer-- - force_update = TRUE - return - - //dont use any power from that channel if we shut that power channel off - lastused_light = APC_CHANNEL_IS_ON(lighting) ? area.power_usage[AREA_USAGE_LIGHT] + area.power_usage[AREA_USAGE_STATIC_LIGHT] : 0 - lastused_equip = APC_CHANNEL_IS_ON(equipment) ? area.power_usage[AREA_USAGE_EQUIP] + area.power_usage[AREA_USAGE_STATIC_EQUIP] : 0 - lastused_environ = APC_CHANNEL_IS_ON(environ) ? area.power_usage[AREA_USAGE_ENVIRON] + area.power_usage[AREA_USAGE_STATIC_ENVIRON] : 0 - area.clear_usage() - - lastused_total = lastused_light + lastused_equip + lastused_environ - - //store states to update icon if any change - var/last_lt = lighting - var/last_eq = equipment - var/last_en = environ - var/last_ch = charging - - var/excess = surplus() - - if(!avail()) - main_status = APC_NO_POWER - else if(excess < 0) - main_status = APC_LOW_POWER - else - main_status = APC_HAS_POWER - - if(cell && !shorted) - // draw power from cell as before to power the area - var/cellused = min(cell.charge, lastused_total JOULES) // clamp deduction to a max, amount left in cell - cell.use(cellused) - - if(excess > lastused_total) // if power excess recharge the cell - // by the same amount just used - cell.give(cellused) - add_load(cellused WATTS) // add the load used to recharge the cell - - - else // no excess, and not enough per-apc - if((cell.charge WATTS + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage? - cell.charge = min(cell.maxcharge, cell.charge + excess JOULES) //recharge with what we can - add_load(excess) // so draw what we can from the grid - charging = APC_NOT_CHARGING - - else // not enough power available to run the last tick! - charging = APC_NOT_CHARGING - chargecount = 0 - // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room. - equipment = autoset(equipment, AUTOSET_FORCE_OFF) - lighting = autoset(lighting, AUTOSET_FORCE_OFF) - environ = autoset(environ, AUTOSET_FORCE_OFF) - - - // set channels depending on how much charge we have left - - // Allow the APC to operate as normal if the cell can charge - if(charging && longtermpower < 10) - longtermpower += 1 - else if(longtermpower > -10) - longtermpower -= 2 - - if(cell.charge <= 0) // zero charge, turn all off - equipment = autoset(equipment, AUTOSET_FORCE_OFF) - lighting = autoset(lighting, AUTOSET_FORCE_OFF) - environ = autoset(environ, AUTOSET_FORCE_OFF) - alarm_manager.send_alarm(ALARM_POWER) - else if(cell.percent() < 15 && longtermpower < 0) // <15%, turn off lighting & equipment - equipment = autoset(equipment, AUTOSET_OFF) - lighting = autoset(lighting, AUTOSET_OFF) - environ = autoset(environ, AUTOSET_ON) - alarm_manager.send_alarm(ALARM_POWER) - else if(cell.percent() < 30 && longtermpower < 0) // <30%, turn off equipment - equipment = autoset(equipment, AUTOSET_OFF) - lighting = autoset(lighting, AUTOSET_ON) - environ = autoset(environ, AUTOSET_ON) - alarm_manager.send_alarm(ALARM_POWER) - else // otherwise all can be on - equipment = autoset(equipment, AUTOSET_ON) - lighting = autoset(lighting, AUTOSET_ON) - environ = autoset(environ, AUTOSET_ON) - if(cell.percent() > 75) - alarm_manager.clear_alarm(ALARM_POWER) - - - // now trickle-charge the cell - if(chargemode && charging == APC_CHARGING && operating) - if(excess > 0) // check to make sure we have enough to charge - // Max charge is capped to % per second constant - var/ch = min(excess JOULES, cell.maxcharge JOULES) - add_load(ch WATTS) // Removes the power we're taking from the grid - cell.give(ch) // actually recharge the cell - - else - charging = APC_NOT_CHARGING // stop charging - chargecount = 0 - - // show cell as fully charged if so - if(cell.charge >= cell.maxcharge) - cell.charge = cell.maxcharge - charging = APC_FULLY_CHARGED - - if(chargemode) - if(!charging) - if(excess > cell.maxcharge*GLOB.CHARGELEVEL) - chargecount++ - else - chargecount = 0 - - if(chargecount == 10) - - chargecount = 0 - charging = APC_CHARGING - - else // chargemode off - charging = APC_NOT_CHARGING - chargecount = 0 - - if(excess >= APC_ARC_LOWERLIMIT && !shock_proof) // SKYRAT EDIT ADD - APC Arcing - var/shock_chance = 5 // 5% - if(excess >= APC_ARC_UPPERLIMIT) - shock_chance = 15 - else if(excess >= APC_ARC_MEDIUMLIMIT) - shock_chance = 10 - if(prob(shock_chance)) - var/list/shock_mobs = list() - for(var/creature in view(get_turf(src), 5)) //We only want to shock a single random mob in range, not every one. - if(isliving(creature)) - shock_mobs += creature - if(shock_mobs.len) - var/mob/living/living_target = pick(shock_mobs) - living_target.electrocute_act(rand(5, 25), "electrical arc") - playsound(get_turf(living_target), 'sound/magic/lightningshock.ogg', 75, TRUE) - Beam(living_target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/beam.dmi', time = 5) // SKYRAT EDIT ADD END - - else // no cell, switch everything off - - charging = APC_NOT_CHARGING - chargecount = 0 - equipment = autoset(equipment, AUTOSET_FORCE_OFF) - lighting = autoset(lighting, AUTOSET_FORCE_OFF) - environ = autoset(environ, AUTOSET_FORCE_OFF) - alarm_manager.send_alarm(ALARM_POWER) - - // update icon & area power if anything changed - - if(last_lt != lighting || last_eq != equipment || last_en != environ || force_update) - force_update = 0 - queue_icon_update() - update() - else if (last_ch != charging) - queue_icon_update() - -/** - * Returns the new status value for an APC channel. - * - * // val 0=off, 1=off(auto) 2=on 3=on(auto) - * // on 0=off, 1=on, 2=autooff - * TODO: Make this use bitflags instead. It should take at most three lines, but it's out of scope for now. - * - * Arguments: - * - val: The current status of the power channel. - * - [APC_CHANNEL_OFF]: The APCs channel has been manually set to off. This channel will not automatically change. - * - [APC_CHANNEL_AUTO_OFF]: The APCs channel is running on automatic and is currently off. Can be automatically set to [APC_CHANNEL_AUTO_ON]. - * - [APC_CHANNEL_ON]: The APCs channel has been manually set to on. This will be automatically changed only if the APC runs completely out of power or is disabled. - * - [APC_CHANNEL_AUTO_ON]: The APCs channel is running on automatic and is currently on. Can be automatically set to [APC_CHANNEL_AUTO_OFF]. - * - on: An enum dictating how to change the channel's status. - * - [AUTOSET_FORCE_OFF]: The APC forces the channel to turn off. This includes manually set channels. - * - [AUTOSET_ON]: The APC allows automatic channels to turn back on. - * - [AUTOSET_OFF]: The APC turns automatic channels off. - */ -/obj/machinery/power/apc/proc/autoset(val, on) - switch(on) - if(AUTOSET_FORCE_OFF) - if(val == APC_CHANNEL_ON) // if on, return off - return APC_CHANNEL_OFF - else if(val == APC_CHANNEL_AUTO_ON) // if auto-on, return auto-off - return APC_CHANNEL_AUTO_OFF - if(AUTOSET_ON) - if(val == APC_CHANNEL_AUTO_OFF) // if auto-off, return auto-on - return APC_CHANNEL_AUTO_ON - if(AUTOSET_OFF) - if(val == APC_CHANNEL_AUTO_ON) // if auto-on, return auto-off - return APC_CHANNEL_AUTO_OFF - return val - -/** - * Used by external forces to set the APCs channel status's. - * - * Arguments: - * - val: The desired value of the subsystem: - * - 1: Manually sets the APCs channel to be [APC_CHANNEL_OFF]. - * - 2: Manually sets the APCs channel to be [APC_CHANNEL_AUTO_ON]. If the APC doesn't have any power this defaults to [APC_CHANNEL_OFF] instead. - * - 3: Sets the APCs channel to be [APC_CHANNEL_AUTO_ON]. If the APC doesn't have enough power this defaults to [APC_CHANNEL_AUTO_OFF] instead. - */ -/obj/machinery/power/apc/proc/setsubsystem(val) - if(cell && cell.charge > 0) - return (val == 1) ? APC_CHANNEL_OFF : val - if(val == 3) - return APC_CHANNEL_AUTO_OFF - return APC_CHANNEL_OFF - -/obj/machinery/power/apc/proc/reset(wire) - switch(wire) - if(WIRE_IDSCAN) - locked = TRUE - if(WIRE_POWER1, WIRE_POWER2) - if(!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2)) - shorted = FALSE - if(WIRE_AI) - if(!wires.is_cut(WIRE_AI)) - aidisabled = FALSE - if(APC_RESET_EMP) - equipment = APC_CHANNEL_AUTO_ON - environ = APC_CHANNEL_AUTO_ON - update_appearance() - update() - -// damage and destruction acts -/obj/machinery/power/apc/emp_act(severity) - . = ..() - if (!(. & EMP_PROTECT_CONTENTS)) - if(cell) - cell.emp_act(severity) - if(occupier) - occupier.emp_act(severity) - if(. & EMP_PROTECT_SELF) - return - lighting = APC_CHANNEL_OFF - equipment = APC_CHANNEL_OFF - environ = APC_CHANNEL_OFF - update_appearance() - update() - addtimer(CALLBACK(src, .proc/reset, APC_RESET_EMP), 600) - -/obj/machinery/power/apc/blob_act(obj/structure/blob/B) - set_broken() - -/obj/machinery/power/apc/disconnect_terminal() - if(terminal) - terminal.master = null - terminal = null - -/obj/machinery/power/apc/proc/set_broken() - if(malfai && operating) - malfai.malf_picker.processing_time = clamp(malfai.malf_picker.processing_time - 10,0,1000) - operating = FALSE - atom_break() - if(occupier) - malfvacate(TRUE) - update() - -// overload all the lights in this APC area - -/obj/machinery/power/apc/proc/overload_lighting() - if(/* !get_connection() || */ !operating || shorted) - return - if( cell && cell.charge>=20) - cell.use(20) - INVOKE_ASYNC(src, .proc/break_lights) - -/obj/machinery/power/apc/proc/break_lights() - for(var/obj/machinery/light/L in area) - L.on = TRUE - L.break_light_tube() - stoplag() - -/obj/machinery/power/apc/proc/shock(mob/user, prb) - if(!prob(prb)) - return FALSE - do_sparks(5, TRUE, src) - if(isalien(user)) - return FALSE - if(electrocute_mob(user, src, src, 1, TRUE)) - return TRUE - else - return FALSE - - -/obj/machinery/power/apc/proc/energy_fail(duration) - for(var/obj/machinery/M in area.contents) - if(M.critical_machine) - return - for(var/A in GLOB.ai_list) - var/mob/living/silicon/ai/I = A - if(get_area(I) == area) - return - - failure_timer = max(failure_timer, round(duration)) - -/obj/machinery/power/apc/proc/set_nightshift(on) - set waitfor = FALSE - nightshift_lights = on - for(var/obj/machinery/light/L in area) - if(L.nightshift_allowed) - L.nightshift_enabled = nightshift_lights - L.update(FALSE) - CHECK_TICK - -/obj/machinery/power/apc/take_damage(damage_amount, damage_type = BRUTE, damage_flag = "", sound_effect = TRUE) - // APC being at 0 integrity doesnt delete it outright. Combined with take_damage this might cause runtimes. - if(machine_stat & BROKEN && atom_integrity <= 0) - if(sound_effect) - play_attack_sound(damage_amount, damage_type, damage_flag) - return - return ..() - -#undef APC_CHANNEL_OFF -#undef APC_CHANNEL_AUTO_OFF -#undef APC_CHANNEL_ON -#undef APC_CHANNEL_AUTO_ON - -#undef AUTOSET_FORCE_OFF -#undef AUTOSET_OFF -#undef AUTOSET_ON - -#undef APC_PIXEL_OFFSET - -#undef APC_NO_POWER -#undef APC_LOW_POWER -#undef APC_HAS_POWER - -#undef APC_ELECTRONICS_MISSING -#undef APC_ELECTRONICS_INSTALLED -#undef APC_ELECTRONICS_SECURED - -#undef APC_COVER_CLOSED -#undef APC_COVER_OPENED -#undef APC_COVER_REMOVED - -#undef APC_NOT_CHARGING -#undef APC_CHARGING -#undef APC_FULLY_CHARGED - -#undef APC_DRAIN_TIME -#undef APC_POWER_GAIN - -#undef APC_RESET_EMP - -// update_state -#undef UPSTATE_CELL_IN -#undef UPSTATE_COVER_SHIFT -#undef UPSTATE_BROKE -#undef UPSTATE_MAINT -#undef UPSTATE_BLUESCREEN -#undef UPSTATE_WIREEXP - -//update_overlay -#undef UPOVERLAY_OPERATING -#undef UPOVERLAY_LOCKED -#undef UPOVERLAY_CHARGING_SHIFT -#undef UPOVERLAY_EQUIPMENT_SHIFT -#undef UPOVERLAY_LIGHTING_SHIFT -#undef UPOVERLAY_ENVIRON_SHIFT - -/*Power module, used for APC construction*/ -/obj/item/electronics/apc - name = "power control module" - icon_state = "power_mod" - desc = "Heavy-duty switching circuits for power control." diff --git a/code/modules/security_levels/security_levels.dm b/code/modules/security_levels/security_levels.dm deleted file mode 100644 index 4c52770e50c..00000000000 --- a/code/modules/security_levels/security_levels.dm +++ /dev/null @@ -1,86 +0,0 @@ -/* SKYRAT EDIT REMOVAL BEGIN -/proc/set_security_level(level) - switch(level) - if("green") - level = SEC_LEVEL_GREEN - if("blue") - level = SEC_LEVEL_BLUE - if("red") - level = SEC_LEVEL_RED - if("delta") - level = SEC_LEVEL_DELTA - - //Will not be announced if you try to set to the same level as it already is - if(level >= SEC_LEVEL_GREEN && level <= SEC_LEVEL_DELTA && level != SSsecurity_level.current_level) - switch(level) - if(SEC_LEVEL_GREEN) - minor_announce(CONFIG_GET(string/alert_green), "Attention! Security level lowered to green:") - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - if(SSsecurity_level.current_level >= SEC_LEVEL_RED) - SSshuttle.emergency.modTimer(4) - else - SSshuttle.emergency.modTimer(2) - if(SEC_LEVEL_BLUE) - if(SSsecurity_level.current_level < SEC_LEVEL_BLUE) - minor_announce(CONFIG_GET(string/alert_blue_upto), "Attention! Security level elevated to blue:",1) - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - SSshuttle.emergency.modTimer(0.5) - else - minor_announce(CONFIG_GET(string/alert_blue_downto), "Attention! Security level lowered to blue:") - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - SSshuttle.emergency.modTimer(2) - if(SEC_LEVEL_RED) - if(SSsecurity_level.current_level < SEC_LEVEL_RED) - minor_announce(CONFIG_GET(string/alert_red_upto), "Attention! Code red!",1) - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - if(SSsecurity_level.current_level == SEC_LEVEL_GREEN) - SSshuttle.emergency.modTimer(0.25) - else - SSshuttle.emergency.modTimer(0.5) - else - minor_announce(CONFIG_GET(string/alert_red_downto), "Attention! Code red!") - if(SEC_LEVEL_DELTA) - minor_announce(CONFIG_GET(string/alert_delta), "Attention! Delta security level reached!",1) - if(SSshuttle.emergency.mode == SHUTTLE_CALL || SSshuttle.emergency.mode == SHUTTLE_RECALL) - if(SSsecurity_level.current_level == SEC_LEVEL_GREEN) - SSshuttle.emergency.modTimer(0.25) - else if(SSsecurity_level.current_level == SEC_LEVEL_BLUE) - SSshuttle.emergency.modTimer(0.5) - - SSsecurity_level.set_level(level) - -/proc/get_security_level() - switch(SSsecurity_level.current_level) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/num2seclevel(num) - switch(num) - if(SEC_LEVEL_GREEN) - return "green" - if(SEC_LEVEL_BLUE) - return "blue" - if(SEC_LEVEL_RED) - return "red" - if(SEC_LEVEL_DELTA) - return "delta" - -/proc/seclevel2num(seclevel) - switch( lowertext(seclevel) ) - if("green") - return SEC_LEVEL_GREEN - if("blue") - return SEC_LEVEL_BLUE - if("red") - return SEC_LEVEL_RED - if("delta") - return SEC_LEVEL_DELTA - -*/ -//SKYRAT EDIT END diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index cace17568c9..761076f5a21 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -105,6 +105,8 @@ window.send_message("ping") var/flush_queue = window.send_asset(get_asset_datum( /datum/asset/simple/namespaced/fontawesome)) + flush_queue |= window.send_asset(get_asset_datum( + /datum/asset/simple/namespaced/tgfont)) for(var/datum/asset/asset in src_object.ui_assets(user)) flush_queue |= window.send_asset(asset) if (flush_queue) diff --git a/code/modules/tgui_panel/tgui_panel.dm b/code/modules/tgui_panel/tgui_panel.dm index 45b6725c893..b60166f8859 100644 --- a/code/modules/tgui_panel/tgui_panel.dm +++ b/code/modules/tgui_panel/tgui_panel.dm @@ -48,6 +48,7 @@ get_asset_datum(/datum/asset/simple/tgui_panel), )) window.send_asset(get_asset_datum(/datum/asset/simple/namespaced/fontawesome)) + window.send_asset(get_asset_datum(/datum/asset/simple/namespaced/tgfont)) window.send_asset(get_asset_datum(/datum/asset/spritesheet/chat)) // Other setup request_telemetry() diff --git a/modular_skyrat/master_files/code/modules/mining/equipment/explorer_gear.dm b/modular_skyrat/master_files/code/modules/mining/equipment/explorer_gear.dm deleted file mode 100644 index 4b41d53ea2f..00000000000 --- a/modular_skyrat/master_files/code/modules/mining/equipment/explorer_gear.dm +++ /dev/null @@ -1,12 +0,0 @@ -/****************Explorer's Suit and Mask****************/ -/obj/item/clothing/suit/hooded/explorer - icon = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi' // To keep the old version. - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/suit.dmi' // To keep the old version. - icon_state = "explorer" - inhand_icon_state = "explorer" - -/obj/item/clothing/head/hooded/explorer - icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' // To keep the old version before #8911 - worn_icon = 'modular_skyrat/master_files/icons/mob/clothing/head.dmi' // To keep the old version before #8911 - icon_state = "explorer" - diff --git a/tgui/packages/tgfont/icons/nanotrasen_logo.svg b/tgui/packages/tgfont/icons/nanotrasen_logo.svg new file mode 100644 index 00000000000..d21b9f0a2a0 --- /dev/null +++ b/tgui/packages/tgfont/icons/nanotrasen_logo.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/tgui/packages/tgfont/icons/syndicate_logo.svg b/tgui/packages/tgfont/icons/syndicate_logo.svg new file mode 100644 index 00000000000..c2863b790df --- /dev/null +++ b/tgui/packages/tgfont/icons/syndicate_logo.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/tools/ci/dm.sh b/tools/ci/dm.sh deleted file mode 100755 index ea432fa5acb..00000000000 --- a/tools/ci/dm.sh +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash - -dmepath="" -retval=1 - -for var -do - if [[ $var != -* && $var == *.dme ]] - then - dmepath=`echo $var | sed -r 's/.{4}$//'` - break - fi -done - -if [[ $dmepath == "" ]] -then - echo "No .dme file specified, aborting." - exit 1 -fi - -if [[ -a $dmepath.mdme ]] -then - rm $dmepath.mdme -fi - -cp $dmepath.dme $dmepath.mdme -if [[ $? != 0 ]] -then - echo "Failed to make modified dme, aborting." - exit 2 -fi - -for var -do - arg=`echo $var | sed -r 's/^.{2}//'` - if [[ $var == -D* ]] - then - sed -i '1s/^/#define '$arg'\n/' $dmepath.mdme - continue - fi -done - -#windows -if [[ `uname` == MINGW* ]] -then - dm="" - - if hash dm.exe 2>/dev/null - then - dm='dm.exe' - elif [[ -a '/c/Program Files (x86)/BYOND/bin/dm.exe' ]] - then - dm='/c/Program Files (x86)/BYOND/bin/dm.exe' - elif [[ -a '/c/Program Files/BYOND/bin/dm.exe' ]] - then - dm='/c/Program Files/BYOND/bin/dm.exe' - fi - - if [[ $dm == "" ]] - then - echo "Couldn't find the DreamMaker executable, aborting." - exit 3 - fi - - "$dm" $dmepath.mdme 2>&1 | tee result.log - retval=$? - if ! grep '\- 0 errors, 0 warnings' result.log - then - retval=1 #hard fail, due to warnings or errors - fi -else - if hash DreamMaker 2>/dev/null - then - DreamMaker -max_errors 0 $dmepath.mdme 2>&1 | tee result.log - retval=$? - if ! grep '\- 0 errors, 0 warnings' result.log - then - retval=1 #hard fail, due to warnings or errors - fi - else - echo "Couldn't find the DreamMaker executable, aborting." - exit 3 - fi -fi - -mv $dmepath.mdme.dmb $dmepath.dmb -mv $dmepath.mdme.rsc $dmepath.rsc - -rm $dmepath.mdme - -exit $retval diff --git a/tools/linux_build.py b/tools/linux_build.py deleted file mode 100755 index 99fb652b940..00000000000 --- a/tools/linux_build.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python - -import subprocess -import os -import sys -import argparse -import time -from subprocess import PIPE, STDOUT - -null = open("/dev/null", "wb") - -def wait(p): - rc = p.wait() - if rc != 0: - p = play("sound/misc/compiler-failure.ogg") - p.wait() - assert p.returncode == 0 - sys.exit(rc) - -def play(soundfile): - p = subprocess.Popen(["play", soundfile], stdout=null, stderr=null) - assert p.wait() == 0 - return p - -def stage1(): - p = subprocess.Popen("(cd tgui; /bin/bash ./build.sh)", shell=True) - wait(p) - play("sound/misc/compiler-stage1.ogg") - -def stage2(map): - if map: - txt = "-M{}".format(map) - else: - txt = '' - args = "bash tools/travis/dm.sh {} tgstation.dme".format(txt) - print(args) - p = subprocess.Popen(args, shell=True) - wait(p) - -def stage3(profile_mode=False): - start_time = time.time() - play("sound/misc/compiler-stage2.ogg") - logfile = open('server.log~','w') - p = subprocess.Popen( - "DreamDaemon tgstation.dmb 25001 -trusted", - shell=True, stdout=PIPE, stderr=STDOUT) - try: - while p.returncode is None: - stdout = p.stdout.readline() - if "Initializations complete" in stdout: - play("sound/misc/server-ready.ogg") - time_taken = time.time() - start_time - print("{} seconds taken to fully start".format(time_taken)) - if "Map is ready." in stdout: - time_taken = time.time() - start_time - print("{} seconds for initial map loading".format(time_taken)) - if profile_mode: - return time_taken - sys.stdout.write(stdout) - sys.stdout.flush() - logfile.write(stdout) - finally: - logfile.flush() - os.fsync(logfile.fileno()) - logfile.close() - p.kill() - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('-s','---stage',default=1,type=int) - parser.add_argument('--only',action='store_true') - parser.add_argument('-m','--map',type=str) - parser.add_argument('--profile-mode',action='store_true') - args = parser.parse_args() - stage = args.stage - assert stage in (1,2,3) - if stage == 1: - stage1() - if not args.only: - stage = 2 - if stage == 2: - stage2(args.map) - if not args.only: - stage = 3 - if stage == 3: - value = stage3(profile_mode=args.profile_mode) - with open('profile~', 'a') as f: - f.write("{}\n".format(value)) - -if __name__=='__main__': - try: - main() - except KeyboardInterrupt: - pass diff --git a/tools/validate_dme.py b/tools/validate_dme.py index c2b4bfda5b3..742fce0aa08 100644 --- a/tools/validate_dme.py +++ b/tools/validate_dme.py @@ -30,7 +30,8 @@ for line in sys.stdin: fail_no_include = False -for code_file in glob.glob("code/**/*.dm", recursive=True): +code_files = glob.glob("code/**/*.dm", recursive=True) + glob.glob("modular_skyrat/**/*.dm", recursive=True) # SKYRAT EDIT CHANGE +for code_file in code_files: # SKYRAT EDIT CHANGE dm_path = code_file.replace('/', '\\') included = f"#include \"{dm_path}\"" in lines