diff --git a/SQL/database_changelog.txt.rej b/SQL/database_changelog.txt.rej new file mode 100644 index 0000000000..1b201ec4aa --- /dev/null +++ b/SQL/database_changelog.txt.rej @@ -0,0 +1,15 @@ +diff a/SQL/database_changelog.txt b/SQL/database_changelog.txt (rejected hunks) +@@ -1,10 +1,10 @@ + Any time you make a change to the schema files, remember to increment the database schema version. Generally increment the minor number, major should be reserved for significant changes to the schema. Both values go up to 255. + +-The latest database version is 3.1; The query to update the schema revision table is: ++The latest database version is 3.0; The query to update the schema revision table is: + +-UPDATE `schema_revision` SET major = 3, minor = 1 LIMIT 1; ++INSERT INTO `schema_revision` (`major`, `minor`) VALUES (3, 0); + or +-UPDATE `SS13_schema_revision` SET major = 3, minor = 1 LIMIT 1; ++INSERT INTO `SS13_schema_revision` (`major`, `minor`) VALUES (3, 0); + + ---------------------------------------------------- + diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 4cc0b5c158..b4b78673a1 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -49675,7 +49675,7 @@ /turf/open/floor/plating, /area/maintenance/department/engine) "cdF" = ( -/obj/structure/closet/secure_closet/miner, +/obj/structure/closet/secure_closet/miner/unlocked, /turf/open/floor/plating, /area/shuttle/auxillary_base) "cdG" = ( diff --git a/apc_repair.dmi b/apc_repair.dmi new file mode 100644 index 0000000000..6e861eef61 Binary files /dev/null and b/apc_repair.dmi differ diff --git a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm index 82d030bf08..24e10a24d1 100644 --- a/code/__DEFINES/logging.dm +++ b/code/__DEFINES/logging.dm @@ -1,15 +1,16 @@ //Investigate logging defines -#define INVESTIGATE_ATMOS "atmos" -#define INVESTIGATE_BOTANY "botany" -#define INVESTIGATE_CARGO "cargo" -#define INVESTIGATE_EXPERIMENTOR "experimentor" -#define INVESTIGATE_GRAVITY "gravity" -#define INVESTIGATE_RECORDS "records" -#define INVESTIGATE_SINGULO "singulo" -#define INVESTIGATE_SUPERMATTER "supermatter" -#define INVESTIGATE_TELESCI "telesci" -#define INVESTIGATE_WIRES "wires" +#define INVESTIGATE_ATMOS "atmos" +#define INVESTIGATE_BOTANY "botany" +#define INVESTIGATE_CARGO "cargo" +#define INVESTIGATE_EXPERIMENTOR "experimentor" +#define INVESTIGATE_GRAVITY "gravity" +#define INVESTIGATE_RECORDS "records" +#define INVESTIGATE_SINGULO "singulo" +#define INVESTIGATE_SUPERMATTER "supermatter" +#define INVESTIGATE_TELESCI "telesci" +#define INVESTIGATE_WIRES "wires" #define INVESTIGATE_PORTAL "portals" +#define INVESTIGATE_HALLUCINATIONS "hallucinations" //Individual logging defines #define INDIVIDUAL_ATTACK_LOG "Attack log" diff --git a/code/__DEFINES/logging.dm.rej b/code/__DEFINES/logging.dm.rej new file mode 100644 index 0000000000..6a7a358a9c --- /dev/null +++ b/code/__DEFINES/logging.dm.rej @@ -0,0 +1,9 @@ +diff a/code/__DEFINES/logging.dm b/code/__DEFINES/logging.dm (rejected hunks) +@@ -9,6 +9,7 @@ + #define INVESTIGATE_SUPERMATTER "supermatter" + #define INVESTIGATE_TELESCI "telesci" + #define INVESTIGATE_WIRES "wires" ++#define INVESTIGATE_HALLUCINATIONS "hallucinations" + + //Individual logging defines + #define INDIVIDUAL_ATTACK_LOG "Attack log" diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index afa77b0207..3344afcaaa 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -250,7 +250,7 @@ SUBSYSTEM_DEF(blackbox) return 0 return value -/datum/feedback_variable/proc/get_variable() +/datum/feedback_variable/proc/get_variable() return variable /datum/feedback_variable/proc/set_details(text) @@ -260,12 +260,12 @@ SUBSYSTEM_DEF(blackbox) /datum/feedback_variable/proc/add_details(text) if (istext(text)) if (!details) - details = text + details = "\"[text]\"" else - details += " [text]" + details += " | \"[text]\"" -/datum/feedback_variable/proc/get_details() +/datum/feedback_variable/proc/get_details() return details /datum/feedback_variable/proc/get_parsed() - return list(variable,value,details) + return list(variable,value,details) \ No newline at end of file diff --git a/code/datums/action.dm b/code/datums/action.dm index 16fbeb8462..ecaa70387b 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -169,7 +169,7 @@ /datum/action/item_action/toggle_firemode name = "Toggle Firemode" - + /datum/action/item_action/rcl name = "Change Cable Color" button_icon_state = "rcl_rainbow" @@ -490,7 +490,8 @@ var/obj/effect/proc_holder/spell/S = target S.action = src name = S.name - icon_icon = S.action_icon + desc = S.desc + button_icon = S.action_icon button_icon_state = S.action_icon_state background_icon_state = S.action_background_icon_state button.name = name diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index e519cf6af3..87c6ad7334 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -929,6 +929,26 @@ manipulate_organs(C) href_list["datumrefresh"] = href_list["editorgans"] + else if(href_list["hallucinate"]) + if(!check_rights(0)) + return + + var/mob/living/carbon/C = locate(href_list["hallucinate"]) in GLOB.mob_list + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/list/hallucinations = subtypesof(/datum/hallucination) + var/result = input(usr, "Choose the hallucination to apply","Send Hallucination") as null|anything in hallucinations + if(!usr) + return + if(QDELETED(C)) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + new result(C, TRUE) + else if(href_list["makehuman"]) if(!check_rights(R_SPAWN)) return diff --git a/code/datums/diseases/advance/symptoms/hallucigen.dm b/code/datums/diseases/advance/symptoms/hallucigen.dm index f913d49573..9bfd5b0baf 100644 --- a/code/datums/diseases/advance/symptoms/hallucigen.dm +++ b/code/datums/diseases/advance/symptoms/hallucigen.dm @@ -59,4 +59,4 @@ Bonus else if(prob(base_message_chance)) to_chat(M, "[pick("Oh, your head...", "Your head pounds.", "They're everywhere! Run!", "Something in the shadows...")]") - M.hallucination += (15 * power) + M.hallucination += (45 * power) diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm index 69b730d574..4c80f53b94 100644 --- a/code/game/gamemodes/cult/runes.dm +++ b/code/game/gamemodes/cult/runes.dm @@ -538,7 +538,7 @@ structure_check() searches for nearby cultist structures required for the invoca mob_to_revive = input(user, "Choose a cultist to revive.", "Cultist to Revive") as null|anything in potential_revive_mobs else mob_to_revive = potential_revive_mobs[1] - if(!src || QDELETED(src) || rune_in_use || !validness_checks(mob_to_revive, user)) + if(QDELETED(src) || !validness_checks(mob_to_revive, user)) rune_in_use = FALSE return if(user.name == "Herbert West") diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 2a0cd230d5..790319e362 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -120,7 +120,7 @@ var/list/datum/game_mode/runnable_modes = config.get_runnable_midround_modes(living_crew.len) var/list/datum/game_mode/usable_modes = list() for(var/datum/game_mode/G in runnable_modes) - if(G.reroll_friendly) + if(G.reroll_friendly && living_crew >= G.required_players) usable_modes += G else qdel(G) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 624d853808..94047727bc 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -233,9 +233,13 @@ return else /*if(src.justzap)*/ return - else if(user.hallucination > 50 && ishuman(user) && prob(10) && src.operating == FALSE) - hallucinate_shock(user) - return + else if(user.hallucinating() && ishuman(user) && prob(4) && !operating) + var/mob/living/carbon/human/H = user + if(H.gloves) + var/obj/item/clothing/gloves/G = H.gloves + if(G.siemens_coefficient)//not insulated + hallucinate_shock(H) + return if (cyclelinkedairlock) if (!shuttledocked && !emergency && !cyclelinkedairlock.shuttledocked && !cyclelinkedairlock.emergency && allowed(user)) if(cyclelinkedairlock.operating) diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm index c9b524836f..005d9c7595 100644 --- a/code/game/objects/effects/mines.dm +++ b/code/game/objects/effects/mines.dm @@ -127,7 +127,7 @@ var/pure_red = list(0,0,0,0,0,0,0,0,0,1,0,0) spawn(0) - new /obj/effect/hallucination/delusion(victim.loc,victim,"demon",duration,0) + new /datum/hallucination/delusion(victim, TRUE, "demon",duration,0) var/obj/item/weapon/twohanded/required/chainsaw/doomslayer/chainsaw = new(victim.loc) chainsaw.flags |= NODROP diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm index 0e6d6cc66f..1829538a01 100755 --- a/code/game/objects/items/weapons/flamethrower.dm +++ b/code/game/objects/items/weapons/flamethrower.dm @@ -26,6 +26,7 @@ var/create_full = FALSE var/create_with_tank = FALSE var/igniter_type = /obj/item/device/assembly/igniter + trigger_guard = TRIGGER_GUARD_NORMAL /obj/item/weapon/flamethrower/Destroy() if(weldtool) @@ -69,12 +70,7 @@ if(flag) return // too close if(ishuman(user)) - var/mob/living/carbon/human/H = user - if(H.dna.check_mutation(HULK)) - to_chat(user, "Your meaty finger is much too large for the trigger guard!") - return - if(NOGUNS in H.dna.species.species_traits) - to_chat(user, "Your fingers don't fit in the trigger guard!") + if(!can_trigger_gun(user)) return if(user && user.get_active_held_item() == src) // Make sure our user is still holding us var/turf/target_turf = get_turf(target) diff --git a/code/game/objects/items/weapons/holy_weapons.dm b/code/game/objects/items/weapons/holy_weapons.dm index 238022d209..8e1cf3301e 100644 --- a/code/game/objects/items/weapons/holy_weapons.dm +++ b/code/game/objects/items/weapons/holy_weapons.dm @@ -320,6 +320,8 @@ desc = "Particularly twisted dieties grant gifts of dubious value." icon_state = "arm_blade" item_state = "arm_blade" + lefthand_file = 'icons/mob/inhands/antag/changeling_lefthand.dmi' + righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' flags = ABSTRACT | NODROP w_class = WEIGHT_CLASS_HUGE sharpness = IS_SHARP diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm index d2f5714d5e..90c0eceaad 100644 --- a/code/game/objects/items/weapons/pneumaticCannon.dm +++ b/code/game/objects/items/weapons/pneumaticCannon.dm @@ -26,6 +26,7 @@ var/fire_mode = PCANNON_FIREALL var/automatic = FALSE var/clumsyCheck = TRUE + trigger_guard = TRIGGER_GUARD_NORMAL /obj/item/weapon/pneumatic_cannon/CanItemAutoclick() return automatic @@ -108,11 +109,7 @@ if(!istype(user) && !target) return var/discharge = 0 - if(user.dna.check_mutation(HULK)) - to_chat(user, "Your meaty finger is much too large for the trigger guard!") - return - if(NOGUNS in user.dna.species.species_traits) - to_chat(user, "Your fingers don't fit in the trigger guard!") + if(!can_trigger_gun(user)) return if(!loadedItems || !loadedWeightClass) to_chat(user, "\The [src] has nothing loaded.") diff --git a/code/game/objects/items/weapons/weaponry.dm b/code/game/objects/items/weapons/weaponry.dm index bb723ffb33..53bfe5d64c 100644 --- a/code/game/objects/items/weapons/weaponry.dm +++ b/code/game/objects/items/weapons/weaponry.dm @@ -1,4 +1,5 @@ /obj/item/weapon + var/trigger_guard = TRIGGER_GUARD_NONE /obj/item/weapon/banhammer desc = "A banhammer" @@ -584,3 +585,8 @@ throwforce = 0 flags = DROPDEL | ABSTRACT attack_verb = list("bopped") + +/obj/item/weapon/proc/can_trigger_gun(mob/living/user) + if(!user.can_use_guns(src)) + return FALSE + return TRUE \ No newline at end of file diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index e478ff5d92..d141f71b7a 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -1,12 +1,13 @@ /obj/structure/flora resistance_flags = FLAMMABLE + obj_integrity = 150 max_integrity = 150 - anchored = TRUE + anchored = 1 //trees /obj/structure/flora/tree name = "tree" - density = TRUE + density = 1 pixel_x = -16 layer = FLY_LAYER var/cut = FALSE @@ -25,7 +26,7 @@ playsound(get_turf(src), 'sound/effects/meteorimpact.ogg', 100 , 0, 0) icon = 'icons/obj/flora/pinetrees.dmi' icon_state = "tree_stump" - density = FALSE + density = 0 pixel_x = -16 name += " stump" cut = TRUE @@ -45,14 +46,14 @@ /obj/structure/flora/tree/pine/Initialize() icon_state = "pine_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/tree/pine/xmas name = "xmas tree" icon_state = "pine_c" /obj/structure/flora/tree/pine/xmas/Initialize() - ..() + . = ..() icon_state = "pine_c" /obj/structure/flora/tree/dead @@ -64,7 +65,7 @@ icon_state = "palm1" /obj/structure/flora/tree/palm/Initialize() - ..() + . = ..() icon_state = pick("palm1","palm2") pixel_x = 0 @@ -76,7 +77,7 @@ /obj/structure/flora/tree/dead/Initialize() icon_state = "tree_[rand(1, 6)]" - ..() + . = ..() /obj/structure/flora/tree/jungle name = "tree" @@ -88,12 +89,7 @@ /obj/structure/flora/tree/jungle/Initialize() icon_state = "[icon_state][rand(1, 6)]" - ..() - -/obj/structure/flora/tree/jungle/small - pixel_y = 0 - pixel_x = -32 - icon = 'icons/obj/flora/jungletreesmall.dmi' + . = ..() //grass /obj/structure/flora/grass @@ -106,7 +102,7 @@ /obj/structure/flora/grass/brown/Initialize() icon_state = "snowgrass[rand(1, 3)]bb" - ..() + . = ..() /obj/structure/flora/grass/green @@ -114,14 +110,14 @@ /obj/structure/flora/grass/green/Initialize() icon_state = "snowgrass[rand(1, 3)]gb" - ..() + . = ..() /obj/structure/flora/grass/both icon_state = "snowgrassall1" /obj/structure/flora/grass/both/Initialize() icon_state = "snowgrassall[rand(1, 3)]" - ..() + . = ..() //bushes @@ -129,11 +125,11 @@ name = "bush" icon = 'icons/obj/flora/snowflora.dmi' icon_state = "snowbush1" - anchored = TRUE + anchored = 1 /obj/structure/flora/bush/Initialize() icon_state = "snowbush[rand(1, 6)]" - ..() + . = ..() //newbushes @@ -145,112 +141,112 @@ /obj/structure/flora/ausbushes/Initialize() if(icon_state == "firstbush_1") icon_state = "firstbush_[rand(1, 4)]" - ..() + . = ..() /obj/structure/flora/ausbushes/reedbush icon_state = "reedbush_1" /obj/structure/flora/ausbushes/reedbush/Initialize() icon_state = "reedbush_[rand(1, 4)]" - ..() + . = ..() /obj/structure/flora/ausbushes/leafybush icon_state = "leafybush_1" /obj/structure/flora/ausbushes/leafybush/Initialize() icon_state = "leafybush_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/palebush icon_state = "palebush_1" /obj/structure/flora/ausbushes/palebush/Initialize() icon_state = "palebush_[rand(1, 4)]" - ..() + . = ..() /obj/structure/flora/ausbushes/stalkybush icon_state = "stalkybush_1" /obj/structure/flora/ausbushes/stalkybush/Initialize() icon_state = "stalkybush_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/grassybush icon_state = "grassybush_1" /obj/structure/flora/ausbushes/grassybush/Initialize() icon_state = "grassybush_[rand(1, 4)]" - ..() + . = ..() /obj/structure/flora/ausbushes/fernybush icon_state = "fernybush_1" /obj/structure/flora/ausbushes/fernybush/Initialize() icon_state = "fernybush_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/sunnybush icon_state = "sunnybush_1" /obj/structure/flora/ausbushes/sunnybush/Initialize() icon_state = "sunnybush_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/genericbush icon_state = "genericbush_1" /obj/structure/flora/ausbushes/genericbush/Initialize() icon_state = "genericbush_[rand(1, 4)]" - ..() + . = ..() /obj/structure/flora/ausbushes/pointybush icon_state = "pointybush_1" /obj/structure/flora/ausbushes/pointybush/Initialize() icon_state = "pointybush_[rand(1, 4)]" - ..() + . = ..() /obj/structure/flora/ausbushes/lavendergrass icon_state = "lavendergrass_1" /obj/structure/flora/ausbushes/lavendergrass/Initialize() icon_state = "lavendergrass_[rand(1, 4)]" - ..() + . = ..() /obj/structure/flora/ausbushes/ywflowers icon_state = "ywflowers_1" /obj/structure/flora/ausbushes/ywflowers/Initialize() icon_state = "ywflowers_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/brflowers icon_state = "brflowers_1" /obj/structure/flora/ausbushes/brflowers/Initialize() icon_state = "brflowers_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/ppflowers icon_state = "ppflowers_1" /obj/structure/flora/ausbushes/ppflowers/Initialize() icon_state = "ppflowers_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/sparsegrass icon_state = "sparsegrass_1" /obj/structure/flora/ausbushes/sparsegrass/Initialize() icon_state = "sparsegrass_[rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/ausbushes/fullgrass icon_state = "fullgrass_1" /obj/structure/flora/ausbushes/fullgrass/Initialize() icon_state = "fullgrass_[rand(1, 3)]" - ..() + . = ..() /obj/item/weapon/twohanded/required/kirbyplants name = "potted plant" @@ -308,10 +304,10 @@ desc = "A volcanic rock" icon = 'icons/obj/flora/rocks.dmi' resistance_flags = FIRE_PROOF - density = TRUE + density = 1 /obj/structure/flora/rock/Initialize() - ..() + . = ..() icon_state = "[icon_state][rand(1,3)]" /obj/structure/flora/rock/pile @@ -319,7 +315,7 @@ desc = "A pile of rocks" /obj/structure/flora/rock/pile/Initialize() - ..() + . = ..() icon_state = "[icon_state][rand(1,3)]" //Jungle grass @@ -333,7 +329,7 @@ /obj/structure/flora/grass/jungle/Initialize() icon_state = "[icon_state][rand(1, 5)]" - ..() + . = ..() /obj/structure/flora/grass/jungle/b icon_state = "grassb" @@ -348,7 +344,7 @@ density = FALSE /obj/structure/flora/rock/jungle/Initialize() - ..() + . = ..() icon_state = "[initial(icon_state)][rand(1,5)]" @@ -361,7 +357,7 @@ /obj/structure/flora/junglebush/Initialize() icon_state = "[icon_state][rand(1, 3)]" - ..() + . = ..() /obj/structure/flora/junglebush/b icon_state = "bushb" diff --git a/code/game/objects/structures/flora.dm.rej b/code/game/objects/structures/flora.dm.rej new file mode 100644 index 0000000000..8257ec2122 --- /dev/null +++ b/code/game/objects/structures/flora.dm.rej @@ -0,0 +1,28 @@ +diff a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm (rejected hunks) +@@ -89,7 +89,7 @@ + + /obj/structure/flora/tree/jungle/Initialize() + icon_state = "[icon_state][rand(1, 6)]" +- ..() ++ . = ..() + + //grass + /obj/structure/flora/grass +@@ -307,7 +307,7 @@ + density = 1 + + /obj/structure/flora/rock/Initialize() +- ..() ++ . = ..() + icon_state = "[icon_state][rand(1,3)]" + + /obj/structure/flora/rock/pile +@@ -381,5 +381,5 @@ + pixel_y = -16 + + /obj/structure/flora/rock/pile/largejungle/Initialize() +- ..() +- icon_state = "[initial(icon_state)][rand(1,3)]" +\ No newline at end of file ++ . = ..() ++ icon_state = "[initial(icon_state)][rand(1,3)]" diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 82ff907a04..a990530056 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -18,6 +18,7 @@ var/sound /turf/open/indestructible/sound/Entered(var/mob/AM) + ..() if(istype(AM)) playsound(src,sound,50,1) diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm index 968e782984..a51240c969 100644 --- a/code/game/turfs/simulated/chasm.dm +++ b/code/game/turfs/simulated/chasm.dm @@ -22,6 +22,7 @@ return /turf/open/chasm/Entered(atom/movable/AM) + ..() START_PROCESSING(SSobj, src) drop_stuff(AM) diff --git a/code/game/turfs/space/transit.dm b/code/game/turfs/space/transit.dm index c7e6973c4d..b877fa9eac 100644 --- a/code/game/turfs/space/transit.dm +++ b/code/game/turfs/space/transit.dm @@ -25,6 +25,7 @@ dir = EAST /turf/open/space/transit/Entered(atom/movable/AM, atom/OldLoc) + ..() if(!locate(/obj/structure/lattice) in src) throw_atom(AM) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index b204406d05..4342d12714 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -160,6 +160,7 @@ return TRUE //Nothing found to block so return success! /turf/Entered(atom/movable/AM) + ..() if(explosion_level && AM.ex_check(explosion_id)) AM.ex_act(explosion_level) diff --git a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm index 54feb11532..2ca0593e8d 100644 --- a/code/modules/admin/admin_investigate.dm +++ b/code/modules/admin/admin_investigate.dm @@ -5,7 +5,7 @@ F << "[time_stamp()] \ref[src] ([x],[y],[z]) || [src] [message]
" -/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY) ) +/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_PORTAL, INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS) ) set name = "Investigate" set category = "Admin" if(!holder) diff --git a/code/modules/admin/admin_investigate.dm.rej b/code/modules/admin/admin_investigate.dm.rej new file mode 100644 index 0000000000..4f8c142c61 --- /dev/null +++ b/code/modules/admin/admin_investigate.dm.rej @@ -0,0 +1,10 @@ +diff a/code/modules/admin/admin_investigate.dm b/code/modules/admin/admin_investigate.dm (rejected hunks) +@@ -5,7 +5,7 @@ + F << "[time_stamp()] \ref[src] ([x],[y],[z]) || [src] [message]
" + + +-/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY) ) ++/client/proc/investigate_show(subject in list("hrefs","notes, memos, watchlist", INVESTIGATE_SINGULO, INVESTIGATE_WIRES, INVESTIGATE_TELESCI, INVESTIGATE_GRAVITY, INVESTIGATE_RECORDS, INVESTIGATE_CARGO, INVESTIGATE_SUPERMATTER, INVESTIGATE_ATMOS, INVESTIGATE_EXPERIMENTOR, INVESTIGATE_BOTANY, INVESTIGATE_HALLUCINATIONS) ) + set name = "Investigate" + set category = "Admin" + if(!holder) diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index 818b0d6f09..81925756fb 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -6,7 +6,7 @@ log_admin("[key_name(usr)] tried to use the admin panel without authorization.") return if(href_list["ahelp"]) - if(!check_rights(R_ADMIN)) + if(!check_rights(R_ADMIN, TRUE)) return var/ahelp_ref = href_list["ahelp"] diff --git a/code/modules/atmospherics/machinery/portable/canister.dm b/code/modules/atmospherics/machinery/portable/canister.dm index d733dfc3fb..a45536430a 100644 --- a/code/modules/atmospherics/machinery/portable/canister.dm +++ b/code/modules/atmospherics/machinery/portable/canister.dm @@ -189,8 +189,9 @@ #define CONNECTED 2 #define EMPTY 4 #define LOW 8 -#define FULL 16 -#define DANGER 32 +#define MEDIUM 16 +#define FULL 32 +#define DANGER 64 /obj/machinery/portable_atmospherics/canister/update_icon() if(stat & BROKEN) cut_overlays() @@ -207,9 +208,11 @@ var/pressure = air_contents.return_pressure() if(pressure < 10) update |= EMPTY - else if(pressure < ONE_ATMOSPHERE) + else if(pressure < 5 * ONE_ATMOSPHERE) update |= LOW - else if(pressure < 15 * ONE_ATMOSPHERE) + else if(pressure < 10 * ONE_ATMOSPHERE) + update |= MEDIUM + else if(pressure < 40 * ONE_ATMOSPHERE) update |= FULL else update |= DANGER @@ -222,9 +225,9 @@ add_overlay("can-open") if(update & CONNECTED) add_overlay("can-connector") - if(update & EMPTY) + if(update & LOW) add_overlay("can-o0") - else if(update & LOW) + else if(update & MEDIUM) add_overlay("can-o1") else if(update & FULL) add_overlay("can-o2") @@ -234,6 +237,7 @@ #undef CONNECTED #undef EMPTY #undef LOW +#undef MEDIUM #undef FULL #undef DANGER diff --git a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm index 1cf215b9f2..7926cfc34d 100644 --- a/code/modules/cargo/console.dm +++ b/code/modules/cargo/console.dm @@ -145,7 +145,7 @@ var/reason = "" if(requestonly) - reason = stripped_input("Reason:", name, "") as text|null + reason = stripped_input("Reason:", name, "") if(isnull(reason) || ..()) return diff --git a/code/modules/cargo/console.dm.rej b/code/modules/cargo/console.dm.rej new file mode 100644 index 0000000000..e8798f179a --- /dev/null +++ b/code/modules/cargo/console.dm.rej @@ -0,0 +1,10 @@ +diff a/code/modules/cargo/console.dm b/code/modules/cargo/console.dm (rejected hunks) +@@ -145,7 +145,7 @@ + + var/reason = "" + if(requestonly) +- reason = stripped_input("Reason:", name, "") as text|null ++ reason = stripped_input("Reason:", name, "") + if(isnull(reason) || ..()) + return + diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index c1b0a387e4..2b8fe4b064 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -11,51 +11,83 @@ Gunshots/explosions/opening doors/less rare audio (done) */ +#define HAL_LINES_FILE "hallucination.json" + /mob/living/carbon var/image/halimage var/image/halbody var/obj/halitem var/hal_screwyhud = SCREWYHUD_NONE - var/handling_hal = 0 + var/next_hallucination = 0 + +GLOBAL_LIST_INIT(hallucinations_minor, list( + /datum/hallucination/sounds, + /datum/hallucination/bolts, + /datum/hallucination/whispers, + /datum/hallucination/message, + /datum/hallucination/hudscrew)) + +GLOBAL_LIST_INIT(hallucinations_medium, list( + /datum/hallucination/fake_alert, + /datum/hallucination/items, + /datum/hallucination/items_other, + /datum/hallucination/dangerflash, + /datum/hallucination/bolts, + /datum/hallucination/fake_flood, + /datum/hallucination/husks, + /datum/hallucination/battle, + /datum/hallucination/fire, + /datum/hallucination/self_delusion)) + +GLOBAL_LIST_INIT(hallucinations_major, list( + /datum/hallucination/fakeattacker, + /datum/hallucination/death, + /datum/hallucination/xeno_attack, + /datum/hallucination/singularity_scare, + /datum/hallucination/delusion, + /datum/hallucination/oh_yeah)) /mob/living/carbon/proc/handle_hallucinations() - if(handling_hal) + if(world.time < next_hallucination) return - //Least obvious - var/list/minor = list("sounds"=25,"bolts_minor"=5,"whispers"=15,"message"=10,"hudscrew"=15) - //Something's wrong here - var/list/medium = list("fake_alert"=15,"items"=10,"items_other"=10,"dangerflash"=10,"bolts"=5,"flood"=5,"husks"=10,"battle"=15,"self_delusion"=10) - //AAAAH - var/list/major = list("fake"=20,"death"=10,"xeno"=10,"singulo"=10,"borer"=10,"delusion"=20,"koolaid"=10) + if(hallucination) + var/list/current = GLOB.hallucinations_minor + if(prob(25) && hallucination > 100) + current = GLOB.hallucinations_medium + else if(prob(10) && hallucination > 200) + current = GLOB.hallucinations_major + var/halpick = pick(current) + new halpick(src, FALSE) - handling_hal = 1 - while(hallucination > 20) - sleep(rand(200,500)/(hallucination/25)) - if(prob(20)) - continue - var/list/current = list() - switch(rand(100)) - if(1 to 50) - current = minor - if(51 to 85) - current = medium - if(86 to 100) - current = major +/mob/living/carbon/proc/set_screwyhud(hud_type) + hal_screwyhud = hud_type + update_health_hud() - var/halpick = pickweight(current) +/datum/hallucination + var/mob/living/carbon/target + var/cost = 5 //affects the amount of hallucination reduced, and cooldown until the next hallucination + var/feedback_details //extra info for investigate - hallucinate(halpick) - handling_hal = 0 +/datum/hallucination/New(mob/living/carbon/T, forced = TRUE) + set waitfor = 0 + target = T + if(!forced) + target.hallucination = max(0, target.hallucination - cost) + target.next_hallucination = world.time + (rand(cost * 0.5, cost * 3) * 10) + +/datum/hallucination/proc/wake_and_restore() + target.set_screwyhud(SCREWYHUD_NONE) + target.SetSleeping(0) + +/datum/hallucination/Destroy() + target.investigate_log("was afflicted with a hallucination of type [type]. [feedback_details]", INVESTIGATE_HALLUCINATIONS) + return ..() /obj/effect/hallucination invisibility = INVISIBILITY_OBSERVER var/mob/living/carbon/target = null -/obj/effect/hallucination/proc/wake_and_restore() - target.hal_screwyhud = SCREWYHUD_NONE - target.SetSleeping(0) - /obj/effect/hallucination/simple var/image_icon = 'icons/mob/alien.dmi' var/image_state = "alienh_pounce" @@ -64,13 +96,14 @@ Gunshots/explosions/opening doors/less rare audio (done) var/col_mod = null var/image/current_image = null var/image_layer = MOB_LAYER - var/active = 1 //qdelery + var/active = TRUE //qdelery /obj/effect/hallucination/simple/Initialize(mapload, var/mob/living/carbon/T) ..() target = T current_image = GetImage() - if(target.client) target.client.images |= current_image + if(target.client) + target.client.images |= current_image /obj/effect/hallucination/simple/proc/GetImage() var/image/I = image(image_icon,src,image_state,image_layer,dir=src.dir) @@ -82,10 +115,12 @@ Gunshots/explosions/opening doors/less rare audio (done) /obj/effect/hallucination/simple/proc/Show(update=1) if(active) - if(target.client) target.client.images.Remove(current_image) + if(target.client) + target.client.images.Remove(current_image) if(update) current_image = GetImage() - if(target.client) target.client.images |= current_image + if(target.client) + target.client.images |= current_image /obj/effect/hallucination/simple/update_icon(new_state,new_icon,new_px=0,new_py=0) image_state = new_state @@ -101,36 +136,39 @@ Gunshots/explosions/opening doors/less rare audio (done) Show() /obj/effect/hallucination/simple/Destroy() - if(target.client) target.client.images.Remove(current_image) - active = 0 + if(target.client) + target.client.images.Remove(current_image) + active = FALSE return ..() #define FAKE_FLOOD_EXPAND_TIME 20 #define FAKE_FLOOD_MAX_RADIUS 10 -/obj/effect/hallucination/fake_flood +/datum/hallucination/fake_flood //Plasma starts flooding from the nearby vent + var/turf/center var/list/flood_images = list() var/list/turf/flood_turfs = list() var/image_icon = 'icons/effects/tile_effects.dmi' var/image_state = "plasma" var/radius = 0 var/next_expand = 0 + cost = 25 -/obj/effect/hallucination/fake_flood/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/fake_flood/New(mob/living/carbon/T, forced = TRUE) ..() - target = T for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target)) if(!U.welded) - src.loc = U.loc + center = get_turf(U) break - flood_images += image(image_icon,src,image_state,MOB_LAYER) - flood_turfs += get_turf(src.loc) + feedback_details += "Vent Coords: [center.x],[center.y],[center.z]" + flood_images += image(image_icon,center,image_state,MOB_LAYER) + flood_turfs += center if(target.client) target.client.images |= flood_images next_expand = world.time + FAKE_FLOOD_EXPAND_TIME START_PROCESSING(SSobj, src) -/obj/effect/hallucination/fake_flood/process() +/datum/hallucination/fake_flood/process() if(next_expand <= world.time) radius++ if(radius > FAKE_FLOOD_MAX_RADIUS) @@ -138,10 +176,10 @@ Gunshots/explosions/opening doors/less rare audio (done) return Expand() if((get_turf(target) in flood_turfs) && !target.internal) - target.hallucinate("fake_alert", "tox_in_air") + new /datum/hallucination/fake_alert(target, TRUE, "tox_in_air") next_expand = world.time + FAKE_FLOOD_EXPAND_TIME -/obj/effect/hallucination/fake_flood/proc/Expand() +/datum/hallucination/fake_flood/proc/Expand() for(var/turf/FT in flood_turfs) for(var/dir in GLOB.cardinals) var/turf/T = get_step(FT, dir) @@ -152,7 +190,7 @@ Gunshots/explosions/opening doors/less rare audio (done) if(target.client) target.client.images |= flood_images -/obj/effect/hallucination/fake_flood/Destroy() +/datum/hallucination/fake_flood/Destroy() STOP_PROCESSING(SSobj, src) qdel(flood_turfs) flood_turfs = list() @@ -167,7 +205,7 @@ Gunshots/explosions/opening doors/less rare audio (done) image_icon = 'icons/mob/alien.dmi' image_state = "alienh_pounce" -/obj/effect/hallucination/simple/xeno/Initialize(mapload, var/mob/living/carbon/T) +/obj/effect/hallucination/simple/xeno/Initialize(mapload, mob/living/carbon/T) ..() name = "alien hunter ([rand(1, 1000)])" @@ -177,18 +215,19 @@ Gunshots/explosions/opening doors/less rare audio (done) target.Knockdown(100) target.visible_message("[target] flails around wildly.","[name] pounces on you!") -/obj/effect/hallucination/xeno_attack +/datum/hallucination/xeno_attack //Xeno crawls from nearby vent,jumps at you, and goes back in var/obj/machinery/atmospherics/components/unary/vent_pump/pump = null var/obj/effect/hallucination/simple/xeno/xeno = null + cost = 25 -/obj/effect/hallucination/xeno_attack/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/xeno_attack/New(mob/living/carbon/T, forced = TRUE) ..() - target = T for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target)) if(!U.welded) pump = U break + feedback_details += "Vent Coords: [pump.x],[pump.y],[pump.z]" if(pump) xeno = new(pump.loc,target) sleep(10) @@ -200,7 +239,7 @@ Gunshots/explosions/opening doors/less rare audio (done) sleep(10) var/xeno_name = xeno.name to_chat(target, "[xeno_name] begins climbing into the ventilation system...") - sleep(10) + sleep(30) qdel(xeno) to_chat(target, "[xeno_name] scrambles into the ventilation ducts!") qdel(src) @@ -209,7 +248,7 @@ Gunshots/explosions/opening doors/less rare audio (done) image_icon = 'icons/mob/animal.dmi' image_state = "clown" -/obj/effect/hallucination/simple/clown/Initialize(mapload, var/mob/living/carbon/T,duration) +/obj/effect/hallucination/simple/clown/Initialize(mapload, mob/living/carbon/T, duration) ..(loc, T) name = pick(GLOB.clown_names) QDEL_IN(src,duration) @@ -217,59 +256,27 @@ Gunshots/explosions/opening doors/less rare audio (done) /obj/effect/hallucination/simple/clown/scary image_state = "scary_clown" -/obj/effect/hallucination/simple/borer - image_icon = 'icons/mob/borer.dmi' - image_state = "brainslug" - -/obj/effect/hallucination/borer - //A borer unconsciouss you and crawls in your ear - var/obj/machinery/atmospherics/components/unary/vent_pump/pump = null - var/obj/effect/hallucination/simple/borer/borer = null - -/obj/effect/hallucination/borer/Initialize(mapload, var/mob/living/carbon/T) - ..() - target = T - for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target)) - if(!U.welded) - pump = U - break - if(pump) - borer = new(pump.loc,target) - for(var/i=0, i<11, i++) - walk_to(borer, get_step(borer, get_cardinal_dir(borer, T))) - if(borer.Adjacent(T)) - to_chat(T, "You feel a creeping, horrible sense of dread come over you, freezing your limbs and setting your heart racing.") - T.Stun(80) - sleep(50) - qdel(borer) - sleep(rand(60, 90)) - to_chat(T, "Primary [rand(1000,9999)] states: [pick("Hello","Hi","You're my slave now!","Don't try to get rid of me...")]") - break - sleep(4) - if(!QDELETED(borer)) - qdel(borer) - qdel(src) - /obj/effect/hallucination/simple/bubblegum name = "Bubblegum" image_icon = 'icons/mob/lavaland/96x96megafauna.dmi' image_state = "bubblegum" px = -32 -/obj/effect/hallucination/oh_yeah +/datum/hallucination/oh_yeah var/obj/effect/hallucination/simple/bubblegum/bubblegum var/image/fakebroken var/image/fakerune + cost = 75 -/obj/effect/hallucination/oh_yeah/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/oh_yeah/New(mob/living/carbon/T, forced = TRUE) . = ..() - target = T var/turf/closed/wall/wall for(var/turf/closed/wall/W in range(7,target)) wall = W break if(!wall) return INITIALIZE_HINT_QDEL + feedback_details += "Source: [wall.x],[wall.y],[wall.z]" fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER) var/turf/landing = get_turf(target) @@ -283,7 +290,7 @@ Gunshots/explosions/opening doors/less rare audio (done) bubblegum = new(wall, target) addtimer(CALLBACK(src, .proc/bubble_attack, landing), 10) -/obj/effect/hallucination/oh_yeah/proc/bubble_attack(turf/landing) +/datum/hallucination/oh_yeah/proc/bubble_attack(turf/landing) var/charged = FALSE //only get hit once while(get_turf(bubblegum) != landing && target && target.stat != DEAD) bubblegum.forceMove(get_step_towards(bubblegum, landing)) @@ -301,7 +308,7 @@ Gunshots/explosions/opening doors/less rare audio (done) sleep(30) qdel(src) -/obj/effect/hallucination/oh_yeah/Destroy() +/datum/hallucination/oh_yeah/Destroy() if(target.client) target.client.images.Remove(fakebroken) target.client.images.Remove(fakerune) @@ -310,23 +317,24 @@ Gunshots/explosions/opening doors/less rare audio (done) QDEL_NULL(bubblegum) return ..() -/obj/effect/hallucination/singularity_scare +/datum/hallucination/singularity_scare //Singularity moving towards you. //todo Hide where it moved with fake space images var/obj/effect/hallucination/simple/singularity/s = null + cost = 75 -/obj/effect/hallucination/singularity_scare/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/singularity_scare/New(mob/living/carbon/T, forced = TRUE) ..() - target = T var/turf/start = get_turf(T) var/screen_border = pick(SOUTH,EAST,WEST,NORTH) - for(var/i = 0,i<11,i++) + for(var/i in 1 to 13) start = get_step(start,screen_border) + feedback_details += "Source: [start.x],[start.y],[start.z]" s = new(start,target) s.parent = src - for(var/i = 0,i<11,i++) - sleep(5) - s.loc = get_step(get_turf(s),get_dir(s,target)) + for(var/i in 1 to 13) + sleep(10) + s.forceMove(get_step(get_turf(s),get_dir(s,target))) s.Show() s.Eat() qdel(s) @@ -337,64 +345,72 @@ Gunshots/explosions/opening doors/less rare audio (done) image_layer = MASSIVE_OBJ_LAYER px = -96 py = -96 - var/obj/effect/hallucination/singularity_scare/parent + var/datum/hallucination/singularity_scare/parent /obj/effect/hallucination/simple/singularity/proc/Eat(atom/OldLoc, Dir) var/target_dist = get_dist(src,target) if(target_dist<=3) //"Eaten" - target.hal_screwyhud = SCREWYHUD_CRIT + target.set_screwyhud(SCREWYHUD_DEAD) target.SetUnconscious(160) - addtimer(CALLBACK(parent, .proc/wake_and_restore), rand(30, 50)) + addtimer(CALLBACK(parent, /datum/hallucination/.proc/wake_and_restore), rand(30, 50)) -/obj/effect/hallucination/battle +/datum/hallucination/battle + cost = 15 -/obj/effect/hallucination/battle/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/battle/New(mob/living/carbon/T, forced = TRUE, battle_type) ..() - target = T var/hits = rand(3,6) - switch(rand(1,5)) - if(1) //Laser fight - for(var/i=0,i...wabbajack...wabbajack...") - target.playsound_local(target,'sound/magic/staff_change.ogg', 50, 1, -1) + if(wabbajack) + to_chat(target, "...wabbajack...wabbajack...") + target.playsound_local(target,'sound/magic/staff_change.ogg', 50, 1) delusion = A target.client.images |= A QDEL_IN(src, duration) -/obj/effect/hallucination/self_delusion/Destroy() +/datum/hallucination/self_delusion/Destroy() if(target.client) target.client.images.Remove(delusion) return ..() -/obj/effect/hallucination/fakeattacker/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/fakeattacker/New(mob/living/carbon/T, forced = TRUE) ..() - target = T var/mob/living/carbon/human/clone = null var/clone_weapon = null @@ -523,6 +541,7 @@ Gunshots/explosions/opening doors/less rare audio (done) if(H.stat || H.lying) continue clone = H + feedback_details += "Clone of: [H.real_name]" break if(!clone) @@ -604,7 +623,7 @@ Gunshots/explosions/opening doors/less rare audio (done) for(var/mob/O in oviewers(world.view , my_target)) to_chat(O, "[my_target] stumbles around.") -/obj/effect/fake_attacker/Initialize(mapload, var/mob/living/carbon/T) +/obj/effect/fake_attacker/Initialize(mapload, mob/living/carbon/T) ..() my_target = T QDEL_IN(src, 300) @@ -651,7 +670,7 @@ Gunshots/explosions/opening doors/less rare audio (done) if(!locate(/obj/effect/overlay) in my_target.loc) fake_blood(my_target) else - my_target.playsound_local(my_target, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'), 25, 1, -1) + my_target.playsound_local(my_target, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'), 25, 1) my_target.show_message("[src.name] has punched [my_target]!", 1) my_target.staminaloss += 30 if(prob(33)) @@ -674,14 +693,15 @@ Gunshots/explosions/opening doors/less rare audio (done) QDEL_IN(O, 300) -/obj/effect/hallucination/bolts +/datum/hallucination/bolts var/list/doors = list() + cost = 25 -/obj/effect/hallucination/bolts/Initialize(mapload, var/mob/living/carbon/T,var/door_number=-1) //-1 for severe, 1-2 for subtle +/datum/hallucination/bolts/New(mob/living/carbon/T, forced, door_number=-1) //-1 for severe, 1-2 for subtle ..() - target = T var/image/I = null var/count = 0 + feedback_details += "Door amount: [door_number]" for(var/obj/machinery/door/airlock/A in range(7, target)) if(count>door_number && door_number>0) break @@ -700,13 +720,30 @@ Gunshots/explosions/opening doors/less rare audio (done) sleep(rand(6,12)) qdel(src) -/obj/effect/hallucination/whispers +/datum/hallucination/whispers + cost = 15 -/obj/effect/hallucination/whispers/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/whispers/New(mob/living/carbon/T, forced = TRUE) ..() - target = T - var/speak_messages = list("I'm watching you...","[target.first_name()]!","Get out!","Kchck-Chkck? Kchchck!","Did you hear that?","What did you do ?","Why?","Give me that!","HELP!!","EI NATH!!", "RUN!!", "Kill me!","O bidai nabora se'sma!", "[text2ratvar("Divinity, grant...")]") - var/radio_messages = list("Xenos!","Singularity loose!","Comms down!","They are arming the nuke!","They butchered Ian!","H-help!","[pick("Cult", "Wizard", "Ling", "Ops", "Revenant", "Murderer", "Harm", "I hear flashing", "Help")] in [pick(GLOB.teleportlocs)][prob(50)?"!":"!!"]","Where's [target.first_name()]?","Call the shuttle!","AI rogue!!") + var/speak_messages = list("[pick_list_replacements(HAL_LINES_FILE, "suspicion")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "greetings")][target.first_name()]!",\ + "[pick_list_replacements(HAL_LINES_FILE, "getout")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "weird")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "didyouhearthat")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "imatraitor")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "doubt")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "aggressive")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "help")]!!",\ + "[pick_list_replacements(HAL_LINES_FILE, "escape")]",\ + "I'm infected, [pick_list_replacements(HAL_LINES_FILE, "infection_advice")]!") + + var/radio_messages = list("Set [target.first_name()] to arrest!",\ + "[pick_list_replacements(HAL_LINES_FILE, "people")] is [pick_list_replacements(HAL_LINES_FILE, "accusations")]!",\ + "Help!",\ + "[pick_list_replacements(HAL_LINES_FILE, "threat")] in [pick_list_replacements(HAL_LINES_FILE, "location")][prob(50)?"!":"!!"]",\ + "Where's [target.first_name()]?"\ + ,"[pick("C","Ai, c","Someone c","Rec")]all the shuttle!"\ + ,"AI [pick("rogue", "is dead")]!!") var/list/mob/living/carbon/people = list() var/list/mob/living/carbon/person = null @@ -722,7 +759,9 @@ Gunshots/explosions/opening doors/less rare audio (done) people += H if(person) //Basic talk var/image/speech_overlay = image('icons/mob/talk.dmi', person, "default0", layer = ABOVE_MOB_LAYER) - to_chat(target, target.compose_message(person,understood_language,pick(speak_messages),null,person.get_spans())) + var/message = target.compose_message(person,understood_language,pick(speak_messages),null,person.get_spans()) + feedback_details += "Type: Talk, Source: [person.real_name], Message: [message]" + to_chat(target, message) if(target.client) target.client.images |= speech_overlay sleep(30) @@ -732,312 +771,381 @@ Gunshots/explosions/opening doors/less rare audio (done) for(var/mob/living/carbon/human/H in GLOB.living_mob_list) humans += H person = pick(humans) - to_chat(target, target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans())) + var/message = target.compose_message(person,understood_language,pick(radio_messages),"1459",person.get_spans()) + feedback_details += "Type: Radio, Source: [person.real_name], Message: [message]" + to_chat(target, message) qdel(src) -/obj/effect/hallucination/message +/datum/hallucination/message + cost = 15 -/obj/effect/hallucination/message/Initialize(mapload, var/mob/living/carbon/T) +/datum/hallucination/message/New(mob/living/carbon/T, forced = TRUE) ..() - target = T var/chosen = pick("The light burns you!", \ "You don't feel like yourself.", \ - "Unknown has punched [target]!", \ "You hear something squeezing through the ducts...", \ "You hear a distant scream.", \ "You feel invincible, nothing can hurt you!", \ "You feel a tiny prick!", \ "[target] sneezes.", \ - "You feel faint.", \ - "You hear a strange, alien voice in your head...[pick("Hiss","Ssss")]", \ - "You can see...everything!") + //The truth, revealed + "You're hallucinating.", \ + //Direct advice + "[pick_list_replacements(HAL_LINES_FILE, "advice")]") + feedback_details += "Message: [chosen]" to_chat(target, chosen) qdel(src) -/mob/living/carbon/proc/hallucinate(hal_type, specific) // specific is used to specify a particular hallucination - set waitfor = 0 - switch(hal_type) - if("xeno") - new /obj/effect/hallucination/xeno_attack(src.loc,src) - if("borer") - new /obj/effect/hallucination/borer(src.loc,src) - if("singulo") - new /obj/effect/hallucination/singularity_scare(src.loc,src) - if("koolaid") - new /obj/effect/hallucination/oh_yeah(src.loc,src) - if("battle") - new /obj/effect/hallucination/battle(src.loc,src) - if("flood") - new /obj/effect/hallucination/fake_flood(src.loc,src) - if("delusion") - new /obj/effect/hallucination/delusion(src.loc,src) - if("self_delusion") - new /obj/effect/hallucination/self_delusion(src.loc,src) - if("fake") - new /obj/effect/hallucination/fakeattacker(src.loc,src) - if("bolts") - new /obj/effect/hallucination/bolts(src.loc,src) - if("bolts_minor") - new /obj/effect/hallucination/bolts(src.loc,src,rand(1,2)) - if("whispers") - new /obj/effect/hallucination/whispers(src.loc,src) - if("message") - new /obj/effect/hallucination/message(src.loc,src) - if("items_other") - new /obj/effect/hallucination/items_other(src.loc,src) - if("sounds") - //Strange audio - switch(rand(1,20)) - if(1) playsound_local(null,'sound/machines/airlock.ogg', 15, 1) - if(2) - if(prob(50)) playsound_local(null,'sound/effects/explosion1.ogg', 50, 1) - else playsound_local(null, 'sound/effects/explosion2.ogg', 50, 1) - if(3) playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1) - if(4) playsound_local(null, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1) - if(5) - playsound_local(null, 'sound/weapons/ring.ogg', 35) - sleep(15) - playsound_local(null, 'sound/weapons/ring.ogg', 35) - sleep(15) - playsound_local(null, 'sound/weapons/ring.ogg', 35) - if(6) playsound_local(null, 'sound/magic/summon_guns.ogg', 50, 1) - if(7) playsound_local(null, 'sound/machines/alarm.ogg', 100, 0) - if(8) playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0) - if(9) - //To make it more realistic, I added two gunshots (enough to kill) - playsound_local(null, 'sound/weapons/gunshot.ogg', 25, 1) - spawn(rand(10,30)) - playsound_local(null, 'sound/weapons/gunshot.ogg', 25, 1) - sleep(rand(5,10)) - playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1) - if(10) playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50) - if(11) - //Same as above, but with tasers. - playsound_local(null, 'sound/weapons/taser.ogg', 25, 1) - spawn(rand(10,30)) - playsound_local(null, 'sound/weapons/taser.ogg', 25, 1) - sleep(rand(5,10)) - playsound_local(null, sound(get_sfx("bodyfall"), 25), 25, 1) - //Rare audio - if(12) - //These sounds are (mostly) taken from Hidden: Source - var/list/creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/screech.ogg',\ - 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\ - 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ - 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ - 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') - playsound_local(null, pick(creepyasssounds), 50, 1) - if(13) - playsound_local(null, 'sound/effects/ratvar_rises.ogg', 100) - sleep(150) - playsound_local(null, 'sound/effects/ratvar_reveal.ogg', 100) - if(14) - to_chat(src, "

Priority Announcement

") - to_chat(src, "

The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.

") - playsound_local(null, 'sound/ai/shuttledock.ogg', 100) - //Deconstructing a wall - if(15) - playsound_local(null, 'sound/items/welder.ogg', 15, 1) - sleep(105) - playsound_local(null, 'sound/items/welder2.ogg', 15, 1) - sleep(15) - playsound_local(null, 'sound/items/ratchet.ogg', 15, 1) - //Hacking a door - if(16) - playsound_local(null, 'sound/items/screwdriver.ogg', 15, 1) - sleep(rand(10,30)) - for(var/i = rand(1,3), i>0, i--) - playsound_local(null, 'sound/weapons/empty.ogg', 15, 1) - sleep(rand(10,30)) - playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1) - if(17) - playsound_local(null, 'sound/weapons/saberon.ogg',35,1) - if(18) - to_chat(src, "

Biohazard Alert

") - to_chat(src, "

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

") - playsound_local(null, 'sound/ai/outbreak5.ogg') - if(19) //Tesla loose! - playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1) - sleep(20) - playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1) - sleep(20) - playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1) - if(20) //AI is doomsdaying! - to_chat(src, "

Anomaly Alert

") - to_chat(src, "

Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.

") - playsound_local(null, 'sound/ai/aimalf.ogg', 100) - if("hudscrew") - //Screwy HUD - //to_chat(src, "Screwy HUD") - hal_screwyhud = pick(SCREWYHUD_NONE,SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY) - sleep(rand(100,250)) - hal_screwyhud = 0 +/datum/hallucination/sounds + cost = 15 - if("fake_alert") - var/alert_type = pick("not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","weightless","fire","locked","hacked","temp","pressure") - if(specific) - alert_type = specific - switch(alert_type) - if("not_enough_oxy") - throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy, override = TRUE) - if("not_enough_tox") - throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox, override = TRUE) - if("not_enough_co2") - throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2, override = TRUE) - if("too_much_oxy") - throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy, override = TRUE) - if("too_much_co2") - throw_alert("too_much_co2", /obj/screen/alert/too_much_co2, override = TRUE) - if("too_much_tox") - throw_alert("too_much_tox", /obj/screen/alert/too_much_tox, override = TRUE) - if("nutrition") - if(prob(50)) - throw_alert("nutrition", /obj/screen/alert/fat, override = TRUE) - else - throw_alert("nutrition", /obj/screen/alert/starving, override = TRUE) - if("weightless") - throw_alert("weightless", /obj/screen/alert/weightless, override = TRUE) - if("fire") - throw_alert("fire", /obj/screen/alert/fire, override = TRUE) - if("temp") - if(prob(50)) - throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE) - else - throw_alert("temp", /obj/screen/alert/cold, 3, override = TRUE) - if("pressure") - if(prob(50)) - throw_alert("pressure", /obj/screen/alert/highpressure, 2, override = TRUE) - else - throw_alert("pressure", /obj/screen/alert/lowpressure, 2, override = TRUE) - //BEEP BOOP I AM A ROBOT - if("newlaw") - throw_alert("newlaw", /obj/screen/alert/newlaw, override = TRUE) - if("locked") - throw_alert("locked", /obj/screen/alert/locked, override = TRUE) - if("hacked") - throw_alert("hacked", /obj/screen/alert/hacked, override = TRUE) - if("charge") - throw_alert("charge", /obj/screen/alert/emptycell, override = TRUE) - sleep(rand(100,200)) - clear_alert(alert_type, clear_override = TRUE) - - if("items") - //Strange items - //to_chat(src, "Traitor Items") - if(!halitem) - halitem = new - var/obj/item/l_hand = get_item_for_held_index(1) - var/obj/item/r_hand = get_item_for_held_index(2) - var/l = ui_hand_position(get_held_index_of_item(l_hand)) - var/r = ui_hand_position(get_held_index_of_item(r_hand)) - var/list/slots_free = list(l,r) - if(l_hand) slots_free -= l - if(r_hand) slots_free -= r - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if(!H.belt) slots_free += ui_belt - if(!H.l_store) slots_free += ui_storage1 - if(!H.r_store) slots_free += ui_storage2 - if(slots_free.len) - halitem.screen_loc = pick(slots_free) - halitem.layer = ABOVE_HUD_LAYER - halitem.plane = ABOVE_HUD_PLANE - switch(rand(1,6)) - if(1) //revolver - halitem.icon = 'icons/obj/guns/projectile.dmi' - halitem.icon_state = "revolver" - halitem.name = "Revolver" - if(2) //c4 - halitem.icon = 'icons/obj/grenade.dmi' - halitem.icon_state = "plastic-explosive0" - halitem.name = "Mysterious Package" - if(prob(25)) - halitem.icon_state = "c4small_1" - if(3) //sword - halitem.icon = 'icons/obj/weapons.dmi' - halitem.icon_state = "sword1" - halitem.name = "Sword" - if(4) //stun baton - halitem.icon = 'icons/obj/weapons.dmi' - halitem.icon_state = "stunbaton" - halitem.name = "Stun Baton" - if(5) //emag - halitem.icon = 'icons/obj/card.dmi' - halitem.icon_state = "emag" - halitem.name = "Cryptographic Sequencer" - if(6) //flashbang - halitem.icon = 'icons/obj/grenade.dmi' - halitem.icon_state = "flashbang1" - halitem.name = "Flashbang" - if(client) client.screen += halitem - QDEL_IN(halitem, rand(100, 250)) - if("dangerflash") - //Flashes of danger - //to_chat(src, "Danger Flash") - if(!halimage) - var/list/possible_points = list() - for(var/turf/open/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/open/floor/target = pick(possible_points) - - switch(rand(1,4)) - if(1) - //to_chat(src, "Space") - halimage = image('icons/turf/space.dmi',target,"[rand(1,25)]",TURF_LAYER) - if(2) - //to_chat(src, "Lava") - halimage = image('icons/turf/floors/lava.dmi',target,"smooth",TURF_LAYER) - if(3) - //to_chat(src, "Chasm") - halimage = image('icons/turf/floors/Chasms.dmi',target,"smooth",TURF_LAYER) - if(4) - //to_chat(src, "C4") - halimage = image('icons/obj/grenade.dmi',target,"plastic-explosive2",OBJ_LAYER+0.01) - - - if(client) client.images += halimage - sleep(rand(40,60)) //Only seen for a brief moment. - if(client) client.images -= halimage - halimage = null - if("death") - //Fake death - hal_screwyhud = SCREWYHUD_DEAD - SetUnconscious(400) - var/area/area = get_area(src) - to_chat(src, "[mind.name] has died at [area.name].") +/datum/hallucination/sounds/New(mob/living/carbon/T, forced = TRUE, sound_type) + ..() + if(!sound_type) + sound_type = pick("airlock","explosion","far_explosion","glass","phone","summon_guns","alarm","beepsky","hallelujah","creepy","ratvar","shuttle_dock", + "wall_decon","door_hack","esword","blob_alert","tesla","malf_ai") + feedback_details += "Type: [sound_type]" + //Strange audio + switch(sound_type) + if("airlock") + target.playsound_local(null,'sound/machines/airlock.ogg', 15, 1) + if("explosion") if(prob(50)) - var/list/dead_people = list() - for(var/mob/dead/observer/G in GLOB.player_list) - dead_people += G - var/mob/dead/observer/fakemob = pick(dead_people) - if(fakemob) - sleep(rand(30, 60)) - to_chat(src, "DEAD: [fakemob.name] says, \"[pick("rip","welcome [first_name()]","you too?","is the AI malf?",\ - "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"") - sleep(rand(50,70)) - hal_screwyhud = SCREWYHUD_NONE - SetSleeping(0) - if("husks") - if(!halbody) - var/list/possible_points = list() - for(var/turf/open/floor/F in view(src,world.view)) - possible_points += F - if(possible_points.len) - var/turf/open/floor/target = pick(possible_points) - switch(rand(1,4)) - if(1) - var/image/body = image('icons/mob/human.dmi',target,"husk",TURF_LAYER) - var/matrix/M = matrix() - M.Turn(90) - body.transform = M - halbody = body - if(2,3) - halbody = image('icons/mob/human.dmi',target,"husk",TURF_LAYER) - if(4) - halbody = image('icons/mob/alien.dmi',target,"alienother",TURF_LAYER) + target.playsound_local(null,'sound/effects/explosion1.ogg', 50, 1) + else + target.playsound_local(null, 'sound/effects/explosion2.ogg', 50, 1) + if("far_explosion") + target.playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1) + if("glass") + target.playsound_local(null, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1) + if("phone") + target.playsound_local(null, 'sound/weapons/ring.ogg', 35) + sleep(15) + target.playsound_local(null, 'sound/weapons/ring.ogg', 35) + sleep(15) + target.playsound_local(null, 'sound/weapons/ring.ogg', 35) + if("summon_guns") + target.playsound_local(null, 'sound/magic/summon_guns.ogg', 50, 1) + if("alarm") + target.playsound_local(null, 'sound/machines/alarm.ogg', 100, 0) + if("beepsky") + target.playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0) + if("hallelujah") + target.playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50) + //Rare audio + if("creepy") + //These sounds are (mostly) taken from Hidden: Source + var/static/list/hallucinations_creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/screech.ogg',\ + 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\ + 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ + 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ + 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') + target.playsound_local(null, pick(hallucinations_creepyasssounds), 50, 1) + if("ratvar") + target.playsound_local(null, 'sound/effects/ratvar_rises.ogg', 100) + sleep(150) + target.playsound_local(null, 'sound/effects/ratvar_reveal.ogg', 100) + if("shuttle_dock") + to_chat(target, "

Priority Announcement

") + to_chat(target, "

The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.

") + target.playsound_local(null, 'sound/ai/shuttledock.ogg', 100) + //Deconstructing a wall + if("wall_decon") + target.playsound_local(null, 'sound/items/welder.ogg', 15, 1) + sleep(105) + target.playsound_local(null, 'sound/items/welder2.ogg', 15, 1) + sleep(15) + target.playsound_local(null, 'sound/items/ratchet.ogg', 15, 1) + //Hacking a door + if("door_hack") + target.playsound_local(null, 'sound/items/screwdriver.ogg', 15, 1) + sleep(rand(10,30)) + for(var/i = rand(1,3), i>0, i--) + target.playsound_local(null, 'sound/weapons/empty.ogg', 15, 1) + sleep(rand(10,30)) + target.playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1) + if("esword") + target.playsound_local(null, 'sound/weapons/saberon.ogg',35,1) + if("blob_alert") + to_chat(target, "

Biohazard Alert

") + to_chat(target, "

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

") + target.playsound_local(null, 'sound/ai/outbreak5.ogg', 100, 0) + if("tesla") //Tesla loose! + target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1) + sleep(20) + target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1) + sleep(20) + target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1) + if("malf_ai") //AI is doomsdaying! + to_chat(target, "

Anomaly Alert

") + to_chat(target, "

Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.

") + target.playsound_local(null, 'sound/ai/aimalf.ogg', 100, 0) + qdel(src) + +/datum/hallucination/hudscrew + cost = 10 + +/datum/hallucination/hudscrew/New(mob/living/carbon/T, forced = TRUE) + ..() + //Screwy HUD + target.set_screwyhud(pick(SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY)) + feedback_details += "Type: [target.hal_screwyhud]" + sleep(rand(100,250)) + target.set_screwyhud(SCREWYHUD_NONE) + qdel(src) + +/datum/hallucination/fake_alert + cost = 15 + +/datum/hallucination/fake_alert/New(mob/living/carbon/T, forced = TRUE, specific, duration = 150) + ..() + var/alert_type = pick("not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","weightless","fire","locked","hacked","temphot","tempcold","pressure") + if(specific) + alert_type = specific + feedback_details += "Type: [alert_type]" + switch(alert_type) + if("oxy") + target.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy, override = TRUE) + if("not_enough_tox") + target.throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox, override = TRUE) + if("not_enough_co2") + target.throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2, override = TRUE) + if("too_much_oxy") + target.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy, override = TRUE) + if("too_much_co2") + target.throw_alert("too_much_co2", /obj/screen/alert/too_much_co2, override = TRUE) + if("tox_in_air") + target.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox, override = TRUE) + if("nutrition") + if(prob(50)) + target.throw_alert("nutrition", /obj/screen/alert/fat, override = TRUE) + else + target.throw_alert("nutrition", /obj/screen/alert/starving, override = TRUE) + if("weightless") + target.throw_alert("weightless", /obj/screen/alert/weightless, override = TRUE) + if("fire") + target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE) + if("temphot") + target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE) + if("tempcold") + target.throw_alert("temp", /obj/screen/alert/cold, 3, override = TRUE) + if("pressure") + if(prob(50)) + target.throw_alert("pressure", /obj/screen/alert/highpressure, 2, override = TRUE) + else + target.throw_alert("pressure", /obj/screen/alert/lowpressure, 2, override = TRUE) + //BEEP BOOP I AM A ROBOT + if("newlaw") + target.throw_alert("newlaw", /obj/screen/alert/newlaw, override = TRUE) + if("locked") + target.throw_alert("locked", /obj/screen/alert/locked, override = TRUE) + if("hacked") + target.throw_alert("hacked", /obj/screen/alert/hacked, override = TRUE) + if("charge") + target.throw_alert("charge",/obj/screen/alert/emptycell, override = TRUE) + sleep(duration) + target.clear_alert(alert_type, clear_override = TRUE) + qdel(src) + +/datum/hallucination/items + cost = 15 + +/datum/hallucination/items/New(mob/living/carbon/T, forced = TRUE) + ..() + //Strange items + if(!target.halitem) + target.halitem = new + var/obj/item/l_hand = target.get_item_for_held_index(1) + var/obj/item/r_hand = target.get_item_for_held_index(2) + var/l = ui_hand_position(target.get_held_index_of_item(l_hand)) + var/r = ui_hand_position(target.get_held_index_of_item(r_hand)) + var/list/slots_free = list(l,r) + if(l_hand) slots_free -= l + if(r_hand) slots_free -= r + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(!H.belt) slots_free += ui_belt + if(!H.l_store) slots_free += ui_storage1 + if(!H.r_store) slots_free += ui_storage2 + if(slots_free.len) + target.halitem.screen_loc = pick(slots_free) + target.halitem.layer = ABOVE_HUD_LAYER + target.halitem.plane = ABOVE_HUD_PLANE + switch(rand(1,6)) + if(1) //revolver + target.halitem.icon = 'icons/obj/guns/projectile.dmi' + target.halitem.icon_state = "revolver" + target.halitem.name = "Revolver" + if(2) //c4 + target.halitem.icon = 'icons/obj/grenade.dmi' + target.halitem.icon_state = "plastic-explosive0" + target.halitem.name = "C4" + if(prob(25)) + target.halitem.icon_state = "plasticx40" + if(3) //sword + target.halitem.icon = 'icons/obj/weapons.dmi' + target.halitem.icon_state = "sword0" + target.halitem.name = "Energy Sword" + if(4) //stun baton + target.halitem.icon = 'icons/obj/weapons.dmi' + target.halitem.icon_state = "stunbaton" + target.halitem.name = "Stun Baton" + if(5) //emag + target.halitem.icon = 'icons/obj/card.dmi' + target.halitem.icon_state = "emag" + target.halitem.name = "Cryptographic Sequencer" + if(6) //flashbang + target.halitem.icon = 'icons/obj/grenade.dmi' + target.halitem.icon_state = "flashbang1" + target.halitem.name = "Flashbang" + feedback_details += "Type: [target.halitem.name]" + if(target.client) target.client.screen += target.halitem + QDEL_IN(target.halitem, rand(150, 350)) + qdel(src) + +/datum/hallucination/dangerflash + cost = 15 + +/datum/hallucination/dangerflash/New(mob/living/carbon/T, forced = TRUE) + ..() + //Flashes of danger + if(!target.halimage) + var/list/possible_points = list() + for(var/turf/open/floor/F in view(target,world.view)) + possible_points += F + if(possible_points.len) + var/turf/open/floor/danger_point = pick(possible_points) + + switch(rand(1,5)) + if(1) + target.halimage = image('icons/turf/space.dmi',danger_point,"[rand(1,25)]",TURF_LAYER) + if(2) + target.halimage = image('icons/turf/floors/lava.dmi',danger_point,"smooth",TURF_LAYER) + if(3) + target.halimage = image('icons/turf/floors/Chasms.dmi',danger_point,"smooth",TURF_LAYER) + if(4) + target.halimage = image('icons/effects/effects.dmi',danger_point,"anom",OBJ_LAYER+0.01) + if(5) + target.halimage = image('icons/effects/effects.dmi',danger_point,"electricity2",OBJ_LAYER+0.01) + + + if(target.client) + target.client.images += target.halimage + sleep(rand(200,450)) + if(target.client) + target.client.images -= target.halimage + QDEL_NULL(target.halimage) + qdel(src) + +/datum/hallucination/death + cost = 40 + +/datum/hallucination/death/New(mob/living/carbon/T, forced = TRUE) + set waitfor = 0 + ..() + target.set_screwyhud(SCREWYHUD_DEAD) + target.Knockdown(300) + target.silent += 10 + var/area/area = get_area(target) + to_chat(target, "[target.mind.name] has died at [area.name].") + if(prob(50)) + var/mob/fakemob + var/list/dead_people = list() + for(var/mob/dead/observer/G in GLOB.player_list) + dead_people += G + if(LAZYLEN(dead_people)) + fakemob = pick(dead_people) + else + fakemob = target //ever been so lonely you had to haunt yourself? + if(fakemob) + sleep(rand(20, 50)) + to_chat(target, "DEAD: [fakemob.name] says, \"[pick("rip","hey [target.first_name()]","you too?","is the AI rogue?",\ + "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"") + sleep(rand(70,90)) + target.set_screwyhud(SCREWYHUD_NONE) + target.SetKnockdown(0) + target.silent = 0 + qdel(src) + +/datum/hallucination/fire + cost = 25 + +/datum/hallucination/fire/New(mob/living/carbon/T, forced = TRUE) + ..() + var/image/fire_overlay = image('icons/mob/OnFire.dmi', target, "Standing", ABOVE_MOB_LAYER) + if(target.client) + target.client.images += fire_overlay + to_chat(target, "You're set on fire!") + target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE) + sleep(20) + target.throw_alert("temp", /obj/screen/alert/hot, 1, override = TRUE) + sleep(30) + target.clear_alert("temp", clear_override = TRUE) + target.throw_alert("temp", /obj/screen/alert/hot, 2, override = TRUE) + sleep(30) + target.clear_alert("temp", clear_override = TRUE) + target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE) + for(var/i in 1 to rand(5, 10)) + target.adjustStaminaLoss(15) + sleep(25) + target.clear_alert("fire", clear_override = TRUE) + target.clear_alert("temp", clear_override = TRUE) + if(target.client) + target.client.images -= fire_overlay + QDEL_NULL(fire_overlay) + qdel(src) + +/datum/hallucination/husks + cost = 20 + +/datum/hallucination/husks/New(mob/living/carbon/T, forced = TRUE) + ..() + if(!target.halbody) + var/list/possible_points = list() + for(var/turf/open/floor/F in view(target,world.view)) + possible_points += F + if(possible_points.len) + var/turf/open/floor/husk_point = pick(possible_points) + switch(rand(1,4)) + if(1) + var/image/body = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER) + var/matrix/M = matrix() + M.Turn(90) + body.transform = M + target.halbody = body + if(2,3) + target.halbody = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER) + if(4) + target.halbody = image('icons/mob/alien.dmi',husk_point,"alienother",TURF_LAYER) + + if(target.client) + target.client.images += target.halbody + sleep(rand(30,50)) //Only seen for a brief moment. + if(target.client) + target.client.images -= target.halbody + QDEL_NULL(target.halbody) + qdel(src) + +//hallucination projectile code in code/modules/projectiles/projectile/special.dm +/datum/hallucination/stray_bullet + cost = 15 + +/datum/hallucination/stray_bullet/New(mob/living/carbon/C, forced = TRUE) + ..() + var/list/turf/startlocs = list() + for(var/turf/open/T in view(world.view+1,target)-view(world.view,target)) + startlocs += T + var/turf/start = pick(startlocs) + var/proj_type = pick(subtypesof(/obj/item/projectile/hallucination)) + feedback_details += "Type: [proj_type]" + var/obj/item/projectile/hallucination/H = new proj_type(start) + target.playsound_local(start, H.hal_fire_sound, 60, 1) + H.hal_target = target + H.current = start + H.starting = start + H.yo = target.y - start.y + H.xo = target.x - start.x + H.original = target + H.fire() + qdel(src) - if(client) client.images += halbody - spawn(rand(30,50)) //Only seen for a brief moment. - if(client) client.images -= halbody - halbody = null diff --git a/code/modules/flufftext/Hallucination.dm.rej b/code/modules/flufftext/Hallucination.dm.rej new file mode 100644 index 0000000000..2b8fe4b064 --- /dev/null +++ b/code/modules/flufftext/Hallucination.dm.rej @@ -0,0 +1,1151 @@ +/* +Ideas for the subtle effects of hallucination: + +Light up oxygen/plasma indicators (done) +Cause health to look critical/dead, even when standing (done) +Characters silently watching you +Brief flashes of fire/space/bombs/c4/dangerous shit (done) +Items that are rare/traitorous/don't exist appearing in your inventory slots (done) +Strange audio (should be rare) (done) +Gunshots/explosions/opening doors/less rare audio (done) + +*/ + +#define HAL_LINES_FILE "hallucination.json" + +/mob/living/carbon + var/image/halimage + var/image/halbody + var/obj/halitem + var/hal_screwyhud = SCREWYHUD_NONE + var/next_hallucination = 0 + +GLOBAL_LIST_INIT(hallucinations_minor, list( + /datum/hallucination/sounds, + /datum/hallucination/bolts, + /datum/hallucination/whispers, + /datum/hallucination/message, + /datum/hallucination/hudscrew)) + +GLOBAL_LIST_INIT(hallucinations_medium, list( + /datum/hallucination/fake_alert, + /datum/hallucination/items, + /datum/hallucination/items_other, + /datum/hallucination/dangerflash, + /datum/hallucination/bolts, + /datum/hallucination/fake_flood, + /datum/hallucination/husks, + /datum/hallucination/battle, + /datum/hallucination/fire, + /datum/hallucination/self_delusion)) + +GLOBAL_LIST_INIT(hallucinations_major, list( + /datum/hallucination/fakeattacker, + /datum/hallucination/death, + /datum/hallucination/xeno_attack, + /datum/hallucination/singularity_scare, + /datum/hallucination/delusion, + /datum/hallucination/oh_yeah)) + +/mob/living/carbon/proc/handle_hallucinations() + if(world.time < next_hallucination) + return + + if(hallucination) + var/list/current = GLOB.hallucinations_minor + if(prob(25) && hallucination > 100) + current = GLOB.hallucinations_medium + else if(prob(10) && hallucination > 200) + current = GLOB.hallucinations_major + var/halpick = pick(current) + new halpick(src, FALSE) + +/mob/living/carbon/proc/set_screwyhud(hud_type) + hal_screwyhud = hud_type + update_health_hud() + +/datum/hallucination + var/mob/living/carbon/target + var/cost = 5 //affects the amount of hallucination reduced, and cooldown until the next hallucination + var/feedback_details //extra info for investigate + +/datum/hallucination/New(mob/living/carbon/T, forced = TRUE) + set waitfor = 0 + target = T + if(!forced) + target.hallucination = max(0, target.hallucination - cost) + target.next_hallucination = world.time + (rand(cost * 0.5, cost * 3) * 10) + +/datum/hallucination/proc/wake_and_restore() + target.set_screwyhud(SCREWYHUD_NONE) + target.SetSleeping(0) + +/datum/hallucination/Destroy() + target.investigate_log("was afflicted with a hallucination of type [type]. [feedback_details]", INVESTIGATE_HALLUCINATIONS) + return ..() + +/obj/effect/hallucination + invisibility = INVISIBILITY_OBSERVER + var/mob/living/carbon/target = null + +/obj/effect/hallucination/simple + var/image_icon = 'icons/mob/alien.dmi' + var/image_state = "alienh_pounce" + var/px = 0 + var/py = 0 + var/col_mod = null + var/image/current_image = null + var/image_layer = MOB_LAYER + var/active = TRUE //qdelery + +/obj/effect/hallucination/simple/Initialize(mapload, var/mob/living/carbon/T) + ..() + target = T + current_image = GetImage() + if(target.client) + target.client.images |= current_image + +/obj/effect/hallucination/simple/proc/GetImage() + var/image/I = image(image_icon,src,image_state,image_layer,dir=src.dir) + I.pixel_x = px + I.pixel_y = py + if(col_mod) + I.color = col_mod + return I + +/obj/effect/hallucination/simple/proc/Show(update=1) + if(active) + if(target.client) + target.client.images.Remove(current_image) + if(update) + current_image = GetImage() + if(target.client) + target.client.images |= current_image + +/obj/effect/hallucination/simple/update_icon(new_state,new_icon,new_px=0,new_py=0) + image_state = new_state + if(new_icon) + image_icon = new_icon + else + image_icon = initial(image_icon) + px = new_px + py = new_py + Show() + +/obj/effect/hallucination/simple/Moved(atom/OldLoc, Dir) + Show() + +/obj/effect/hallucination/simple/Destroy() + if(target.client) + target.client.images.Remove(current_image) + active = FALSE + return ..() + +#define FAKE_FLOOD_EXPAND_TIME 20 +#define FAKE_FLOOD_MAX_RADIUS 10 + +/datum/hallucination/fake_flood + //Plasma starts flooding from the nearby vent + var/turf/center + var/list/flood_images = list() + var/list/turf/flood_turfs = list() + var/image_icon = 'icons/effects/tile_effects.dmi' + var/image_state = "plasma" + var/radius = 0 + var/next_expand = 0 + cost = 25 + +/datum/hallucination/fake_flood/New(mob/living/carbon/T, forced = TRUE) + ..() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target)) + if(!U.welded) + center = get_turf(U) + break + feedback_details += "Vent Coords: [center.x],[center.y],[center.z]" + flood_images += image(image_icon,center,image_state,MOB_LAYER) + flood_turfs += center + if(target.client) target.client.images |= flood_images + next_expand = world.time + FAKE_FLOOD_EXPAND_TIME + START_PROCESSING(SSobj, src) + +/datum/hallucination/fake_flood/process() + if(next_expand <= world.time) + radius++ + if(radius > FAKE_FLOOD_MAX_RADIUS) + qdel(src) + return + Expand() + if((get_turf(target) in flood_turfs) && !target.internal) + new /datum/hallucination/fake_alert(target, TRUE, "tox_in_air") + next_expand = world.time + FAKE_FLOOD_EXPAND_TIME + +/datum/hallucination/fake_flood/proc/Expand() + for(var/turf/FT in flood_turfs) + for(var/dir in GLOB.cardinals) + var/turf/T = get_step(FT, dir) + if((T in flood_turfs) || !FT.CanAtmosPass(T)) + continue + flood_images += image(image_icon,T,image_state,MOB_LAYER) + flood_turfs += T + if(target.client) + target.client.images |= flood_images + +/datum/hallucination/fake_flood/Destroy() + STOP_PROCESSING(SSobj, src) + qdel(flood_turfs) + flood_turfs = list() + if(target.client) + target.client.images.Remove(flood_images) + target = null + qdel(flood_images) + flood_images = list() + return ..() + +/obj/effect/hallucination/simple/xeno + image_icon = 'icons/mob/alien.dmi' + image_state = "alienh_pounce" + +/obj/effect/hallucination/simple/xeno/Initialize(mapload, mob/living/carbon/T) + ..() + name = "alien hunter ([rand(1, 1000)])" + +/obj/effect/hallucination/simple/xeno/throw_impact(A) + update_icon("alienh_pounce") + if(A == target && target.stat!=DEAD) + target.Knockdown(100) + target.visible_message("[target] flails around wildly.","[name] pounces on you!") + +/datum/hallucination/xeno_attack + //Xeno crawls from nearby vent,jumps at you, and goes back in + var/obj/machinery/atmospherics/components/unary/vent_pump/pump = null + var/obj/effect/hallucination/simple/xeno/xeno = null + cost = 25 + +/datum/hallucination/xeno_attack/New(mob/living/carbon/T, forced = TRUE) + ..() + for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in orange(7,target)) + if(!U.welded) + pump = U + break + feedback_details += "Vent Coords: [pump.x],[pump.y],[pump.z]" + if(pump) + xeno = new(pump.loc,target) + sleep(10) + xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32) + xeno.throw_at(target,7,1, spin = 0, diagonals_first = 1) + sleep(10) + xeno.update_icon("alienh_leap",'icons/mob/alienleap.dmi',-32,-32) + xeno.throw_at(pump,7,1, spin = 0, diagonals_first = 1) + sleep(10) + var/xeno_name = xeno.name + to_chat(target, "[xeno_name] begins climbing into the ventilation system...") + sleep(30) + qdel(xeno) + to_chat(target, "[xeno_name] scrambles into the ventilation ducts!") + qdel(src) + +/obj/effect/hallucination/simple/clown + image_icon = 'icons/mob/animal.dmi' + image_state = "clown" + +/obj/effect/hallucination/simple/clown/Initialize(mapload, mob/living/carbon/T, duration) + ..(loc, T) + name = pick(GLOB.clown_names) + QDEL_IN(src,duration) + +/obj/effect/hallucination/simple/clown/scary + image_state = "scary_clown" + +/obj/effect/hallucination/simple/bubblegum + name = "Bubblegum" + image_icon = 'icons/mob/lavaland/96x96megafauna.dmi' + image_state = "bubblegum" + px = -32 + +/datum/hallucination/oh_yeah + var/obj/effect/hallucination/simple/bubblegum/bubblegum + var/image/fakebroken + var/image/fakerune + cost = 75 + +/datum/hallucination/oh_yeah/New(mob/living/carbon/T, forced = TRUE) + . = ..() + var/turf/closed/wall/wall + for(var/turf/closed/wall/W in range(7,target)) + wall = W + break + if(!wall) + return INITIALIZE_HINT_QDEL + feedback_details += "Source: [wall.x],[wall.y],[wall.z]" + + fakebroken = image('icons/turf/floors.dmi', wall, "plating", layer = TURF_LAYER) + var/turf/landing = get_turf(target) + var/turf/landing_image_turf = get_step(landing, SOUTHWEST) //the icon is 3x3 + fakerune = image('icons/effects/96x96.dmi', landing_image_turf, "landing", layer = ABOVE_OPEN_TURF_LAYER) + fakebroken.override = TRUE + if(target.client) + target.client.images |= fakebroken + target.client.images |= fakerune + target.playsound_local(wall,'sound/effects/meteorimpact.ogg', 150, 1) + bubblegum = new(wall, target) + addtimer(CALLBACK(src, .proc/bubble_attack, landing), 10) + +/datum/hallucination/oh_yeah/proc/bubble_attack(turf/landing) + var/charged = FALSE //only get hit once + while(get_turf(bubblegum) != landing && target && target.stat != DEAD) + bubblegum.forceMove(get_step_towards(bubblegum, landing)) + bubblegum.setDir(get_dir(bubblegum, landing)) + target.playsound_local(get_turf(bubblegum), 'sound/effects/meteorimpact.ogg', 150, 1) + shake_camera(target, 2, 1) + if(bubblegum.Adjacent(target) && !charged) + charged = TRUE + target.Knockdown(80) + target.adjustStaminaLoss(40) + step_away(target, bubblegum) + shake_camera(target, 4, 3) + target.visible_message("[target] jumps backwards, falling on the ground!","[bubblegum] slams into you!") + sleep(2) + sleep(30) + qdel(src) + +/datum/hallucination/oh_yeah/Destroy() + if(target.client) + target.client.images.Remove(fakebroken) + target.client.images.Remove(fakerune) + QDEL_NULL(fakebroken) + QDEL_NULL(fakerune) + QDEL_NULL(bubblegum) + return ..() + +/datum/hallucination/singularity_scare + //Singularity moving towards you. + //todo Hide where it moved with fake space images + var/obj/effect/hallucination/simple/singularity/s = null + cost = 75 + +/datum/hallucination/singularity_scare/New(mob/living/carbon/T, forced = TRUE) + ..() + var/turf/start = get_turf(T) + var/screen_border = pick(SOUTH,EAST,WEST,NORTH) + for(var/i in 1 to 13) + start = get_step(start,screen_border) + feedback_details += "Source: [start.x],[start.y],[start.z]" + s = new(start,target) + s.parent = src + for(var/i in 1 to 13) + sleep(10) + s.forceMove(get_step(get_turf(s),get_dir(s,target))) + s.Show() + s.Eat() + qdel(s) + +/obj/effect/hallucination/simple/singularity + image_icon = 'icons/effects/224x224.dmi' + image_state = "singularity_s7" + image_layer = MASSIVE_OBJ_LAYER + px = -96 + py = -96 + var/datum/hallucination/singularity_scare/parent + +/obj/effect/hallucination/simple/singularity/proc/Eat(atom/OldLoc, Dir) + var/target_dist = get_dist(src,target) + if(target_dist<=3) //"Eaten" + target.set_screwyhud(SCREWYHUD_DEAD) + target.SetUnconscious(160) + addtimer(CALLBACK(parent, /datum/hallucination/.proc/wake_and_restore), rand(30, 50)) + +/datum/hallucination/battle + cost = 15 + +/datum/hallucination/battle/New(mob/living/carbon/T, forced = TRUE, battle_type) + ..() + var/hits = rand(3,6) + if(!battle_type) + battle_type = pick("laser","esword","gun","stunprod","bomb") + feedback_details += "Type: [battle_type]" + switch(battle_type) + if("laser") //Laser fight + for(var/i in 1 to hits) + target.playsound_local(null, 'sound/weapons/laser.ogg', 25, 1) + if(prob(50)) + addtimer(CALLBACK(target, /mob/.proc/playsound_local, null, 'sound/weapons/sear.ogg', 25, 1), rand(10,20)) + else + addtimer(CALLBACK(target, /mob/.proc/playsound_local, null, 'sound/weapons/effects/searwall.ogg', 25, 1), rand(10,20)) + sleep(rand(CLICK_CD_RANGE, CLICK_CD_RANGE + 8)) + target.playsound_local(null, get_sfx("bodyfall"), 25, 1) + if("esword") //Esword fight + target.playsound_local(null, 'sound/weapons/saberon.ogg',15, 1) + for(var/i=0,i...wabbajack...wabbajack...") + target.playsound_local(target,'sound/magic/staff_change.ogg', 50, 1) + delusion = A + target.client.images |= A + QDEL_IN(src, duration) + +/datum/hallucination/self_delusion/Destroy() + if(target.client) + target.client.images.Remove(delusion) + return ..() + +/datum/hallucination/fakeattacker/New(mob/living/carbon/T, forced = TRUE) + ..() + var/mob/living/carbon/human/clone = null + var/clone_weapon = null + + for(var/mob/living/carbon/human/H in GLOB.living_mob_list) + if(H.stat || H.lying) + continue + clone = H + feedback_details += "Clone of: [H.real_name]" + break + + if(!clone) + return + + var/static/list/non_fakeattack_weapons = list(/obj/item/weapon/gun/ballistic, /obj/item/ammo_box/a357,\ + /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow, /obj/item/weapon/melee/transforming/energy/sword/saber,\ + /obj/item/weapon/storage/box/syndicate, /obj/item/weapon/storage/box/emps,\ + /obj/item/weapon/cartridge/virus/syndicate, /obj/item/clothing/under/chameleon,\ + /obj/item/clothing/shoes/chameleon, /obj/item/weapon/card/id/syndicate,\ + /obj/item/clothing/mask/chameleon, /obj/item/clothing/glasses/thermal,\ + /obj/item/device/chameleon, /obj/item/weapon/card/emag, /obj/item/weapon/grenade/plastic/x4,\ + /obj/item/weapon/storage/toolbox/syndicate, /obj/item/weapon/aiModule,\ + /obj/item/device/radio/headset/syndicate, /obj/item/weapon/grenade/plastic/c4,\ + /obj/item/device/powersink, /obj/item/weapon/storage/box/syndie_kit,\ + /obj/item/toy/syndicateballoon, /obj/item/weapon/gun/energy/laser/captain,\ + /obj/item/weapon/hand_tele, /obj/item/weapon/construction/rcd, /obj/item/weapon/tank/jetpack,\ + /obj/item/clothing/under/rank/captain, /obj/item/device/aicard,\ + /obj/item/clothing/shoes/magboots, /obj/item/areaeditor/blueprints, /obj/item/weapon/disk/nuclear,\ + /obj/item/clothing/suit/space/nasavoid, /obj/item/weapon/tank) + + var/obj/effect/fake_attacker/F = new/obj/effect/fake_attacker(get_turf(target),target) + + for(var/obj/item/I in clone.held_items) + if(!(locate(I) in non_fakeattack_weapons)) + clone_weapon = I.name + F.weap = I + + F.name = clone.name + F.my_target = target + F.weapon_name = clone_weapon + + F.left = image(clone,dir = WEST) + F.right = image(clone,dir = EAST) + F.up = image(clone,dir = NORTH) + F.down = image(clone,dir = SOUTH) + + F.updateimage() + qdel(src) + +/obj/effect/fake_attacker + icon = null + icon_state = null + name = "" + desc = "" + density = FALSE + anchored = TRUE + opacity = 0 + var/mob/living/carbon/human/my_target = null + var/weapon_name = null + var/obj/item/weap = null + var/image/stand_icon = null + var/image/currentimage = null + var/icon/base = null + var/skin_tone + var/mob/living/clone = null + var/image/left + var/image/right + var/image/up + var/collapse + var/image/down + + max_integrity = 100 + +/obj/effect/fake_attacker/attackby(obj/item/weapon/P, mob/living/user, params) + step_away(src,my_target,2) + user.changeNext_move(CLICK_CD_MELEE) + user.do_attack_animation(src) + my_target.playsound_local(src, P.hitsound, 1) + my_target.visible_message("[my_target] flails around wildly.", \ + "[my_target] has attacked [src]!") + + obj_integrity -= P.force + +/obj/effect/fake_attacker/Crossed(mob/M, somenumber) + if(M == my_target) + step_away(src,my_target,2) + if(prob(30)) + for(var/mob/O in oviewers(world.view , my_target)) + to_chat(O, "[my_target] stumbles around.") + +/obj/effect/fake_attacker/Initialize(mapload, mob/living/carbon/T) + ..() + my_target = T + QDEL_IN(src, 300) + step_away(src,my_target,2) + INVOKE_ASYNC(src, .proc/attack_loop) + + +/obj/effect/fake_attacker/proc/updateimage() +// del src.currentimage + if(src.dir == NORTH) + del src.currentimage + src.currentimage = new /image(up,src) + else if(src.dir == SOUTH) + del src.currentimage + src.currentimage = new /image(down,src) + else if(src.dir == EAST) + del src.currentimage + src.currentimage = new /image(right,src) + else if(src.dir == WEST) + del src.currentimage + src.currentimage = new /image(left,src) + SEND_IMAGE(my_target, currentimage) + + +/obj/effect/fake_attacker/proc/attack_loop() + while(1) + sleep(rand(5,10)) + if(obj_integrity < 0 || my_target.stat) + collapse() + continue + if(get_dist(src,my_target) > 1) + src.setDir(get_dir(src,my_target)) + step_towards(src,my_target) + updateimage() + else + if(prob(15)) + if(weapon_name) + my_target.playsound_local(my_target, weap.hitsound, weap.get_clamped_volume(), 1) + my_target.show_message("[src.name] has attacked [my_target] with [weapon_name]!", 1) + my_target.staminaloss += 30 + if(prob(20)) + my_target.blur_eyes(3) + if(prob(33)) + if(!locate(/obj/effect/overlay) in my_target.loc) + fake_blood(my_target) + else + my_target.playsound_local(my_target, pick('sound/weapons/punch1.ogg','sound/weapons/punch2.ogg','sound/weapons/punch3.ogg','sound/weapons/punch4.ogg'), 25, 1) + my_target.show_message("[src.name] has punched [my_target]!", 1) + my_target.staminaloss += 30 + if(prob(33)) + if(!locate(/obj/effect/overlay) in my_target.loc) + fake_blood(my_target) + + if(prob(15)) + step_away(src,my_target,2) + +/obj/effect/fake_attacker/proc/collapse() + collapse = 1 + updateimage() + qdel(src) + +/obj/effect/fake_attacker/proc/fake_blood(mob/target) + var/obj/effect/overlay/O = new/obj/effect/overlay(target.loc) + O.name = "blood" + var/image/I = image('icons/effects/blood.dmi',O,"floor[rand(1,7)]",O.dir,1) + SEND_IMAGE(target, I) + QDEL_IN(O, 300) + + +/datum/hallucination/bolts + var/list/doors = list() + cost = 25 + +/datum/hallucination/bolts/New(mob/living/carbon/T, forced, door_number=-1) //-1 for severe, 1-2 for subtle + ..() + var/image/I = null + var/count = 0 + feedback_details += "Door amount: [door_number]" + for(var/obj/machinery/door/airlock/A in range(7, target)) + if(count>door_number && door_number>0) + break + count++ + I = image(A.overlays_file, get_turf(A), "lights_bolts",layer=A.layer+0.1) + doors += I + if(target.client) + target.client.images |= I + target.playsound_local(get_turf(A), 'sound/machines/boltsdown.ogg',30,0,3) + sleep(rand(6,12)) + sleep(100) + for(var/image/B in doors) + if(target.client) + target.client.images.Remove(B) + target.playsound_local(get_turf(B), 'sound/machines/boltsup.ogg',30,0,3) + sleep(rand(6,12)) + qdel(src) + +/datum/hallucination/whispers + cost = 15 + +/datum/hallucination/whispers/New(mob/living/carbon/T, forced = TRUE) + ..() + var/speak_messages = list("[pick_list_replacements(HAL_LINES_FILE, "suspicion")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "greetings")][target.first_name()]!",\ + "[pick_list_replacements(HAL_LINES_FILE, "getout")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "weird")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "didyouhearthat")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "imatraitor")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "doubt")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "aggressive")]",\ + "[pick_list_replacements(HAL_LINES_FILE, "help")]!!",\ + "[pick_list_replacements(HAL_LINES_FILE, "escape")]",\ + "I'm infected, [pick_list_replacements(HAL_LINES_FILE, "infection_advice")]!") + + var/radio_messages = list("Set [target.first_name()] to arrest!",\ + "[pick_list_replacements(HAL_LINES_FILE, "people")] is [pick_list_replacements(HAL_LINES_FILE, "accusations")]!",\ + "Help!",\ + "[pick_list_replacements(HAL_LINES_FILE, "threat")] in [pick_list_replacements(HAL_LINES_FILE, "location")][prob(50)?"!":"!!"]",\ + "Where's [target.first_name()]?"\ + ,"[pick("C","Ai, c","Someone c","Rec")]all the shuttle!"\ + ,"AI [pick("rogue", "is dead")]!!") + + var/list/mob/living/carbon/people = list() + var/list/mob/living/carbon/person = null + var/datum/language/understood_language = target.get_random_understood_language() + for(var/mob/living/carbon/H in view(target)) + if(H == target) + continue + if(!person) + person = H + else + if(get_dist(target,H)The light burns you!", \ + "You don't feel like yourself.", \ + "You hear something squeezing through the ducts...", \ + "You hear a distant scream.", \ + "You feel invincible, nothing can hurt you!", \ + "You feel a tiny prick!", \ + "[target] sneezes.", \ + //The truth, revealed + "You're hallucinating.", \ + //Direct advice + "[pick_list_replacements(HAL_LINES_FILE, "advice")]") + feedback_details += "Message: [chosen]" + to_chat(target, chosen) + qdel(src) + +/datum/hallucination/sounds + cost = 15 + +/datum/hallucination/sounds/New(mob/living/carbon/T, forced = TRUE, sound_type) + ..() + if(!sound_type) + sound_type = pick("airlock","explosion","far_explosion","glass","phone","summon_guns","alarm","beepsky","hallelujah","creepy","ratvar","shuttle_dock", + "wall_decon","door_hack","esword","blob_alert","tesla","malf_ai") + feedback_details += "Type: [sound_type]" + //Strange audio + switch(sound_type) + if("airlock") + target.playsound_local(null,'sound/machines/airlock.ogg', 15, 1) + if("explosion") + if(prob(50)) + target.playsound_local(null,'sound/effects/explosion1.ogg', 50, 1) + else + target.playsound_local(null, 'sound/effects/explosion2.ogg', 50, 1) + if("far_explosion") + target.playsound_local(null, 'sound/effects/explosionfar.ogg', 50, 1) + if("glass") + target.playsound_local(null, pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg'), 50, 1) + if("phone") + target.playsound_local(null, 'sound/weapons/ring.ogg', 35) + sleep(15) + target.playsound_local(null, 'sound/weapons/ring.ogg', 35) + sleep(15) + target.playsound_local(null, 'sound/weapons/ring.ogg', 35) + if("summon_guns") + target.playsound_local(null, 'sound/magic/summon_guns.ogg', 50, 1) + if("alarm") + target.playsound_local(null, 'sound/machines/alarm.ogg', 100, 0) + if("beepsky") + target.playsound_local(null, 'sound/voice/bfreeze.ogg', 35, 0) + if("hallelujah") + target.playsound_local(null, 'sound/effects/pray_chaplain.ogg', 50) + //Rare audio + if("creepy") + //These sounds are (mostly) taken from Hidden: Source + var/static/list/hallucinations_creepyasssounds = list('sound/effects/ghost.ogg', 'sound/effects/ghost2.ogg', 'sound/effects/heart_beat.ogg', 'sound/effects/screech.ogg',\ + 'sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/behind_you2.ogg', 'sound/hallucinations/far_noise.ogg', 'sound/hallucinations/growl1.ogg', 'sound/hallucinations/growl2.ogg',\ + 'sound/hallucinations/growl3.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/im_here2.ogg', 'sound/hallucinations/i_see_you1.ogg', 'sound/hallucinations/i_see_you2.ogg',\ + 'sound/hallucinations/look_up1.ogg', 'sound/hallucinations/look_up2.ogg', 'sound/hallucinations/over_here1.ogg', 'sound/hallucinations/over_here2.ogg', 'sound/hallucinations/over_here3.ogg',\ + 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/turn_around2.ogg', 'sound/hallucinations/veryfar_noise.ogg', 'sound/hallucinations/wail.ogg') + target.playsound_local(null, pick(hallucinations_creepyasssounds), 50, 1) + if("ratvar") + target.playsound_local(null, 'sound/effects/ratvar_rises.ogg', 100) + sleep(150) + target.playsound_local(null, 'sound/effects/ratvar_reveal.ogg', 100) + if("shuttle_dock") + to_chat(target, "

Priority Announcement

") + to_chat(target, "

The Emergency Shuttle has docked with the station. You have 3 minutes to board the Emergency Shuttle.

") + target.playsound_local(null, 'sound/ai/shuttledock.ogg', 100) + //Deconstructing a wall + if("wall_decon") + target.playsound_local(null, 'sound/items/welder.ogg', 15, 1) + sleep(105) + target.playsound_local(null, 'sound/items/welder2.ogg', 15, 1) + sleep(15) + target.playsound_local(null, 'sound/items/ratchet.ogg', 15, 1) + //Hacking a door + if("door_hack") + target.playsound_local(null, 'sound/items/screwdriver.ogg', 15, 1) + sleep(rand(10,30)) + for(var/i = rand(1,3), i>0, i--) + target.playsound_local(null, 'sound/weapons/empty.ogg', 15, 1) + sleep(rand(10,30)) + target.playsound_local(null, 'sound/machines/airlockforced.ogg', 15, 1) + if("esword") + target.playsound_local(null, 'sound/weapons/saberon.ogg',35,1) + if("blob_alert") + to_chat(target, "

Biohazard Alert

") + to_chat(target, "

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

") + target.playsound_local(null, 'sound/ai/outbreak5.ogg', 100, 0) + if("tesla") //Tesla loose! + target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 35, 1) + sleep(20) + target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 65, 1) + sleep(20) + target.playsound_local(null, 'sound/magic/lightningbolt.ogg', 100, 1) + if("malf_ai") //AI is doomsdaying! + to_chat(target, "

Anomaly Alert

") + to_chat(target, "

Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.

") + target.playsound_local(null, 'sound/ai/aimalf.ogg', 100, 0) + qdel(src) + +/datum/hallucination/hudscrew + cost = 10 + +/datum/hallucination/hudscrew/New(mob/living/carbon/T, forced = TRUE) + ..() + //Screwy HUD + target.set_screwyhud(pick(SCREWYHUD_CRIT,SCREWYHUD_DEAD,SCREWYHUD_HEALTHY)) + feedback_details += "Type: [target.hal_screwyhud]" + sleep(rand(100,250)) + target.set_screwyhud(SCREWYHUD_NONE) + qdel(src) + +/datum/hallucination/fake_alert + cost = 15 + +/datum/hallucination/fake_alert/New(mob/living/carbon/T, forced = TRUE, specific, duration = 150) + ..() + var/alert_type = pick("not_enough_oxy","not_enough_tox","not_enough_co2","too_much_oxy","too_much_co2","too_much_tox","newlaw","nutrition","charge","weightless","fire","locked","hacked","temphot","tempcold","pressure") + if(specific) + alert_type = specific + feedback_details += "Type: [alert_type]" + switch(alert_type) + if("oxy") + target.throw_alert("not_enough_oxy", /obj/screen/alert/not_enough_oxy, override = TRUE) + if("not_enough_tox") + target.throw_alert("not_enough_tox", /obj/screen/alert/not_enough_tox, override = TRUE) + if("not_enough_co2") + target.throw_alert("not_enough_co2", /obj/screen/alert/not_enough_co2, override = TRUE) + if("too_much_oxy") + target.throw_alert("too_much_oxy", /obj/screen/alert/too_much_oxy, override = TRUE) + if("too_much_co2") + target.throw_alert("too_much_co2", /obj/screen/alert/too_much_co2, override = TRUE) + if("tox_in_air") + target.throw_alert("too_much_tox", /obj/screen/alert/too_much_tox, override = TRUE) + if("nutrition") + if(prob(50)) + target.throw_alert("nutrition", /obj/screen/alert/fat, override = TRUE) + else + target.throw_alert("nutrition", /obj/screen/alert/starving, override = TRUE) + if("weightless") + target.throw_alert("weightless", /obj/screen/alert/weightless, override = TRUE) + if("fire") + target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE) + if("temphot") + target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE) + if("tempcold") + target.throw_alert("temp", /obj/screen/alert/cold, 3, override = TRUE) + if("pressure") + if(prob(50)) + target.throw_alert("pressure", /obj/screen/alert/highpressure, 2, override = TRUE) + else + target.throw_alert("pressure", /obj/screen/alert/lowpressure, 2, override = TRUE) + //BEEP BOOP I AM A ROBOT + if("newlaw") + target.throw_alert("newlaw", /obj/screen/alert/newlaw, override = TRUE) + if("locked") + target.throw_alert("locked", /obj/screen/alert/locked, override = TRUE) + if("hacked") + target.throw_alert("hacked", /obj/screen/alert/hacked, override = TRUE) + if("charge") + target.throw_alert("charge",/obj/screen/alert/emptycell, override = TRUE) + sleep(duration) + target.clear_alert(alert_type, clear_override = TRUE) + qdel(src) + +/datum/hallucination/items + cost = 15 + +/datum/hallucination/items/New(mob/living/carbon/T, forced = TRUE) + ..() + //Strange items + if(!target.halitem) + target.halitem = new + var/obj/item/l_hand = target.get_item_for_held_index(1) + var/obj/item/r_hand = target.get_item_for_held_index(2) + var/l = ui_hand_position(target.get_held_index_of_item(l_hand)) + var/r = ui_hand_position(target.get_held_index_of_item(r_hand)) + var/list/slots_free = list(l,r) + if(l_hand) slots_free -= l + if(r_hand) slots_free -= r + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(!H.belt) slots_free += ui_belt + if(!H.l_store) slots_free += ui_storage1 + if(!H.r_store) slots_free += ui_storage2 + if(slots_free.len) + target.halitem.screen_loc = pick(slots_free) + target.halitem.layer = ABOVE_HUD_LAYER + target.halitem.plane = ABOVE_HUD_PLANE + switch(rand(1,6)) + if(1) //revolver + target.halitem.icon = 'icons/obj/guns/projectile.dmi' + target.halitem.icon_state = "revolver" + target.halitem.name = "Revolver" + if(2) //c4 + target.halitem.icon = 'icons/obj/grenade.dmi' + target.halitem.icon_state = "plastic-explosive0" + target.halitem.name = "C4" + if(prob(25)) + target.halitem.icon_state = "plasticx40" + if(3) //sword + target.halitem.icon = 'icons/obj/weapons.dmi' + target.halitem.icon_state = "sword0" + target.halitem.name = "Energy Sword" + if(4) //stun baton + target.halitem.icon = 'icons/obj/weapons.dmi' + target.halitem.icon_state = "stunbaton" + target.halitem.name = "Stun Baton" + if(5) //emag + target.halitem.icon = 'icons/obj/card.dmi' + target.halitem.icon_state = "emag" + target.halitem.name = "Cryptographic Sequencer" + if(6) //flashbang + target.halitem.icon = 'icons/obj/grenade.dmi' + target.halitem.icon_state = "flashbang1" + target.halitem.name = "Flashbang" + feedback_details += "Type: [target.halitem.name]" + if(target.client) target.client.screen += target.halitem + QDEL_IN(target.halitem, rand(150, 350)) + qdel(src) + +/datum/hallucination/dangerflash + cost = 15 + +/datum/hallucination/dangerflash/New(mob/living/carbon/T, forced = TRUE) + ..() + //Flashes of danger + if(!target.halimage) + var/list/possible_points = list() + for(var/turf/open/floor/F in view(target,world.view)) + possible_points += F + if(possible_points.len) + var/turf/open/floor/danger_point = pick(possible_points) + + switch(rand(1,5)) + if(1) + target.halimage = image('icons/turf/space.dmi',danger_point,"[rand(1,25)]",TURF_LAYER) + if(2) + target.halimage = image('icons/turf/floors/lava.dmi',danger_point,"smooth",TURF_LAYER) + if(3) + target.halimage = image('icons/turf/floors/Chasms.dmi',danger_point,"smooth",TURF_LAYER) + if(4) + target.halimage = image('icons/effects/effects.dmi',danger_point,"anom",OBJ_LAYER+0.01) + if(5) + target.halimage = image('icons/effects/effects.dmi',danger_point,"electricity2",OBJ_LAYER+0.01) + + + if(target.client) + target.client.images += target.halimage + sleep(rand(200,450)) + if(target.client) + target.client.images -= target.halimage + QDEL_NULL(target.halimage) + qdel(src) + +/datum/hallucination/death + cost = 40 + +/datum/hallucination/death/New(mob/living/carbon/T, forced = TRUE) + set waitfor = 0 + ..() + target.set_screwyhud(SCREWYHUD_DEAD) + target.Knockdown(300) + target.silent += 10 + var/area/area = get_area(target) + to_chat(target, "[target.mind.name] has died at [area.name].") + if(prob(50)) + var/mob/fakemob + var/list/dead_people = list() + for(var/mob/dead/observer/G in GLOB.player_list) + dead_people += G + if(LAZYLEN(dead_people)) + fakemob = pick(dead_people) + else + fakemob = target //ever been so lonely you had to haunt yourself? + if(fakemob) + sleep(rand(20, 50)) + to_chat(target, "DEAD: [fakemob.name] says, \"[pick("rip","hey [target.first_name()]","you too?","is the AI rogue?",\ + "i[prob(50)?" fucking":""] hate [pick("blood cult", "clock cult", "revenants", "abductors","double agents","viruses","badmins","you")]")]\"") + sleep(rand(70,90)) + target.set_screwyhud(SCREWYHUD_NONE) + target.SetKnockdown(0) + target.silent = 0 + qdel(src) + +/datum/hallucination/fire + cost = 25 + +/datum/hallucination/fire/New(mob/living/carbon/T, forced = TRUE) + ..() + var/image/fire_overlay = image('icons/mob/OnFire.dmi', target, "Standing", ABOVE_MOB_LAYER) + if(target.client) + target.client.images += fire_overlay + to_chat(target, "You're set on fire!") + target.throw_alert("fire", /obj/screen/alert/fire, override = TRUE) + sleep(20) + target.throw_alert("temp", /obj/screen/alert/hot, 1, override = TRUE) + sleep(30) + target.clear_alert("temp", clear_override = TRUE) + target.throw_alert("temp", /obj/screen/alert/hot, 2, override = TRUE) + sleep(30) + target.clear_alert("temp", clear_override = TRUE) + target.throw_alert("temp", /obj/screen/alert/hot, 3, override = TRUE) + for(var/i in 1 to rand(5, 10)) + target.adjustStaminaLoss(15) + sleep(25) + target.clear_alert("fire", clear_override = TRUE) + target.clear_alert("temp", clear_override = TRUE) + if(target.client) + target.client.images -= fire_overlay + QDEL_NULL(fire_overlay) + qdel(src) + +/datum/hallucination/husks + cost = 20 + +/datum/hallucination/husks/New(mob/living/carbon/T, forced = TRUE) + ..() + if(!target.halbody) + var/list/possible_points = list() + for(var/turf/open/floor/F in view(target,world.view)) + possible_points += F + if(possible_points.len) + var/turf/open/floor/husk_point = pick(possible_points) + switch(rand(1,4)) + if(1) + var/image/body = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER) + var/matrix/M = matrix() + M.Turn(90) + body.transform = M + target.halbody = body + if(2,3) + target.halbody = image('icons/mob/human.dmi',husk_point,"husk",TURF_LAYER) + if(4) + target.halbody = image('icons/mob/alien.dmi',husk_point,"alienother",TURF_LAYER) + + if(target.client) + target.client.images += target.halbody + sleep(rand(30,50)) //Only seen for a brief moment. + if(target.client) + target.client.images -= target.halbody + QDEL_NULL(target.halbody) + qdel(src) + +//hallucination projectile code in code/modules/projectiles/projectile/special.dm +/datum/hallucination/stray_bullet + cost = 15 + +/datum/hallucination/stray_bullet/New(mob/living/carbon/C, forced = TRUE) + ..() + var/list/turf/startlocs = list() + for(var/turf/open/T in view(world.view+1,target)-view(world.view,target)) + startlocs += T + var/turf/start = pick(startlocs) + var/proj_type = pick(subtypesof(/obj/item/projectile/hallucination)) + feedback_details += "Type: [proj_type]" + var/obj/item/projectile/hallucination/H = new proj_type(start) + target.playsound_local(start, H.hal_fire_sound, 60, 1) + H.hal_target = target + H.current = start + H.starting = start + H.yo = target.y - start.y + H.xo = target.x - start.x + H.original = target + H.fire() + qdel(src) + diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index a1251381b4..06845ba0cb 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -284,7 +284,7 @@ L.adjustBruteLoss(bonus_value) /obj/item/crusher_trophy/tail_spike/proc/pushback(mob/living/target, mob/living/user) - if(!target.anchored || ismegafauna(target)) //megafauna will always be pushed + if(!QDELETED(target) && !QDELETED(user) && (!target.anchored || ismegafauna(target))) //megafauna will always be pushed step(target, get_dir(user, target)) //bubblegum diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 91a178ca36..9179221137 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -240,6 +240,12 @@ /mob/living/carbon/is_muzzled() return(istype(src.wear_mask, /obj/item/clothing/mask/muzzle)) +/mob/living/carbon/hallucinating() + if(hallucination) + return TRUE + else + return FALSE + /mob/living/carbon/resist_buckle() if(restrained()) changeNext_move(CLICK_CD_BREAKOUT) @@ -812,3 +818,4 @@ .["Make AI"] = "?_src_=vars;makeai=\ref[src]" .["Modify bodypart"] = "?_src_=vars;editbodypart=\ref[src]" .["Modify organs"] = "?_src_=vars;editorgans=\ref[src]" + .["Hallucinate"] = "?_src_=vars;hallucinate=\ref[src]" diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 69b581995b..3dacc2f444 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -143,7 +143,7 @@ var/protection = (prot["head"] + prot["arms"] + prot["feet"] + prot["legs"] + prot["groin"] + prot["chest"] + prot["hands"])/7 return protection -/mob/living/carbon/human/can_use_guns(var/obj/item/weapon/gun/G) +/mob/living/carbon/human/can_use_guns(var/obj/item/weapon/G) . = ..() if(G.trigger_guard == TRIGGER_GUARD_NORMAL) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 72c65ae471..c52d9862ad 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -378,8 +378,7 @@ adjust_drugginess(-1) if(hallucination) - spawn handle_hallucinations() - hallucination = max(hallucination-2,0) + handle_hallucinations() //used in human and monkey handle_environment() /mob/living/carbon/proc/natural_bodytemperature_stabilization() diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index f57a48b5c6..9ed0a74d31 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -140,7 +140,7 @@ return 0 return 1 -/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/gun/G) +/mob/living/carbon/monkey/can_use_guns(var/obj/item/weapon/G) return 1 /mob/living/carbon/monkey/angry diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b58fb0ec13..edf54e547a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -795,7 +795,7 @@ else to_chat(src, "You don't have the dexterity to do this!") return -/mob/living/proc/can_use_guns(var/obj/item/weapon/gun/G) +/mob/living/proc/can_use_guns(var/obj/item/weapon/G) if (G.trigger_guard != TRIGGER_GUARD_ALLOW_ALL && !IsAdvancedToolUser()) to_chat(src, "You don't have the dexterity to do this!") return 0 diff --git a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm index c984194805..51d28df31b 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/extra_drone_types.dm @@ -176,7 +176,7 @@ else ..() -/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/weapon/gun/G) +/mob/living/simple_animal/drone/cogscarab/can_use_guns(obj/item/weapon/G) return GLOB.ratvar_awakens /mob/living/simple_animal/drone/cogscarab/get_armor_effectiveness() diff --git a/code/modules/mob/living/simple_animal/guardian/types/fire.dm b/code/modules/mob/living/simple_animal/guardian/types/fire.dm index b0a8ba5215..8f456abc53 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/fire.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/fire.dm @@ -21,7 +21,7 @@ /mob/living/simple_animal/hostile/guardian/fire/AttackingTarget() . = ..() if(. && ishuman(target) && target != summoner) - new /obj/effect/hallucination/delusion(target.loc,target,"custom",200,0, icon_state,icon) + new /datum/hallucination/delusion(target,TRUE,"custom",200,0, icon_state,icon) /mob/living/simple_animal/hostile/guardian/fire/Crossed(AM as mob|obj) ..() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 11c59a2d28..0ca966df35 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -57,6 +57,7 @@ Difficulty: Hard ranged_cooldown_time = 40 aggro_vision_range = 21 //so it can see to one side of the arena to the other loot = list(/obj/item/weapon/hierophant_club) + crusher_loot = list(/obj/item/weapon/hierophant_club) wander = FALSE var/burst_range = 3 //range on burst aoe var/beam_range = 5 //range on cross blast beams diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index a704c2e43f..46f5db920b 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -325,6 +325,9 @@ It's fairly easy to fix if dealing with single letters but not so much with comp return B.eye_blind return 0 +/mob/proc/hallucinating() + return FALSE + /proc/is_special_character(mob/M) // returns 1 for special characters and 2 for heroes of gamemode //moved out of admins.dm because things other than admin procs were calling this. if(!SSticker.HasRoundStarted()) return 0 diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index e36c639eb9..aec4bb82ea 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -120,8 +120,8 @@ if(auto_name) name = "\improper [get_area(src)] APC" - pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24) - pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0 + pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -25) + pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 23 : -24) : 0 if (building) area = get_area(src) opened = 1 diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 156a5ee81e..d5109a2c0c 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -27,7 +27,7 @@ var/recoil = 0 //boom boom shake the room var/clumsy_check = 1 var/obj/item/ammo_casing/chambered = null - var/trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers + trigger_guard = TRIGGER_GUARD_NORMAL //trigger guard on the weapon, hulks can't fire them with their big meaty fingers var/sawn_desc = null //description change if weapon is sawn-off var/sawn_state = SAWN_INTACT var/burst_size = 1 //how large a burst is @@ -188,12 +188,10 @@ -/obj/item/weapon/gun/proc/can_trigger_gun(var/mob/living/user) - - if(!handle_pins(user) || !user.can_use_guns(src)) - return 0 - - return 1 +/obj/item/weapon/gun/can_trigger_gun(mob/living/user) + . = ..() + if(!handle_pins(user)) + return FALSE /obj/item/weapon/gun/proc/handle_pins(mob/living/user) if(pin) diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm index 4b1d5af6c4..5a8f49f45a 100644 --- a/code/modules/projectiles/projectile/special.dm +++ b/code/modules/projectiles/projectile/special.dm @@ -387,3 +387,232 @@ var/obj/effect/ebeam/B = b animate(B, alpha = 0, time = 32) return ..() + +/obj/item/projectile/hallucination + name = "bullet" + icon = null + icon_state = null + hitsound = "" + suppressed = TRUE + ricochets_max = 0 + ricochet_chance = 0 + damage = 0 + nodamage = TRUE + projectile_type = /obj/item/projectile/hallucination + log_override = TRUE + var/hal_icon_state + var/image/fake_icon + var/mob/living/carbon/hal_target + var/hal_fire_sound + var/hal_hitsound + var/hal_hitsound_wall + var/hal_impact_effect + var/hal_impact_effect_wall + var/hit_duration + var/hit_duration_wall + +/obj/item/projectile/hallucination/fire() + ..() + fake_icon = image('icons/obj/projectiles.dmi', src, hal_icon_state, ABOVE_MOB_LAYER) + if(hal_target.client) + hal_target.client.images += fake_icon + +/obj/item/projectile/hallucination/Destroy() + if(hal_target.client) + hal_target.client.images -= fake_icon + QDEL_NULL(fake_icon) + return ..() + +/obj/item/projectile/hallucination/Collide(atom/A) + if(!ismob(A)) + if(hal_hitsound_wall) + hal_target.playsound_local(loc, hal_hitsound_wall, 40, 1) + if(hal_impact_effect_wall) + spawn_hit(A, TRUE) + else if(A == hal_target) + if(hal_hitsound) + hal_target.playsound_local(A, hal_hitsound, 100, 1) + target_on_hit(A) + qdel(src) + return TRUE + +/obj/item/projectile/hallucination/proc/target_on_hit(mob/M) + if(M == hal_target) + to_chat(hal_target, "[M] is hit by \a [src] in the chest!") + hal_apply_effect() + else if(M in view(hal_target)) + to_chat(hal_target, "[M] is hit by \a [src] in the chest!!") + if(damage_type == BRUTE) + var/splatter_dir = dir + if(starting) + splatter_dir = get_dir(starting, get_turf(M)) + spawn_blood(M, splatter_dir) + else if(hal_impact_effect) + spawn_hit(M, FALSE) + +/obj/item/projectile/hallucination/proc/spawn_blood(mob/M, set_dir) + set waitfor = 0 + if(!hal_target.client) + return + + var/splatter_icon_state + if(set_dir in GLOB.diagonals) + splatter_icon_state = "splatter[pick(1, 2, 6)]" + else + splatter_icon_state = "splatter[pick(3, 4, 5)]" + + var/image/blood = image('icons/effects/blood.dmi', M, splatter_icon_state, ABOVE_MOB_LAYER) + var/target_pixel_x = 0 + var/target_pixel_y = 0 + switch(set_dir) + if(NORTH) + target_pixel_y = 16 + if(SOUTH) + target_pixel_y = -16 + layer = ABOVE_MOB_LAYER + if(EAST) + target_pixel_x = 16 + if(WEST) + target_pixel_x = -16 + if(NORTHEAST) + target_pixel_x = 16 + target_pixel_y = 16 + if(NORTHWEST) + target_pixel_x = -16 + target_pixel_y = 16 + if(SOUTHEAST) + target_pixel_x = 16 + target_pixel_y = -16 + layer = ABOVE_MOB_LAYER + if(SOUTHWEST) + target_pixel_x = -16 + target_pixel_y = -16 + layer = ABOVE_MOB_LAYER + hal_target.client.images += blood + animate(blood, pixel_x = target_pixel_x, pixel_y = target_pixel_y, alpha = 0, time = 5) + sleep(5) + hal_target.client.images -= blood + qdel(blood) + +/obj/item/projectile/hallucination/proc/spawn_hit(atom/A, is_wall) + set waitfor = 0 + if(!hal_target.client) + return + + var/image/hit_effect = image('icons/effects/blood.dmi', A, is_wall ? hal_impact_effect_wall : hal_impact_effect, ABOVE_MOB_LAYER) + hit_effect.pixel_x = A.pixel_x + rand(-4,4) + hit_effect.pixel_y = A.pixel_y + rand(-4,4) + hal_target.client.images += hit_effect + sleep(is_wall ? hit_duration_wall : hit_duration) + hal_target.client.images -= hit_effect + qdel(hit_effect) + + +/obj/item/projectile/hallucination/proc/hal_apply_effect() + return + +/obj/item/projectile/hallucination/bullet + name = "bullet" + hal_icon_state = "bullet" + hal_fire_sound = "gunshot" + hal_hitsound = 'sound/weapons/pierce.ogg' + hal_hitsound_wall = "ricochet" + hal_impact_effect = "impact_bullet" + hal_impact_effect_wall = "impact_bullet" + hit_duration = 5 + hit_duration_wall = 5 + +/obj/item/projectile/hallucination/bullet/hal_apply_effect() + hal_target.adjustStaminaLoss(60) + +/obj/item/projectile/hallucination/laser + name = "laser" + damage_type = BURN + hal_icon_state = "laser" + hal_fire_sound = 'sound/weapons/laser.ogg' + hal_hitsound = 'sound/weapons/sear.ogg' + hal_hitsound_wall = 'sound/weapons/effects/searwall.ogg' + hal_impact_effect = "impact_laser" + hal_impact_effect_wall = "impact_laser_wall" + hit_duration = 4 + hit_duration_wall = 10 + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + +/obj/item/projectile/hallucination/laser/hal_apply_effect() + hal_target.adjustStaminaLoss(20) + hal_target.blur_eyes(2) + +/obj/item/projectile/hallucination/taser + name = "electrode" + damage_type = BURN + hal_icon_state = "spark" + color = "#FFFF00" + hal_fire_sound = 'sound/weapons/taser.ogg' + hal_hitsound = 'sound/weapons/taserhit.ogg' + hal_hitsound_wall = null + hal_impact_effect = null + hal_impact_effect_wall = null + +/obj/item/projectile/hallucination/taser/hal_apply_effect() + hal_target.Knockdown(100) + hal_target.stuttering += 20 + if(hal_target.dna && hal_target.dna.check_mutation(HULK)) + hal_target.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" )) + else if(hal_target.status_flags & CANKNOCKDOWN) + addtimer(CALLBACK(hal_target, /mob/living/carbon.proc/do_jitter_animation, 20), 5) + +/obj/item/projectile/hallucination/disabler + name = "disabler beam" + damage_type = STAMINA + hal_icon_state = "omnilaser" + hal_fire_sound = 'sound/weapons/taser2.ogg' + hal_hitsound = 'sound/weapons/tap.ogg' + hal_hitsound_wall = 'sound/weapons/effects/searwall.ogg' + hal_impact_effect = "impact_laser_blue" + hal_impact_effect_wall = null + hit_duration = 4 + pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE + +/obj/item/projectile/hallucination/disabler/hal_apply_effect() + hal_target.adjustStaminaLoss(25) + +/obj/item/projectile/hallucination/ebow + name = "bolt" + damage_type = TOX + hal_icon_state = "cbbolt" + hal_fire_sound = 'sound/weapons/genhit.ogg' + hal_hitsound = null + hal_hitsound_wall = null + hal_impact_effect = null + hal_impact_effect_wall = null + +/obj/item/projectile/hallucination/ebow/hal_apply_effect() + hal_target.Knockdown(100) + hal_target.stuttering += 5 + hal_target.adjustStaminaLoss(8) + +/obj/item/projectile/hallucination/change + name = "bolt of change" + damage_type = BURN + hal_icon_state = "ice_1" + hal_fire_sound = 'sound/magic/staff_change.ogg' + hal_hitsound = null + hal_hitsound_wall = null + hal_impact_effect = null + hal_impact_effect_wall = null + +/obj/item/projectile/hallucination/change/hal_apply_effect() + new /datum/hallucination/self_delusion(hal_target, TRUE, wabbajack = FALSE) + +/obj/item/projectile/hallucination/death + name = "bolt of death" + damage_type = BURN + hal_icon_state = "pulse1_bl" + hal_fire_sound = 'sound/magic/wandodeath.ogg' + hal_hitsound = null + hal_hitsound_wall = null + hal_impact_effect = null + hal_impact_effect_wall = null + +/obj/item/projectile/hallucination/death/hal_apply_effect() + new /datum/hallucination/death(hal_target, TRUE) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 27cad406fa..3811512a02 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -101,9 +101,11 @@ ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) if(!ui) ui = new(user, src, ui_key, "chem_dispenser", name, 550, 550, master_ui, state) + if(user.hallucinating()) + ui.set_autoupdate(FALSE) //to not ruin the immersion by constantly changing the fake chemicals ui.open() -/obj/machinery/chem_dispenser/ui_data() +/obj/machinery/chem_dispenser/ui_data(mob/user) var/data = list() data["amount"] = amount data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI. @@ -128,10 +130,16 @@ data["beakerTransferAmounts"] = null var chemicals[0] + var/is_hallucinating = FALSE + if(user.hallucinating()) + is_hallucinating = TRUE for(var/re in dispensable_reagents) var/datum/reagent/temp = GLOB.chemical_reagents_list[re] if(temp) - chemicals.Add(list(list("title" = temp.name, "id" = temp.id))) + var/chemname = temp.name + if(is_hallucinating && prob(5)) + chemname = "[pick_list_replacements("hallucination.json", "chemicals")]" + chemicals.Add(list(list("title" = chemname, "id" = temp.id))) data["chemicals"] = chemicals return data diff --git a/code/modules/surgery/organs/vocal_cords.dm b/code/modules/surgery/organs/vocal_cords.dm index ff44804e75..0f5f1de91d 100644 --- a/code/modules/surgery/organs/vocal_cords.dm +++ b/code/modules/surgery/organs/vocal_cords.dm @@ -290,9 +290,8 @@ //HALLUCINATE else if((findtext(message, hallucinate_words))) cooldown = COOLDOWN_MEME - for(var/V in listeners) - var/mob/living/L = V - new /obj/effect/hallucination/delusion(get_turf(L),L,null,150 * power_multiplier,0) + for(var/mob/living/carbon/C in listeners) + new /datum/hallucination/delusion(C, TRUE, null,150 * power_multiplier,0) //WAKE UP else if((findtext(message, wakeup_words))) diff --git a/code/world.dm b/code/world.dm index 5ef7491f45..a5853c6e12 100644 --- a/code/world.dm +++ b/code/world.dm @@ -59,16 +59,16 @@ if(config.sql_enabled) if(SSdbcore.Connect()) log_world("Database connection established.") - var/datum/DBQuery/db_version = SSdbcore.NewQuery("SELECT major, minor FROM [format_table_name("schema_version")]") - db_version.Execute() - if(db_version.NextRow()) - var/db_major = db_version.item[1] - var/db_minor = db_version.item[2] + var/datum/DBQuery/query_db_version = SSdbcore.NewQuery("SELECT major, minor FROM [format_table_name("schema_version")] ORDER BY date DESC LIMIT 1") + query_db_version.Execute() + if(query_db_version.NextRow()) + var/db_major = query_db_version.item[1] + var/db_minor = query_db_version.item[2] if(db_major < DB_MAJOR_VERSION || db_minor < DB_MINOR_VERSION) - message_admins("db schema ([db_major].[db_minor]) is behind latest tg schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") - log_sql("db schema ([db_major].[db_minor]) is behind latest tg schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") + message_admins("Database schema ([db_major].[db_minor]) is behind latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") + log_sql("Database schema ([db_major].[db_minor]) is behind latest schema version ([DB_MAJOR_VERSION].[DB_MINOR_VERSION]), this may lead to undefined behaviour or errors") else - message_admins("Could not get schema version from db") + message_admins("Could not get schema version from database") else log_world("Your server failed to establish a connection with the database.") @@ -105,10 +105,10 @@ /world/Topic(T, addr, master, key) var/list/input = params2list(T) - + var/pinging = ("ping" in input) var/playing = ("players" in input) - + if(!pinging && !playing && config && config.log_world_topic) GLOB.world_game_log << "TOPIC: \"[T]\", from:[addr], master:[master], key:[key]" diff --git a/html/changelogs/AutoChangeLog-pr-2231.yml b/html/changelogs/AutoChangeLog-pr-2231.yml new file mode 100644 index 0000000000..c25b4b2b49 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2231.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - tweak: "Spell action buttons now have their description in a tooltip." diff --git a/html/changelogs/AutoChangeLog-pr-2359.yml b/html/changelogs/AutoChangeLog-pr-2359.yml new file mode 100644 index 0000000000..8455963dc6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2359.yml @@ -0,0 +1,4 @@ +author: "Joan" +delete-after: True +changes: + - imageadd: "Ported CEV-Eris's APC sprites." diff --git a/html/changelogs/AutoChangeLog-pr-2363.yml b/html/changelogs/AutoChangeLog-pr-2363.yml new file mode 100644 index 0000000000..e8f5b574ae --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2363.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - tweak: "Canisters don't flash red lights anymore when empty." diff --git a/html/changelogs/AutoChangeLog-pr-2371.yml b/html/changelogs/AutoChangeLog-pr-2371.yml new file mode 100644 index 0000000000..ec1810b8a6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-2371.yml @@ -0,0 +1,4 @@ +author: "Xhuis" +delete-after: True +changes: + - bugfix: "The Resurrect Cultist rune now works as intended." diff --git a/icons/obj/power.dmi b/icons/obj/power.dmi index f3b2233283..6b2ae55351 100644 Binary files a/icons/obj/power.dmi and b/icons/obj/power.dmi differ diff --git a/icons/obj/wallframe.dmi b/icons/obj/wallframe.dmi index 0e416cac77..70149901e3 100644 Binary files a/icons/obj/wallframe.dmi and b/icons/obj/wallframe.dmi differ diff --git a/interface/interface.dm b/interface/interface.dm index 64e39587ce..253738064b 100644 --- a/interface/interface.dm +++ b/interface/interface.dm @@ -1,14 +1,12 @@ //Please use mob or src (not usr) in these procs. This way they can be called in the same fashion as procs. -/client/verb/wiki(query as text | null) +/client/verb/wiki() set name = "wiki" - set desc = "Type what you want to know about. This will open the wiki on your web browser. Type nothing to go to the main page." + set desc = "Visit the wiki." set hidden = 1 if(config.wikiurl) - if(query) - var/output = config.wikiurl + "/index.php?title=Special%3ASearch&profile=default&search=" + query - src << link(output) - else if (query != null) - src << link(config.wikiurl) + if(alert("This will open the wiki in your browser. Are you sure?",,"Yes","No")=="No") + return + src << link(config.wikiurl) else to_chat(src, "The wiki URL is not set in the server configuration.") return diff --git a/power.dmi b/power.dmi new file mode 100644 index 0000000000..d0066b96de Binary files /dev/null and b/power.dmi differ diff --git a/strings/brain_damage_lines.json b/strings/brain_damage_lines.json index ce3e726dbc..af040d5ba0 100644 --- a/strings/brain_damage_lines.json +++ b/strings/brain_damage_lines.json @@ -1,17 +1,17 @@ { "brain_damage": [ - "IM A PONY NEEEEEEIIIIIIIIIGH", + "@pick(semicolon)IM A PONY NEEEEEEIIIIIIIIIGH", "without oxigen blob don't evoluate?", - "CAPTAINS A COMDOM", - "@pick(faggot_traitor) @pick(george) @pick(mellens) is grifing me HALP!!!", + "@pick(semicolon)CAPTAINS A COMDOM", + "@pick(semicolon)@pick(faggot_traitor) @pick(george) @pick(mellens) is grifing me HALP!!!", "can u give me @pick(mutations)?", "THe saiyans screwed", "Bi is THE BEST OF BOTH WORLDS>", - "I WANNA PET TEH monkeyS", + "@pick(semicolon)I WANNA PET TEH monkeyS", "stop grifing me!!!!", "SOTP IT#", "shiggey diggey!!", - "A PIRATE APPEAR", + "@pick(semicolon)A PIRATE APPEAR", "FUS RO DAH", "fucking 4rries!", "stat me", @@ -136,7 +136,8 @@ "random_gibberish": [ "g", "squid", - "r" + "r", + "carbon dioxide" ], "y_replacements": [ @@ -171,6 +172,19 @@ "abdoocters" ], + "bug": [ + "", + "IS TIS A BUG??", + "SI IST A BUGG/", + "BUG!!!" + ], + + "semicolon": [ + "", + ";", + ".h" + ], + "roles": [ "heds", "ceptin", diff --git a/strings/brain_damage_lines.json.rej b/strings/brain_damage_lines.json.rej new file mode 100644 index 0000000000..6d8e1cdb62 --- /dev/null +++ b/strings/brain_damage_lines.json.rej @@ -0,0 +1,10 @@ +diff a/strings/brain_damage_lines.json b/strings/brain_damage_lines.json (rejected hunks) +@@ -131,7 +131,7 @@ + "", + "IS TIS A BUG??", + "SI IST A BUGG/", +- "BUG!!!" ++ "BUG!!!" + ], + + "semicolon": [ diff --git a/strings/hallucination.json b/strings/hallucination.json new file mode 100644 index 0000000000..b28c70db4a --- /dev/null +++ b/strings/hallucination.json @@ -0,0 +1,229 @@ +{ + "suspicion": [ + "I'm watching you...", + "I know what you're doing", + "What are you hiding?", + "I saw that" + ], + + "greetings": [ + "", + "Hey, ", + "Hi ", + "Hello ", + "Wait, ", + "It's " + ], + + "getout": [ + "Get out", + "Get out!", + "Go away", + "Fuck off", + "OUT!", + "Out!" + ], + + "weird": [ + "Kchck-Chkck? Kchchck!", + "Kchckchk...", + "EEEeeeeEEEE", + "khhhhh", + "#@§*&£", + "H**p m*", + "H-hhhhh..." + ], + + "didyouhearthat": [ + "Did you hear that?", + "Did you see that?", + "What was that?" + ], + + "imatraitor": [ + "Hail Ratvar", + "Hail Nar'Sie", + "Hey, i've got some TC left, want something?", + "Viva!", + "I'll spare you if you don't tell anybody about me", + "Hey, are you a traitor too?", + "You're my target, but @pick(excuses)", + "Are you mr. @pick(ling_names)?" + ], + + "excuses": [ + "i like you, so i'll spare you", + "i don't really feel like following objectives today", + "i'm not robust enough to fight you", + "who cares", + "i'll kill you later" + ] + + "ling_names": [ + "Alpha", + "Beta", + "Gamma", + "Delta", + "Epsilon", + "Eta", + "Theta", + "Lambda", + "Mu", + "Xi", + "Rho", + "Sigma", + "Tau", + "Upsilon", + "Phi", + "Psi", + "Omega" + ] + + "doubt": [ + "Why?", + "What?", + "Wait, what?", + "Wait", + "Hold on", + "Uh..." + ], + + "aggressive": [ + "Give me that!", + "I'm going to kill you!", + "Fuck you!" + ], + + "help": [ + "HELP", + "HELP ME", + "HELP HIM", + "HELP HER", + "HELP THEM", + "HELP US", + "HELP YOURSELF" + ], + + "escape": [ + "RUN!!", + "They're behind me!", + "It's here!", + "Follow me!", + "Follow me" + ] + + "infection_advice": [ + "stay away", + "don't get close", + "be careful", + "help me", + "kill me" + ] + + "people": [ + "Captain", + "Hos", + "Cmo", + "Rd", + "Ce", + "Hop", + "Janitor", + "AI", + "Viro", + "Qm", + "[target.first_name()]" + ] + + "accusations": [ + "rogue", + "cult", + "a cultist", + "clockcult", + "a clock cultist", + "a revhead", + "a rev", + "a gang leader", + "a gangster", + "a traitor", + "a tator", + "a ling", + "a changeling" + ] + + "threat": [ + "Cult", + "Wizard", + "Blob", + "Ling", + "Ops", + "Swarmers", + "Revenant", + "Traitor", + "Harm", + "I hear flashing", + "Help" + ] + + "location": [ + "bridge", + "armory", + "sec", + "security", + "science", + "engineering", + "cargo", + "medbay", + "atmos", + "maint", + "hops office", + "captains office", + "chapel", + "library", + "tool storage", + "botany", + "kitchen", + "the ai sat" + ] + + "advice": [ + "Hmm...not sure about that.", + "Yes. You're doing the right thing.", + "No. Stop what you're doing.", + "You should be wary of that person.", + "Trust that person.", + "That person wants to kill you.", + "Kill that person. You know who.", + "You should go somewhere else. Quickly.", + "Good luck. You'll need it.", + "You have my permission. Do it." + ] + + "chemicals": [ + "Ooze", + "Fire", + "Earth", + "Lightning", + "Air", + "Magic", + "Spiders", + "Button", + "Surprise", + "Happiness", + "Despair", + "Blood", + "Awesome", + "Infinity", + "Electronics", + "Time", + "Space", + "Pain", + "Guts", + "Life", + "Death", + "Phlebotinium", + "Mana", + "Energy", + "?????" + ] + +}