diff --git a/code/__DEFINES/layers.dm b/code/__DEFINES/layers.dm index 35b70bdb84..d33eaa35da 100644 --- a/code/__DEFINES/layers.dm +++ b/code/__DEFINES/layers.dm @@ -6,7 +6,8 @@ #define PLANE_SPACE -95 #define PLANE_SPACE_PARALLAX -90 -#define GAME_PLANE 0 +#define GAME_PLANE -1 +#define BLACKNESS_PLANE 0 //To keep from conflicts with SEE_BLACKNESS internals #define SPACE_LAYER 1.8 #define ABOVE_SPACE_LAYER 1.9 //#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define diff --git a/code/controllers/configuration/configuration.dm b/code/controllers/configuration/configuration.dm index 49ccb411fc..a9807a599c 100644 --- a/code/controllers/configuration/configuration.dm +++ b/code/controllers/configuration/configuration.dm @@ -74,6 +74,10 @@ GLOBAL_PROTECT(config_dir) if(copytext(L, 1, 2) == "#") continue + var/lockthis = copytext(L, 1, 2) == "@" + if(lockthis) + L = copytext(L, 2) + var/pos = findtext(L, " ") var/entry = null var/value = null @@ -96,6 +100,9 @@ GLOBAL_PROTECT(config_dir) log_config("Found [entry] in [filename] when it should have been in [E.resident_file]! Ignoring.") continue + if(lockthis) + E.protection |= CONFIG_ENTRY_LOCKED + var/validated = E.ValidateAndSet(value) if(!validated) log_config("Failed to validate setting \"[value]\" for [entry]") diff --git a/code/datums/action.dm b/code/datums/action.dm index a65294fa40..cf1046ca8f 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -591,3 +591,50 @@ var/mob/M = owner var/datum/language_holder/H = M.get_language_holder() H.open_language_menu(usr) + +/datum/action/innate/dash + name = "Dash" + desc = "Teleport to the targeted location." + icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon_state = "jetboot" + var/charged = TRUE + var/charge_rate = 250 + var/mob/living/carbon/human/holder + var/obj/item/dashing_item + var/dash_sound = 'sound/magic/blink.ogg' + var/recharge_sound = 'sound/magic/charge.ogg' + var/beam_effect = "blur" + var/phasein = /obj/effect/temp_visual/dir_setting/ninja/phase + var/phaseout = /obj/effect/temp_visual/dir_setting/ninja/phase/out + +/datum/action/innate/dash/Grant(mob/user, obj/dasher) + . = ..() + dashing_item = dasher + holder = user + +/datum/action/innate/dash/IsAvailable() + if(charged) + return TRUE + else + return FALSE + +/datum/action/innate/dash/Activate() + dashing_item.attack_self(holder) //Used to toggle dash behavior in the dashing item + +/datum/action/innate/dash/proc/Teleport(mob/user, atom/target) + var/turf/T = get_turf(target) + if(target in view(user.client.view, get_turf(user))) + var/obj/spot1 = new phaseout(get_turf(user), user.dir) + user.forceMove(T) + playsound(T, dash_sound, 25, 1) + var/obj/spot2 = new phasein(get_turf(user), user.dir) + spot1.Beam(spot2,beam_effect,time=20) + charged = FALSE + holder.update_action_buttons_icon() + addtimer(CALLBACK(src, .proc/charge), charge_rate) + +/datum/action/innate/dash/proc/charge() + charged = TRUE + holder.update_action_buttons_icon() + playsound(dashing_item, recharge_sound, 50, 1) + to_chat(holder, "[dashing_item] is ready for another jaunt.") \ No newline at end of file diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 25b04b4312..20d218f767 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -384,3 +384,31 @@ if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"]) owner.stun_absorption -= "blooddrunk" +/datum/status_effect/sword_spin + id = "Bastard Sword Spin" + duration = 50 + tick_interval = 8 + alert_type = null + + +/datum/status_effect/sword_spin/on_apply() + owner.visible_message("[owner] begins swinging the sword with inhuman strength!") + var/oldcolor = owner.color + owner.color = "#ff0000" + owner.add_stun_absorption("bloody bastard sword", duration, 2, "doesn't even flinch as the sword's power courses through them!", "You shrug off the stun!", " glowing with a blazing red aura!") + owner.spin(duration,1) + animate(owner, color = oldcolor, time = duration, easing = EASE_IN) + addtimer(CALLBACK(owner, /atom/proc/update_atom_colour), duration) + playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0) + return ..() + + +/datum/status_effect/sword_spin/tick() + playsound(owner, 'sound/weapons/fwoosh.wav', 75, 0) + var/obj/item/slashy + slashy = owner.get_active_held_item() + for(var/mob/living/M in orange(1,owner)) + slashy.attack(M, owner) + +/datum/status_effect/sword_spin/on_remove() + owner.visible_message("[owner]'s inhuman strength dissipates and the sword's runes grow cold!") diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 55f8ece5e6..876cace14d 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -72,6 +72,170 @@ if(is_servant_of_ratvar(C) && C.reagents) C.reagents.add_reagent("heparin", 1) +/obj/item/twohanded/required/cult_bastard + name = "bloody bastard sword" + desc = "An enormous sword used by Nar-Sien cultists to rapidly harvest the souls of non-believers." + w_class = WEIGHT_CLASS_HUGE + block_chance = 50 + throwforce = 20 + force = 35 + armour_penetration = 45 + throw_speed = 1 + throw_range = 3 + sharpness = IS_SHARP + light_color = "#ff0000" + attack_verb = list("cleaved", "slashed", "torn", "hacked", "ripped", "diced", "carved") + icon_state = "cultbastard" + item_state = "cultbastard" + hitsound = 'sound/weapons/bladeslice.ogg' + lefthand_file = 'icons/mob/inhands/64x64_lefthand.dmi' + righthand_file = 'icons/mob/inhands/64x64_righthand.dmi' + inhand_x_dimension = 64 + inhand_y_dimension = 64 + actions_types = list() + flags_2 = SLOWS_WHILE_IN_HAND_2 + var/datum/action/innate/dash/cult/jaunt + var/datum/action/innate/cult/spin2win/linked_action + var/spinning = FALSE + var/spin_cooldown = 250 + var/list/shards = list() + var/dash_toggled = TRUE + +/obj/item/twohanded/required/cult_bastard/Initialize() + . = ..() + set_light(4) + jaunt = new(src) + linked_action = new(src) + +/obj/item/twohanded/required/cult_bastard/can_be_pulled(user) + return FALSE + +/obj/item/twohanded/required/cult_bastard/attack_self(mob/user) + dash_toggled = !dash_toggled + if(dash_toggled) + to_chat(loc, "You raise the [src] and prepare to jaunt with it.") + else + to_chat(loc, "You lower the [src] and prepare to swing it normally.") + +/obj/item/twohanded/required/cult_bastard/pickup(mob/living/user) + . = ..() + if(!iscultist(user)) + if(!is_servant_of_ratvar(user)) + to_chat(user, "\"I wouldn't advise that.\"") + to_chat(user, "An overwhelming sense of nausea overpowers you!") + user.Dizzy(80) + user.Knockdown(30) + return + else + to_chat(user, "\"One of Ratvar's toys is trying to play with things [user.p_they()] shouldn't. Cute.\"") + to_chat(user, "A horrible force yanks at your arm!") + user.emote("scream") + user.apply_damage(30, BRUTE, pick("l_arm", "r_arm")) + user.Knockdown(50) + return + jaunt.Grant(user, src) + linked_action.Grant(user, src) + user.update_icons() + +/obj/item/twohanded/required/cult_bastard/dropped(mob/user) + . = ..() + linked_action.Remove(user) + jaunt.Remove(user) + user.update_icons() + +/obj/item/twohanded/required/cult_bastard/IsReflect() + if(spinning) + playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) + return TRUE + else + ..() + +/obj/item/twohanded/required/cult_bastard/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + if(prob(final_block_chance)) + if(attack_type == PROJECTILE_ATTACK) + owner.visible_message("[owner] deflects [attack_text] with [src]!") + playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 100, 1) + return TRUE + else + playsound(src, 'sound/weapons/parry.ogg', 75, 1) + owner.visible_message("[owner] parries [attack_text] with [src]!") + return TRUE + return FALSE + +/obj/item/twohanded/required/cult_bastard/afterattack(atom/target, mob/user, proximity, click_parameters) + . = ..() + if(dash_toggled && jaunt.IsAvailable()) + jaunt.Teleport(user, target) + return + if(!proximity) + return + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(H.stat != CONSCIOUS) + var/obj/item/device/soulstone/SS = new /obj/item/device/soulstone(src) + SS.attack(H, user) + shards += SS + return + if(istype(target, /obj/structure/constructshell) && contents.len) + var/obj/item/device/soulstone/SS = contents[1] + if(istype(SS) && SS.transfer_soul("CONSTRUCT",target,user)) + qdel(SS) + +/datum/action/innate/dash/cult + name = "Rend the Veil" + desc = "Use the sword to shear open the flimsy fabric of this reality and teleport to your target." + icon_icon = 'icons/mob/actions/actions_cult.dmi' + button_icon_state = "phaseshift" + dash_sound = 'sound/magic/enter_blood.ogg' + recharge_sound = 'sound/magic/exit_blood.ogg' + beam_effect = "sendbeam" + phasein = /obj/effect/temp_visual/dir_setting/cult/phase + phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out + +/datum/action/innate/dash/cult/IsAvailable() + if(iscultist(holder) && charged) + return TRUE + else + return FALSE + + + +/datum/action/innate/cult/spin2win + name = "Geometer's Fury" + desc = "You draw on the power of the sword's ancient runes, spinning it wildly around you as you become immune to most attacks." + background_icon_state = "bg_demon" + button_icon_state = "sintouch" + var/cooldown = 0 + var/mob/living/carbon/human/holder + var/obj/item/twohanded/required/cult_bastard/sword + +/datum/action/innate/cult/spin2win/Grant(mob/user, obj/bastard) + . = ..() + sword = bastard + holder = user + +/datum/action/innate/cult/spin2win/IsAvailable() + if(iscultist(holder) && cooldown <= world.time) + return TRUE + else + return FALSE + +/datum/action/innate/cult/spin2win/Activate() + cooldown = world.time + sword.spin_cooldown + holder.changeNext_move(50) + holder.apply_status_effect(/datum/status_effect/sword_spin) + sword.spinning = TRUE + sword.block_chance = 100 + sword.slowdown += 1.5 + addtimer(CALLBACK(src, .proc/stop_spinning), 50) + holder.update_action_buttons_icon() + +/datum/action/innate/cult/spin2win/proc/stop_spinning() + sword.spinning = FALSE + sword.block_chance = 50 + sword.slowdown -= 1.5 + sleep(sword.spin_cooldown) + holder.update_action_buttons_icon() /obj/item/restraints/legcuffs/bola/cult name = "nar'sien bola" diff --git a/code/game/gamemodes/cult/cult_structures.dm b/code/game/gamemodes/cult/cult_structures.dm index c1ccf9a368..0144872c17 100644 --- a/code/game/gamemodes/cult/cult_structures.dm +++ b/code/game/gamemodes/cult/cult_structures.dm @@ -100,15 +100,21 @@ if(cooldowntime > world.time) to_chat(user, "The magic in [src] is weak, it will be ready to use again in [DisplayTimeText(cooldowntime - world.time)].") return - var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Nar-Sien Hardsuit") + var/choice = alert(user,"You study the schematics etched into the forge...",,"Shielded Robe","Flagellant's Robe","Bastard Sword") var/pickedtype switch(choice) if("Shielded Robe") pickedtype = /obj/item/clothing/suit/hooded/cultrobes/cult_shield if("Flagellant's Robe") pickedtype = /obj/item/clothing/suit/hooded/cultrobes/berserker - if("Nar-Sien Hardsuit") - pickedtype = /obj/item/clothing/suit/space/hardsuit/cult + if("Bastard Sword") + if((world.time - SSticker.round_start_time) >= 12000) + pickedtype = /obj/item/twohanded/required/cult_bastard + else + cooldowntime = 12000 - (world.time - SSticker.round_start_time) + to_chat(user, "The forge fires are not yet hot enough for this weapon, give it another [DisplayTimeText(cooldowntime - world.time)].") + cooldowntime = 0 + return if(src && !QDELETED(src) && anchored && pickedtype && Adjacent(user) && !user.incapacitated() && iscultist(user) && cooldowntime <= world.time) cooldowntime = world.time + 2400 var/obj/item/N = new pickedtype(get_turf(src)) diff --git a/code/game/gamemodes/wizard/soulstone.dm b/code/game/gamemodes/wizard/soulstone.dm index df57ded774..149c2ae912 100644 --- a/code/game/gamemodes/wizard/soulstone.dm +++ b/code/game/gamemodes/wizard/soulstone.dm @@ -199,7 +199,6 @@ SSticker.mode.cult -= A.mind SSticker.mode.update_cult_icons_removed(A.mind) qdel(T) - user.drop_item() qdel(src) else to_chat(user, "Creation failed!: The soul stone is empty! Go kill someone!") diff --git a/code/game/objects/items/storage/book.dm b/code/game/objects/items/storage/book.dm index dc6993cdbe..28856e17d8 100644 --- a/code/game/objects/items/storage/book.dm +++ b/code/game/objects/items/storage/book.dm @@ -156,6 +156,24 @@ GLOBAL_LIST_INIT(bibleitemstates, list("bible", "koran", "scrapbook", "bible", var/unholy2clean = A.reagents.get_reagent_amount("unholywater") A.reagents.del_reagent("unholywater") A.reagents.add_reagent("holywater",unholy2clean) + if(istype(A, /obj/item/twohanded/required/cult_bastard)) + var/obj/item/twohanded/required/cult_bastard/sword = A + to_chat(user, "You begin to exorcise [sword].") + playsound(src,'sound/hallucinations/veryfar_noise.ogg',40,1) + if(do_after(user, 40, target = sword)) + playsound(src,'sound/effects/pray_chaplain.ogg',60,1) + for(var/obj/item/device/soulstone/SS in sword.shards) + SS.usability = TRUE + for(var/mob/living/simple_animal/shade/EX in SS) + SSticker.mode.remove_cultist(EX.mind, 1, 0) + EX.icon_state = "ghost1" + EX.name = "Purified [EX.name]" + SS.release_shades(user) + qdel(SS) + new /obj/item/nullrod/claymore(get_turf(sword)) + user.visible_message("[user] has purified the [sword]!!") + qdel(sword) + /obj/item/storage/book/bible/booze desc = "To be applied to the head repeatedly." diff --git a/code/game/objects/structures/beds_chairs/bed.dm b/code/game/objects/structures/beds_chairs/bed.dm index 935b62f46a..5c36c5a6ba 100644 --- a/code/game/objects/structures/beds_chairs/bed.dm +++ b/code/game/objects/structures/beds_chairs/bed.dm @@ -21,6 +21,10 @@ var/buildstacktype = /obj/item/stack/sheet/metal var/buildstackamount = 2 +/obj/structure/bed/examine(mob/user) + ..() + to_chat(user, "It's held together by a couple of bolts.") + /obj/structure/bed/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) if(buildstacktype) diff --git a/code/game/objects/structures/beds_chairs/chair.dm b/code/game/objects/structures/beds_chairs/chair.dm index aed1679322..9d6985c620 100644 --- a/code/game/objects/structures/beds_chairs/chair.dm +++ b/code/game/objects/structures/beds_chairs/chair.dm @@ -1,6 +1,6 @@ /obj/structure/chair name = "chair" - desc = "You sit in this. Either by will or force.\nDrag your sprite to sit in the chair. Alt-click to rotate it clockwise." + desc = "You sit in this. Either by will or force." icon = 'icons/obj/chairs.dmi' icon_state = "chair" anchored = TRUE @@ -14,6 +14,14 @@ var/item_chair = /obj/item/chair // if null it can't be picked up layer = OBJ_LAYER +/obj/structure/chair/examine(mob/user) + ..() + to_chat(user, "It's held together by a couple of bolts.") + if(!has_buckled_mobs()) + to_chat(user, "Drag your sprite to sit in it. Alt-click to rotate.") + else + to_chat(user, "Alt-click to rotate.") + /obj/structure/chair/Initialize() . = ..() if(!anchored) //why would you put these on the shuttle? @@ -140,7 +148,7 @@ /obj/structure/chair/comfy name = "comfy chair" - desc = "It looks comfy.\nAlt-click to rotate it clockwise." + desc = "It looks comfy." icon_state = "comfychair" color = rgb(255,255,255) resistance_flags = FLAMMABLE diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index c7b63be32b..3d77be1bb5 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -76,8 +76,12 @@ /obj/structure/closet/examine(mob/user) ..() + if(welded) + to_chat(user, "It's welded shut.") if(anchored) - to_chat(user, "It is anchored to the ground.") + to_chat(user, "It is bolted to the ground.") + if(opened) + to_chat(user, "The parts are welded together.") else if(secure && !opened) to_chat(user, "Alt-click to [locked ? "unlock" : "lock"].") @@ -453,4 +457,4 @@ /obj/structure/closet/return_temperature() - return \ No newline at end of file + return diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 914be24cfd..1683ac00e6 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -1,5 +1,5 @@ /obj/structure/grille - desc = "A flimsy lattice of metal rods, with screws to secure it to the floor." + desc = "A flimsy framework of metal rods." name = "grille" icon = 'icons/obj/structures.dmi' icon_state = "grille" @@ -17,6 +17,13 @@ var/grille_type = null var/broken_type = /obj/structure/grille/broken +/obj/structure/grille/examine(mob/user) + ..() + if(anchored) + to_chat(user, "It's secured in place with screws. The rods look like they could be cut through.") + if(!anchored) + to_chat(user, "The anchoring screws are unscrewed. The rods look like they could be cut through.") + /obj/structure/grille/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd) switch(the_rcd.mode) if(RCD_DECONSTRUCT) diff --git a/code/game/objects/structures/lattice.dm b/code/game/objects/structures/lattice.dm index d578b307db..c0dcd866d8 100644 --- a/code/game/objects/structures/lattice.dm +++ b/code/game/objects/structures/lattice.dm @@ -16,6 +16,13 @@ smooth = SMOOTH_MORE // flags_1 = CONDUCT_1 +/obj/structure/lattice/examine(mob/user) + ..() + deconstruction_hints(user) + +/obj/structure/lattice/proc/deconstruction_hints(mob/user) + to_chat(user, "The rods look like they could be cut. There's space for more rods or a tile.") + /obj/structure/lattice/Initialize(mapload) . = ..() for(var/obj/structure/lattice/LAT in loc) @@ -79,6 +86,9 @@ smooth = SMOOTH_TRUE canSmoothWith = null +/obj/structure/lattice/catwalk/deconstruction_hints(mob/user) + to_chat(user, "The supporting rods look like they could be cut.") + /obj/structure/lattice/catwalk/ratvar_act() new /obj/structure/lattice/catwalk/clockwork(loc) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 116ced183f..c54661066a 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -34,6 +34,13 @@ smooth = SMOOTH_TRUE canSmoothWith = list(/obj/structure/table, /obj/structure/table/reinforced) +/obj/structure/table/examine(mob/user) + ..() + deconstruction_hints(user) + +/obj/structure/table/proc/deconstruction_hints(mob/user) + to_chat(user, "The top is screwed on, but the main bolts are also visible.") + /obj/structure/table/Initialize() . = ..() for(var/obj/structure/table/T in src.loc) @@ -285,7 +292,7 @@ */ /obj/structure/table/reinforced name = "reinforced table" - desc = "A reinforced version of the four legged table, much harder to simply deconstruct." + desc = "A reinforced version of the four legged table." icon = 'icons/obj/smooth_structures/reinforced_table.dmi' icon_state = "r_table" deconstruction_ready = 0 @@ -295,6 +302,12 @@ integrity_failure = 50 armor = list(melee = 10, bullet = 30, laser = 30, energy = 100, bomb = 20, bio = 0, rad = 0, fire = 80, acid = 70) +/obj/structure/table/reinforced/deconstruction_hints(mob/user) + if(deconstruction_ready) + to_chat(user, "The top cover has been welded loose and the main frame's bolts are exposed.") + else + to_chat(user, "The top cover is firmly welded on.") + /obj/structure/table/reinforced/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/weldingtool)) var/obj/item/weldingtool/WT = W @@ -405,6 +418,10 @@ pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density. max_integrity = 20 +/obj/structure/rack/examine(mob/user) + ..() + to_chat(user, "It's held together by a couple of bolts.") + /obj/structure/rack/CanPass(atom/movable/mover, turf/target) if(src.density == 0) //Because broken racks -Agouri |TODO: SPRITE!| return 1 diff --git a/code/game/turfs/simulated/floor.dm b/code/game/turfs/simulated/floor.dm index 02206646d2..97634f7629 100644 --- a/code/game/turfs/simulated/floor.dm +++ b/code/game/turfs/simulated/floor.dm @@ -161,10 +161,10 @@ broken = 0 burnt = 0 if(user && !silent) - to_chat(user, "You remove the broken plating.") + to_chat(user, "You remove the broken plating.") else if(user && !silent) - to_chat(user, "You remove the floor tile.") + to_chat(user, "You remove the floor tile.") if(floor_tile && make_tile) new floor_tile(src) return make_plating() diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index a24642c735..428c965197 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -8,10 +8,15 @@ */ /turf/open/floor/wood + desc = "Stylish dark wood." icon_state = "wood" floor_tile = /obj/item/stack/tile/wood broken_states = list("wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7") +/turf/open/floor/wood/examine(mob/user) + ..() + to_chat(user, "There's a few screws and a small crack visible.") + /turf/open/floor/wood/attackby(obj/item/C, mob/user, params) if(..()) return @@ -42,16 +47,16 @@ broken = 0 burnt = 0 if(user && !silent) - to_chat(user, "You remove the broken planks.") + to_chat(user, "You remove the broken planks.") else if(make_tile) if(user && !silent) - to_chat(user, "You unscrew the planks.") + to_chat(user, "You unscrew the planks.") if(floor_tile) new floor_tile(src) else if(user && !silent) - to_chat(user, "You forcefully pry off the planks, destroying them in the process.") + to_chat(user, "You forcefully pry off the planks, destroying them in the process.") return make_plating() /turf/open/floor/wood/cold @@ -78,7 +83,7 @@ if(istype(C, /obj/item/shovel) && params) new ore_type(src) new ore_type(src) //Make some sand if you shovel grass - user.visible_message("[user] digs up [src].", "You [src.turfverb] [src].") + user.visible_message("[user] digs up [src].", "You [src.turfverb] [src].") playsound(src, 'sound/effects/shovel_dig.ogg', 50, 1) make_plating() if(..()) @@ -143,6 +148,10 @@ canSmoothWith = list(/turf/open/floor/carpet) flags_1 = NONE +/turf/open/floor/carpet/examine(mob/user) + ..() + to_chat(user, "There's a small crack on the edge of it.") + /turf/open/floor/carpet/Initialize() . = ..() update_icon() diff --git a/code/game/turfs/simulated/floor/light_floor.dm b/code/game/turfs/simulated/floor/light_floor.dm index 247382d03c..0dd3673f6a 100644 --- a/code/game/turfs/simulated/floor/light_floor.dm +++ b/code/game/turfs/simulated/floor/light_floor.dm @@ -12,6 +12,10 @@ var/can_modify_colour = TRUE +/turf/open/floor/light/examine(mob/user) + ..() + to_chat(user, "There's a small crack on the edge of it.") + /turf/open/floor/light/Initialize() . = ..() update_icon() diff --git a/code/game/turfs/simulated/floor/plasteel_floor.dm b/code/game/turfs/simulated/floor/plasteel_floor.dm index 63c883f88c..b194127de8 100644 --- a/code/game/turfs/simulated/floor/plasteel_floor.dm +++ b/code/game/turfs/simulated/floor/plasteel_floor.dm @@ -4,6 +4,10 @@ broken_states = list("damaged1", "damaged2", "damaged3", "damaged4", "damaged5") burnt_states = list("floorscorched1", "floorscorched2") +/turf/open/floor/plasteel/examine(mob/user) + ..() + to_chat(user, "There's a small crack on the edge of it.") + /turf/open/floor/plasteel/update_icon() if(!..()) return 0 diff --git a/code/game/turfs/simulated/floor/plating.dm b/code/game/turfs/simulated/floor/plating.dm index 8ad6657784..3e16da8b9f 100644 --- a/code/game/turfs/simulated/floor/plating.dm +++ b/code/game/turfs/simulated/floor/plating.dm @@ -12,6 +12,13 @@ icon_state = "plating" intact = FALSE +/turf/open/floor/plating/examine(mob/user) + ..() + if(broken || burnt) + to_chat(user, "It looks like the dents could be welded smooth.") + return + to_chat(user, "There are few attachment holes for a new tile or reinforcement rods.") + /turf/open/floor/plating/Initialize() if (!broken_states) broken_states = list("platingdmg1", "platingdmg2", "platingdmg3") diff --git a/code/game/turfs/simulated/floor/plating/asteroid.dm b/code/game/turfs/simulated/floor/plating/asteroid.dm index 2649a3a14d..848a7e8219 100644 --- a/code/game/turfs/simulated/floor/plating/asteroid.dm +++ b/code/game/turfs/simulated/floor/plating/asteroid.dm @@ -193,7 +193,7 @@ var/list/L = list(45) if(IsOdd(dir2angle(dir))) // We're going at an angle and we want thick angled tunnels. - L += -45 + L -= 45 // Expand the edges of our tunnel for(var/edge_angle in L) diff --git a/code/game/turfs/simulated/floor/reinf_floor.dm b/code/game/turfs/simulated/floor/reinf_floor.dm index 04c97aa7d5..74354e78c7 100644 --- a/code/game/turfs/simulated/floor/reinf_floor.dm +++ b/code/game/turfs/simulated/floor/reinf_floor.dm @@ -1,11 +1,16 @@ /turf/open/floor/engine name = "reinforced floor" + desc = "Extremely sturdy." icon_state = "engine" thermal_conductivity = 0.025 heat_capacity = INFINITY floor_tile = /obj/item/stack/rods +/turf/open/floor/engine/examine(mob/user) + ..() + to_chat(user, "The reinforcement rods are wrenched firmly in place.") + /turf/open/floor/engine/airless initial_gas_mix = "TEMP=2.7" diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm index ae5f5c2fbb..33f02bc759 100644 --- a/code/modules/library/lib_items.dm +++ b/code/modules/library/lib_items.dm @@ -25,6 +25,21 @@ var/list/allowed_books = list(/obj/item/book, /obj/item/spellbook, /obj/item/storage/book) //Things allowed in the bookcase +/obj/structure/bookcase/examine(mob/user) + ..() + if(!anchored) + to_chat(user, "The bolts on the bottom are unsecured.") + if(anchored) + to_chat(user, "It's secured in place with bolts.") + switch(state) + if(0) + to_chat(user, "There's a small crack visible on the back panel.") + if(1) + to_chat(user, "There's space inside for a wooden shelf.") + if(2) + to_chat(user, "There's a small crack visible on the shelf.") + + /obj/structure/bookcase/Initialize(mapload) . = ..() if(!mapload) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 6068ef2d66..d90db23679 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -250,6 +250,9 @@ if(health >= 0 && !(status_flags & FAKEDEATH)) if(lying) + if(buckled) + to_chat(M, "You need to unbuckle [src] first to do that!") + return M.visible_message("[M] shakes [src] trying to get [p_them()] up!", \ "You shake [src] trying to get [p_them()] up!") else if(check_zone(M.zone_selected) == "head") diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 70a5f5225c..63b84b9cf3 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -4,6 +4,7 @@ voice_name = "Unknown" icon = 'icons/mob/human.dmi' icon_state = "caucasian_m" + appearance_flags = KEEP_TOGETHER|TILE_BOUND|PIXEL_SCALE /mob/living/carbon/human/Initialize() verbs += /mob/living/proc/mob_sleep diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index ef044e462b..84bf5bdf80 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -37,7 +37,7 @@ if(H.nutrition > NUTRITION_LEVEL_FULL) H.nutrition = NUTRITION_LEVEL_FULL if(light_amount > 0.2) //if there's enough light, heal - H.heal_overall_damage(0.05,0) + H.heal_overall_damage(0.75,0) H.adjustOxyLoss(-0.5) if(H.nutrition < NUTRITION_LEVEL_STARVING + 55) diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index 4ce8570c2b..016a3635ef 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -37,6 +37,7 @@ C.a_intent = INTENT_HARM // THE SUFFERING MUST FLOW if(regen_cooldown < world.time) C.heal_overall_damage(4,4) + C.adjustToxLoss(-4) if(prob(4)) playsound(C, pick(spooks), 50, TRUE, 10) if(C.InCritical()) diff --git a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm index 259ca4327d..325b971171 100644 --- a/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm +++ b/code/modules/mob/living/simple_animal/friendly/drone/visuals_icons.dm @@ -86,7 +86,7 @@ if(istype(head, /obj/item/clothing/mask)) used_head_icon = 'icons/mob/mask.dmi' var/mutable_appearance/head_overlay = head.build_worn_icon(state = head.icon_state, default_layer = DRONE_HEAD_LAYER, default_icon_file = used_head_icon) - head_overlay.pixel_y += -15 + head_overlay.pixel_y -= 15 drone_overlays[DRONE_HEAD_LAYER] = head_overlay diff --git a/code/modules/ninja/suit/gloves.dm b/code/modules/ninja/suit/gloves.dm index 62b8cee415..8eaaa40097 100644 --- a/code/modules/ninja/suit/gloves.dm +++ b/code/modules/ninja/suit/gloves.dm @@ -63,7 +63,7 @@ if(isnum(.)) //Numerical values of drained handle their feedback here, Alpha values handle it themselves (Research hacking) if(.) - to_chat(H, "Gained [.] energy from \the [A].") + to_chat(H, "Gained [DisplayPower(.)] of energy from [A].") else to_chat(H, "\The [A] has run dry of power, you must find another source!") else diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm index 603f8843ca..5ee2ecec05 100644 --- a/code/modules/projectiles/guns/misc/blastcannon.dm +++ b/code/modules/projectiles/guns/misc/blastcannon.dm @@ -12,21 +12,17 @@ randomspread = FALSE var/obj/item/device/transfer_valve/bomb - var/datum/gas_mixture/air1 - var/datum/gas_mixture/air2 /obj/item/gun/blastcannon/New() if(!pin) pin = new - . = ..() + return ..() /obj/item/gun/blastcannon/Destroy() if(bomb) qdel(bomb) bomb = null - air1 = null - air2 = null - . = ..() + return ..() /obj/item/gun/blastcannon/attack_self(mob/user) if(bomb) @@ -35,7 +31,7 @@ user.visible_message("[user] detaches the [bomb] from the [src]") bomb = null update_icon() - . = ..(user) + return ..() /obj/item/gun/blastcannon/update_icon() if(bomb) @@ -46,7 +42,6 @@ icon_state = initial(icon_state) name = initial(name) desc = initial(desc) - . = ..() /obj/item/gun/blastcannon/attackby(obj/O, mob/user) if(istype(O, /obj/item/device/transfer_valve)) @@ -59,20 +54,17 @@ return FALSE user.visible_message("[user] attaches the [O] to the [src]!") bomb = O - O.loc = src + O.forceMove(src) update_icon() return TRUE - . = ..() + return ..() /obj/item/gun/blastcannon/proc/calculate_bomb() if(!istype(bomb)||!istype(bomb.tank_one)||!istype(bomb.tank_two)) return 0 - air1 = bomb.tank_one.air_contents - air2 = bomb.tank_two.air_contents - var/datum/gas_mixture/temp - temp.volume = air1.volume + air2.volume - temp.merge(air1) - temp.merge(air2) + var/datum/gas_mixture/temp = new(60) //directional buff. + temp.merge(bomb.tank_one.air_contents.remove_ratio(1)) + temp.merge(bomb.tank_two.air_contents.remove_ratio(2)) for(var/i in 1 to 6) temp.react() var/pressure = temp.return_pressure() @@ -82,7 +74,7 @@ return (pressure/TANK_FRAGMENT_SCALE) /obj/item/gun/blastcannon/afterattack(atom/target, mob/user, flag, params) - if((!bomb) || (target == user) || (target.loc == user) || (!target) || (target.loc == user.loc) || (target.loc in range(user, 2)) || (target in range(user, 2))) + if((!bomb) || (!target) || (get_dist(get_turf(target), get_turf(user)) <= 2)) return ..() var/power = calculate_bomb() qdel(bomb) @@ -90,13 +82,17 @@ var/heavy = power * 0.2 var/medium = power * 0.5 var/light = power - user.visible_message("[user] opens \the [bomb] on \his [src.name] and fires a blast wave at \the [target]!","You open \the [bomb] on your [src.name] and fire a blast wave at \the [target]!") + user.visible_message("[user] opens \the [bomb] on \his [name] and fires a blast wave at \the [target]!","You open \the [bomb] on your [name] and fire a blast wave at \the [target]!") playsound(user, "explosion", 100, 1) var/turf/starting = get_turf(user) + var/turf/targturf = get_turf(target) var/area/A = get_area(user) - var/log_str = "Blast wave fired at [ADMIN_COORDJMP(starting)] ([A.name]) by [user.name]([user.ckey]) with power [heavy]/[medium]/[light]." + var/log_str = "Blast wave fired from [ADMIN_COORDJMP(starting)] ([A.name]) at [ADMIN_COORDJMP(targturf)] ([target.name]) by [user.name]([user.ckey]) with power [heavy]/[medium]/[light]." message_admins(log_str) log_game(log_str) + var/obj/item/projectile/blastwave/BW = new(loc, heavy, medium, light) + BW.preparePixelProjectile(target, get_turf(target), user, params, 0) + BW.fire() /obj/item/projectile/blastwave name = "blast wave" @@ -109,6 +105,12 @@ var/lightr = 0 range = 150 +/obj/item/projectile/blastwave/Initialize(mapload, _h, _m, _l) + heavyr = _h + mediumr = _m + lightr = _l + return ..() + /obj/item/projectile/blastwave/Range() ..() if(heavyr) diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 3aba80fe64..937326a60b 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -90,8 +90,6 @@ new impact_effect_type(target_loca, target, src) return 0 var/mob/living/L = target - if(L.buckled && ismob(L.buckled)) - L = L.buckled if(blocked != 100) // not completely blocked if(damage && L.blood_volume && damage_type == BRUTE) var/splatter_dir = dir @@ -178,6 +176,8 @@ var/mob/living/picked_mob = pick(mobs_list) if(!prehit(picked_mob)) return FALSE + if(ismob(picked_mob.buckled)) + picked_mob = picked_mob.buckled picked_mob.bullet_act(src, def_zone) qdel(src) return TRUE diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 6f4ae50243..8395ef4d83 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -10,7 +10,7 @@ /obj/item/projectile/bullet/pellet/Range() ..() - damage += -0.75 + damage -= 0.75 if(damage < 0) qdel(src) @@ -66,7 +66,7 @@ /obj/item/projectile/bullet/c38 name = ".38 bullet" damage = 15 - knockdown = 30 + knockdown = 60 stamina = 50 // 10mm (Stechkin) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 4b939bf4f1..3b83dd8e62 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -44,9 +44,11 @@ see_in_dark = 8 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE actions_types = list(/datum/action/item_action/organ_action/use) + sight_flags = SEE_BLACKNESS var/night_vision = TRUE /obj/item/organ/eyes/night_vision/ui_action_click() + sight_flags = initial(sight_flags) switch(lighting_alpha) if (LIGHTING_PLANE_ALPHA_VISIBLE) lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE @@ -56,6 +58,7 @@ lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE else lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE + sight_flags &= ~SEE_BLACKNESS owner.update_sight() /obj/item/organ/eyes/night_vision/alien diff --git a/config/config.txt b/config/config.txt index d5d2725714..72f168dcce 100644 --- a/config/config.txt +++ b/config/config.txt @@ -1,3 +1,11 @@ +# You can use the @ character at the beginning of a config option to lock it from being edited in-game +# Example usage: +# @SERVERNAME tgstation +# Which sets the SERVERNAME, and disallows admins from being able to change it using View Variables. +# @LOG_TWITTER 0 +# Which explicitly disables LOG_TWITTER, as well as locking it. +# There are various options which are hard-locked for security reasons. + ## Server name: This appears at the top of the screen in-game and in the BYOND hub. Uncomment and replace 'tgstation' with the name of your choice. # SERVERNAME tgstation diff --git a/html/changelogs/AutoChangeLog-pr-3041.yml b/html/changelogs/AutoChangeLog-pr-3041.yml new file mode 100644 index 0000000000..872bbc4b99 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3041.yml @@ -0,0 +1,5 @@ +author: "Robustin" +delete-after: True +changes: + - rscadd: "Blood cultists can now create a unique bastard sword at their forge" + - rscdel: "Blood cultists can no longer obtain a hardsuit from the forge" diff --git a/html/changelogs/AutoChangeLog-pr-3105.yml b/html/changelogs/AutoChangeLog-pr-3105.yml new file mode 100644 index 0000000000..b48644c148 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3105.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - balance: "The detectives gun has been restored from a system change that nerfed knockdown in general. We need to have a serious discussion about anti revolver hate in this community." diff --git a/html/changelogs/AutoChangeLog-pr-3114.yml b/html/changelogs/AutoChangeLog-pr-3114.yml new file mode 100644 index 0000000000..abe6380887 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3114.yml @@ -0,0 +1,4 @@ +author: "Daniel0Mclovin" +delete-after: True +changes: + - tweak: "Modify health regeneration from 0.05 to 0.75" diff --git a/html/changelogs/AutoChangeLog-pr-3127.yml b/html/changelogs/AutoChangeLog-pr-3127.yml new file mode 100644 index 0000000000..050e9cb4d7 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3127.yml @@ -0,0 +1,4 @@ +author: "Raeschen" +delete-after: True +changes: + - rscadd: "FTL Milky Way added to music" diff --git a/html/changelogs/AutoChangeLog-pr-3133.yml b/html/changelogs/AutoChangeLog-pr-3133.yml new file mode 100644 index 0000000000..ac49ae1821 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3133.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - spellcheck: "Beds, chairs, closets, grilles, lattices, catwalks, tables, racks, floors, plating and bookcases now show hints about constructing/deconstructing them." diff --git a/html/changelogs/AutoChangeLog-pr-3134.yml b/html/changelogs/AutoChangeLog-pr-3134.yml new file mode 100644 index 0000000000..5b8bcf21b6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-3134.yml @@ -0,0 +1,4 @@ +author: "ShizCalev" +delete-after: True +changes: + - bugfix: "You now have to unbuckle a player PRIOR to shaking them up off a bed or resin nest." diff --git a/icons/mob/inhands/64x64_lefthand.dmi b/icons/mob/inhands/64x64_lefthand.dmi index a9a952733a..1b450ab3e0 100644 Binary files a/icons/mob/inhands/64x64_lefthand.dmi and b/icons/mob/inhands/64x64_lefthand.dmi differ diff --git a/icons/mob/inhands/64x64_righthand.dmi b/icons/mob/inhands/64x64_righthand.dmi index bff96a991b..bbeddf9152 100644 Binary files a/icons/mob/inhands/64x64_righthand.dmi and b/icons/mob/inhands/64x64_righthand.dmi differ diff --git a/icons/obj/items_and_weapons.dmi b/icons/obj/items_and_weapons.dmi index 94c0c03835..b5ac65c2a8 100644 Binary files a/icons/obj/items_and_weapons.dmi and b/icons/obj/items_and_weapons.dmi differ diff --git a/sound/music/milkyway.ogg b/sound/music/milkyway.ogg new file mode 100644 index 0000000000..59d9ba63f4 Binary files /dev/null and b/sound/music/milkyway.ogg differ diff --git a/sound/weapons/fwoosh.wav b/sound/weapons/fwoosh.wav new file mode 100644 index 0000000000..1723c4e9b8 Binary files /dev/null and b/sound/weapons/fwoosh.wav differ diff --git a/sound/weapons/parry.ogg b/sound/weapons/parry.ogg new file mode 100644 index 0000000000..1f86716337 Binary files /dev/null and b/sound/weapons/parry.ogg differ diff --git a/strings/round_start_sounds.txt b/strings/round_start_sounds.txt index 01323a6120..177f612ee1 100644 --- a/strings/round_start_sounds.txt +++ b/strings/round_start_sounds.txt @@ -20,3 +20,4 @@ sound/music/oceanman.ogg sound/music/indeep.ogg sound/music/goodbyemoonmen.ogg sound/music/flytothemoon_otomatone.ogg +sound/music/milkyway.ogg \ No newline at end of file