diff --git a/baystation12.dme b/baystation12.dme index 803c6cb0e5..90c6c726d2 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -841,6 +841,7 @@ #include "code\modules\admin\admin_investigate.dm" #include "code\modules\admin\admin_memo.dm" #include "code\modules\admin\admin_ranks.dm" +#include "code\modules\admin\admin_secrets.dm" #include "code\modules\admin\admin_verbs.dm" #include "code\modules\admin\banjob.dm" #include "code\modules\admin\create_mob.dm" @@ -856,6 +857,43 @@ #include "code\modules\admin\ToRban.dm" #include "code\modules\admin\DB ban\functions.dm" #include "code\modules\admin\permissionverbs\permissionedit.dm" +#include "code\modules\admin\secrets\admin_secrets\admin_logs.dm" +#include "code\modules\admin\secrets\admin_secrets\alter_narsie.dm" +#include "code\modules\admin\secrets\admin_secrets\bombing_list.dm" +#include "code\modules\admin\secrets\admin_secrets\jump_shuttle.dm" +#include "code\modules\admin\secrets\admin_secrets\launch_shuttle.dm" +#include "code\modules\admin\secrets\admin_secrets\launch_shuttle_forced.dm" +#include "code\modules\admin\secrets\admin_secrets\list_dna.dm" +#include "code\modules\admin\secrets\admin_secrets\list_fingerprints.dm" +#include "code\modules\admin\secrets\admin_secrets\move_shuttle.dm" +#include "code\modules\admin\secrets\admin_secrets\prison_warp.dm" +#include "code\modules\admin\secrets\admin_secrets\show_ai_laws.dm" +#include "code\modules\admin\secrets\admin_secrets\show_crew_manifest.dm" +#include "code\modules\admin\secrets\admin_secrets\show_game_mode.dm" +#include "code\modules\admin\secrets\admin_secrets\show_law_changes.dm" +#include "code\modules\admin\secrets\admin_secrets\show_signalers.dm" +#include "code\modules\admin\secrets\admin_secrets\traitors_and_objectives.dm" +#include "code\modules\admin\secrets\final_solutions\summon_narsie.dm" +#include "code\modules\admin\secrets\final_solutions\supermatter_cascade.dm" +#include "code\modules\admin\secrets\fun_secrets\break_all_lights.dm" +#include "code\modules\admin\secrets\fun_secrets\break_some_lights.dm" +#include "code\modules\admin\secrets\fun_secrets\fix_all_lights.dm" +#include "code\modules\admin\secrets\fun_secrets\ghost_mode.dm" +#include "code\modules\admin\secrets\fun_secrets\make_all_areas_powered.dm" +#include "code\modules\admin\secrets\fun_secrets\make_all_areas_unpowered.dm" +#include "code\modules\admin\secrets\fun_secrets\only_one.dm" +#include "code\modules\admin\secrets\fun_secrets\paintball_mode.dm" +#include "code\modules\admin\secrets\fun_secrets\power_all_smes.dm" +#include "code\modules\admin\secrets\fun_secrets\remove_all_clothing.dm" +#include "code\modules\admin\secrets\fun_secrets\remove_internal_clothing.dm" +#include "code\modules\admin\secrets\fun_secrets\send_strike_team.dm" +#include "code\modules\admin\secrets\fun_secrets\toggle_bomb_cap.dm" +#include "code\modules\admin\secrets\fun_secrets\triple_ai_mode.dm" +#include "code\modules\admin\secrets\fun_secrets\turn_humans_into_corgies.dm" +#include "code\modules\admin\secrets\fun_secrets\turn_humans_into_monkeys.dm" +#include "code\modules\admin\secrets\random_events\gravity.dm" +#include "code\modules\admin\secrets\random_events\trigger_cordical_borer_infestation.dm" +#include "code\modules\admin\secrets\random_events\trigger_xenomorph_infestation.dm" #include "code\modules\admin\verbs\adminhelp.dm" #include "code\modules\admin\verbs\adminjump.dm" #include "code\modules\admin\verbs\adminpm.dm" @@ -1280,6 +1318,7 @@ #include "code\modules\mob\living\silicon\silicon.dm" #include "code\modules\mob\living\silicon\subystems.dm" #include "code\modules\mob\living\silicon\ai\ai.dm" +#include "code\modules\mob\living\silicon\ai\ai_movement.dm" #include "code\modules\mob\living\silicon\ai\death.dm" #include "code\modules\mob\living\silicon\ai\examine.dm" #include "code\modules\mob\living\silicon\ai\icons.dm" @@ -1427,6 +1466,7 @@ #include "code\modules\paperwork\paper.dm" #include "code\modules\paperwork\paper_bundle.dm" #include "code\modules\paperwork\paperbin.dm" +#include "code\modules\paperwork\papershredder.dm" #include "code\modules\paperwork\pen.dm" #include "code\modules\paperwork\photocopier.dm" #include "code\modules\paperwork\photography.dm" diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index 7136175519..20747361d3 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -126,7 +126,7 @@ obj/item/check_airflow_movable(n) step_towards(src, src.airflow_dest) var/mob/M = src if(istype(M) && M.client) - M.client.move_delay = world.time + vsc.airflow_mob_slowdown + M.setMoveCooldown(vsc.airflow_mob_slowdown) airflow_dest = null airflow_speed = 0 airflow_time = 0 diff --git a/code/__defines/items_clothing.dm b/code/__defines/items_clothing.dm index b822c4badc..aa32b0016e 100644 --- a/code/__defines/items_clothing.dm +++ b/code/__defines/items_clothing.dm @@ -24,15 +24,13 @@ // Flags bitmasks. #define NOBLUDGEON 0x1 // When an item has this it produces no "X has been hit by Y with Z" message with the default handler. -#define USEDELAY 0x2 // 1 second extra delay on use. (Can be used once every 2s) -#define CONDUCT 0x4 // Conducts electricity. (metal etc.) -#define ON_BORDER 0x8 // Item has priority to check when entering or leaving. -#define NOBLOODY 0x10 // Used for items if they don't want to get a blood overlay. -#define NODELAY 0x20 // 1 second attack-by delay skipped (Can be used once every 0.2s). Most objects have a 1s attack-by delay, which doesn't require a flag. -#define OPENCONTAINER 0x40 // Is an open container for chemistry purposes. -#define PHORONGUARD 0x80 // Does not get contaminated by phoron. -#define NOREACT 0x100 // Reagents don't react inside this container. -#define PROXMOVE 0x200 // Does this object require proximity checking in Enter()? +#define CONDUCT 0x2 // Conducts electricity. (metal etc.) +#define ON_BORDER 0x4 // Item has priority to check when entering or leaving. +#define NOBLOODY 0x8 // Used for items if they don't want to get a blood overlay. +#define OPENCONTAINER 0x10 // Is an open container for chemistry purposes. +#define PHORONGUARD 0x20 // Does not get contaminated by phoron. +#define NOREACT 0x40 // Reagents don't react inside this container. +#define PROXMOVE 0x80 // Does this object require proximity checking in Enter()? //Flags for items (equipment) #define THICKMATERIAL 0x1 // Prevents syringes, parapens and hyposprays if equiped to slot_suit or slot_head. diff --git a/code/__defines/mobs.dm b/code/__defines/mobs.dm index b0858101d6..5bcab4704d 100644 --- a/code/__defines/mobs.dm +++ b/code/__defines/mobs.dm @@ -61,8 +61,6 @@ #define HEAVY 64 #define ALLMOBS (HUMAN|MONKEY|ALIEN|ROBOT|SLIME|SIMPLE_ANIMAL|HEAVY) -#define NEXT_MOVE_DELAY 8 - // Robot AI notifications #define ROBOT_NOTIFICATION_NEW_UNIT 1 #define ROBOT_NOTIFICATION_NEW_NAME 2 @@ -82,6 +80,9 @@ #define APPEARANCE_ALL_HAIR (APPEARANCE_HAIR|APPEARANCE_HAIR_COLOR|APPEARANCE_FACIAL_HAIR|APPEARANCE_FACIAL_HAIR_COLOR) #define APPEARANCE_ALL 0xFFFF +// Click cooldown +#define DEFAULT_ATTACK_COOLDOWN 8 //Default timeout for aggressive actions + #define MIN_SUPPLIED_LAW_NUMBER 15 #define MAX_SUPPLIED_LAW_NUMBER 50 diff --git a/code/_helpers/lists.dm b/code/_helpers/lists.dm index c3a99bcf82..8a8d13de6b 100644 --- a/code/_helpers/lists.dm +++ b/code/_helpers/lists.dm @@ -592,7 +592,7 @@ proc/dd_sortedTextList(list/incoming) return dd_sortedtextlist(incoming, case_sensitive) -datum/proc/dd_SortValue() +/datum/proc/dd_SortValue() return "[src]" /obj/machinery/dd_SortValue() diff --git a/code/_helpers/unsorted.dm b/code/_helpers/unsorted.dm index dece128cbf..366fcbbbc1 100644 --- a/code/_helpers/unsorted.dm +++ b/code/_helpers/unsorted.dm @@ -565,10 +565,13 @@ proc/GaussRandRound(var/sigma,var/roundto) return toReturn //Step-towards method of determining whether one atom can see another. Similar to viewers() -/proc/can_see(var/atom/source, var/atom/target, var/length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate. +/proc/can_see(var/atom/source, var/atom/target, var/length=5) // I couldn't be arsed to do actual raycasting :I This is horribly inaccurate. var/turf/current = get_turf(source) var/turf/target_turf = get_turf(target) var/steps = 0 + + if(!current || !target_turf) + return 0 while(current != target_turf) if(steps > length) return 0 diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm index e05cbeb9ba..4dee15388d 100644 --- a/code/_onclick/ai.dm +++ b/code/_onclick/ai.dm @@ -15,7 +15,6 @@ return if(control_disabled || stat) return - next_move = world.time + 9 if(ismob(A)) ai_actual_track(A) @@ -52,9 +51,8 @@ CtrlClickOn(A) return - if(world.time <= next_move) + if(!canClick()) return - next_move = world.time + 9 if(aiCamera.in_camera_mode) aiCamera.camera_mode_off() diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 33e8dae8d6..61b98a9994 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -4,7 +4,7 @@ */ // 1 decisecond click delay (above and beyond mob/next_move) -/mob/var/next_click = 0 +/mob/var/next_click = 0 /* Before anything else, defer these calls to a per-mobtype handler. This allows us to @@ -15,12 +15,14 @@ Note that this proc can be overridden, and is in the case of screen objects. */ -/atom/Click(location,control,params) + +/atom/Click(var/location, var/control, var/params) // This is their reaction to being clicked on (standard proc) if(src) usr.ClickOn(src, params) -/atom/DblClick(location,control,params) + +/atom/DblClick(var/location, var/control, var/params) if(src) - usr.DblClickOn(src,params) + usr.DblClickOn(src, params) /* Standard mob ClickOn() @@ -35,8 +37,8 @@ * item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent * mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed */ -/mob/proc/ClickOn( var/atom/A, var/params ) - if(world.time <= next_click) +/mob/proc/ClickOn(var/atom/A, var/params) + if(world.time <= next_click) // Hard check, before anything else, to avoid crashing return next_click = world.time + 1 @@ -66,16 +68,17 @@ face_atom(A) // change direction to face what you clicked on - if(next_move > world.time) // in the year 2000... + if(!canClick()) // in the year 2000... return - if(istype(loc,/obj/mecha)) - if(!locate(/turf) in list(A,A.loc)) // Prevents inventory from being drilled + if(istype(loc, /obj/mecha)) + if(!locate(/turf) in list(A, A.loc)) // Prevents inventory from being drilled return var/obj/mecha/M = loc - return M.click_action(A,src) + return M.click_action(A, src) if(restrained()) + setClickCooldown(10) RestrainedClickOn(A) return @@ -85,79 +88,78 @@ return throw_mode_off() - if(!istype(A,/obj/item/weapon/gun) && !isturf(A) && !istype(A,/obj/screen)) + if(!istype(A, /obj/item/weapon/gun) && !isturf(A) && !istype(A, /obj/screen)) last_target_click = world.time var/obj/item/W = get_active_hand() - if(W == A) - next_move = world.time + 6 - if(W.flags&USEDELAY) - next_move += 5 + if(W == A) // Handle attack_self W.attack_self(src) if(hand) update_inv_l_hand(0) else update_inv_r_hand(0) - return - // operate two STORAGE levels deep here (item in backpack in src; NOT item in box in backpack in src) + //Atoms on your person + // A is your location but is not a turf; or is on you (backpack); or is on something on you (box in backpack); sdepth is needed here because contents depth does not equate inventory storage depth. var/sdepth = A.storage_depth(src) - if(A == loc || (A in loc) || (sdepth != -1 && sdepth <= 1)) - + if((!isturf(A) && A == loc) || (sdepth != -1 && sdepth <= 1)) // faster access to objects already on you if(A in contents) - next_move = world.time + 6 // on your person + setMoveCooldown(5) //taking an item off of an inventory slot else - next_move = world.time + 8 // in a box/bag or in your square - - // No adjacency needed + setMoveCooldown(10) //getting something out of a backpack + if(W) - if(W.flags&USEDELAY) - next_move += 5 - var/resolved = W.resolve_attackby(A, src) if(!resolved && A && W) - W.afterattack(A,src,1,params) // 1 indicates adjacency + W.afterattack(A, src, 1, params) // 1 indicates adjacency else + if(ismob(A)) // No instant mob attacking + setClickCooldown(DEFAULT_ATTACK_COOLDOWN) UnarmedAttack(A, 1) return if(!isturf(loc)) // This is going to stop you from telekinesing from inside a closet, but I don't shed many tears for that return - // Allows you to click on a box's contents, if that box is on the ground, but no deeper than that + //Atoms on turfs (not on your person) + // A is a turf or is on a turf, or in something on a turf (pen in a box); but not something in something on a turf (pen in a box in a backpack) sdepth = A.storage_depth_turf() if(isturf(A) || isturf(A.loc) || (sdepth != -1 && sdepth <= 1)) - next_move = world.time + 10 - if(A.Adjacent(src)) // see adjacent.dm + setMoveCooldown(10) + if(W) - if(W.flags&USEDELAY) - next_move += 5 - // Return 1 in attackby() to prevent afterattack() effects (when safely moving items for example) var/resolved = W.resolve_attackby(A,src) if(!resolved && A && W) - W.afterattack(A,src,1,params) // 1: clicking something Adjacent + W.afterattack(A, src, 1, params) // 1: clicking something Adjacent else + if(ismob(A)) // No instant mob attacking + setClickCooldown(DEFAULT_ATTACK_COOLDOWN) UnarmedAttack(A, 1) return else // non-adjacent click if(W) - W.afterattack(A,src,0,params) // 0: not Adjacent + W.afterattack(A, src, 0, params) // 0: not Adjacent else RangedAttack(A, params) return -/mob/proc/changeNext_move(num) - next_move = world.time + num +/mob/proc/setClickCooldown(var/timeout) + next_move = max(world.time + timeout, next_move) -// Default behavior: ignore double clicks, consider them normal clicks instead +/mob/proc/canClick() + if(config.no_click_cooldown || next_move <= world.time) + return 1 + return 0 + +// Default behavior: ignore double clicks, the second click that makes the doubleclick call already calls for a normal click /mob/proc/DblClickOn(var/atom/A, var/params) - ClickOn(A,params) + return /* Translates into attack_hand, etc. @@ -201,14 +203,12 @@ LaserEyes(A) // moved into a proc below else if(TK in mutations) switch(get_dist(src,A)) - if(0) - ; if(1 to 5) // not adjacent may mean blocked by window - next_move += 2 + setMoveCooldown(2) if(5 to 7) - next_move += 5 + setMoveCooldown(5) if(8 to tk_maxrange) - next_move += 10 + setMoveCooldown(10) else return A.attack_tk(src) @@ -231,7 +231,6 @@ /mob/living/carbon/MiddleClickOn(var/atom/A) swap_hand() - // In case of use break glass /* /atom/proc/MiddleClick(var/mob/M as mob) @@ -307,7 +306,7 @@ return /mob/living/LaserEyes(atom/A) - next_move = world.time + 6 + setClickCooldown(4) var/turf/T = get_turf(src) var/turf/U = get_turf(A) diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm index 5986011688..414071a964 100644 --- a/code/_onclick/cyborg.dm +++ b/code/_onclick/cyborg.dm @@ -35,7 +35,7 @@ if(stat || lockcharge || weakened || stunned || paralysis) return - if(next_move >= world.time) + if(!canClick()) return face_atom(A) // change direction to face what you clicked on @@ -68,9 +68,6 @@ return if(W == A) - next_move = world.time + 8 - if(W.flags&USEDELAY) - next_move += 5 W.attack_self(src) return @@ -78,9 +75,6 @@ // cyborgs are prohibited from using storage items so we can I think safely remove (A.loc in contents) if(A == loc || (A in loc) || (A in contents)) // No adjacency checks - next_move = world.time + 8 - if(W.flags&USEDELAY) - next_move += 5 var/resolved = A.attackby(W,src) if(!resolved && A && W) @@ -93,16 +87,12 @@ // cyborgs are prohibited from using storage items so we can I think safely remove (A.loc && isturf(A.loc.loc)) if(isturf(A) || isturf(A.loc)) if(A.Adjacent(src)) // see adjacent.dm - next_move = world.time + 10 - if(W.flags&USEDELAY) - next_move += 5 var/resolved = A.attackby(W, src) if(!resolved && A && W) W.afterattack(A, src, 1, params) return else - next_move = world.time + 10 W.afterattack(A, src, 0, params) return return diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index d4f323e323..62df4c26c8 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -52,9 +52,8 @@ /obj/screen/item_action/Click() if(!usr || !owner) return 1 - if(usr.next_move >= world.time) + if(!usr.canClick()) return - usr.next_move = world.time + 6 if(usr.stat || usr.restrained() || usr.stunned || usr.lying) return 1 @@ -84,7 +83,7 @@ name = "storage" /obj/screen/storage/Click() - if(world.time <= usr.next_move) + if(!usr.canClick()) return 1 if(usr.stat || usr.paralysis || usr.stunned || usr.weakened) return 1 @@ -94,7 +93,6 @@ var/obj/item/I = usr.get_active_hand() if(I) usr.ClickOn(master) - usr.next_move = world.time+2 return 1 /obj/screen/gun @@ -480,7 +478,7 @@ /obj/screen/inventory/Click() // At this point in client Click() code we have passed the 1/10 sec check and little else // We don't even know if it's a middle click - if(world.time <= usr.next_move) + if(!usr.canClick()) return 1 if(usr.stat || usr.paralysis || usr.stunned || usr.weakened) return 1 @@ -491,12 +489,10 @@ if(iscarbon(usr)) var/mob/living/carbon/C = usr C.activate_hand("r") - usr.next_move = world.time+2 if("l_hand") if(iscarbon(usr)) var/mob/living/carbon/C = usr C.activate_hand("l") - usr.next_move = world.time+2 if("swap") usr:swap_hand() if("hand") @@ -505,5 +501,4 @@ if(usr.attack_ui(slot_id)) usr.update_inv_l_hand(0) usr.update_inv_r_hand(0) - usr.next_move = world.time+6 return 1 diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index d3c3df942e..0cca5569c2 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -6,11 +6,13 @@ // No comment /atom/proc/attackby(obj/item/W, mob/user) return + /atom/movable/attackby(obj/item/W, mob/user) if(!(W.flags&NOBLUDGEON)) visible_message("[src] has been hit by [user] with [W].") /mob/living/attackby(obj/item/I, mob/user) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(istype(I) && ismob(user)) I.attack(src, user) diff --git a/code/_onclick/observer.dm b/code/_onclick/observer.dm index abc0e6114e..324dcc234d 100644 --- a/code/_onclick/observer.dm +++ b/code/_onclick/observer.dm @@ -32,8 +32,8 @@ if(client.buildmode) build_click(src, client.buildmode, params, A) return - if(world.time <= next_move) return - next_move = world.time + 8 + if(!canClick()) return + setClickCooldown(4) // You are responsible for checking config.ghost_interaction when you override this function // Not all of them require checking, see below A.attack_ghost(src) diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 179a470fc6..95c77d6708 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -38,15 +38,6 @@ return else if(TK in mutations) - switch(get_dist(src,A)) - if(1 to 5) // not adjacent may mean blocked by window - next_move += 2 - if(5 to 7) - next_move += 5 - if(8 to 15) - next_move += 10 - if(16 to 128) - return A.attack_tk(src) /mob/living/RestrainedClickOn(var/atom/A) diff --git a/code/_onclick/rig.dm b/code/_onclick/rig.dm index ad9346ec15..600d8c5619 100644 --- a/code/_onclick/rig.dm +++ b/code/_onclick/rig.dm @@ -48,12 +48,14 @@ ..() /mob/living/carbon/human/proc/HardsuitClickOn(atom/A) + if(!canClick()) + return if(back) var/obj/item/weapon/rig/rig = back if(istype(rig) && rig.selected_module) - if(world.time <= next_move) return 1 - next_move = world.time + 8 rig.selected_module.engage(A) + if(ismob(A)) // No instant mob attacking - though modules have their own cooldowns + setClickCooldown(DEFAULT_ATTACK_COOLDOWN) return 1 return 0 diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm index f3419b074a..f772ac8ea9 100644 --- a/code/_onclick/telekinesis.dm +++ b/code/_onclick/telekinesis.dm @@ -111,12 +111,16 @@ var/const/tk_maxrange = 15 if(0) ; if(1 to 5) // not adjacent may mean blocked by window - if(!proximity) - user.next_move += 2 + ; + //TODO replace these with movement timeouts + //if(!proximity) + // user.next_move += 2 if(5 to 7) - user.next_move += 5 + ; + //user.next_move += 5 if(8 to tk_maxrange) - user.next_move += 10 + ; + //user.next_move += 10 else user << "Your mind won't reach that far." return diff --git a/code/controllers/Processes/initialize.dm b/code/controllers/Processes/initialize.dm new file mode 100644 index 0000000000..055a056bed --- /dev/null +++ b/code/controllers/Processes/initialize.dm @@ -0,0 +1,31 @@ +var/list/pending_init_objects + +/datum/controller/process/initialize + var/list/objects_to_initialize + +/datum/controller/process/initialize/setup() + name = "init" + schedule_interval = 1 // Every tick, scary + objects_to_initialize = pending_init_objects + +/datum/controller/process/initialize/doWork() + for(var/atom/movable/A in objects_to_initialize) + A.initialize() + scheck() + objects_to_initialize.Remove(A) + + if(!objects_to_initialize.len) + disable() + +/proc/initialize_object(var/atom/movable/obj_to_init) + if(processScheduler.hasProcess("init")) + var/datum/controller/process/initialize/init = processScheduler.getProcess("init") + init.objects_to_initialize += obj_to_init + init.enable() + else + world.log << "Not yet" + if(!pending_init_objects) pending_init_objects = list() + pending_init_objects += obj_to_init + +/datum/controller/process/initialize/getStatName() + return ..()+"([objects_to_initialize.len])" diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 06adfe42f9..a0558775e9 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -139,6 +139,7 @@ var/list/gamemode_cache = list() var/welder_vision = 1 var/generate_asteroid = 0 + var/no_click_cooldown = 0 //Used for modifying movement speed for mobs. //Unversal modifiers @@ -328,6 +329,9 @@ var/list/gamemode_cache = list() if ("generate_asteroid") config.generate_asteroid = 1 + if ("no_click_cooldown") + config.no_click_cooldown = 1 + if("allow_admin_ooccolor") config.allow_admin_ooccolor = 1 diff --git a/code/game/gamemodes/blob/theblob.dm b/code/game/gamemodes/blob/theblob.dm index 44486d605b..123bb97a3f 100644 --- a/code/game/gamemodes/blob/theblob.dm +++ b/code/game/gamemodes/blob/theblob.dm @@ -157,6 +157,7 @@ attackby(var/obj/item/weapon/W, var/mob/user) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) playsound(src.loc, 'sound/effects/attackblob.ogg', 50, 1) src.visible_message("The [src.name] has been attacked with \the [W][(user ? " by [user]." : ".")]") var/damage = 0 diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index f0ced03da7..19ea17104a 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -186,6 +186,7 @@ src.bugged = 1 else if(W.damtype == BRUTE || W.damtype == BURN) //bashing cameras + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if (W.force >= src.toughness) user.do_attack_animation(src) visible_message("[src] has been [pick(W.attack_verb)] with [W] by [user]!") @@ -301,6 +302,9 @@ /obj/machinery/camera/proc/can_see() var/list/see = null var/turf/pos = get_turf(src) + if(!pos) + return list() + if(isXRay()) see = range(view_range, pos) else diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm index 2da65d273f..ccf2fb97ae 100644 --- a/code/game/machinery/deployable.dm +++ b/code/game/machinery/deployable.dm @@ -64,7 +64,7 @@ for reference: var/health = 100 var/maxhealth = 100 var/material/material - + /obj/structure/barricade/New(var/newloc, var/material_name) ..(newloc) if(!material_name) @@ -77,7 +77,7 @@ for reference: desc = "This space is blocked off by a barricade made of [material.display_name]." color = material.icon_colour maxhealth = material.integrity - health = maxhealth + health = maxhealth /obj/structure/barricade/get_material() return material @@ -99,6 +99,7 @@ for reference: return return else + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) switch(W.damtype) if("fire") src.health -= W.force * 1 @@ -111,6 +112,7 @@ for reference: qdel(src) return ..() + /obj/structure/barricade/proc/dismantle() material.place_dismantled_product(get_turf(src)) qdel(src) diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index 9075da2a05..2def8f8086 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -266,6 +266,7 @@ //psa to whoever coded this, there are plenty of objects that need to call attack() on doors without bludgeoning them. if(src.density && istype(I, /obj/item/weapon) && user.a_intent == I_HURT && !istype(I, /obj/item/weapon/card)) var/obj/item/weapon/W = I + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) if(W.force < min_force) diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index dc3edc9328..e50af2bcf0 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -229,6 +229,7 @@ //If it's a weapon, smash windoor. Unless it's an id card, agent card, ect.. then ignore it (Cards really shouldnt damage a door anyway) if(src.density && istype(I, /obj/item/weapon) && !istype(I, /obj/item/weapon/card)) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) var/aforce = I.force playsound(src.loc, 'sound/effects/Glasshit.ogg', 75, 1) visible_message("[src] was hit by [I].") diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 5d184f0b07..2fa0281ecd 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -338,7 +338,7 @@ var/list/turret_icons else //if the turret was attacked with the intention of harming it: - user.changeNext_move(NEXT_MOVE_DELAY) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) take_damage(I.force * 0.5) if(I.force * 0.5 > 1) //if the force of impact dealt at least 1 damage, the turret gets pissed off if(!attacked && !emagged) diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index 96dda70158..573ede3fb0 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -505,6 +505,7 @@ return /obj/mecha/attack_hand(mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) src.log_message("Attack by hand/paw. Attacker - [user].",1) if(istype(user,/mob/living/carbon/human)) @@ -664,6 +665,7 @@ return /obj/mecha/proc/dynattackby(obj/item/weapon/W as obj, mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) src.log_message("Attacked by [W]. Attacker - [user]") if(prob(src.deflect_chance)) user << "\The [W] bounces off [src.name]." @@ -1683,6 +1685,7 @@ /obj/mecha/attack_generic(var/mob/user, var/damage, var/attack_message) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(!damage) return 0 diff --git a/code/game/objects/effects/aliens.dm b/code/game/objects/effects/aliens.dm index 1bb11016d7..5257cff014 100644 --- a/code/game/objects/effects/aliens.dm +++ b/code/game/objects/effects/aliens.dm @@ -98,6 +98,7 @@ return /obj/effect/alien/resin/attack_hand() + usr.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if (HULK in usr.mutations) usr << "You easily destroy the [name]." for(var/mob/O in oviewers(src)) @@ -124,6 +125,7 @@ /obj/effect/alien/resin/attackby(obj/item/weapon/W as obj, mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) var/aforce = W.force health = max(0, health - aforce) playsound(loc, 'sound/effects/attackblob.ogg', 100, 1) @@ -231,6 +233,7 @@ Alien plants should do something if theres a lot of poison return /obj/effect/alien/weeds/attackby(var/obj/item/weapon/W, var/mob/user) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(W.attack_verb.len) visible_message("\The [src] have been [pick(W.attack_verb)] with \the [W][(user ? " by [user]." : ".")]") else diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 34625759e3..8f36b1d007 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -172,7 +172,6 @@ else if(isliving(src.loc)) return - user.next_move = max(user.next_move+2,world.time + 2) user.put_in_active_hand(src) return @@ -607,10 +606,10 @@ modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out. usr.visible_message("[zoomdevicename ? "[usr] looks up from the [src.name]" : "[usr] lowers the [src.name]"].") return - - + /obj/item/proc/pwr_drain() return 0 // Process Kill /obj/item/proc/resolve_attackby(atom/A, mob/source) return A.attackby(src,source) + diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index 90e296f881..43acc06908 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -5,6 +5,7 @@ var/active_w_class sharp = 0 edge = 0 + armor_penetration = 50 flags = NOBLOODY /obj/item/weapon/melee/energy/proc/activate(mob/living/user) @@ -173,7 +174,8 @@ name = "energy blade" desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal." icon_state = "blade" - force = 70.0//Normal attacks deal very high damage. + force = 40 //Normal attacks deal very high damage - about the same as wielded fire axe + armor_penetration = 100 sharp = 1 edge = 1 anchored = 1 // Never spawned outside of inventory, should be fine. diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 786a198770..d856be051c 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -13,6 +13,7 @@ var/damtype = "brute" var/force = 0 + var/armor_penetration = 0 /obj/Destroy() processing_objects -= src diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 91b19ae087..60cf0474df 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -341,9 +341,12 @@ if(!req_breakout()) return + if(!escapee.canClick()) + return + + escapee.setClickCooldown(100) + //okay, so the closet is either welded or locked... resist!!! - escapee.next_move = world.time + 100 - escapee.last_special = world.time + 100 escapee << "You lean on the back of \the [src] and start pushing the door open. (this will take about [breakout_time] minutes)" visible_message("The [src] begins to shake violently!") diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 149d6bf394..e52db4f150 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -30,6 +30,7 @@ /obj/structure/grille/attack_hand(mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) user.do_attack_animation(src) @@ -155,7 +156,8 @@ //window placing end else if(!(W.flags & CONDUCT) || !shock(user, 70)) - user.do_attack_animation(src) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) + user.do_attack_animation(src) playsound(loc, 'sound/effects/grillehit.ogg', 80, 1) switch(W.damtype) if("fire") diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index b91f6bb641..2bb2c29a39 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -171,6 +171,7 @@ playsound(loc, 'sound/effects/Glasshit.ogg', 50, 1) /obj/structure/window/attack_hand(mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(HULK in user.mutations) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!")) user.visible_message("[user] smashes through [src]!") @@ -198,6 +199,7 @@ return /obj/structure/window/attack_generic(var/mob/user, var/damage) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(!damage) return if(damage >= 10) @@ -268,6 +270,7 @@ new glasstype(loc) qdel(src) else + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(W.damtype == BRUTE || W.damtype == BURN) user.do_attack_animation(src) hit(W.force) diff --git a/code/game/turfs/simulated/wall_attacks.dm b/code/game/turfs/simulated/wall_attacks.dm index 5cc6ee9289..cd3397858b 100644 --- a/code/game/turfs/simulated/wall_attacks.dm +++ b/code/game/turfs/simulated/wall_attacks.dm @@ -56,6 +56,7 @@ radiate() add_fingerprint(user) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) var/rotting = (locate(/obj/effect/overlay/wallrot) in src) if (HULK in user.mutations) if (rotting || !prob(material.hardness)) @@ -69,6 +70,7 @@ /turf/simulated/wall/attack_generic(var/mob/user, var/damage, var/attack_message, var/wallbreaker) radiate() + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) var/rotting = (locate(/obj/effect/overlay/wallrot) in src) if(!damage || !wallbreaker) try_touch(user, rotting) @@ -86,6 +88,7 @@ /turf/simulated/wall/attackby(obj/item/weapon/W as obj, mob/user as mob) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if (!user.) user << "You don't have the dexterity to do this!" return diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 1e1e998e02..52f6668b56 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -604,110 +604,17 @@ proc/admin_notice(var/message, var/rights) if(!check_rights(0)) return var/dat = "The first rule of adminbuse is: you don't talk about the adminbuse.
" - - if(check_rights(R_ADMIN,0)) - dat += {" - Admin Secrets
-
- Bombing List
- Show current traitors and objectives
- Show last [length(lastsignalers)] signalers
- Show last [length(lawchanges)] law changes
- Show AI Laws
- Show Game Mode
- Show Crew Manifest
- List DNA (Blood)
- List Fingerprints

-
- "} - - if(check_rights(R_FUN,0)) - dat += {" - 'Random' Events
-
- Toggle station artificial gravity
- Spawn a wave of meteors (aka lagocolyptic shower)
- Spawn a gravitational anomaly (aka lagitational anomolag)
- Spawn wormholes
- Spawn blob
- Trigger a Xenomorph infestation
- Trigger a Cortical Borer infestation
- Spawn an Alien silently
- Trigger a Spider infestation
- Send in a space ninja
- Send in a strike team
- Trigger an Carp migration
- Irradiate the station
- Trigger a Prison Break
- Trigger a Virus Outbreak
- Spawn an Immovable Rod
- Toggle a "lights out" event
- Spawn an Ion Storm
- Spawn Space-Vines
- Trigger a communication blackout
-
- Fun Secrets
-
- Remove 'internal' clothing
- Remove ALL clothing
- Turn all humans into monkeys
- Remove firesuits, grilles, and pods
- Make all areas powered
- Make all areas unpowered
- Power all SMES
- Toggle Prison Shuttle Status(Use with S/R)
- Send Prison Shuttle
- Return Prison Shuttle
- Warp all Players to Prison
- Triple AI mode (needs to be used in the lobby)
- Everyone is the traitor
- There can only be one!
- Ghost Mode
- Make all players retarded
- Make all items look like guns
- Paintball Mode
- Japanese Animes Mode
- Egalitarian Station Mode
- Launch a shuttle
- Force launch a shuttle
- Jump a shuttle
- Move a shuttle
- Break all lights
- Fix all lights
- Best Friend AI
- The floor is lava! (DANGEROUS: extremely lame)
- "} - - if(check_rights(R_SERVER,0)) - dat += "Toggle bomb cap
" - - if(check_rights(R_SERVER|R_FUN,0)) - dat += {" -
- Final Solutions
- (Warning, these will end the round!)
-
- Summon Nar-Sie
- Start a Supermatter Cascade
- "} - - dat += "
" - - if(check_rights(R_DEBUG,0)) - dat += {" - Security Level Elevated
-
- Change all maintenance doors to engie/brig access only
- Change all maintenance doors to brig access only
- Remove cap on security officers
-
- Coder Secrets
-
- Show Job Debug
- Admin Log
-
- "} - + for(var/datum/admin_secret_category/category in admin_secrets.categories) + if(!category.can_view(usr)) + continue + dat += "[category.name]
" + if(category.desc) + dat += "[category.desc]
" + for(var/datum/admin_secret_item/item in category.items) + if(!item.can_view(usr)) + continue + dat += "[item.name()]
" + dat += "
" usr << browse(dat, "window=secrets") return diff --git a/code/modules/admin/admin_secrets.dm b/code/modules/admin/admin_secrets.dm new file mode 100644 index 0000000000..38bebb844a --- /dev/null +++ b/code/modules/admin/admin_secrets.dm @@ -0,0 +1,110 @@ +var/datum/admin_secrets/admin_secrets = new() + +/datum/admin_secrets + var/list/datum/admin_secret_category/categories + var/list/datum/admin_secret_item/items + +/datum/admin_secrets/New() + ..() + categories = init_subtypes(/datum/admin_secret_category) + items = list() + var/list/category_assoc = list() + for(var/datum/admin_secret_category/category in categories) + category_assoc[category.type] = category + + for(var/item_type in (typesof(/datum/admin_secret_item) - /datum/admin_secret_item)) + var/datum/admin_secret_item/secret_item = item_type + if(!initial(secret_item.name)) + continue + + var/datum/admin_secret_item/item = new item_type() + var/datum/admin_secret_category/category = category_assoc[item.category] + dd_insertObjectList(category.items, item) + items += item + +/datum/admin_secret_category + var/name = "" + var/desc = "" + var/list/datum/admin_secret_item/items + +/datum/admin_secret_category + ..() + items = list() + +/datum/admin_secret_category/proc/can_view(var/mob/user) + for(var/datum/admin_secret_item/item in items) + if(item.can_view(user)) + return 1 + return 0 + +/datum/admin_secret_item + var/name = "" + var/category = null + var/log = 1 + var/feedback = 1 + var/permissions = R_HOST + var/warn_before_use = 0 + +/datum/admin_secret_item/dd_SortValue() + return "[name]" + +/datum/admin_secret_item/proc/name() + return name + +/datum/admin_secret_item/proc/can_view(var/mob/user) + return check_rights(permissions, 0, user) + +/datum/admin_secret_item/proc/can_execute(var/mob/user) + if(can_view(user)) + if(!warn_before_use || alert("Execute the command '[name]'?", name, "No","Yes") == "Yes") + return 1 + return 0 + +/datum/admin_secret_item/proc/execute(var/mob/user) + if(!can_execute(user)) + return 0 + + if(log) + log_and_message_admins("used secret '[name]'", user) + if(feedback) + feedback_inc("admin_secrets_used",1) + feedback_add_details("admin_secrets_used","[name]") + return 1 + +/************************* +* Pre-defined categories * +*************************/ +/datum/admin_secret_category/admin_secrets + name = "Admin Secrets" + +/datum/admin_secret_category/random_events + name = "'Random' Events" + +/datum/admin_secret_category/fun_secrets + name = "Fun Secrets" + +/datum/admin_secret_category/final_solutions + name = "Final Solutions" + desc = "(Warning, these will end the round!)" + +/************************* +* Pre-defined base items * +*************************/ +/datum/admin_secret_item/admin_secret + category = /datum/admin_secret_category/admin_secrets + log = 0 + permissions = R_ADMIN + +/datum/admin_secret_item/random_event + category = /datum/admin_secret_category/random_events + permissions = R_FUN + warn_before_use = 1 + +/datum/admin_secret_item/fun_secret + category = /datum/admin_secret_category/fun_secrets + permissions = R_FUN + warn_before_use = 1 + +/datum/admin_secret_item/final_solution + category = /datum/admin_secret_category/final_solutions + permissions = R_FUN|R_SERVER|R_ADMIN diff --git a/code/modules/admin/secrets/admin_secrets/admin_logs.dm b/code/modules/admin/secrets/admin_secrets/admin_logs.dm new file mode 100644 index 0000000000..d2664f1e2b --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/admin_logs.dm @@ -0,0 +1,13 @@ +/datum/admin_secret_item/admin_secret/admin_logs + name = "Admin Logs" + +/datum/admin_secret_item/admin_secret/admin_logs/execute(var/mob/user) + . = ..() + if(!.) + return + var/dat = "Admin Log
" + for(var/l in admin_log) + dat += "
  • [l]
  • " + if(!admin_log.len) + dat += "No-one has done anything this round!" + user << browse(dat, "window=admin_log") diff --git a/code/modules/admin/secrets/admin_secrets/alter_narsie.dm b/code/modules/admin/secrets/admin_secrets/alter_narsie.dm new file mode 100644 index 0000000000..75281adca8 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/alter_narsie.dm @@ -0,0 +1,14 @@ +/datum/admin_secret_item/admin_secret/alter_narise + name = "Alter Nar-Sie" + +/datum/admin_secret_item/admin_secret/alter_narise/execute(var/mob/user) + . = ..() + if(!.) + return + var/choice = input(user, "How do you wish for Nar-Sie to interact with its surroundings?") as null|anything in list("CultStation13", "Nar-Singulo") + if(choice == "CultStation13") + log_and_message_admins("has set narsie's behaviour to \"CultStation13\".", user) + narsie_behaviour = choice + if(choice == "Nar-Singulo") + log_and_message_admins("has set narsie's behaviour to \"Nar-Singulo\".", user) + narsie_behaviour = choice diff --git a/code/modules/admin/secrets/admin_secrets/bombing_list.dm b/code/modules/admin/secrets/admin_secrets/bombing_list.dm new file mode 100644 index 0000000000..fa3f268396 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/bombing_list.dm @@ -0,0 +1,12 @@ +/datum/admin_secret_item/admin_secret/bombing_list + name = "Bombing List" + +/datum/admin_secret_item/admin_secret/bombing_list/execute(var/mob/user) + . = ..() + if(!.) + return + + var/dat = "Bombing List
    " + for(var/l in bombers) + dat += text("[l]
    ") + user << browse(dat, "window=bombers") diff --git a/code/modules/admin/secrets/admin_secrets/jump_shuttle.dm b/code/modules/admin/secrets/admin_secrets/jump_shuttle.dm new file mode 100644 index 0000000000..4097632aa3 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/jump_shuttle.dm @@ -0,0 +1,36 @@ +/datum/admin_secret_item/admin_secret/jump_shuttle + name = "Jump a Shuttle" + +/datum/admin_secret_item/admin_secret/jump_shuttle/can_execute(var/mob/user) + if(!shuttle_controller) return 0 + return ..() + +/datum/admin_secret_item/admin_secret/jump_shuttle/execute(var/mob/user) + . = ..() + if(!.) + return + var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles + if (!shuttle_tag) return + + var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag] + + var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world + if (!origin_area) return + + var/destination_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world + if (!destination_area) return + + var/long_jump = alert(user, "Is there a transition area for this jump?","", "Yes", "No") + if (long_jump == "Yes") + var/transition_area = input(user, "Which area is the transition area? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world + if (!transition_area) return + + var/move_duration = input(user, "How many seconds will this jump take?") as num + + S.long_jump(origin_area, destination_area, transition_area, move_duration) + message_admins("[key_name_admin(user)] has initiated a jump from [origin_area] to [destination_area] lasting [move_duration] seconds for the [shuttle_tag] shuttle", 1) + log_admin("[key_name_admin(user)] has initiated a jump from [origin_area] to [destination_area] lasting [move_duration] seconds for the [shuttle_tag] shuttle") + else + S.short_jump(origin_area, destination_area) + message_admins("[key_name_admin(user)] has initiated a jump from [origin_area] to [destination_area] for the [shuttle_tag] shuttle", 1) + log_admin("[key_name_admin(user)] has initiated a jump from [origin_area] to [destination_area] for the [shuttle_tag] shuttle") diff --git a/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm b/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm new file mode 100644 index 0000000000..9d6ce44a2d --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/launch_shuttle.dm @@ -0,0 +1,26 @@ +/datum/admin_secret_item/admin_secret/launch_shuttle + name = "Launch a Shuttle" + +/datum/admin_secret_item/admin_secret/launch_shuttle/can_execute(var/mob/user) + if(!shuttle_controller) return 0 + return ..() + +/datum/admin_secret_item/admin_secret/launch_shuttle/execute(var/mob/user) + . = ..() + if(!.) + return + var/list/valid_shuttles = list() + for (var/shuttle_tag in shuttle_controller.shuttles) + if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry)) + valid_shuttles += shuttle_tag + + var/shuttle_tag = input(user, "Which shuttle do you want to launch?") as null|anything in valid_shuttles + if (!shuttle_tag) + return + + var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag] + if (S.can_launch()) + S.launch(user) + log_and_message_admins("launched the [shuttle_tag] shuttle", user) + else + alert(user, "The [shuttle_tag] shuttle cannot be launched at this time. It's probably busy.") diff --git a/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm b/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm new file mode 100644 index 0000000000..d1a86fec98 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/launch_shuttle_forced.dm @@ -0,0 +1,26 @@ +/datum/admin_secret_item/admin_secret/launch_shuttle_forced + name = "Launch a Shuttle (Forced)" + +/datum/admin_secret_item/admin_secret/launch_shuttle_forced/can_execute(var/mob/user) + if(!shuttle_controller) return 0 + return ..() + +/datum/admin_secret_item/admin_secret/launch_shuttle_forced/execute(var/mob/user) + . = ..() + if(!.) + return + var/list/valid_shuttles = list() + for (var/shuttle_tag in shuttle_controller.shuttles) + if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry)) + valid_shuttles += shuttle_tag + + var/shuttle_tag = input(user, "Which shuttle's launch do you want to force?") as null|anything in valid_shuttles + if (!shuttle_tag) + return + + var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag] + if (S.can_force()) + S.force_launch(user) + log_and_message_admins("forced the [shuttle_tag] shuttle", user) + else + alert(user, "The [shuttle_tag] shuttle launch cannot be forced at this time. It's busy, or hasn't been launched yet.") diff --git a/code/modules/admin/secrets/admin_secrets/list_dna.dm b/code/modules/admin/secrets/admin_secrets/list_dna.dm new file mode 100644 index 0000000000..f1c49f4897 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/list_dna.dm @@ -0,0 +1,14 @@ +/datum/admin_secret_item/admin_secret/list_dna + name = "List DNA (Blood)" + +/datum/admin_secret_item/admin_secret/list_dna/execute(var/mob/user) + . = ..() + if(!.) + return + var/dat = "Showing DNA from blood.
    " + dat += "" + for(var/mob/living/carbon/human/H in mob_list) + if(H.dna && H.ckey) + dat += "" + dat += "
    NameDNABlood Type
    [H][H.dna.unique_enzymes][H.b_type]
    " + user << browse(dat, "window=DNA;size=440x410") diff --git a/code/modules/admin/secrets/admin_secrets/list_fingerprints.dm b/code/modules/admin/secrets/admin_secrets/list_fingerprints.dm new file mode 100644 index 0000000000..03cb9701c4 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/list_fingerprints.dm @@ -0,0 +1,19 @@ +/datum/admin_secret_item/admin_secret/list_fingerprints + name = "List Fingerprints" + +/datum/admin_secret_item/admin_secret/list_fingerprints/execute(var/mob/user) + . = ..() + if(!.) + return + var/dat = "Showing Fingerprints.
    " + dat += "" + for(var/mob/living/carbon/human/H in mob_list) + if(H.ckey) + if(H.dna && H.dna.uni_identity) + dat += "" + else if(H.dna && !H.dna.uni_identity) + dat += "" + else if(!H.dna) + dat += "" + dat += "
    NameFingerprints
    [H][md5(H.dna.uni_identity)]
    [H]H.dna.uni_identity = null
    [H]H.dna = null
    " + user << browse(dat, "window=fingerprints;size=440x410") diff --git a/code/modules/admin/secrets/admin_secrets/move_shuttle.dm b/code/modules/admin/secrets/admin_secrets/move_shuttle.dm new file mode 100644 index 0000000000..5772bbed54 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/move_shuttle.dm @@ -0,0 +1,28 @@ +/datum/admin_secret_item/admin_secret/move_shuttle + name = "Move a Shuttle" + +/datum/admin_secret_item/admin_secret/move_shuttle/can_execute(var/mob/user) + if(!shuttle_controller) return 0 + return ..() + +/datum/admin_secret_item/admin_secret/move_shuttle/execute(var/mob/user) + . = ..() + if(!.) + return + var/confirm = alert(user, "This command directly moves a shuttle from one area to another. DO NOT USE THIS UNLESS YOU ARE DEBUGGING A SHUTTLE AND YOU KNOW WHAT YOU ARE DOING.", "Are you sure?", "Ok", "Cancel") + if (confirm == "Cancel") + return + + var/shuttle_tag = input(user, "Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles + if (!shuttle_tag) return + + var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag] + + var/origin_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world + if (!origin_area) return + + var/destination_area = input(user, "Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world + if (!destination_area) return + + S.move(origin_area, destination_area) + log_and_message_admins("moved the [shuttle_tag] shuttle", user) diff --git a/code/modules/admin/secrets/admin_secrets/prison_warp.dm b/code/modules/admin/secrets/admin_secrets/prison_warp.dm new file mode 100644 index 0000000000..eec85c2f04 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/prison_warp.dm @@ -0,0 +1,38 @@ +/datum/admin_secret_item/admin_secret/prison_warp + name = "Prison Warp" + +/datum/admin_secret_item/admin_secret/prison_warp/can_execute(var/mob/user) + if(!ticker) return 0 + return ..() + +/datum/admin_secret_item/admin_secret/prison_warp/execute(var/mob/user) + . = ..() + if(!.) + return + for(var/mob/living/carbon/human/H in mob_list) + var/turf/T = get_turf(H) + var/security = 0 + if((T && T in config.admin_levels) || prisonwarped.Find(H)) + //don't warp them if they aren't ready or are already there + continue + H.Paralyse(5) + if(H.wear_id) + var/obj/item/weapon/card/id/id = H.get_idcard() + for(var/A in id.access) + if(A == access_security) + security++ + if(!security) + //strip their stuff before they teleport into a cell :downs: + for(var/obj/item/weapon/W in H) + if(istype(W, /obj/item/organ/external)) + continue + //don't strip organs + H.drop_from_inventory(W) + //teleport person to cell + H.loc = pick(prisonwarp) + H.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(H), slot_w_uniform) + H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) + else + //teleport security person + H.loc = pick(prisonsecuritywarp) + prisonwarped += H diff --git a/code/modules/admin/secrets/admin_secrets/show_ai_laws.dm b/code/modules/admin/secrets/admin_secrets/show_ai_laws.dm new file mode 100644 index 0000000000..c76ff2d9c1 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/show_ai_laws.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/admin_secret/show_ai_laws + name = "Show AI laws" + +/datum/admin_secret_item/admin_secret/show_ai_laws/execute(var/mob/user) + . = ..() + if(.) + user.client.holder.output_ai_laws() diff --git a/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm b/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm new file mode 100644 index 0000000000..f4bb82224b --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/show_crew_manifest.dm @@ -0,0 +1,12 @@ +/datum/admin_secret_item/admin_secret/show_crew_manifest + name = "Show Crew Manifest" + +/datum/admin_secret_item/admin_secret/show_crew_manifest/execute(var/mob/user) + . = ..() + if(!.) + return + var/dat + dat += "

    Crew Manifest

    " + dat += data_core.get_manifest() + + user << browse(dat, "window=manifest;size=370x420;can_close=1") diff --git a/code/modules/admin/secrets/admin_secrets/show_game_mode.dm b/code/modules/admin/secrets/admin_secrets/show_game_mode.dm new file mode 100644 index 0000000000..b586e10846 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/show_game_mode.dm @@ -0,0 +1,14 @@ +/datum/admin_secret_item/admin_secret/show_game_mode + name = "Show Game Mode" + +/datum/admin_secret_item/admin_secret/show_game_mode/can_execute(var/mob/user) + if(!ticker) + return 0 + return ..() + +/datum/admin_secret_item/admin_secret/show_game_mode/execute(var/mob/user) + . = ..() + if(!.) + return + if (ticker.mode) alert("The game mode is [ticker.mode.name]") + else alert("For some reason there's a ticker, but not a game mode") diff --git a/code/modules/admin/secrets/admin_secrets/show_law_changes.dm b/code/modules/admin/secrets/admin_secrets/show_law_changes.dm new file mode 100644 index 0000000000..877e2c217d --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/show_law_changes.dm @@ -0,0 +1,15 @@ +/datum/admin_secret_item/admin_secret/show_law_changes + name = "Show law changes" + +/datum/admin_secret_item/admin_secret/show_law_changes/name() + return "Show Last [length(lawchanges)] Law change\s" + +/datum/admin_secret_item/admin_secret/show_law_changes/execute(var/mob/user) + . = ..() + if(!.) + return + + var/dat = "Showing last [length(lawchanges)] law changes.
    " + for(var/sig in lawchanges) + dat += "[sig]
    " + user << browse(dat, "window=lawchanges;size=800x500") diff --git a/code/modules/admin/secrets/admin_secrets/show_signalers.dm b/code/modules/admin/secrets/admin_secrets/show_signalers.dm new file mode 100644 index 0000000000..32a77cbef2 --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/show_signalers.dm @@ -0,0 +1,15 @@ +/datum/admin_secret_item/admin_secret/show_signalers + name = "Show Last Signalers" + +/datum/admin_secret_item/admin_secret/show_signalers/name() + return "Show Last [length(lastsignalers)] Signaler\s" + +/datum/admin_secret_item/admin_secret/show_signalers/execute(var/mob/user) + . = ..() + if(!.) + return + + var/dat = "Showing last [length(lastsignalers)] signalers.
    " + for(var/sig in lastsignalers) + dat += "[sig]
    " + user << browse(dat, "window=lastsignalers;size=800x500") diff --git a/code/modules/admin/secrets/admin_secrets/traitors_and_objectives.dm b/code/modules/admin/secrets/admin_secrets/traitors_and_objectives.dm new file mode 100644 index 0000000000..591c13bd3f --- /dev/null +++ b/code/modules/admin/secrets/admin_secrets/traitors_and_objectives.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/admin_secret/traitors_and_objectives + name = "Show current traitors and objectives" + +/datum/admin_secret_item/admin_secret/traitors_and_objectives/execute(var/mob/user) + . = ..() + if(.) + user.client.holder.check_antagonists() diff --git a/code/modules/admin/secrets/final_solutions/summon_narsie.dm b/code/modules/admin/secrets/final_solutions/summon_narsie.dm new file mode 100644 index 0000000000..8062f76752 --- /dev/null +++ b/code/modules/admin/secrets/final_solutions/summon_narsie.dm @@ -0,0 +1,11 @@ +/datum/admin_secret_item/final_solution/summon_narsie + name = "Summon Nar-Sie" + +/datum/admin_secret_item/final_solution/summon_narsie/execute(var/mob/user) + . = ..() + if(!.) + return + var/choice = input(user, "You sure you want to end the round and summon Nar-Sie at your location? Misuse of this could result in removal of flags or hilarity.") in list("PRAISE SATAN", "Cancel") + if(choice == "PRAISE SATAN") + new /obj/singularity/narsie/large(get_turf(user)) + log_and_message_admins("has summoned Nar-Sie and brought about a new realm of suffering.", user) diff --git a/code/modules/admin/secrets/final_solutions/supermatter_cascade.dm b/code/modules/admin/secrets/final_solutions/supermatter_cascade.dm new file mode 100644 index 0000000000..a50596985c --- /dev/null +++ b/code/modules/admin/secrets/final_solutions/supermatter_cascade.dm @@ -0,0 +1,13 @@ +/datum/admin_secret_item/final_solution/supermatter_cascade + name = "Supermatter Cascade" + +/datum/admin_secret_item/final_solution/supermatter_cascade/execute(var/mob/user) + . = ..() + if(!.) + return + var/choice = input(user, "You sure you want to destroy the universe and create a large explosion at your location? Misuse of this could result in removal of flags or hilarity.") in list("NO TIME TO EXPLAIN", "Cancel") + if(choice == "NO TIME TO EXPLAIN") + explosion(get_turf(user), 8, 16, 24, 32, 1) + new /turf/unsimulated/wall/supermatter(get_turf(user)) + SetUniversalState(/datum/universal_state/supermatter_cascade) + message_admins("[key_name_admin(user)] has managed to destroy the universe with a supermatter cascade. Good job, [key_name_admin(user)]") diff --git a/code/modules/admin/secrets/fun_secrets/break_all_lights.dm b/code/modules/admin/secrets/fun_secrets/break_all_lights.dm new file mode 100644 index 0000000000..ea54952a7e --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/break_all_lights.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/fun_secret/break_all_lights + name = "Break All Lights" + +/datum/admin_secret_item/fun_secret/break_all_lights/execute(var/mob/user) + . = ..() + if(.) + lightsout(0,0) diff --git a/code/modules/admin/secrets/fun_secrets/break_some_lights.dm b/code/modules/admin/secrets/fun_secrets/break_some_lights.dm new file mode 100644 index 0000000000..0c9aae1b16 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/break_some_lights.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/fun_secret/break_some_lights + name = "Break Some Lights" + +/datum/admin_secret_item/fun_secret/break_some_lights/execute(var/mob/user) + . = ..() + if(.) + lightsout(1,2) diff --git a/code/modules/admin/secrets/fun_secrets/fix_all_lights.dm b/code/modules/admin/secrets/fun_secrets/fix_all_lights.dm new file mode 100644 index 0000000000..387f6d3ce7 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/fix_all_lights.dm @@ -0,0 +1,10 @@ +/datum/admin_secret_item/fun_secret/fix_all_lights + name = "Fix All Lights" + +/datum/admin_secret_item/fun_secret/fix_all_lights/execute(var/mob/user) + . = ..() + if(!.) + return + + for(var/obj/machinery/light/L in world) + L.fix() diff --git a/code/modules/admin/secrets/fun_secrets/ghost_mode.dm b/code/modules/admin/secrets/fun_secrets/ghost_mode.dm new file mode 100644 index 0000000000..dfa84e4cf6 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/ghost_mode.dm @@ -0,0 +1,48 @@ +/datum/admin_secret_item/fun_secret/ghost_mode + name = "Ghost Mode" + var/list/affected_mobs + +/datum/admin_secret_item/fun_secret/ghost_mode/New() + ..() + affected_mobs = list() + +/datum/admin_secret_item/fun_secret/ghost_mode/execute(var/mob/user) + . = ..() + if(!.) + return + + var/list/affected_areas = list() + for(var/mob/M in living_mob_list) + if(M.stat == CONSCIOUS && !(M in affected_mobs)) + affected_mobs |= M + switch(rand(1,4)) + if(1) + M.show_message(text("You shudder as if cold..."), 1) + if(2) + M.show_message(text("You feel something gliding across your back..."), 1) + if(3) + M.show_message(text("Your eyes twitch, you feel like something you can't see is here..."), 1) + if(4) + M.show_message(text("You notice something moving out of the corner of your eye, but nothing is there..."), 1) + + for(var/obj/W in orange(5,M)) + if(prob(25) && !W.anchored) + step_rand(W) + + var/area/A = get_area(M) + if(A.requires_power && !A.always_unpowered && A.power_light && (A.z in config.player_levels)) + affected_areas |= get_area(M) + + affected_mobs |= user + for(var/area/AffectedArea in affected_areas) + AffectedArea.power_light = 0 + AffectedArea.power_change() + spawn(rand(25,50)) + AffectedArea.power_light = 1 + AffectedArea.power_change() + + sleep(100) + for(var/mob/M in affected_mobs) + M.show_message(text("The chilling wind suddenly stops..."), 1) + affected_mobs.Cut() + affected_areas.Cut() diff --git a/code/modules/admin/secrets/fun_secrets/make_all_areas_powered.dm b/code/modules/admin/secrets/fun_secrets/make_all_areas_powered.dm new file mode 100644 index 0000000000..3309190028 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/make_all_areas_powered.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/fun_secret/make_all_areas_powered + name = "Make All Areas Powered" + +/datum/admin_secret_item/fun_secret/make_all_areas_powered/execute(var/mob/user) + . = ..() + if(.) + power_restore() diff --git a/code/modules/admin/secrets/fun_secrets/make_all_areas_unpowered.dm b/code/modules/admin/secrets/fun_secrets/make_all_areas_unpowered.dm new file mode 100644 index 0000000000..a840006a23 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/make_all_areas_unpowered.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/fun_secret/make_all_areas_unpowered + name = "Make All Areas Unpowered" + +/datum/admin_secret_item/fun_secret/make_all_areas_unpowered/execute(var/mob/user) + . = ..() + if(.) + power_failure() diff --git a/code/modules/admin/secrets/fun_secrets/only_one.dm b/code/modules/admin/secrets/fun_secrets/only_one.dm new file mode 100644 index 0000000000..bc0c962b29 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/only_one.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/fun_secret/only_one + name = "There Can Be Only One" + +/datum/admin_secret_item/fun_secret/only_one/execute(var/mob/user) + . = ..() + if(.) + only_one() diff --git a/code/modules/admin/secrets/fun_secrets/paintball_mode.dm b/code/modules/admin/secrets/fun_secrets/paintball_mode.dm new file mode 100644 index 0000000000..8225b96b29 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/paintball_mode.dm @@ -0,0 +1,14 @@ +/datum/admin_secret_item/fun_secret/paintbal_mode + name = "Paintball Mode" + +/datum/admin_secret_item/fun_secret/paintbal_mode/execute(var/mob/user) + . = ..() + if(!.) + return + + for(var/species in all_species) + var/datum/species/S = all_species[species] + S.blood_color = "rainbow" + for(var/obj/effect/decal/cleanable/blood/B in world) + B.basecolor = "rainbow" + B.update_icon() diff --git a/code/modules/admin/secrets/fun_secrets/power_all_smes.dm b/code/modules/admin/secrets/fun_secrets/power_all_smes.dm new file mode 100644 index 0000000000..277edd5a43 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/power_all_smes.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/fun_secret/power_all_smes + name = "Power All SMES" + +/datum/admin_secret_item/fun_secret/power_all_smes/execute(var/mob/user) + . = ..() + if(.) + power_restore_quick() diff --git a/code/modules/admin/secrets/fun_secrets/remove_all_clothing.dm b/code/modules/admin/secrets/fun_secrets/remove_all_clothing.dm new file mode 100644 index 0000000000..28e9497f53 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/remove_all_clothing.dm @@ -0,0 +1,10 @@ +/datum/admin_secret_item/fun_secret/remove_all_clothing + name = "Remove ALL Clothing" + +/datum/admin_secret_item/fun_secret/remove_all_clothing/execute(var/mob/user) + . = ..() + if(!.) + return + + for(var/obj/item/clothing/O in world) + qdel(O) diff --git a/code/modules/admin/secrets/fun_secrets/remove_internal_clothing.dm b/code/modules/admin/secrets/fun_secrets/remove_internal_clothing.dm new file mode 100644 index 0000000000..73dba4ce4f --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/remove_internal_clothing.dm @@ -0,0 +1,10 @@ +/datum/admin_secret_item/fun_secret/remove_internal_clothing + name = "Remove 'Internal' Clothing" + +/datum/admin_secret_item/fun_secret/remove_internal_clothing/execute(var/mob/user) + . = ..() + if(!.) + return + + for(var/obj/item/clothing/under/O in world) + qdel(O) diff --git a/code/modules/admin/secrets/fun_secrets/send_strike_team.dm b/code/modules/admin/secrets/fun_secrets/send_strike_team.dm new file mode 100644 index 0000000000..3ec1bacb2c --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/send_strike_team.dm @@ -0,0 +1,11 @@ +/datum/admin_secret_item/fun_secret/send_strike_team + name = "Send Strike Team" + +/datum/admin_secret_item/fun_secret/send_strike_team/can_execute(var/mob/user) + if(!ticker) return 0 + return ..() + +/datum/admin_secret_item/fun_secret/send_strike_team/execute(var/mob/user) + . = ..() + if(.) + return user.client.strike_team() diff --git a/code/modules/admin/secrets/fun_secrets/toggle_bomb_cap.dm b/code/modules/admin/secrets/fun_secrets/toggle_bomb_cap.dm new file mode 100644 index 0000000000..33ba8a861c --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/toggle_bomb_cap.dm @@ -0,0 +1,21 @@ +/datum/admin_secret_item/fun_secret/toggle_bomb_cap + name = "Toggle Bomb Cap" + permissions = R_SERVER + +/datum/admin_secret_item/fun_secret/toggle_bomb_cap/execute(var/mob/user) + . = ..() + if(!.) + return + + switch(max_explosion_range) + if(14) max_explosion_range = 16 + if(16) max_explosion_range = 20 + if(20) max_explosion_range = 28 + if(28) max_explosion_range = 56 + if(56) max_explosion_range = 128 + if(128) max_explosion_range = 14 + var/range_dev = max_explosion_range *0.25 + var/range_high = max_explosion_range *0.5 + var/range_low = max_explosion_range + message_admins("[key_name_admin(user)] changed the bomb cap to [range_dev], [range_high], [range_low]", 1) + log_admin("[key_name_admin(user)] changed the bomb cap to [max_explosion_range]") diff --git a/code/modules/admin/secrets/fun_secrets/triple_ai_mode.dm b/code/modules/admin/secrets/fun_secrets/triple_ai_mode.dm new file mode 100644 index 0000000000..81b77eabb6 --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/triple_ai_mode.dm @@ -0,0 +1,13 @@ +/datum/admin_secret_item/fun_secret/triple_ai_mode + name = "Triple AI Mode" + +/datum/admin_secret_item/fun_secret/triple_ai_mode/can_execute(var/mob/user) + if(ticker && ticker.current_state > GAME_STATE_PREGAME) + return 0 + + return ..() + +/datum/admin_secret_item/admin_secret/triple_ai_mode/execute(var/mob/user) + . = ..() + if(.) + user.client.triple_ai() diff --git a/code/modules/admin/secrets/fun_secrets/turn_humans_into_corgies.dm b/code/modules/admin/secrets/fun_secrets/turn_humans_into_corgies.dm new file mode 100644 index 0000000000..ae6f36a1ac --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/turn_humans_into_corgies.dm @@ -0,0 +1,11 @@ +/datum/admin_secret_item/fun_secret/turn_humans_into_corgies + name = "Turn All Humans Into Corgies" + +/datum/admin_secret_item/fun_secret/turn_humans_into_corgies/execute(var/mob/user) + . = ..() + if(!.) + return + + for(var/mob/living/carbon/human/H in mob_list) + spawn(0) + H.corgize() diff --git a/code/modules/admin/secrets/fun_secrets/turn_humans_into_monkeys.dm b/code/modules/admin/secrets/fun_secrets/turn_humans_into_monkeys.dm new file mode 100644 index 0000000000..99b1573ade --- /dev/null +++ b/code/modules/admin/secrets/fun_secrets/turn_humans_into_monkeys.dm @@ -0,0 +1,11 @@ +/datum/admin_secret_item/fun_secret/turn_humans_into_monkeys + name = "Turn All Humans Into Monkeys" + +/datum/admin_secret_item/fun_secret/turn_humans_into_monkeys/execute(var/mob/user) + . = ..() + if(!.) + return + + for(var/mob/living/carbon/human/H in mob_list) + spawn(0) + H.monkeyize() diff --git a/code/modules/admin/secrets/random_events/gravity.dm b/code/modules/admin/secrets/random_events/gravity.dm new file mode 100644 index 0000000000..8d4cad4960 --- /dev/null +++ b/code/modules/admin/secrets/random_events/gravity.dm @@ -0,0 +1,31 @@ +/********** +* Gravity * +**********/ +/datum/admin_secret_item/random_event/gravity + name = "Toggle Station Artificial Gravity" + +/datum/admin_secret_item/random_event/gravity/can_execute(var/mob/user) + if(!(ticker && ticker.mode)) + return 0 + + return ..() + +/datum/admin_secret_item/random_event/gravity/execute(var/mob/user) + . = ..() + if(!.) + return + + gravity_is_on = !gravity_is_on + for(var/area/A in world) + A.gravitychange(gravity_is_on,A) + + feedback_inc("admin_secrets_fun_used",1) + feedback_add_details("admin_secrets_fun_used","Grav") + if(gravity_is_on) + log_admin("[key_name(user)] toggled gravity on.", 1) + message_admins("[key_name_admin(user)] toggled gravity on.", 1) + command_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") + else + log_admin("[key_name(user)] toggled gravity off.", 1) + message_admins("[key_name_admin(usr)] toggled gravity off.", 1) + command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artificial gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") diff --git a/code/modules/admin/secrets/random_events/trigger_cordical_borer_infestation.dm b/code/modules/admin/secrets/random_events/trigger_cordical_borer_infestation.dm new file mode 100644 index 0000000000..f96004565d --- /dev/null +++ b/code/modules/admin/secrets/random_events/trigger_cordical_borer_infestation.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/random_event/trigger_cordical_borer_infestation + name = "Trigger a Cortical Borer infestation" + +/datum/admin_secret_item/random_event/trigger_cordical_borer_infestation/execute(var/mob/user) + . = ..() + if(.) + return borers.attempt_random_spawn() diff --git a/code/modules/admin/secrets/random_events/trigger_xenomorph_infestation.dm b/code/modules/admin/secrets/random_events/trigger_xenomorph_infestation.dm new file mode 100644 index 0000000000..11dad2e84c --- /dev/null +++ b/code/modules/admin/secrets/random_events/trigger_xenomorph_infestation.dm @@ -0,0 +1,7 @@ +/datum/admin_secret_item/random_event/trigger_xenomorph_infestation + name = "Trigger a Xenomorph Infestation" + +/datum/admin_secret_item/random_event/trigger_xenomorph_infestation/execute(var/mob/user) + . = ..() + if(.) + return xenomorphs.attempt_random_spawn() diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index a27f1ab393..e3a2a83aab 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -1328,15 +1328,15 @@ return if(L.can_centcom_reply()) - var/input = sanitize(input(src.owner, "Please enter a message to reply to [key_name(L)] via their headset.","Outgoing message from [boss_short]", "")) + var/input = sanitize(input(src.owner, "Please enter a message to reply to [key_name(L)] via their headset.","Outgoing message from Centcomm", "")) if(!input) return src.owner << "You sent [input] to [L] via a secure channel." - log_admin("[src.owner] replied to [key_name(L)]'s [boss_short] message with the message [input].") - message_admins("[src.owner] replied to [key_name(L)]'s [boss_short] message with: \"[input]\"") + log_admin("[src.owner] replied to [key_name(L)]'s Centcomm message with the message [input].") + message_admins("[src.owner] replied to [key_name(L)]'s Centcom message with: \"[input]\"") if(!L.isMobAI()) L << "You hear something crackle in your headset for a moment before a voice speaks." - L << "Please stand by for a message from [boss_name]." + L << "Please stand by for a message from Central Command." L << "Message as follows." L << "[input]" L << "Message ends." @@ -1401,7 +1401,7 @@ var/obj/machinery/photocopier/faxmachine/fax = locate(href_list["originfax"]) //todo: sanitize - var/input = input(src.owner, "Please enter a message to reply to [key_name(sender)] via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
    for line breaks.", "Outgoing message from [boss_short]", "") as message|null + var/input = input(src.owner, "Please enter a message to reply to [key_name(sender)] via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
    for line breaks.", "Outgoing message from Centcomm", "") as message|null if(!input) return var/customname = input(src.owner, "Pick a title for the report", "Title") as text|null @@ -1419,7 +1419,7 @@ P.stamped = new P.stamped += /obj/item/weapon/stamp P.overlays += stampoverlay - P.stamps += "
    This paper has been stamped by the [boss_name] Quantum Relay." + P.stamps += "
    This paper has been stamped by the Central Command Quantum Relay." if(fax.recievefax(P)) src.owner << "\blue Message reply to transmitted successfully." @@ -1654,739 +1654,9 @@ log_and_message_admins("created [number] [english_list(paths)]") return - else if(href_list["secretsfun"]) - if(!check_rights(R_FUN)) return - - var/ok = 0 - switch(href_list["secretsfun"]) - if("sec_clothes") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SC") - for(var/obj/item/clothing/under/O in world) - qdel(O) - ok = 1 - if("sec_all_clothes") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SAC") - for(var/obj/item/clothing/O in world) - qdel(O) - ok = 1 - if("sec_classic1") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SC1") - for(var/obj/item/clothing/suit/fire/O in world) - qdel(O) - for(var/obj/structure/grille/O in world) - qdel(O) -/* for(var/obj/machinery/vehicle/pod/O in world) - for(var/mob/M in src) - M.loc = src.loc - if (M.client) - M.client.perspective = MOB_PERSPECTIVE - M.client.eye = M - qdel(O) - ok = 1*/ - if("monkey") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","M") - for(var/mob/living/carbon/human/H in mob_list) - spawn(0) - H.monkeyize() - ok = 1 - if("corgi") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","M") - for(var/mob/living/carbon/human/H in mob_list) - spawn(0) - H.corgize() - ok = 1 - if("striketeam") - if(usr.client.strike_team()) - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Strike") - if("tripleAI") - usr.client.triple_ai() - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TriAI") - if("gravity") - if(!(ticker && ticker.mode)) - usr << "Please wait until the game starts! Not sure how it will work otherwise." - return - gravity_is_on = !gravity_is_on - for(var/area/A in world) - A.gravitychange(gravity_is_on,A) - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Grav") - if(gravity_is_on) - log_admin("[key_name(usr)] toggled gravity on.", 1) - message_admins("\blue [key_name_admin(usr)] toggled gravity on.", 1) - command_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.") - else - log_admin("[key_name(usr)] toggled gravity off.", 1) - message_admins("\blue [key_name_admin(usr)] toggled gravity off.", 1) - command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artifical gravity has been disabled whilst the system reinitializes. Further failures may result in a gravitational collapse and formation of blackholes. Have a nice day.") - if("wave") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Meteor") - log_admin("[key_name(usr)] spawned a meteor wave", 1) - message_admins("\blue [key_name_admin(usr)] spawned a meteor wave.", 1) - new /datum/event/meteor_wave - if("goblob") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Blob") - log_admin("[key_name(usr)] spawned a blob", 1) - message_admins("\blue [key_name_admin(usr)] spawned a blob.", 1) - new /datum/event/blob - - if("aliens") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Aliens") - log_admin("[key_name(usr)] spawned an alien infestation", 1) - message_admins("\blue [key_name_admin(usr)] attempted an alien infestation", 1) - xenomorphs.attempt_random_spawn() - if("borers") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","Borers") - log_admin("[key_name(usr)] spawned a cortical borer infestation.", 1) - message_admins("\blue [key_name_admin(usr)] spawned a cortical borer infestation.", 1) - borers.attempt_random_spawn() - - if("power") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","P") - log_admin("[key_name(usr)] made all areas powered", 1) - message_admins("\blue [key_name_admin(usr)] made all areas powered", 1) - power_restore() - if("unpower") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","UP") - log_admin("[key_name(usr)] made all areas unpowered", 1) - message_admins("\blue [key_name_admin(usr)] made all areas unpowered", 1) - power_failure() - if("quickpower") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","QP") - log_admin("[key_name(usr)] made all SMESs powered", 1) - message_admins("\blue [key_name_admin(usr)] made all SMESs powered", 1) - power_restore_quick() - if("activateprison") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","AP") - world << "\blue Transit signature detected." - world << "\blue Incoming shuttle." - /* - var/A = locate(/area/shuttle_prison) - for(var/atom/movable/AM as mob|obj in A) - AM.z = 1 - AM.Move() - */ - message_admins("\blue [key_name_admin(usr)] sent the prison shuttle to the station.", 1) - if("deactivateprison") - /* - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","DP") - var/A = locate(/area/shuttle_prison) - for(var/atom/movable/AM as mob|obj in A) - AM.z = 2 - AM.Move() - */ - message_admins("\blue [key_name_admin(usr)] sent the prison shuttle back.", 1) - if("toggleprisonstatus") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","TPS") - for(var/obj/machinery/computer/prison_shuttle/PS in world) - PS.allowedtocall = !(PS.allowedtocall) - message_admins("\blue [key_name_admin(usr)] toggled status of prison shuttle to [PS.allowedtocall].", 1) - if("prisonwarp") - if(!ticker) - alert("The game hasn't started yet!", null, null, null, null, null) - return - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","PW") - message_admins("\blue [key_name_admin(usr)] teleported all players to the prison station.", 1) - for(var/mob/living/carbon/human/H in mob_list) - var/turf/loc = find_loc(H) - var/security = 0 - if(loc.z > 1 || prisonwarped.Find(H)) -//don't warp them if they aren't ready or are already there - continue - H.Paralyse(5) - if(H.wear_id) - var/obj/item/weapon/card/id/id = H.get_idcard() - for(var/A in id.access) - if(A == access_security) - security++ - if(!security) - //strip their stuff before they teleport into a cell :downs: - for(var/obj/item/weapon/W in H) - if(istype(W, /obj/item/organ/external)) - continue - //don't strip organs - H.drop_from_inventory(W) - //teleport person to cell - H.loc = pick(prisonwarp) - H.equip_to_slot_or_del(new /obj/item/clothing/under/color/orange(H), slot_w_uniform) - H.equip_to_slot_or_del(new /obj/item/clothing/shoes/orange(H), slot_shoes) - else - //teleport security person - H.loc = pick(prisonsecuritywarp) - prisonwarped += H - if("launchshuttle") - if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created. - - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShL") - - var/list/valid_shuttles = list() - for (var/shuttle_tag in shuttle_controller.shuttles) - if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry)) - valid_shuttles += shuttle_tag - - var/shuttle_tag = input("Which shuttle do you want to launch?") as null|anything in valid_shuttles - - if (!shuttle_tag) - return - - var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag] - if (S.can_launch()) - S.launch(usr) - message_admins("\blue [key_name_admin(usr)] launched the [shuttle_tag] shuttle", 1) - log_admin("[key_name(usr)] launched the [shuttle_tag] shuttle") - else - alert("The [shuttle_tag] shuttle cannot be launched at this time. It's probably busy.") - - if("forcelaunchshuttle") - if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created. - - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShFL") - - var/list/valid_shuttles = list() - for (var/shuttle_tag in shuttle_controller.shuttles) - if (istype(shuttle_controller.shuttles[shuttle_tag], /datum/shuttle/ferry)) - valid_shuttles += shuttle_tag - - var/shuttle_tag = input("Which shuttle's launch do you want to force?") as null|anything in valid_shuttles - - if (!shuttle_tag) - return - - var/datum/shuttle/ferry/S = shuttle_controller.shuttles[shuttle_tag] - if (S.can_force()) - S.force_launch(usr) - message_admins("\blue [key_name_admin(usr)] has forced the [shuttle_tag] shuttle launch", 1) - log_admin("[key_name(usr)] has forced the [shuttle_tag] shuttle launch") - else - alert("The [shuttle_tag] shuttle launch cannot be forced at this time. It's busy, or hasn't been launched yet.") - - if("jumpshuttle") - if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created. - - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShJ") - - var/shuttle_tag = input("Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles - if (!shuttle_tag) return - - var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag] - - var/origin_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world - if (!origin_area) return - - var/destination_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world - if (!destination_area) return - - var/long_jump = alert("Is there a transition area for this jump?","", "Yes", "No") - if (long_jump == "Yes") - var/transition_area = input("Which area is the transition area? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world - if (!transition_area) return - - var/move_duration = input("How many seconds will this jump take?") as num - - S.long_jump(origin_area, destination_area, transition_area, move_duration) - message_admins("\blue [key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] lasting [move_duration] seconds for the [shuttle_tag] shuttle", 1) - log_admin("[key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] lasting [move_duration] seconds for the [shuttle_tag] shuttle") - else - S.short_jump(origin_area, destination_area) - message_admins("\blue [key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] for the [shuttle_tag] shuttle", 1) - log_admin("[key_name_admin(usr)] has initiated a jump from [origin_area] to [destination_area] for the [shuttle_tag] shuttle") - - if("moveshuttle") - - if(!shuttle_controller) return // Something is very wrong, the shuttle controller has not been created. - - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","ShM") - - var/confirm = alert("This command directly moves a shuttle from one area to another. DO NOT USE THIS UNLESS YOU ARE DEBUGGING A SHUTTLE AND YOU KNOW WHAT YOU ARE DOING.", "Are you sure?", "Ok", "Cancel") - if (confirm == "Cancel") - return - - var/shuttle_tag = input("Which shuttle do you want to jump?") as null|anything in shuttle_controller.shuttles - if (!shuttle_tag) return - - var/datum/shuttle/S = shuttle_controller.shuttles[shuttle_tag] - - var/origin_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world - if (!origin_area) return - - var/destination_area = input("Which area is the shuttle at now? (MAKE SURE THIS IS CORRECT OR THINGS WILL BREAK)") as null|area in world - if (!destination_area) return - - S.move(origin_area, destination_area) - message_admins("\blue [key_name_admin(usr)] moved the [shuttle_tag] shuttle", 1) - log_admin("[key_name(usr)] moved the [shuttle_tag] shuttle") - - if("togglebombcap") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BC") - switch(max_explosion_range) - if(14) max_explosion_range = 16 - if(16) max_explosion_range = 20 - if(20) max_explosion_range = 28 - if(28) max_explosion_range = 56 - if(56) max_explosion_range = 128 - if(128) max_explosion_range = 14 - var/range_dev = max_explosion_range *0.25 - var/range_high = max_explosion_range *0.5 - var/range_low = max_explosion_range - message_admins("\red [key_name_admin(usr)] changed the bomb cap to [range_dev], [range_high], [range_low]", 1) - log_admin("[key_name_admin(usr)] changed the bomb cap to [max_explosion_range]") - - if("flicklights") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FL") - while(!usr.stat) -//knock yourself out to stop the ghosts - for(var/mob/M in player_list) - if(M.stat != 2 && prob(25)) - var/area/AffectedArea = get_area(M) - if(AffectedArea.name != "Space" && AffectedArea.name != "Engine Walls" && AffectedArea.name != "Chemical Lab Test Chamber" && AffectedArea.name != "Escape Shuttle" && AffectedArea.name != "Arrival Area" && AffectedArea.name != "Arrival Shuttle" && AffectedArea.name != "start area" && AffectedArea.name != "Engine Combustion Chamber") - AffectedArea.power_light = 0 - AffectedArea.power_change() - spawn(rand(55,185)) - AffectedArea.power_light = 1 - AffectedArea.power_change() - var/Message = rand(1,4) - switch(Message) - if(1) - M.show_message(text("\blue You shudder as if cold..."), 1) - if(2) - M.show_message(text("\blue You feel something gliding across your back..."), 1) - if(3) - M.show_message(text("\blue Your eyes twitch, you feel like something you can't see is here..."), 1) - if(4) - M.show_message(text("\blue You notice something moving out of the corner of your eye, but nothing is there..."), 1) - for(var/obj/W in orange(5,M)) - if(prob(25) && !W.anchored) - step_rand(W) - sleep(rand(100,1000)) - for(var/mob/M in player_list) - if(M.stat != 2) - M.show_message(text("\blue The chilling wind suddenly stops..."), 1) -/* if("shockwave") - ok = 1 - world << "\red ALERT: STATION STRESS CRITICAL" - sleep(60) - world << "\red ALERT: STATION STRESS CRITICAL. TOLERABLE LEVELS EXCEEDED!" - sleep(80) - world << "\red ALERT: STATION STRUCTURAL STRESS CRITICAL. SAFETY MECHANISMS FAILED!" - sleep(40) - for(var/mob/M in world) - shake_camera(M, 400, 1) - for(var/obj/structure/window/W in world) - spawn(0) - sleep(rand(10,400)) - W.ex_act(rand(2,1)) - for(var/obj/structure/grille/G in world) - spawn(0) - sleep(rand(20,400)) - G.ex_act(rand(2,1)) - for(var/obj/machinery/door/D in world) - spawn(0) - sleep(rand(20,400)) - D.ex_act(rand(2,1)) - for(var/turf/station/floor/Floor in world) - spawn(0) - sleep(rand(30,400)) - Floor.ex_act(rand(2,1)) - for(var/obj/structure/cable/Cable in world) - spawn(0) - sleep(rand(30,400)) - Cable.ex_act(rand(2,1)) - for(var/obj/structure/closet/Closet in world) - spawn(0) - sleep(rand(30,400)) - Closet.ex_act(rand(2,1)) - for(var/obj/machinery/Machinery in world) - spawn(0) - sleep(rand(30,400)) - Machinery.ex_act(rand(1,3)) - for(var/turf/station/wall/Wall in world) - spawn(0) - sleep(rand(30,400)) - Wall.ex_act(rand(2,1)) */ - if("wave") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","MW") - new /datum/event/meteor_wave - - if("gravanomalies") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","GA") - command_announcement.Announce("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert", 'sound/AI/granomalies.ogg') - var/turf/T = pick(blobstart) - var/obj/effect/bhole/bh = new /obj/effect/bhole( T.loc, 30 ) - spawn(rand(100, 600)) - qdel(bh) - - if("timeanomalies") //dear god this code was awful :P Still needs further optimisation - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","STA") - //moved to its own dm so I could split it up and prevent the spawns copying variables over and over - //can be found in code\game\game_modes\events\wormholes.dm - wormhole_event() - - if("goblob") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BL") - mini_blob_event() - message_admins("[key_name_admin(usr)] has spawned blob", 1) - if("aliens") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","AL") - if(xenomorphs.attempt_random_spawn()) - message_admins("[key_name_admin(usr)] has spawned aliens", 1) - if("spiders") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SL") - new /datum/event/spider_infestation - message_admins("[key_name_admin(usr)] has spawned spiders", 1) - if("comms_blackout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","CB") - var/answer = alert(usr, "Would you like to alert the crew?", "Alert", "Yes", "No") - if(answer == "Yes") - communications_blackout(0) - else - communications_blackout(1) - message_admins("[key_name_admin(usr)] triggered a communications blackout.", 1) - if("carp") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","C") - var/choice = input("You sure you want to spawn carp?") in list("Badmin", "Cancel") - if(choice == "Badmin") - message_admins("[key_name_admin(usr)] has spawned carp.", 1) - new /datum/event/carp_migration - if("radiation") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","R") - message_admins("[key_name_admin(usr)] has has irradiated the station", 1) - new /datum/event/radiation_storm - if("immovable") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","IR") - message_admins("[key_name_admin(usr)] has sent an immovable rod to the station", 1) - immovablerod() - if("prison_break") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","PB") - message_admins("[key_name_admin(usr)] has allowed a prison break", 1) - prison_break() - if("lightout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","LO") - message_admins("[key_name_admin(usr)] has broke a lot of lights", 1) - lightsout(1,2) - if("blackout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","BO") - message_admins("[key_name_admin(usr)] broke all lights", 1) - lightsout(0,0) - if("whiteout") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","WO") - for(var/obj/machinery/light/L in world) - L.fix() - message_admins("[key_name_admin(usr)] fixed all lights", 1) - if("friendai") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FA") - for(var/mob/eye/aiEye/aE in mob_list) - aE.icon_state = "ai_friend" - for(var/obj/machinery/M in machines) - if(istype(M, /obj/machinery/ai_status_display)) - var/obj/machinery/ai_status_display/A = M - A.emotion = "Friend Computer" - else if(istype(M, /obj/machinery/status_display)) - var/obj/machinery/status_display/A = M - A.friendc = 1 - message_admins("[key_name_admin(usr)] turned all AIs into best friends.", 1) - if("floorlava") - if(floorIsLava) - usr << "The floor is lava already." - return - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","LF") - - //Options - var/length = input(usr, "How long will the lava last? (in seconds)", "Length", 180) as num - length = min(abs(length), 1200) - - var/damage = input(usr, "How deadly will the lava be?", "Damage", 2) as num - damage = min(abs(damage), 100) - - var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "YES!", "Nah") - if(sure == "Nah") - return - floorIsLava = 1 - - message_admins("[key_name_admin(usr)] made the floor LAVA! It'll last [length] seconds and it will deal [damage] damage to everyone.", 1) - - for(var/turf/simulated/floor/F in world) - if(F.z in config.station_levels) - F.name = "lava" - F.desc = "The floor is LAVA!" - F.overlays += "lava" - F.lava = 1 - - spawn(0) - for(var/i = i, i < length, i++) // 180 = 3 minutes - if(damage) - for(var/mob/living/carbon/L in living_mob_list) - if(istype(L.loc, /turf/simulated/floor)) // Are they on LAVA?! - var/turf/simulated/floor/F = L.loc - if(F.lava) - var/safe = 0 - for(var/obj/structure/O in F.contents) - if(O.level > F.level && !istype(O, /obj/structure/window)) // Something to stand on and it isn't under the floor! - safe = 1 - break - if(!safe) - L.adjustFireLoss(damage) - - - sleep(10) - - for(var/turf/simulated/floor/F in world) // Reset everything. - if(F.z in config.station_levels) - F.name = initial(F.name) - F.desc = initial(F.desc) - F.overlays.Cut() - F.lava = 0 - F.update_icon() - floorIsLava = 0 - return - if("virus") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","V") - var/answer = alert("Do you want this to be a greater disease or a lesser one?",,"Greater","Lesser") - if(answer=="Lesser") - virus2_lesser_infection() - message_admins("[key_name_admin(usr)] has triggered a lesser virus outbreak.", 1) - else - virus2_greater_infection() - message_admins("[key_name_admin(usr)] has triggered a greater virus outbreak.", 1) - if("retardify") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","RET") - for(var/mob/living/carbon/human/H in player_list) - H << "\red You suddenly feel stupid." - H.setBrainLoss(60) - message_admins("[key_name_admin(usr)] made everybody retarded") - if("fakeguns") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","FG") - for(var/obj/item/W in world) - if(istype(W, /obj/item/clothing) || istype(W, /obj/item/weapon/card/id) || istype(W, /obj/item/weapon/disk) || istype(W, /obj/item/weapon/tank)) - continue - W.icon = 'icons/obj/gun.dmi' - W.icon_state = "revolver" - W.item_state = "gun" - message_admins("[key_name_admin(usr)] made every item look like a gun") - if("schoolgirl") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SG") - for(var/obj/item/clothing/under/W in world) - W.icon_state = "schoolgirl" - W.item_state = "w_suit" - message_admins("[key_name_admin(usr)] activated Japanese Animes mode") - world << sound('sound/AI/animes.ogg') - if("paintball") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","PB") - for(var/species in all_species) - var/datum/species/S = all_species[species] - S.blood_color = "rainbow" - for(var/obj/effect/decal/cleanable/blood/B in world) - B.basecolor = "rainbow" - B.update_icon() - message_admins("[key_name_admin(usr)] activated Paintball mode") - if("eagles")//SCRAW - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","EgL") - for(var/obj/machinery/door/airlock/W in world) - if(W.z in config.station_levels && !istype(get_area(W), /area/bridge) && !istype(get_area(W), /area/crew_quarters) && !istype(get_area(W), /area/security/prison)) - W.req_access = list() - message_admins("[key_name_admin(usr)] activated Egalitarian Station mode") - command_announcement.Announce("[boss_short] airlock control override activated. Please take this time to get acquainted with your coworkers.", new_sound = 'sound/AI/commandreport.ogg') - if("dorf") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","DF") - for(var/mob/living/carbon/human/B in mob_list) - B.f_style = "Dward Beard" - B.update_hair() - message_admins("[key_name_admin(usr)] activated dorf mode") - if("ionstorm") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","I") - IonStorm() - message_admins("[key_name_admin(usr)] triggered an ion storm") - var/show_log = alert(usr, "Show ion message?", "Message", "Yes", "No") - if(show_log == "Yes") - command_announcement.Announce("Ion storm detected near the station. Please check all AI-controlled equipment for errors.", "Anomaly Alert", new_sound = 'sound/AI/ionstorm.ogg') - if("onlyone") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","OO") - only_one() - message_admins("[key_name_admin(usr)] has triggered a battle to the death (only one)") - - if("togglenarsie") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","NA") - var/choice = input("How do you wish for narsie to interact with her surroundings?") in list("CultStation13", "Nar-Singulo") - if(choice == "CultStation13") - message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"CultStation13\".") - narsie_behaviour = "CultStation13" - if(choice == "Nar-Singulo") - message_admins("[key_name_admin(usr)] has set narsie's behaviour to \"Nar-Singulo\".") - narsie_behaviour = "Nar-Singulo" - if("hellonearth") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","NS") - var/choice = input("You sure you want to end the round and summon narsie at your location? Misuse of this could result in removal of flags or hilarity.") in list("PRAISE SATAN", "Cancel") - if(choice == "PRAISE SATAN") - new /obj/singularity/narsie/large(get_turf(usr)) - message_admins("[key_name_admin(usr)] has summoned narsie and brought about a new realm of suffering.") - if("supermattercascade") - feedback_inc("admin_secrets_fun_used",1) - feedback_add_details("admin_secrets_fun_used","SC") - var/choice = input("You sure you want to destroy the universe and create a large explosion at your location? Misuse of this could result in removal of flags or hilarity.") in list("NO TIME TO EXPLAIN", "Cancel") - if(choice == "NO TIME TO EXPLAIN") - explosion(get_turf(usr), 8, 16, 24, 32, 1) - new /turf/unsimulated/wall/supermatter(get_turf(usr)) - SetUniversalState(/datum/universal_state/supermatter_cascade) - message_admins("[key_name_admin(usr)] has managed to destroy the universe with a supermatter cascade. Good job, [key_name_admin(usr)]") - if(usr) - log_admin("[key_name(usr)] used secret [href_list["secretsfun"]]") - if (ok) - world << text("A secret has been activated by []!", usr.key) - - else if(href_list["secretsadmin"]) - if(!check_rights(R_ADMIN)) return - - var/ok = 0 - switch(href_list["secretsadmin"]) - if("clear_bombs") - //I do nothing - if("list_bombers") - var/dat = "Bombing List
    " - for(var/l in bombers) - dat += text("[l]
    ") - usr << browse(dat, "window=bombers") - if("list_signalers") - var/dat = "Showing last [length(lastsignalers)] signalers.
    " - for(var/sig in lastsignalers) - dat += "[sig]
    " - usr << browse(dat, "window=lastsignalers;size=800x500") - if("list_lawchanges") - var/dat = "Showing last [length(lawchanges)] law changes.
    " - for(var/sig in lawchanges) - dat += "[sig]
    " - usr << browse(dat, "window=lawchanges;size=800x500") - if("list_job_debug") - var/dat = "Job Debug info.
    " - if(job_master) - for(var/line in job_master.job_debug) - dat += "[line]
    " - dat+= "*******

    " - for(var/datum/job/job in job_master.occupations) - if(!job) continue - dat += "job: [job.title], current_positions: [job.current_positions], total_positions: [job.total_positions]
    " - usr << browse(dat, "window=jobdebug;size=600x500") - if("showailaws") - output_ai_laws() - if("showgm") - if(!ticker) - alert("The game hasn't started yet!") - else if (ticker.mode) - alert("The game mode is [ticker.mode.name]") - else alert("For some reason there's a ticker, but not a game mode") - if("manifest") - var/dat = "Showing Crew Manifest.
    " - dat += "" - for(var/mob/living/carbon/human/H in mob_list) - if(H.ckey) - dat += text("", H.name, H.get_assignment()) - dat += "
    NamePosition
    [][]
    " - usr << browse(dat, "window=manifest;size=440x410") - if("check_antagonist") - check_antagonists() - if("DNA") - var/dat = "Showing DNA from blood.
    " - dat += "" - for(var/mob/living/carbon/human/H in mob_list) - if(H.dna && H.ckey) - dat += "" - dat += "
    NameDNABlood Type
    [H][H.dna.unique_enzymes][H.b_type]
    " - usr << browse(dat, "window=DNA;size=440x410") - if("fingerprints") - var/dat = "Showing Fingerprints.
    " - dat += "" - for(var/mob/living/carbon/human/H in mob_list) - if(H.ckey) - if(H.dna && H.dna.uni_identity) - dat += "" - else if(H.dna && !H.dna.uni_identity) - dat += "" - else if(!H.dna) - dat += "" - dat += "
    NameFingerprints
    [H][md5(H.dna.uni_identity)]
    [H]H.dna.uni_identity = null
    [H]H.dna = null
    " - usr << browse(dat, "window=fingerprints;size=440x410") - else - if (usr) - log_admin("[key_name(usr)] used secret [href_list["secretsadmin"]]") - if (ok) - world << text("A secret has been activated by []!", usr.key) - - else if(href_list["secretscoder"]) - if(!check_rights(R_DEBUG)) return - - switch(href_list["secretscoder"]) - if("spawn_objects") - var/dat = "Admin Log
    " - for(var/l in admin_log) - dat += "
  • [l]
  • " - if(!admin_log.len) - dat += "No-one has done anything this round!" - usr << browse(dat, "window=admin_log") - if("maint_access_brig") - for(var/obj/machinery/door/airlock/maintenance/M in world) - if (access_maint_tunnels in M.req_access) - M.req_access = list(access_brig) - message_admins("[key_name_admin(usr)] made all maint doors brig access-only.") - if("maint_access_engiebrig") - for(var/obj/machinery/door/airlock/maintenance/M in world) - if (access_maint_tunnels in M.req_access) - M.req_access = list() - M.req_one_access = list(access_brig,access_engine) - message_admins("[key_name_admin(usr)] made all maint doors engineering and brig access-only.") - if("infinite_sec") - var/datum/job/J = job_master.GetJob("Security Officer") - if(!J) return - J.total_positions = -1 - J.spawn_positions = -1 - message_admins("[key_name_admin(usr)] has removed the cap on security officers.") + else if(href_list["admin_secrets"]) + var/datum/admin_secret_item/item = locate(href_list["admin_secrets"]) in admin_secrets.items + item.execute(usr) else if(href_list["ac_view_wanted"]) //Admin newscaster Topic() stuff be here src.admincaster_screen = 18 //The ac_ prefix before the hrefs stands for AdminCaster. diff --git a/code/modules/hydroponics/spreading/spreading.dm b/code/modules/hydroponics/spreading/spreading.dm index 07d83e6f64..e8f2cfa918 100644 --- a/code/modules/hydroponics/spreading/spreading.dm +++ b/code/modules/hydroponics/spreading/spreading.dm @@ -234,6 +234,7 @@ /obj/effect/plant/attackby(var/obj/item/weapon/W, var/mob/user) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) plant_controller.add_plant(src) if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel)) diff --git a/code/modules/hydroponics/trays/tray.dm b/code/modules/hydroponics/trays/tray.dm index faf0e83551..4716a191b8 100644 --- a/code/modules/hydroponics/trays/tray.dm +++ b/code/modules/hydroponics/trays/tray.dm @@ -533,6 +533,7 @@ user << "You [anchored ? "wrench" : "unwrench"] \the [src]." else if(O.force && seed) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) user.visible_message("\The [seed.display_name] has been attacked by [user] with \the [O]!") if(!dead) health -= O.force diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 311fe54bd0..c08df56a13 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -492,7 +492,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp host << "You are now a mouse. Try to avoid interaction with players, and do not give hints away that you are more than a simple rodent." /mob/dead/observer/verb/view_manfiest() - set name = "View Crew Manifest" + set name = "Show Crew Manifest" set category = "Ghost" var/dat diff --git a/code/modules/mob/freelook/ai/chunk.dm b/code/modules/mob/freelook/ai/chunk.dm index 89a07bb465..5d82f66d66 100644 --- a/code/modules/mob/freelook/ai/chunk.dm +++ b/code/modules/mob/freelook/ai/chunk.dm @@ -24,6 +24,10 @@ for(var/turf/t in c.can_see()) visible[t] = t + for(var/mob/living/silicon/ai/AI in living_mob_list) + for(var/turf/t in AI.seen_camera_turfs()) + visible[t] = t + // Create a new camera chunk, since the chunks are made as they are needed. /datum/chunk/camera/New(loc, x, y, z) @@ -31,3 +35,15 @@ if(c.can_use()) cameras += c ..() + +/mob/living/silicon/proc/provides_camera_vision() + return 0 + +/mob/living/silicon/ai/provides_camera_vision() + return stat != DEAD + +/mob/living/silicon/robot/provides_camera_vision() + return src.camera && src.camera.network.len + +/mob/living/silicon/ai/proc/seen_camera_turfs() + return seen_turfs_in_range(src, world.view) diff --git a/code/modules/mob/freelook/ai/update_triggers.dm b/code/modules/mob/freelook/ai/update_triggers.dm index 8a91d0540e..f4fea0aa58 100644 --- a/code/modules/mob/freelook/ai/update_triggers.dm +++ b/code/modules/mob/freelook/ai/update_triggers.dm @@ -4,13 +4,13 @@ // Update the portable camera everytime the Robot moves. // This might be laggy, comment it out if there are problems. -/mob/living/silicon/robot/var/updating = 0 +/mob/living/silicon/var/updating = 0 /mob/living/silicon/robot/Move() var/oldLoc = src.loc . = ..() if(.) - if(src.camera && src.camera.network.len) + if(provides_camera_vision()) if(!updating) updating = 1 spawn(BORG_CAMERA_BUFFER) @@ -18,6 +18,21 @@ cameranet.updatePortableCamera(src.camera) updating = 0 +/mob/living/silicon/AI/Move() + var/oldLoc = src.loc + . = ..() + if(.) + if(provides_camera_vision()) + if(!updating) + updating = 1 + spawn(BORG_CAMERA_BUFFER) + if(oldLoc != src.loc) + cameranet.updateVisibility(oldLoc, 0) + cameranet.updateVisibility(loc, 0) + updating = 0 + +#undef BORG_CAMERA_BUFFER + // CAMERA // An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not. @@ -42,8 +57,19 @@ update_coverage(1) /obj/machinery/camera/Destroy() - cameranet.cameras -= src clear_all_networks() + cameranet.cameras -= src ..() -#undef BORG_CAMERA_BUFFER +// Mobs +/mob/living/silicon/ai/rejuvenate() + var/was_dead = stat == DEAD + ..() + if(was_dead && stat != DEAD) + // Arise! + cameranet.updateVisibility(src, 0) + +/mob/living/silicon/ai/death(gibbed) + if(..()) + // If true, the mob went from living to dead (assuming everyone has been overriding as they should...) + cameranet.updateVisibility(src, 0) diff --git a/code/modules/mob/freelook/eye.dm b/code/modules/mob/freelook/eye.dm index fb2b04a434..437b2979dc 100644 --- a/code/modules/mob/freelook/eye.dm +++ b/code/modules/mob/freelook/eye.dm @@ -41,12 +41,15 @@ mob/eye/Destroy() updateallghostimages() ..() -// Movement code. Returns 0 to stop air movement from moving it. /mob/eye/Move(n, direct) if(owner == src) - EyeMove(n, direct) + return EyeMove(n, direct) return 0 +/mob/eye/airflow_hit(atom/A) + airflow_speed = 0 + airflow_dest = null + /mob/eye/examinate() set popup_menu = 0 set src = usr.contents @@ -110,3 +113,4 @@ mob/eye/Destroy() sprint = min(sprint + 0.5, max_sprint) else sprint = initial + return 1 diff --git a/code/modules/mob/freelook/mask/chunk.dm b/code/modules/mob/freelook/mask/chunk.dm index b0973951cc..f98a9b936b 100644 --- a/code/modules/mob/freelook/mask/chunk.dm +++ b/code/modules/mob/freelook/mask/chunk.dm @@ -11,27 +11,24 @@ /datum/chunk/cult/acquireVisibleTurfs(var/list/visible) for(var/mob/living/L in living_mob_list) - for(var/turf/t in L.seen_turfs()) + for(var/turf/t in L.seen_cult_turfs()) visible[t] = t -/mob/living/proc/seen_turfs() +/mob/living/proc/seen_cult_turfs() return seen_turfs_in_range(src, 3) -/mob/living/carbon/human/seen_turfs() - /*if(src.isSynthetic()) - return list()*/ - +/mob/living/carbon/human/seen_cult_turfs() if(mind in cult.current_antagonists) - return seen_turfs_in_range(src, client ? client.view : 7) + return seen_turfs_in_range(src, world.view) return ..() -/mob/living/silicon/seen_turfs() +/mob/living/silicon/seen_cult_turfs() return list() -/mob/living/simple_animal/seen_turfs() +/mob/living/simple_animal/seen_cult_turfs() return seen_turfs_in_range(src, 1) -/mob/living/simple_animal/shade/narsie/seen_turfs() +/mob/living/simple_animal/shade/narsie/seen_cult_turfs() return view(2, src) /proc/seen_turfs_in_range(var/source, var/range) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 310225d736..65d1f0fa89 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1311,9 +1311,10 @@ set desc = "Pop a joint back into place. Extremely painful." set src in view(1) - if(!isliving(usr) || usr.next_move > world.time) + if(!isliving(usr) || !usr.canClick()) return - usr.next_move = world.time + 20 + + usr.setClickCooldown(20) if(usr.stat > 0) usr << "You are unconcious and cannot do that!" diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 2a67aae045..5ecfa1807c 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -227,7 +227,7 @@ emp_act else visible_message("\red [src] has been attacked in the [hit_area] with [I.name] by [user]!") - var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") + var/armor = run_armor_check(affecting, "melee", I.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") var/weapon_sharp = is_sharp(I) var/weapon_edge = has_edge(I) if ((weapon_sharp || weapon_edge) && prob(getarmor(target_zone, "melee"))) @@ -342,7 +342,7 @@ emp_act var/hit_area = affecting.name src.visible_message("\red [src] has been hit in the [hit_area] by [O].") - var/armor = run_armor_check(affecting, "melee", "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here + var/armor = run_armor_check(affecting, "melee", O.armor_penetration, "Your armor has protected your [hit_area].", "Your armor has softened hit to your [hit_area].") //I guess "melee" is the best fit here if(armor < 2) apply_damage(throw_damage, dtype, zone, armor, is_sharp(O), has_edge(O), O) diff --git a/code/modules/mob/living/carbon/resist.dm b/code/modules/mob/living/carbon/resist.dm index 51b39343ea..a5ad3f5845 100644 --- a/code/modules/mob/living/carbon/resist.dm +++ b/code/modules/mob/living/carbon/resist.dm @@ -27,10 +27,11 @@ spawn() escape_legcuffs() /mob/living/carbon/proc/escape_handcuffs() - if(!(last_special <= world.time)) return + //if(!(last_special <= world.time)) return - next_move = world.time + 100 - last_special = world.time + 100 + //These two lines represent a significant buff to grabs... + if(!canClick()) return + setClickCooldown(100) if(can_break_cuffs()) //Don't want to do a lot of logic gating here. break_handcuffs() @@ -60,11 +61,11 @@ ) drop_from_inventory(handcuffed) -/mob/living/carbon/proc/escape_legcuffs() - if(!(last_special <= world.time)) return +/mob/living/carbon/proc/escape_legcuffs() + if(!canClick()) + return - next_move = world.time + 100 - last_special = world.time + 100 + setClickCooldown(100) if(can_break_cuffs()) //Don't want to do a lot of logic gating here. break_legcuffs() @@ -149,14 +150,15 @@ return ..() /mob/living/carbon/escape_buckle() + if(!canClick()) + return + + setClickCooldown(100) if(!buckled) return - if(!(last_special <= world.time)) return if(!restrained()) ..() else - next_move = world.time + 100 - last_special = world.time + 100 visible_message( "[usr] attempts to unbuckle themself!", "You attempt to unbuckle yourself. (This will take around 2 minutes and you need to stand still)" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 632bd4dc73..c306bacdcd 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -574,7 +574,7 @@ default behaviour is: set category = "IC" if(can_resist()) - next_move = world.time + 20 + setClickCooldown(20) process_resist() /mob/living/proc/can_resist() @@ -582,7 +582,7 @@ default behaviour is: //so just check weakened instead. if(stat || weakened) return 0 - if(next_move > world.time) + if(!canClick()) return 0 return 1 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index fd6d71150a..871e95c8b4 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -10,24 +10,36 @@ 1 - halfblock 2 - fullblock */ -/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/absorb_text = null, var/soften_text = null) +/mob/living/proc/run_armor_check(var/def_zone = null, var/attack_flag = "melee", var/armour_pen = 0, var/absorb_text = null, var/soften_text = null) + if(armour_pen >= 100) + return 0 //might as well just skip the processing + var/armor = getarmor(def_zone, attack_flag) var/absorb = 0 + + //Roll armour if(prob(armor)) absorb += 1 if(prob(armor)) absorb += 1 + + //Roll penetration + if(prob(armour_pen)) + absorb -= 1 + if(prob(armour_pen)) + absorb -= 1 + if(absorb >= 2) if(absorb_text) show_message("[absorb_text]") else - show_message("\red Your armor absorbs the blow!") + show_message("Your armor absorbs the blow!") return 2 if(absorb == 1) if(absorb_text) show_message("[soften_text]",4) else - show_message("\red Your armor softens the blow!") + show_message("Your armor softens the blow!") return 1 return 0 @@ -64,7 +76,7 @@ return //Armor - var/absorb = run_armor_check(def_zone, P.check_armour) + var/absorb = run_armor_check(def_zone, P.check_armour, P.armor_penetration) var/proj_sharp = is_sharp(P) var/proj_edge = has_edge(P) if ((proj_sharp || proj_edge) && prob(getarmor(def_zone, P.check_armour))) diff --git a/code/modules/mob/living/silicon/ai/ai_movement.dm b/code/modules/mob/living/silicon/ai/ai_movement.dm new file mode 100644 index 0000000000..456d11a981 --- /dev/null +++ b/code/modules/mob/living/silicon/ai/ai_movement.dm @@ -0,0 +1,2 @@ +/mob/living/silicon/ai/SelfMove(turf/n, direct) + return 0 diff --git a/code/modules/mob/living/simple_animal/borer/borer_captive.dm b/code/modules/mob/living/simple_animal/borer/borer_captive.dm index c0b2999b2f..e666f7ac71 100644 --- a/code/modules/mob/living/simple_animal/borer/borer_captive.dm +++ b/code/modules/mob/living/simple_animal/borer/borer_captive.dm @@ -35,7 +35,7 @@ return /mob/living/captive_brain/can_resist() - return !(stat || next_move > world.time) + return !(stat || !canClick()) /mob/living/captive_brain/process_resist() //Resisting control by an alien mind. diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 0eb187213d..82cd1683cc 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -269,7 +269,6 @@ /mob/living/simple_animal/attackby(var/obj/item/O, var/mob/user) if(istype(O, /obj/item/stack/medical)) - user.changeNext_move(4) if(stat != DEAD) var/obj/item/stack/medical/MED = O if(health < maxHealth) @@ -286,12 +285,12 @@ if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead. if(istype(O, /obj/item/weapon/material/knife) || istype(O, /obj/item/weapon/material/knife/butch)) harvest(user) - else + else attacked_with_item(O, user) //TODO: refactor mob attackby(), attacked_by(), and friends. /mob/living/simple_animal/proc/attacked_with_item(var/obj/item/O, var/mob/user) - user.changeNext_move(8) + user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN) if(!O.force) visible_message("[user] gently taps [src] with \the [O].") return @@ -308,7 +307,7 @@ usr << "This weapon is ineffective, it does no damage." visible_message("\The [src] has been attacked with \the [O] by [user].") - user.do_attack_animation(src) + user.do_attack_animation(src) /mob/living/simple_animal/movement_delay() var/tally = 0 //Incase I need to add stuff other than "speed" later diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index e08fb82fb8..43269113d9 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -277,8 +277,6 @@ if (W) W.attack_self(src) update_inv_r_hand() - if(next_move < world.time) - next_move = world.time + 2 return /* @@ -886,9 +884,9 @@ mob/proc/yank_out_object() set desc = "Remove an embedded item at the cost of bleeding and pain." set src in view(1) - if(!isliving(usr) || usr.next_move > world.time) + if(!isliving(usr) || !usr.canClick()) return - usr.next_move = world.time + 20 + usr.setClickCooldown(20) if(usr.stat == 1) usr << "You are unconcious and cannot do that!" diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index f179920e3d..8960d5128e 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -209,7 +209,7 @@ return if(state == GRAB_UPGRADING) return - if(assailant.next_move > world.time) + if(!assailant.canClick()) return if(world.time < (last_action + UPGRADE_COOLDOWN)) return @@ -250,7 +250,7 @@ hud.name = "kill" affecting.Stun(10) //10 ticks of ensured grab else if(state < GRAB_UPGRADING) - assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!") + assailant.visible_message("[assailant] starts to tighten \his grip on [affecting]'s neck!") hud.icon_state = "kill1" state = GRAB_KILL @@ -259,10 +259,10 @@ assailant.attack_log += "\[[time_stamp()]\] Strangled (kill intent) [affecting.name] ([affecting.ckey])" msg_admin_attack("[key_name(assailant)] strangled (kill intent) [key_name(affecting)]") - assailant.next_move = world.time + 10 + affecting.setClickCooldown(10) affecting.losebreath += 1 affecting.set_dir(WEST) - adjust_position() + adjust_position() //This is used to make sure the victim hasn't managed to yackety sax away before using the grab. diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 9dc893a286..8f0c90062b 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -10,6 +10,9 @@ return (!mover.density || !density || lying) return +/mob/proc/setMoveCooldown(var/timeout) + if(client) + client.move_delay = max(world.time + timeout, client.move_delay) /client/North() ..() diff --git a/code/modules/paperwork/papershredder.dm b/code/modules/paperwork/papershredder.dm new file mode 100644 index 0000000000..37cfdaa86b --- /dev/null +++ b/code/modules/paperwork/papershredder.dm @@ -0,0 +1,139 @@ +/obj/machinery/papershredder + name = "paper shredder" + desc = "For those documents you don't want seen." + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "papershredder0" + density = 1 + anchored = 1 + var/max_paper = 10 + var/paperamount = 0 + var/list/shred_amounts = list( + /obj/item/weapon/photo = 1, + /obj/item/weapon/shreddedp = 1, + /obj/item/weapon/paper = 1, + /obj/item/weapon/newspaper = 3, + /obj/item/weapon/card/id = 3, + /obj/item/weapon/paper_bundle = 3, + ) + +/obj/machinery/papershredder/attackby(var/obj/item/W, var/mob/user) + + if(istype(W, /obj/item/weapon/storage)) + empty_bin(user, W) + return + else + var/paper_result + for(var/shred_type in shred_amounts) + if(istype(W, shred_type)) + paper_result = shred_amounts[shred_type] + if(paper_result) + if(paperamount == max_paper) + user << "\The [src] is full; please empty it before you continue." + return + paperamount += paper_result + user.drop_from_inventory(W) + qdel(W) + playsound(src.loc, 'sound/items/pshred.ogg', 75, 1) + if(paperamount > max_paper) + user <<"\The [src] was too full, and shredded paper goes everywhere!" + for(var/i=(paperamount-max_paper);i>0;i--) + var/obj/item/weapon/shreddedp/SP = get_shredded_paper() + SP.loc = get_turf(src) + SP.throw_at(get_edge_target_turf(src,pick(alldirs)),1,5) + paperamount = max_paper + update_icon() + return + return ..() + +/obj/machinery/papershredder/verb/empty_contents() + set name = "Empty bin" + set category = "Object" + set src in range(1) + + if(usr.stat || usr.restrained() || usr.weakened || usr.paralysis || usr.lying || usr.stunned) + return + + if(!paperamount) + usr << "\The [src] is empty." + return + + empty_bin(usr) + +/obj/machinery/papershredder/proc/empty_bin(var/mob/living/user, var/obj/item/weapon/storage/empty_into) + + // Sanity. + if(empty_into && !istype(empty_into)) + empty_into = null + + if(empty_into && empty_into.contents.len >= empty_into.storage_slots) + user << "\The [empty_into] is full." + return + + while(paperamount) + var/obj/item/weapon/shreddedp/SP = get_shredded_paper() + if(!SP) break + if(empty_into) + empty_into.handle_item_insertion(SP) + if(empty_into.contents.len >= empty_into.storage_slots) + break + if(empty_into) + if(paperamount) + user << "You fill \the [empty_into] with as much shredded paper as it will carry." + else + user << "You empty \the [src] into \the [empty_into]." + + else + user << "You empty \the [src]." + update_icon() + +/obj/machinery/papershredder/proc/get_shredded_paper() + if(!paperamount) + return + paperamount-- + return PoolOrNew(/obj/item/weapon/shreddedp, get_turf(src)) + +/obj/machinery/papershredder/update_icon() + icon_state = "papershredder[max(0,min(5,Floor(paperamount/2)))]" + +/obj/item/weapon/shreddedp/attackby(var/obj/item/W as obj, var/mob/user) + if(istype(W, /obj/item/weapon/flame/lighter)) + burnpaper(W, user) + else + ..() + +/obj/item/weapon/shreddedp/proc/burnpaper(var/obj/item/weapon/flame/lighter/P, var/mob/user) + if(user.restrained()) + return + if(!P.lit) + user << "\The [P] is not lit." + return + user.visible_message("\The [user] holds \the [P] up to \the [src]. It looks like \he's trying to burn it!", \ + "You hold \the [P] up to \the [src], burning it slowly.") + if(!do_after(user,20)) + user << "You must hold \the [P] steady to burn \the [src]." + return + user.visible_message("\The [user] burns right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.", \ + "You burn right through \the [src], turning it to ash. It flutters through the air before settling on the floor in a heap.") + FireBurn() + +/obj/item/weapon/shreddedp/proc/FireBurn() + var/mob/living/M = loc + if(istype(M)) + M.drop_from_inventory(src) + PoolOrNew(/obj/effect/decal/cleanable/ash,get_turf(src)) + qdel(src) + +/obj/item/weapon/shreddedp + name = "shredded paper" + icon = 'icons/obj/bureaucracy.dmi' + icon_state = "shredp" + throwforce = 0 + w_class = 1 + throw_range = 3 + throw_speed = 1 + +/obj/item/weapon/shreddedp/New() + ..() + pixel_x = rand(-5,5) + pixel_y = rand(-5,5) + if(prob(65)) color = pick("#BABABA","#7F7F7F") diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 1d1b905c45..87689d9969 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -151,10 +151,10 @@ if (world.time % 3) //to prevent spam user << "[src] is not ready to fire again!" return - + var/shoot_time = (burst - 1)* burst_delay - user.next_move = world.time + shoot_time //no clicking on things while shooting - if(user.client) user.client.move_delay = world.time + shoot_time //no moving while shooting either + user.setClickCooldown(shoot_time) //no clicking on things while shooting + user.setMoveCooldown(shoot_time) //no moving while shooting either next_fire_time = world.time + shoot_time //actually attempt to shoot @@ -186,9 +186,9 @@ update_held_icon() //update timing - user.next_move = world.time + 4 - if(user.client) user.client.move_delay = world.time + move_delay - next_fire_time = world.time + fire_delay + user.setClickCooldown(4) + user.setMoveCooldown(move_delay) + next_fire_time = world.time + fire_delay if(muzzle_flash) set_light(0) diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm index b1c47fd605..3b53c8b5f4 100644 --- a/code/modules/projectiles/guns/energy/laser.dm +++ b/code/modules/projectiles/guns/energy/laser.dm @@ -7,10 +7,9 @@ slot_flags = SLOT_BELT|SLOT_BACK w_class = 3 force = 10 - origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2) - matter = list(DEFAULT_WALL_MATERIAL = 2000) - projectile_type = /obj/item/projectile/beam - fire_delay = 1 //rapid fire + origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2) + matter = list(DEFAULT_WALL_MATERIAL = 2000) + projectile_type = /obj/item/projectile/beam/midlaser /obj/item/weapon/gun/energy/laser/mounted self_recharge = 1 diff --git a/code/modules/projectiles/guns/launcher/rocket.dm b/code/modules/projectiles/guns/launcher/rocket.dm index 9747922caf..12338ee5c3 100644 --- a/code/modules/projectiles/guns/launcher/rocket.dm +++ b/code/modules/projectiles/guns/launcher/rocket.dm @@ -7,7 +7,7 @@ throw_speed = 2 throw_range = 10 force = 5.0 - flags = CONDUCT | USEDELAY + flags = CONDUCT slot_flags = 0 origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 5) fire_sound = 'sound/effects/bang.ogg' diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index 8aa493404a..af93e5cefd 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -23,10 +23,15 @@ check_armour = "laser" eyeblur = 2 +/obj/item/projectile/beam/midlaser + damage = 40 + armor_penetration = 10 + /obj/item/projectile/beam/heavylaser name = "heavy laser" icon_state = "heavylaser" damage = 60 + armor_penetration = 30 muzzle_type = /obj/effect/projectile/laser_heavy/muzzle tracer_type = /obj/effect/projectile/laser_heavy/tracer @@ -35,7 +40,8 @@ /obj/item/projectile/beam/xray name = "xray beam" icon_state = "xray" - damage = 30 + damage = 25 + armor_penetration = 50 muzzle_type = /obj/effect/projectile/xray/muzzle tracer_type = /obj/effect/projectile/xray/tracer @@ -45,6 +51,7 @@ name = "pulse" icon_state = "u_laser" damage = 50 + armor_penetration = 30 muzzle_type = /obj/effect/projectile/laser_pulse/muzzle tracer_type = /obj/effect/projectile/laser_pulse/tracer @@ -122,7 +129,8 @@ /obj/item/projectile/beam/sniper name = "sniper beam" icon_state = "xray" - damage = 60 + damage = 50 + armor_penetration = 10 stun = 3 weaken = 3 stutter = 3 diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 2038d718e0..cc18d93d87 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -119,7 +119,8 @@ /obj/item/projectile/bullet/shotgun name = "slug" - damage = 60 + damage = 50 + armor_penetration = 15 /obj/item/projectile/bullet/shotgun/beanbag //because beanbags are not bullets name = "beanbag" @@ -139,21 +140,24 @@ /* "Rifle" rounds */ -/obj/item/projectile/bullet/rifle/a762 - damage = 30 +/obj/item/projectile/bullet/rifle + armor_penetration = 20 penetrating = 1 +/obj/item/projectile/bullet/rifle/a762 + damage = 25 + +/obj/item/projectile/bullet/rifle/a556 + damage = 35 + /obj/item/projectile/bullet/rifle/a145 damage = 80 stun = 3 weaken = 3 penetrating = 5 + armor_penetration = 80 hitscan = 1 //so the PTR isn't useless as a sniper weapon -/obj/item/projectile/bullet/rifle/a556 - damage = 40 - penetrating = 1 - /* Miscellaneous */ /obj/item/projectile/bullet/suffocationbullet//How does this even work? diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index 339722fee3..15059ee327 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -40,6 +40,8 @@ playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6) + user.setClickCooldown(4) + if(reagents.has_reagent("sacid")) message_admins("[key_name_admin(user)] fired sulphuric acid from \a [src].") log_game("[key_name(user)] fired sulphuric acid from \a [src].") diff --git a/html/changelogs/HarpyEagle-armourpen.yml b/html/changelogs/HarpyEagle-armourpen.yml new file mode 100644 index 0000000000..28599d484f --- /dev/null +++ b/html/changelogs/HarpyEagle-armourpen.yml @@ -0,0 +1,34 @@ +################################ +# Example Changelog File +# +# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb. +# +# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.) +# When it is, any changes listed below will disappear. +# +# Valid Prefixes: +# bugfix +# wip (For works in progress) +# tweak +# soundadd +# sounddel +# rscadd (general adding of nice things) +# rscdel (general deleting of nice things) +# imageadd +# imagedel +# maptweak +# spellcheck (typo fixes) +# experiment +################################# + +# Your name. +author: HarpyEagle + +# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again. +delete-after: True + +changes: + - rscadd: "Adds armour penetration mechanic for projectiles and melee weapons." + - rscadd: "Laser carbines, LWAP, and shotgun now have a small amount of armour penetration, ballistic rifles (not SMGs) have moderate amounts, laser cannon has high armour penetration, and the PTR mostly ignores body armour." + - tweak: "Shotgun slugs and Z8/STS damage has been lowered slightly to accomodate for their higher penetration. In general ballistics deal less damage but have higher penetration than comparable laser weapons. Notable exception: X-Ray lasers have had their damage lowered slightly but gain very high armour penetration." + - rscadd: "Energy swords now have very high armour penetration. Ninja blades do less damage but ignore armour completely." diff --git a/html/changelogs/Kelenius-ofClicksAndCooldowns.yml b/html/changelogs/Kelenius-ofClicksAndCooldowns.yml new file mode 100644 index 0000000000..a6768a8573 --- /dev/null +++ b/html/changelogs/Kelenius-ofClicksAndCooldowns.yml @@ -0,0 +1,6 @@ +author: Kelenius + +delete-after: True + +changes: + - experiment: "Click cooldowns have been removed on pretty much everything that isn't an attack." diff --git a/html/changelogs/PsiOmegaDelta-AISight.yml b/html/changelogs/PsiOmegaDelta-AISight.yml new file mode 100644 index 0000000000..329cda695d --- /dev/null +++ b/html/changelogs/PsiOmegaDelta-AISight.yml @@ -0,0 +1,5 @@ +author: PsiOmegaDelta +delete-after: True + +changes: + - tweak: "Active AI cores now provides coverage on the AI camera network. Does not utilize actual cameras, thus will not show up on security consoles." diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index a2a99f01f8..cc54c091e1 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/sound/items/pshred.ogg b/sound/items/pshred.ogg new file mode 100644 index 0000000000..a722f30068 Binary files /dev/null and b/sound/items/pshred.ogg differ